diff --git a/src/Traits/PayPalAPI/Orders.php b/src/Traits/PayPalAPI/Orders.php index 463b05ce..afcff5ec 100644 --- a/src/Traits/PayPalAPI/Orders.php +++ b/src/Traits/PayPalAPI/Orders.php @@ -4,6 +4,8 @@ trait Orders { + use Orders\Helpers; + /** * Creates an order. * @@ -26,6 +28,38 @@ public function createOrder(array $data) return $this->doPayPalRequest(); } + /** + * Shows details for an order. + * + * @param string $order_id + * + * @throws \Throwable + * + * @return array|\Psr\Http\Message\StreamInterface|string + * + * @see https://developer.paypal.com/docs/api/orders/v2/#orders_get + */ + public function showOrderDetails(string $order_id) + { + $this->apiEndPoint = "v2/checkout/orders/{$order_id}"; + + $this->verb = 'get'; + + return $this->doPayPalRequest(); + } + + /** + * Update order details. + * + * @param string $order_id + * @param array $data + * + * @throws \Throwable + * + * @return array|\Psr\Http\Message\StreamInterface|string + * + * @see https://developer.paypal.com/docs/api/orders/v2/#orders_patch + */ public function updateOrder(string $order_id, array $data) { $this->apiEndPoint = "v2/checkout/orders/{$order_id}"; @@ -38,21 +72,22 @@ public function updateOrder(string $order_id, array $data) } /** - * Shows details for an order. + * Confirm the order. * * @param string $order_id + * @param array $data * * @throws \Throwable * * @return array|\Psr\Http\Message\StreamInterface|string - * - * @see https://developer.paypal.com/docs/api/orders/v2/#orders_get */ - public function showOrderDetails(string $order_id) + public function confirmOrder(string $order_id, array $data) { - $this->apiEndPoint = "v2/checkout/orders/{$order_id}"; + $this->apiEndPoint = "v2/checkout/orders/{$order_id}/confirm-payment-source"; - $this->verb = 'get'; + $this->options['json'] = (object) $data; + + $this->verb = 'post'; return $this->doPayPalRequest(); } diff --git a/src/Traits/PayPalAPI/Orders/Helpers.php b/src/Traits/PayPalAPI/Orders/Helpers.php new file mode 100644 index 00000000..8fa4517d --- /dev/null +++ b/src/Traits/PayPalAPI/Orders/Helpers.php @@ -0,0 +1,31 @@ + $processing_instruction, + 'application_context' => $this->experience_context, + 'payment_source' => $this->payment_source, + ]; + + return $this->confirmOrder($order_id, $body); + } +} diff --git a/src/Traits/PayPalAPI/Subscriptions/Helpers.php b/src/Traits/PayPalAPI/Subscriptions/Helpers.php index a7ee3efc..6fcf936d 100644 --- a/src/Traits/PayPalAPI/Subscriptions/Helpers.php +++ b/src/Traits/PayPalAPI/Subscriptions/Helpers.php @@ -43,16 +43,6 @@ trait Helpers */ protected $has_setup_fee = false; - /** - * @var string - */ - protected $return_url; - - /** - * @var string - */ - protected $cancel_url; - /** * @var array */ @@ -95,11 +85,8 @@ public function setupSubscription(string $customer_name, string $customer_email, $body['subscriber']['shipping_address'] = $this->shipping_address; } - if ($this->return_url && $this->cancel_url) { - $body['application_context'] = [ - 'return_url' => $this->return_url, - 'cancel_url' => $this->cancel_url, - ]; + if (isset($this->experience_context)) { + $body['application_context'] = $this->experience_context; } if (isset($this->taxes)) { @@ -396,22 +383,6 @@ protected function addBillingPlan(string $name, string $description, array $bill $this->billing_plan = $this->createPlan($plan_params, $request_id); } - /** - * Set return & cancel urls. - * - * @param string $return_url - * @param string $cancel_url - * - * @return \Srmklive\PayPal\Services\PayPal - */ - public function setReturnAndCancelUrl(string $return_url, string $cancel_url): \Srmklive\PayPal\Services\PayPal - { - $this->return_url = $return_url; - $this->cancel_url = $cancel_url; - - return $this; - } - /** * Set custom failure threshold when adding a subscription. * diff --git a/src/Traits/PayPalExperienceContext.php b/src/Traits/PayPalExperienceContext.php new file mode 100644 index 00000000..c5018b93 --- /dev/null +++ b/src/Traits/PayPalExperienceContext.php @@ -0,0 +1,80 @@ +experience_context = array_merge($this->experience_context, [ + 'brand_name' => $brand, + ]); + + return $this; + } + + /** + * Set return & cancel urls. + * + * @param string $return_url + * @param string $cancel_url + * + * @return \Srmklive\PayPal\Services\PayPal + */ + public function setReturnAndCancelUrl(string $return_url, string $cancel_url): \Srmklive\PayPal\Services\PayPal + { + $this->experience_context = array_merge($this->experience_context, [ + 'return_url' => $return_url, + 'cancel_url' => $cancel_url, + ]); + + return $this; + } + + /** + * Set stored payment source. + * + * @param string $initiator + * @param string $type + * @param string $usage + * @param bool $previous_reference + * @param string|null $previous_transaction_id + * @param string|null $previous_transaction_date + * @param string|null $previous_transaction_reference_number + * @param string|null $previous_transaction_network + * + * @return \Srmklive\PayPal\Services\PayPal + */ + public function setStoredPaymentSource(string $initiator, string $type, string $usage, bool $previous_reference = false, string $previous_transaction_id = null, string $previous_transaction_date = null, string $previous_transaction_reference_number = null, string $previous_transaction_network = null): \Srmklive\PayPal\Services\PayPal + { + $this->experience_context = array_merge($this->experience_context, [ + 'stored_payment_source' => [ + 'payment_initiator' => $initiator, + 'payment_type' => $type, + 'usage' => $usage, + ], + ]); + + if ($previous_reference === true) { + $this->experience_context['stored_payment_source']['previous_network_transaction_reference'] = [ + 'id' => $previous_transaction_id, + 'date' => $previous_transaction_date, + 'acquirer_reference_number' => $previous_transaction_reference_number, + 'network' => $previous_transaction_network, + ]; + } + + return $this; + } +} diff --git a/src/Traits/PayPalRequest.php b/src/Traits/PayPalRequest.php index b3b542b4..09aecb50 100644 --- a/src/Traits/PayPalRequest.php +++ b/src/Traits/PayPalRequest.php @@ -8,6 +8,7 @@ trait PayPalRequest { use PayPalHttpClient; use PayPalAPI; + use PayPalExperienceContext; /** * PayPal API mode to be used. diff --git a/tests/Feature/AdapterExperienceContextTest.php b/tests/Feature/AdapterExperienceContextTest.php new file mode 100644 index 00000000..7018e2f3 --- /dev/null +++ b/tests/Feature/AdapterExperienceContextTest.php @@ -0,0 +1,69 @@ +client = new PayPalClient($this->getApiCredentials()); + + $this->client->setClient( + $this->mock_http_client( + $this->mockAccessTokenResponse() + ) + ); + $response = $this->client->getAccessToken(); + + self::$access_token = $response['access_token']; + + parent::setUp(); + } + + /** @test */ + public function it_can_set_payment_experience_context_before_performing_api_call() + { + $this->client->setAccessToken([ + 'access_token' => self::$access_token, + 'token_type' => 'Bearer', + ]); + + $start_date = Carbon::now()->addDay()->toDateString(); + + $this->client = $this->client->setReturnAndCancelUrl('https://example.com/paypal-success', 'https://example.com/paypal-cancel') + ->setBrandName('Test Brand') + ->addProductById('PROD-XYAB12ABSB7868434') + ->addBillingPlanById('P-5ML4271244454362WXNWU5NQ'); + + $this->client->setClient( + $this->mock_http_client( + $this->mockCreateSubscriptionResponse() + ) + ); + + $response = $this->client->setupSubscription('John Doe', 'john@example.com', $start_date); + + $this->assertNotEmpty($response); + $this->assertArrayHasKey('id', $response); + $this->assertArrayHasKey('plan_id', $response); + } +} diff --git a/tests/Feature/AdapterOrdersHelperTest.php b/tests/Feature/AdapterOrdersHelperTest.php new file mode 100644 index 00000000..e25ee6f4 --- /dev/null +++ b/tests/Feature/AdapterOrdersHelperTest.php @@ -0,0 +1,74 @@ +client = new PayPalClient($this->getApiCredentials()); + + $this->client->setClient( + $this->mock_http_client( + $this->mockAccessTokenResponse() + ) + ); + $response = $this->client->getAccessToken(); + + self::$access_token = $response['access_token']; + + parent::setUp(); + } + + /** @test */ + public function it_can_confirm_payment_for_an_order() + { + $this->client->setAccessToken([ + 'access_token' => self::$access_token, + 'token_type' => 'Bearer', + ]); + + $start_date = Carbon::now()->subDays(10)->toDateString(); + + $this->client = $this->client->setReturnAndCancelUrl('https://example.com/paypal-success', 'https://example.com/paypal-cancel') + ->setBrandName('Test Brand') + ->setStoredPaymentSource( + 'MERCHANT', + 'RECURRING', + 'SUBSEQUENT', + true, + '5TY05013RG002845M', + $start_date, + 'Invoice-005', + 'VISA' + ); + + $this->client->setClient( + $this->mock_http_client( + $this->mockConfirmOrderResponse() + ) + ); + + $response = $this->client->setupOrderConfirmation('5O190127TN364715T', 'ORDER_COMPLETE_ON_PAYMENT_APPROVAL'); + + $this->assertNotEmpty($response); + $this->assertArrayHasKey('id', $response); + } +} diff --git a/tests/Mocks/Responses/Orders.php b/tests/Mocks/Responses/Orders.php index d0cbdb1c..0dcc35db 100644 --- a/tests/Mocks/Responses/Orders.php +++ b/tests/Mocks/Responses/Orders.php @@ -1,16 +1,16 @@ -