Skip to content

Commit

Permalink
Fixed circular dependency for Capture handler
Browse files Browse the repository at this point in the history
  • Loading branch information
L3RAZ committed Jan 10, 2025
1 parent 8ec4e70 commit 0ea929f
Show file tree
Hide file tree
Showing 7 changed files with 302 additions and 175 deletions.
1 change: 1 addition & 0 deletions config/command-handlers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ services:
- '@PrestaShop\Module\PrestashopCheckout\Context\PrestaShopContext'
- '@PrestaShop\Module\PrestashopCheckout\Repository\PayPalCustomerRepository'
- '@PrestaShop\Module\PrestashopCheckout\Repository\PayPalOrderRepository'
- '@PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventProcessor\PayPalOrderEventProcessor'

PrestaShop\Module\PrestashopCheckout\Checkout\CommandHandler\SaveCheckoutCommandHandler:
class: 'PrestaShop\Module\PrestashopCheckout\Checkout\CommandHandler\SaveCheckoutCommandHandler'
Expand Down
10 changes: 9 additions & 1 deletion config/common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,15 @@ services:
PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventSubscriber\PayPalOrderEventSubscriber:
class: 'PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventSubscriber\PayPalOrderEventSubscriber'
public: true
arguments:
- '@PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository'
- '@PrestaShop\Module\PrestashopCheckout\Checkout\CheckoutChecker'
- '@PrestaShop\Module\PrestashopCheckout\PayPal\Order\CommandHandler\CapturePayPalOrderCommandHandler'
- '@PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventProcessor\PayPalOrderEventProcessor'

PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventProcessor\PayPalOrderEventProcessor:
class: 'PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventProcessor\PayPalOrderEventProcessor'
public: true
arguments:
- "@ps_checkout.bus.query"
- '@PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository'
Expand All @@ -135,7 +144,6 @@ services:
- '@PrestaShop\Module\PrestashopCheckout\PayPal\Order\CommandHandler\SavePayPalOrderCommandHandler'
- '@PrestaShop\Module\PrestashopCheckout\Checkout\CommandHandler\SaveCheckoutCommandHandler'
- '@PrestaShop\Module\PrestashopCheckout\Checkout\CommandHandler\SavePayPalOrderStatusCommandHandler'
- '@PrestaShop\Module\PrestashopCheckout\PayPal\Order\CommandHandler\CapturePayPalOrderCommandHandler'
- '@PrestaShop\Module\PrestashopCheckout\Order\CommandHandler\UpdateOrderStatusCommandHandler'

PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\EventSubscriber\PayPalCaptureEventSubscriber:
Expand Down
1 change: 0 additions & 1 deletion src/Http/MaaslandHttpClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ public function fetchOrder(array $payload, array $options = [])
*/
public function captureOrder(array $payload, array $options = [])
{
// $options['NT-PayPalOrderCapture'] = 'INTERNAL_SERVER_ERROR';
return $this->sendRequest(new Request('POST', '/payments/order/capture', $options, json_encode($payload)));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
namespace PrestaShop\Module\PrestashopCheckout\PayPal\Order\CommandHandler;

use Configuration;
use Exception;
use PrestaShop\Module\PrestashopCheckout\Context\PrestaShopContext;
use PrestaShop\Module\PrestashopCheckout\Customer\ValueObject\CustomerId;
use PrestaShop\Module\PrestashopCheckout\Event\EventDispatcherInterface;
Expand All @@ -31,7 +32,7 @@
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Command\CapturePayPalOrderCommand;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Entity\PayPalOrder;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Event\PayPalOrderCompletedEvent;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventSubscriber\PayPalOrderEventSubscriber;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventProcessor\PayPalOrderEventProcessor;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\PayPalOrderStatus;
use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\Event\PayPalCaptureCompletedEvent;
use PrestaShop\Module\PrestashopCheckout\PayPal\Payment\Capture\Event\PayPalCaptureDeclinedEvent;
Expand Down Expand Up @@ -71,7 +72,7 @@ class CapturePayPalOrderCommandHandler
* @var PayPalOrderRepository
*/
private $payPalOrderRepository;
private PayPalOrderEventSubscriber $payPalOrderEventSubscriber;
private PayPalOrderEventProcessor $payPalOrderEventProcessor;

public function __construct(
MaaslandHttpClient $maaslandHttpClient,
Expand All @@ -80,18 +81,19 @@ public function __construct(
PrestaShopContext $prestaShopContext,
PayPalCustomerRepository $payPalCustomerRepository,
PayPalOrderRepository $payPalOrderRepository,
PayPalOrderEventSubscriber $payPalOrderEventSubscriber
PayPalOrderEventProcessor $payPalOrderEventProcessor
) {
$this->maaslandHttpClient = $maaslandHttpClient;
$this->eventDispatcher = $eventDispatcher;
$this->orderPayPalCache = $orderPayPalCache;
$this->prestaShopContext = $prestaShopContext;
$this->payPalCustomerRepository = $payPalCustomerRepository;
$this->payPalOrderRepository = $payPalOrderRepository;
$this->payPalOrderEventSubscriber = $payPalOrderEventSubscriber;
$this->payPalOrderEventProcessor = $payPalOrderEventProcessor;
}

public function __invoke(CapturePayPalOrderCommand $capturePayPalOrderCommand) {
public function __invoke(CapturePayPalOrderCommand $capturePayPalOrderCommand)
{
$this->handle($capturePayPalOrderCommand);
}

Expand Down Expand Up @@ -128,7 +130,7 @@ public function handle(CapturePayPalOrderCommand $capturePayPalOrderCommand)
$payPalCustomerId = new PayPalCustomerId($vault['customer']['id']);
$customerId = new CustomerId($this->prestaShopContext->getCustomerId());
$this->payPalCustomerRepository->save($customerId, $payPalCustomerId);
} catch (\Exception $exception) {
} catch (Exception $exception) {
}
}

Expand All @@ -151,8 +153,8 @@ public function handle(CapturePayPalOrderCommand $capturePayPalOrderCommand)

if ($orderPayPal['status'] === PayPalOrderStatus::COMPLETED) {
$event = new PayPalOrderCompletedEvent($orderPayPal['id'], $orderPayPal);
$this->payPalOrderEventSubscriber->saveCompletedPayPalOrder($event);
$this->payPalOrderEventSubscriber->updateCache($event);
$this->payPalOrderEventProcessor->saveCompletedPayPalOrder($event);
$this->payPalOrderEventProcessor->updateCache($event);
}

if ($capturePayPal['status'] === PayPalCaptureStatus::PENDING) {
Expand Down
240 changes: 240 additions & 0 deletions src/PayPal/Order/EventProcessor/PayPalOrderEventProcessor.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/

namespace PrestaShop\Module\PrestashopCheckout\PayPal\Order\EventProcessor;

use Exception;
use PrestaShop\Module\PrestashopCheckout\Checkout\CheckoutChecker;
use PrestaShop\Module\PrestashopCheckout\Checkout\Command\SaveCheckoutCommand;
use PrestaShop\Module\PrestashopCheckout\Checkout\Command\SavePayPalOrderStatusCommand;
use PrestaShop\Module\PrestashopCheckout\Checkout\CommandHandler\SaveCheckoutCommandHandler;
use PrestaShop\Module\PrestashopCheckout\Checkout\CommandHandler\SavePayPalOrderStatusCommandHandler;
use PrestaShop\Module\PrestashopCheckout\CommandBus\QueryBusInterface;
use PrestaShop\Module\PrestashopCheckout\Exception\PsCheckoutException;
use PrestaShop\Module\PrestashopCheckout\Order\Command\UpdateOrderStatusCommand;
use PrestaShop\Module\PrestashopCheckout\Order\CommandHandler\UpdateOrderStatusCommandHandler;
use PrestaShop\Module\PrestashopCheckout\Order\Exception\OrderNotFoundException;
use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForApprovalReversedQuery;
use PrestaShop\Module\PrestashopCheckout\Order\Query\GetOrderForApprovalReversedQueryResult;
use PrestaShop\Module\PrestashopCheckout\Order\State\OrderStateConfigurationKeys;
use PrestaShop\Module\PrestashopCheckout\Order\State\Service\OrderStateMapper;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\CheckTransitionPayPalOrderStatusService;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Command\SavePayPalOrderCommand;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\CommandHandler\SavePayPalOrderCommandHandler;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Event\PayPalOrderApprovalReversedEvent;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Event\PayPalOrderApprovedEvent;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Event\PayPalOrderCompletedEvent;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Event\PayPalOrderCreatedEvent;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\Event\PayPalOrderEvent;
use PrestaShop\Module\PrestashopCheckout\PayPal\Order\PayPalOrderStatus;
use PrestaShop\Module\PrestashopCheckout\PayPal\PayPalConfiguration;
use PrestaShop\Module\PrestashopCheckout\Repository\PayPalOrderRepository;
use PrestaShop\Module\PrestashopCheckout\Repository\PsCheckoutCartRepository;
use Symfony\Contracts\Cache\CacheInterface;

class PayPalOrderEventProcessor
{
private PsCheckoutCartRepository $psCheckoutCartRepository;
private CacheInterface $orderPayPalCache;
private CheckoutChecker $checkoutChecker;
private CheckTransitionPayPalOrderStatusService $checkTransitionPayPalOrderStatusService;
private OrderStateMapper $orderStateMapper;
private PayPalConfiguration $payPalConfiguration;
private PayPalOrderRepository $payPalOrderRepository;
private SavePayPalOrderCommandHandler $savePayPalOrderCommandHandler;
private SaveCheckoutCommandHandler $saveCheckoutCommandHandler;
private SavePayPalOrderStatusCommandHandler $savePayPalOrderStatusCommandHandler;
private QueryBusInterface $queryBus;
private UpdateOrderStatusCommandHandler $updateOrderStatusCommandHandler;

public function __construct(
QueryBusInterface $queryBus,
PsCheckoutCartRepository $psCheckoutCartRepository,
CacheInterface $orderPayPalCache,
CheckoutChecker $checkoutChecker,
CheckTransitionPayPalOrderStatusService $checkTransitionPayPalOrderStatusService,
OrderStateMapper $orderStateMapper,
PayPalConfiguration $payPalConfiguration,
PayPalOrderRepository $payPalOrderRepository,
SavePayPalOrderCommandHandler $savePayPalOrderCommandHandler,
SaveCheckoutCommandHandler $saveCheckoutCommandHandler,
SavePayPalOrderStatusCommandHandler $savePayPalOrderStatusCommandHandler,
UpdateOrderStatusCommandHandler $updateOrderStatusCommandHandler
) {
$this->queryBus = $queryBus;
$this->psCheckoutCartRepository = $psCheckoutCartRepository;
$this->orderPayPalCache = $orderPayPalCache;
$this->checkoutChecker = $checkoutChecker;
$this->checkTransitionPayPalOrderStatusService = $checkTransitionPayPalOrderStatusService;
$this->orderStateMapper = $orderStateMapper;
$this->payPalConfiguration = $payPalConfiguration;
$this->payPalOrderRepository = $payPalOrderRepository;
$this->savePayPalOrderCommandHandler = $savePayPalOrderCommandHandler;
$this->saveCheckoutCommandHandler = $saveCheckoutCommandHandler;
$this->savePayPalOrderStatusCommandHandler = $savePayPalOrderStatusCommandHandler;
$this->updateOrderStatusCommandHandler = $updateOrderStatusCommandHandler;
}

public function saveCreatedPayPalOrder(PayPalOrderCreatedEvent $event)
{
$order = $event->getOrderPayPal();

try {
$payPalOrder = $this->payPalOrderRepository->getPayPalOrderByCartId($event->getCartId()->getValue());
$this->payPalOrderRepository->deletePayPalOrder($payPalOrder->getId());
} catch (Exception $e) {
}

$this->savePayPalOrderCommandHandler->handle(new SavePayPalOrderCommand(
$order,
$event->getCartId(),
$event->getFundingSource(),
$this->payPalConfiguration->getPaymentMode(),
$event->getCustomerIntent(),
$event->isExpressCheckout(),
$event->isCardFields(),
$event->getPaymentTokenId()
));

$this->saveCheckoutCommandHandler->handle(new SaveCheckoutCommand(
$event->getCartId()->getValue(),
$event->getOrderPayPalId()->getValue(),
$order['status'],
isset($order['intent']) ? $order['intent'] : $this->payPalConfiguration->getIntent(),
$event->getFundingSource(),
$event->isExpressCheckout(),
$event->isCardFields(),
$this->payPalConfiguration->getPaymentMode()
));
}

public function saveApprovedPayPalOrder(PayPalOrderApprovedEvent $event)
{
$psCheckoutCart = $this->psCheckoutCartRepository->findOneByPayPalOrderId($event->getOrderPayPalId()->getValue());

if (false === $psCheckoutCart) {
throw new PsCheckoutException(sprintf('PayPal Order %s is not linked to a cart', $event->getOrderPayPalId()->getValue()), PsCheckoutException::PRESTASHOP_CART_NOT_FOUND);
}

if (!$this->checkTransitionPayPalOrderStatusService->checkAvailableStatus($psCheckoutCart->getPaypalStatus(), PayPalOrderStatus::APPROVED)) {
return;
}

try {
$this->savePayPalOrderCommandHandler->handle(new SavePayPalOrderCommand($event->getOrderPayPal()));
} catch (Exception $exception) {
}

$this->savePayPalOrderStatusCommandHandler->handle(new SavePayPalOrderStatusCommand(
$event->getOrderPayPalId()->getValue(),
PayPalOrderStatus::APPROVED
));
}

public function saveCompletedPayPalOrder(PayPalOrderCompletedEvent $event)
{
$psCheckoutCart = $this->psCheckoutCartRepository->findOneByPayPalOrderId($event->getOrderPayPalId()->getValue());

if (false === $psCheckoutCart) {
throw new PsCheckoutException(sprintf('PayPal Order %s is not linked to a cart', $event->getOrderPayPalId()->getValue()), PsCheckoutException::PRESTASHOP_CART_NOT_FOUND);
}

if (!$this->checkTransitionPayPalOrderStatusService->checkAvailableStatus($psCheckoutCart->getPaypalStatus(), PayPalOrderStatus::COMPLETED)) {
return;
}

try {
$this->savePayPalOrderCommandHandler->handle(new SavePayPalOrderCommand($event->getOrderPayPal()));
} catch (Exception $exception) {
}

$this->savePayPalOrderStatusCommandHandler->handle(new SavePayPalOrderStatusCommand(
$event->getOrderPayPalId()->getValue(),
PayPalOrderStatus::COMPLETED
));
}

public function saveApprovalReversedPayPalOrder(PayPalOrderApprovalReversedEvent $event)
{
$psCheckoutCart = $this->psCheckoutCartRepository->findOneByPayPalOrderId($event->getOrderPayPalId()->getValue());

if (false === $psCheckoutCart) {
throw new PsCheckoutException(sprintf('PayPal Order %s is not linked to a cart', $event->getOrderPayPalId()->getValue()), PsCheckoutException::PRESTASHOP_CART_NOT_FOUND);
}

if (!$this->checkTransitionPayPalOrderStatusService->checkAvailableStatus($psCheckoutCart->getPaypalStatus(), PayPalOrderStatus::REVERSED)) {
return;
}

$this->savePayPalOrderStatusCommandHandler->handle(new SavePayPalOrderStatusCommand(
$event->getOrderPayPalId()->getValue(),
PayPalOrderStatus::REVERSED
));
}

public function setApprovalReversedOrderStatus(PayPalOrderApprovalReversedEvent $event)
{
try {
/** @var GetOrderForApprovalReversedQueryResult $order */
$order = $this->queryBus->handle(
new GetOrderForApprovalReversedQuery(
$event->getOrderPayPalId()->getValue()
)
);
} catch (OrderNotFoundException $exception) {
return;
}

if ($order->hasBeenCanceled() || $order->hasBeenPaid()) {
return;
}

$this->updateOrderStatusCommandHandler->handle(
new UpdateOrderStatusCommand(
$order->getOrderId()->getValue(),
$this->orderStateMapper->getIdByKey(OrderStateConfigurationKeys::PS_CHECKOUT_STATE_CANCELED)
)
);
}

public function updatePayPalOrder(PayPalOrderEvent $event)
{
$this->savePayPalOrderCommandHandler->handle(new SavePayPalOrderCommand(
$event->getOrderPayPal()
));
}

public function updateCache(PayPalOrderEvent $event)
{
$currentOrderPayPal = $this->orderPayPalCache->getItem($event->getOrderPayPalId()->getValue())->get();
$newOrderPayPal = $event->getOrderPayPal();

if ($currentOrderPayPal && !$this->checkTransitionPayPalOrderStatusService->checkAvailableStatus($currentOrderPayPal['status'], $newOrderPayPal['status'])) {
return;
}

$this->orderPayPalCache->set($event->getOrderPayPalId()->getValue(), $newOrderPayPal);
}

public function clearCache(PayPalOrderEvent $event)
{
$this->orderPayPalCache->delete($event->getOrderPayPalId()->getValue());
}
}
28 changes: 28 additions & 0 deletions src/PayPal/Order/EventProcessor/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License version 3.0
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/AFL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to [email protected] so we can send you a copy immediately.
*
* @author PrestaShop SA and Contributors <[email protected]>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/AFL-3.0 Academic Free License version 3.0
*/
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');

header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');

header('Location: ../');
exit;
Loading

0 comments on commit 0ea929f

Please sign in to comment.