Skip to content

Commit

Permalink
Implement the following:
Browse files Browse the repository at this point in the history
* Implement Confirm Order Payment API.
* Add helper method to set Experience Context as suggested in #554.
  • Loading branch information
srmklive committed Sep 13, 2023
1 parent bac5d52 commit 2d99c7f
Show file tree
Hide file tree
Showing 8 changed files with 382 additions and 85 deletions.
47 changes: 41 additions & 6 deletions src/Traits/PayPalAPI/Orders.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

trait Orders
{
use Orders\Helpers;

/**
* Creates an order.
*
Expand All @@ -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}";
Expand All @@ -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();
}
Expand Down
31 changes: 31 additions & 0 deletions src/Traits/PayPalAPI/Orders/Helpers.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Srmklive\PayPal\Traits\PayPalAPI\Orders;

use Carbon\Carbon;
use Illuminate\Support\Str;
use Throwable;

trait Helpers
{
/**
* Confirm payment for an order.
*
* @param string $order_id
* @param string $processing_instruction
*
* @throws Throwable
*
* @return array|\Psr\Http\Message\StreamInterface|string
*/
public function setupOrderConfirmation(string $order_id, string $processing_instruction = '')
{
$body = [
'processing_instruction' => $processing_instruction,
'application_context' => $this->experience_context,
'payment_source' => $this->payment_source,
];

return $this->confirmOrder($order_id, $body);
}
}
33 changes: 2 additions & 31 deletions src/Traits/PayPalAPI/Subscriptions/Helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,6 @@ trait Helpers
*/
protected $has_setup_fee = false;

/**
* @var string
*/
protected $return_url;

/**
* @var string
*/
protected $cancel_url;

/**
* @var array
*/
Expand Down Expand Up @@ -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)) {
Expand Down Expand Up @@ -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.
*
Expand Down
80 changes: 80 additions & 0 deletions src/Traits/PayPalExperienceContext.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace Srmklive\PayPal\Traits;

trait PayPalExperienceContext
{
/**
* @var array
*/
protected $experience_context = [];

/**
* Set Brand Name when setting experience context for payment.
* @param string $brand
*
* @return \Srmklive\PayPal\Services\PayPal
*/
public function setBrandName(string $brand): \Srmklive\PayPal\Services\PayPal
{
$this->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;
}
}
1 change: 1 addition & 0 deletions src/Traits/PayPalRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ trait PayPalRequest
{
use PayPalHttpClient;
use PayPalAPI;
use PayPalExperienceContext;

/**
* PayPal API mode to be used.
Expand Down
69 changes: 69 additions & 0 deletions tests/Feature/AdapterExperienceContextTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php

namespace Feature;

namespace Srmklive\PayPal\Tests\Feature;

use Carbon\Carbon;
use PHPUnit\Framework\TestCase;
use Srmklive\PayPal\Services\PayPal as PayPalClient;
use Srmklive\PayPal\Tests\MockClientClasses;
use Srmklive\PayPal\Tests\MockRequestPayloads;
use Srmklive\PayPal\Tests\MockResponsePayloads;

class AdapterExperienceContextTest extends TestCase
{
use MockClientClasses;
use MockRequestPayloads;
use MockResponsePayloads;

/** @var string */
protected static $access_token = '';

/** @var \Srmklive\PayPal\Services\PayPal */
protected $client;

protected function setUp(): void
{
$this->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', '[email protected]', $start_date);

$this->assertNotEmpty($response);
$this->assertArrayHasKey('id', $response);
$this->assertArrayHasKey('plan_id', $response);
}
}
74 changes: 74 additions & 0 deletions tests/Feature/AdapterOrdersHelperTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php

namespace Srmklive\PayPal\Tests\Feature;

use Carbon\Carbon;
use PHPUnit\Framework\TestCase;
use Srmklive\PayPal\Services\PayPal as PayPalClient;
use Srmklive\PayPal\Tests\MockClientClasses;
use Srmklive\PayPal\Tests\MockRequestPayloads;
use Srmklive\PayPal\Tests\MockResponsePayloads;

class AdapterOrdersHelperTest extends TestCase
{
use MockClientClasses;
use MockRequestPayloads;
use MockResponsePayloads;

/** @var string */
protected static $access_token = '';

/** @var \Srmklive\PayPal\Services\PayPal */
protected $client;

protected function setUp(): void
{
$this->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);
}
}
Loading

0 comments on commit 2d99c7f

Please sign in to comment.