From 993c3fd55aae5ef6e7ef78db9558b32d97fcef0d Mon Sep 17 00:00:00 2001 From: Vitalij Mik Date: Wed, 23 Oct 2024 14:30:51 +0200 Subject: [PATCH] NTR: clear PPE Session and control when to clear the backup cart --- .../PaypalExpress/PayPalExpress.php | 9 +++- .../PaypalExpressControllerBase.php | 51 +++++++++++++++++-- .../routes/storefront/paypal_express.xml | 6 +++ src/Resources/config/services/controller.xml | 1 + src/Resources/config/services/subscriber.xml | 5 ++ src/Service/Router/RoutingBuilder.php | 2 +- .../ExpressCartRestoreSubscriber.php | 4 -- ...esChannelContextTokenChangedSubscriber.php | 33 ++++++++++++ 8 files changed, 101 insertions(+), 10 deletions(-) create mode 100644 src/Subscriber/SalesChannelContextTokenChangedSubscriber.php diff --git a/src/Components/PaypalExpress/PayPalExpress.php b/src/Components/PaypalExpress/PayPalExpress.php index 05d2f5744..679ba057f 100644 --- a/src/Components/PaypalExpress/PayPalExpress.php +++ b/src/Components/PaypalExpress/PayPalExpress.php @@ -138,7 +138,7 @@ public function loadSession(string $sessionId, SalesChannelContext $context): Se $sleepTimer = self::SESSION_BASE_TIMEOUT * ($i+1); usleep($sleepTimer); $session = $mollie->sessions->get($sessionId); - if ($session->methodDetails !== null && $session->methodDetails->shippingAddress !== null) { + if ($session->methodDetails !== null && property_exists($session->methodDetails, 'shippingAddress') && $session->methodDetails->shippingAddress !== null) { break; } } @@ -202,4 +202,11 @@ public function prepareCustomer(AddressStruct $shippingAddress, SalesChannelCont # also (always) update our payment method to use Apple Pay for our cart return $this->cartService->updatePaymentMethod($context, $paypalExpressId); } + + public function cancelSession(string $sessionId, SalesChannelContext $context): Session + { + $mollie = $this->mollieApiFactory->getLiveClient($context->getSalesChannelId()); + + return $mollie->sessions->cancel($sessionId); + } } diff --git a/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php b/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php index 3a5209c1c..e6c469aeb 100644 --- a/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php +++ b/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php @@ -3,6 +3,7 @@ namespace Kiener\MolliePayments\Controller\Storefront\PaypalExpress; use Kiener\MolliePayments\Components\PaypalExpress\PayPalExpress; +use Kiener\MolliePayments\Service\Cart\CartBackupService; use Kiener\MolliePayments\Service\CartService; use Kiener\MolliePayments\Service\CustomFieldsInterface; use Kiener\MolliePayments\Service\SettingsService; @@ -42,6 +43,7 @@ class PaypalExpressControllerBase extends StorefrontController */ private $logger; private SettingsService $settingsService; + private CartBackupService $cartBackupService; /** @@ -50,13 +52,14 @@ class PaypalExpressControllerBase extends StorefrontController * @param RouterInterface $router * @param LoggerInterface $logger */ - public function __construct(PayPalExpress $paypalExpress, CartService $cartService, RouterInterface $router, SettingsService $settingsService, LoggerInterface $logger) + public function __construct(PayPalExpress $paypalExpress, CartService $cartService, RouterInterface $router, SettingsService $settingsService, CartBackupService $cartBackupService, LoggerInterface $logger) { $this->paypalExpress = $paypalExpress; $this->cartService = $cartService; $this->router = $router; $this->logger = $logger; $this->settingsService = $settingsService; + $this->cartBackupService = $cartBackupService; } /** @@ -112,6 +115,49 @@ public function startCheckout(Request $request, SalesChannelContext $context): R return new RedirectResponse($redirectUrl); } + public function cancelCheckout(SalesChannelContext $context): Response + { + $redirectUrl = $this->getCheckoutCartPage($this->router); + + $settings = $this->settingsService->getSettings($context->getSalesChannelId()); + + if ($settings->isPaypalExpressEnabled() === false) { + $this->logger->error('Paypal Express is disabled'); + return new RedirectResponse($redirectUrl); + } + + + + $cart = $this->cartService->getCalculatedMainCart($context); + + + $cartExtension = $cart->getExtension(CustomFieldsInterface::MOLLIE_KEY); + $sessionId = null; + + if ($cartExtension instanceof ArrayStruct) { + $sessionId = $cartExtension[CustomFieldsInterface::PAYPAL_EXPRESS_SESSION_ID_KEY] ?? null; + } + + $this->cartBackupService->restoreCart($context); + $this->cartBackupService->clearBackup($context); + + if ($sessionId === null) { + $this->logger->error('Paypal Express session id is null'); + return new RedirectResponse($redirectUrl); + } + try { + $session = $this->paypalExpress->cancelSession($sessionId, $context); + } catch (\Throwable $e) { + $this->logger->error('Failed to cancel Session at mollie', [ + 'message' => $e->getMessage(), + 'sessionId' => $sessionId, + ]); + } + + + return new RedirectResponse($redirectUrl); + } + /** * @param SalesChannelContext $context * @return Response @@ -141,9 +187,6 @@ public function finishCheckout(SalesChannelContext $context): Response } - - - if ($payPalExpressSessionId === null) { $this->logger->error('Failed to finish checkout, session not exists'); diff --git a/src/Resources/config/routes/storefront/paypal_express.xml b/src/Resources/config/routes/storefront/paypal_express.xml index 415e18085..03dfe80f0 100644 --- a/src/Resources/config/routes/storefront/paypal_express.xml +++ b/src/Resources/config/routes/storefront/paypal_express.xml @@ -18,4 +18,10 @@ + + Kiener\MolliePayments\Controller\Storefront\PaypalExpress\PaypalExpressControllerBase::cancelCheckout + storefront + true + + diff --git a/src/Resources/config/services/controller.xml b/src/Resources/config/services/controller.xml index f305c0d04..2fe80a9ee 100644 --- a/src/Resources/config/services/controller.xml +++ b/src/Resources/config/services/controller.xml @@ -221,6 +221,7 @@ + diff --git a/src/Resources/config/services/subscriber.xml b/src/Resources/config/services/subscriber.xml index 60475b33c..48604b7af 100644 --- a/src/Resources/config/services/subscriber.xml +++ b/src/Resources/config/services/subscriber.xml @@ -82,6 +82,11 @@ + + + + + diff --git a/src/Service/Router/RoutingBuilder.php b/src/Service/Router/RoutingBuilder.php index d30ab7e36..8d8700216 100644 --- a/src/Service/Router/RoutingBuilder.php +++ b/src/Service/Router/RoutingBuilder.php @@ -207,7 +207,7 @@ public function buildPaypalExpressRedirectUrl(): string */ public function buildPaypalExpressCancelUrl(): string { - $confirmPage = $this->router->generate('frontend.checkout.confirm.page', [], $this->router::ABSOLUTE_URL); + $confirmPage = $this->router->generate('frontend.mollie.paypal-express.cancel', [], $this->router::ABSOLUTE_URL); return $confirmPage; } diff --git a/src/Subscriber/ExpressCartRestoreSubscriber.php b/src/Subscriber/ExpressCartRestoreSubscriber.php index 3f63233da..f14b7de68 100644 --- a/src/Subscriber/ExpressCartRestoreSubscriber.php +++ b/src/Subscriber/ExpressCartRestoreSubscriber.php @@ -4,9 +4,7 @@ namespace Kiener\MolliePayments\Subscriber; use Kiener\MolliePayments\Service\Cart\CartBackupService; -use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent; use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent; -use Shopware\Storefront\Page\Checkout\Register\CheckoutRegisterPageLoadedEvent; use Shopware\Storefront\Page\PageLoadedEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -26,8 +24,6 @@ public static function getSubscribedEvents(): array { return [ CheckoutFinishPageLoadedEvent::class => 'onRestoreBackup', - CheckoutConfirmPageLoadedEvent::class => 'onRestoreBackup', - CheckoutRegisterPageLoadedEvent::class => 'onRestoreBackup' ]; } diff --git a/src/Subscriber/SalesChannelContextTokenChangedSubscriber.php b/src/Subscriber/SalesChannelContextTokenChangedSubscriber.php new file mode 100644 index 000000000..e1c8b4f36 --- /dev/null +++ b/src/Subscriber/SalesChannelContextTokenChangedSubscriber.php @@ -0,0 +1,33 @@ +cartBackupService = $cartBackupService; + } + + public static function getSubscribedEvents() + { + return [ + SalesChannelContextTokenChangeEvent::class => 'onTokenChange', + ]; + } + + public function onTokenChange(SalesChannelContextTokenChangeEvent $event): void + { + $this->cartBackupService->replaceToken($event->getPreviousToken(), $event->getCurrentToken(), $event->getSalesChannelContext()); + } +}