Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PAYSHIP-3046] Order capture retry #1275

Merged
merged 20 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions controllers/front/payment.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,10 @@ public function postProcess()
$this->redirectToOrderPage();
}

$payPalOrderQuery = new GetPayPalOrderForCheckoutCompletedQuery($orderId);

/** @var GetPayPalOrderForCheckoutCompletedQueryResult $payPalOrderQueryResult */
$payPalOrderQueryResult = $commandBus->handle(new GetPayPalOrderForCheckoutCompletedQuery($this->paypalOrderId->getValue()));
$payPalOrderQueryResult = $commandBus->handle($payPalOrderQuery);
$payPalOrderFromCache = $payPalOrderQueryResult->getPayPalOrder();

if ($payPalOrderFromCache['status'] === 'COMPLETED') {
Expand All @@ -120,8 +122,8 @@ public function postProcess()
$this->redirectTo3DSVerification($payPalOrderFromCache);
break;
case Card3DSecure::PROCEED:
$commandBus->handle(new CapturePayPalOrderCommand($this->paypalOrderId->getValue(), array_keys($payPalOrderFromCache['payment_source'])[0]));
$payPalOrderFromCache = $payPalOrderCache->get($this->paypalOrderId->getValue());
$commandBus->handle(new CapturePayPalOrderCommand($orderId, array_keys($payPalOrderFromCache['payment_source'])[0]));
$payPalOrderFromCache = $payPalOrderCache->get($orderId);
$this->createOrder($payPalOrderFromCache, $payPalOrder);
break;
case Card3DSecure::NO_DECISION:
Expand All @@ -131,8 +133,8 @@ public function postProcess()
}

if ($payPalOrderFromCache['status'] === 'APPROVED') {
$commandBus->handle(new CapturePayPalOrderCommand($this->paypalOrderId->getValue(), array_keys($payPalOrderFromCache['payment_source'])[0]));
$payPalOrderFromCache = $payPalOrderCache->get($this->paypalOrderId->getValue());
$commandBus->handle(new CapturePayPalOrderCommand($orderId, array_keys($payPalOrderFromCache['payment_source'])[0]));
$payPalOrderFromCache = $payPalOrderCache->get($orderId);
$this->createOrder($payPalOrderFromCache, $payPalOrder);
}
} catch (Exception $exception) {
Expand Down
2 changes: 1 addition & 1 deletion controllers/front/validate.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ private function generateResponse()
}

$response = [
'status' => $psCheckoutCart->paypal_status, // Need to change this to get the status from PayPal Order instead?
'status' => $psCheckoutCart->paypal_status,
'paypalOrderId' => $psCheckoutCart->paypal_order,
'transactionIdentifier' => $paypalOrder && isset($paypalOrder->getOrderPayPal()['purchase_units'][0]['payments']['captures'][0]) ? $paypalOrder->getOrderPayPal()['purchase_units'][0]['payments']['captures'][0]['id'] : null,
];
Expand Down
20 changes: 11 additions & 9 deletions src/Checkout/EventSubscriber/CheckoutEventSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@ public function updatePaymentMethodSelected(CheckoutCompletedEvent $event)
*/
public function proceedToPayment(CheckoutCompletedEvent $event)
{
$payPalOrderId = $event->getPayPalOrderId()->getValue();

/** @var GetPayPalOrderForCheckoutCompletedQueryResult $getPayPalOrderForCheckoutCompletedQueryResult */
$getPayPalOrderForCheckoutCompletedQueryResult = $this->commandBus->handle(new GetPayPalOrderForCheckoutCompletedQuery(
$event->getPayPalOrderId()->getValue()
$payPalOrderId
));

$payPalOrder = $getPayPalOrderForCheckoutCompletedQueryResult->getPayPalOrder();
Expand All @@ -134,7 +136,7 @@ public function proceedToPayment(CheckoutCompletedEvent $event)
} catch (PsCheckoutException $exception) {
if ($exception->getCode() === PsCheckoutException::PAYPAL_ORDER_ALREADY_CAPTURED) {
$capture = isset($payPalOrder['purchase_units'][0]['payments']['captures'][0]) ? $payPalOrder['purchase_units'][0]['payments']['captures'][0] : null;
$this->commandBus->handle(new CreateOrderCommand($event->getPayPalOrderId()->getValue(), $capture));
$this->commandBus->handle(new CreateOrderCommand($payPalOrderId, $capture));

return;
} else {
Expand All @@ -145,17 +147,17 @@ public function proceedToPayment(CheckoutCompletedEvent $event)
try {
$this->commandBus->handle(
new CapturePayPalOrderCommand(
$event->getPayPalOrderId()->getValue(),
$payPalOrderId,
$event->getFundingSource()
)
);
} catch (PayPalException $exception) {
if ($exception->getCode() === PayPalException::ORDER_NOT_APPROVED) {
$this->commandBus->handle(new CreateOrderCommand($event->getPayPalOrderId()->getValue()));
$this->commandBus->handle(new CreateOrderCommand($payPalOrderId));

return;
} elseif ($exception->getCode() === PayPalException::RESOURCE_NOT_FOUND) {
$psCheckoutCart = $this->psCheckoutCartRepository->findOneByPayPalOrderId($event->getPayPalOrderId()->getValue());
$psCheckoutCart = $this->psCheckoutCartRepository->findOneByPayPalOrderId($payPalOrderId);

if (Validate::isLoadedObject($psCheckoutCart)) {
$psCheckoutCart->paypal_status = PsCheckoutCart::STATUS_CANCELED;
Expand All @@ -167,14 +169,14 @@ public function proceedToPayment(CheckoutCompletedEvent $event)
if (isset($payPalOrder['purchase_units'][0]['payments']['captures'][0])) {
L3RAZ marked this conversation as resolved.
Show resolved Hide resolved
$capture = $payPalOrder['purchase_units'][0]['payments']['captures'][0];
} else {
$payPalOrderQuery = new GetPayPalOrderForCheckoutCompletedQuery($payPalOrderId);

/** @var GetPayPalOrderForCheckoutCompletedQueryResult $getPayPalOrderForCheckoutCompletedQueryResult */
$getPayPalOrderForCheckoutCompletedQueryResult = $this->commandBus->handle(new GetPayPalOrderForCheckoutCompletedQuery(
$event->getPayPalOrderId()->getValue()
));
$getPayPalOrderForCheckoutCompletedQueryResult = $this->commandBus->handle($payPalOrderQuery);
$payPalOrder = $getPayPalOrderForCheckoutCompletedQueryResult->getPayPalOrder();
$capture = isset($payPalOrder['purchase_units'][0]['payments']['captures'][0]) ? $payPalOrder['purchase_units'][0]['payments']['captures'][0] : null;
}
$this->commandBus->handle(new CreateOrderCommand($event->getPayPalOrderId()->getValue(), $capture));
$this->commandBus->handle(new CreateOrderCommand($payPalOrderId, $capture));

return;
} else {
Expand Down
10 changes: 10 additions & 0 deletions src/PayPal/Order/Cache/PayPalOrderCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
namespace PrestaShop\Module\PrestashopCheckout\PayPal\Order\Cache;

use PsCheckoutCart;
use Psr\SimpleCache\InvalidArgumentException;
use Symfony\Component\Cache\Simple\ChainCache;

class PayPalOrderCache extends ChainCache
Expand All @@ -36,7 +37,16 @@
PsCheckoutCart::STATUS_COMPLETED => 3600,
];

/**
* @param string $key
* @param $value
* @param int $ttl Time To Live in seconds. Defines how long the value will be stored in the cache.
*
* @return bool
*
* @throws InvalidArgumentException
*/
public function set($key, $value, $ttl = null)

Check failure on line 49 in src/PayPal/Order/Cache/PayPalOrderCache.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0.0)

PHPDoc tag @param has invalid value ($value): Unexpected token "$value", expected type at offset 44

Check failure on line 49 in src/PayPal/Order/Cache/PayPalOrderCache.php

View workflow job for this annotation

GitHub Actions / PHPStan (8.0.0)

PHPDoc tag @throws with type Psr\SimpleCache\InvalidArgumentException is not subtype of Throwable

Check failure on line 49 in src/PayPal/Order/Cache/PayPalOrderCache.php

View workflow job for this annotation

GitHub Actions / PHPStan (latest)

PHPDoc tag @param has invalid value ($value): Unexpected token "$value", expected type at offset 44

Check failure on line 49 in src/PayPal/Order/Cache/PayPalOrderCache.php

View workflow job for this annotation

GitHub Actions / PHPStan (latest)

PHPDoc tag @throws with type Psr\SimpleCache\InvalidArgumentException is not subtype of Throwable
L3RAZ marked this conversation as resolved.
Show resolved Hide resolved
L3RAZ marked this conversation as resolved.
Show resolved Hide resolved
{
if (!$ttl && isset($value['status']) && isset(self::CACHE_TTL[$value['status']])) {
$ttl = self::CACHE_TTL[$value['status']];
Expand Down
8 changes: 5 additions & 3 deletions src/PayPal/Order/PaypalOrderDataProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,12 @@ public function isTokenSaved()

public function getPaymentTokenIdentifier()
{
if ($this->payPalOrder && isset($this->payPalOrder->getPaymentSource()[$this->payPalOrder->getFundingSource()])) {
$paymentSource = $this->payPalOrder->getPaymentSource()[$this->payPalOrder->getFundingSource()];
$fundingSource = $this->payPalOrder->getFundingSource();

if ($this->payPalOrder && isset($this->payPalOrder->getPaymentSource()[$fundingSource])) {
$paymentSource = $this->payPalOrder->getPaymentSource()[$fundingSource];

if ($this->payPalOrder->getFundingSource() === 'card') {
if ($fundingSource === 'card') {
return (isset($paymentSource['brand']) ? $paymentSource['brand'] : '') . (isset($paymentSource['last_digits']) ? ' *' . $paymentSource['last_digits'] : '');
} else {
return isset($paymentSource['email_address']) ? $paymentSource['email_address'] : '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,25 +46,27 @@ public function __construct(CacheInterface $orderPayPalCache)

public function handle(GetPayPalOrderForCheckoutCompletedQuery $getPayPalOrderQuery)
{
$payPalOrderId = $getPayPalOrderQuery->getOrderPayPalId()->getValue();

/** @var array{id: string, status: string} $order */
$order = $this->orderPayPalCache->get($getPayPalOrderQuery->getOrderPayPalId()->getValue());
$order = $this->orderPayPalCache->get($payPalOrderId);

if (!empty($order) && in_array($order['status'], ['COMPLETED', 'CANCELED'])) {
return new GetPayPalOrderForCheckoutCompletedQueryResult($order);
}

try {
$orderPayPal = new PaypalOrder($getPayPalOrderQuery->getOrderPayPalId()->getValue());
$orderPayPal = new PaypalOrder($payPalOrderId);
$orderToStoreInCache = !empty($order) ? array_replace_recursive($order, $orderPayPal->getOrder()) : $orderPayPal->getOrder();
$this->orderPayPalCache->set($getPayPalOrderQuery->getOrderPayPalId()->getValue(), $orderToStoreInCache);
$this->orderPayPalCache->set($payPalOrderId, $orderToStoreInCache);
} catch (HttpTimeoutException $exception) {
throw $exception;
} catch (Exception $exception) {
throw new PayPalOrderException(sprintf('Unable to retrieve PayPal Order %s', $getPayPalOrderQuery->getOrderPayPalId()->getValue()), PayPalOrderException::CANNOT_RETRIEVE_ORDER, $exception);
throw new PayPalOrderException(sprintf('Unable to retrieve PayPal Order %s', $payPalOrderId), PayPalOrderException::CANNOT_RETRIEVE_ORDER, $exception);
}

if (!$orderPayPal->isLoaded()) {
throw new PayPalOrderException(sprintf('No data for PayPal Order %s', $getPayPalOrderQuery->getOrderPayPalId()->getValue()), PayPalOrderException::EMPTY_ORDER_DATA);
throw new PayPalOrderException(sprintf('No data for PayPal Order %s', $payPalOrderId), PayPalOrderException::EMPTY_ORDER_DATA);
}

return new GetPayPalOrderForCheckoutCompletedQueryResult($orderPayPal->getOrder());
Expand Down
Loading