custom/plugins/MolliePayments/src/Subscriber/PaypalExpressSubscriber.php line 96

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Kiener\MolliePayments\Subscriber;
  4. use Kiener\MolliePayments\Components\PaypalExpress\PayPalExpress;
  5. use Kiener\MolliePayments\Handler\Method\PayPalExpressPayment;
  6. use Kiener\MolliePayments\Service\Cart\CartBackupService;
  7. use Kiener\MolliePayments\Service\CartServiceInterface;
  8. use Kiener\MolliePayments\Service\SettingsService;
  9. use Kiener\MolliePayments\Traits\StringTrait;
  10. use Mollie\Shopware\Entity\Cart\MollieShopwareCart;
  11. use Mollie\Shopware\Entity\Order\MollieShopwareOrder;
  12. use Shopware\Core\Checkout\Cart\SalesChannel\CartService;
  13. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
  14. use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
  15. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  16. use Shopware\Storefront\Event\StorefrontRenderEvent;
  17. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Component\HttpFoundation\RedirectResponse;
  20. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  21. class PaypalExpressSubscriber implements EventSubscriberInterface
  22. {
  23.     use StringTrait;
  24.     /**
  25.      * @var SettingsService
  26.      */
  27.     private $settingsService;
  28.     /**
  29.      * @var PayPalExpress
  30.      */
  31.     private $paypal;
  32.     /**
  33.      * @var CartService
  34.      */
  35.     private $cartService;
  36.     /**
  37.      * @var CartServiceInterface
  38.      */
  39.     private $mollieCartService;
  40.     /**
  41.      * @var CartBackupService
  42.      */
  43.     private $cartBackupService;
  44.     public function __construct(SettingsService $settingsServicePayPalExpress $paypalCartBackupService $cartBackupServiceCartService $cartServiceCartServiceInterface $mollieCartService)
  45.     {
  46.         $this->settingsService $settingsService;
  47.         $this->paypal $paypal;
  48.         $this->cartBackupService $cartBackupService;
  49.         $this->cartService $cartService;
  50.         $this->mollieCartService $mollieCartService;
  51.     }
  52.     public static function getSubscribedEvents()
  53.     {
  54.         return [
  55.             StorefrontRenderEvent::class => 'onStorefrontRender',
  56.             CheckoutFinishPageLoadedEvent::class => 'onCheckoutSuccess',
  57.             ResponseEvent::class => 'onResetPaypalExpress',
  58.         ];
  59.     }
  60.     /**
  61.      * @throws \Exception
  62.      */
  63.     public function onStorefrontRender(StorefrontRenderEvent $event): void
  64.     {
  65.         $settings $this->settingsService->getSettings($event->getSalesChannelContext()->getSalesChannel()->getId());
  66.         $paymentEnabled $this->isPPEActive($event->getSalesChannelContext());
  67.         $event->setParameter('mollie_paypalexpress_enabled'$paymentEnabled);
  68.         $style $settings->getPaypalExpressButtonStyle();
  69.         $shape $settings->getPaypalExpressButtonShape();
  70.         $restrictions $settings->getPaypalExpressRestrictions();
  71.         $event->setParameter('mollie_paypalexpress_style'$style);
  72.         $event->setParameter('mollie_paypalexpress_shape'$shape);
  73.         $event->setParameter('mollie_paypalexpress_restrictions'$restrictions);
  74.     }
  75.     /**
  76.      * If our apple pay direct payment is done, we want to restore the original cart
  77.      * just in case if the customer had some items in there.
  78.      */
  79.     public function onCheckoutSuccess(CheckoutFinishPageLoadedEvent $event): void
  80.     {
  81.         $mollieShopwareOrder = new MollieShopwareOrder($event->getPage()->getOrder());
  82.         $latestTransaction $mollieShopwareOrder->getLatestTransaction();
  83.         if (! $latestTransaction instanceof OrderTransactionEntity) {
  84.             return;
  85.         }
  86.         $paymentMethod $latestTransaction->getPaymentMethod();
  87.         if (! $paymentMethod instanceof PaymentMethodEntity) {
  88.             return;
  89.         }
  90.         $paymentIdentifier $paymentMethod->getHandlerIdentifier();
  91.         if ($paymentIdentifier !== PayPalExpressPayment::class) {
  92.             return;
  93.         }
  94.         $context $event->getSalesChannelContext();
  95.         if ($this->cartBackupService->isBackupExisting($context)) {
  96.             $this->cartBackupService->clearBackup($context);
  97.         }
  98.     }
  99.     /**
  100.      * If the user is on the PayPal page during the express checkout
  101.      * but somehow gets back to the shop outside of our success/cancel controller actions
  102.      * we need to check if we need to cancel PPE. otherwise the user would be stuck in that process.
  103.      */
  104.     public function onResetPaypalExpress(ResponseEvent $event): void
  105.     {
  106.         $salesChannelContext $event->getRequest()->attributes->get('sw-sales-channel-context');
  107.         if (! $salesChannelContext instanceof SalesChannelContext) {
  108.             return;
  109.         }
  110.         $pathInfo $event->getRequest()->getPathInfo();
  111.         // we must not clear things in our controlled PayPal express process
  112.         if ($this->stringContains($pathInfo'/mollie/paypal-express')) {
  113.             return;
  114.         }
  115.         $paymentEnabled $this->isPPEActive($salesChannelContext);
  116.         // now we need to figure out if the user came back from PayPal express before finalizing the authentication.
  117.         // If so, we need to reset PayPal express, otherwise the user would be stuck in using it
  118.         if (! $paymentEnabled) {
  119.             return;
  120.         }
  121.         $cart $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext);
  122.         $mollieShopwareCart = new MollieShopwareCart($cart);
  123.         // if paypal is either not started or confirmed, then do nothing
  124.         // incomplete means, we have started it, but authorization was not finished
  125.         if (! $mollieShopwareCart->isPayPalExpressIncomplete()) {
  126.             return;
  127.         }
  128.         if ($mollieShopwareCart->isSingleProductExpressCheckout()) {
  129.             // we want to restore our original cart
  130.             $cart $this->cartBackupService->restoreCart($salesChannelContext);
  131.             $this->cartBackupService->clearBackup($salesChannelContext);
  132.             $mollieShopwareCart = new MollieShopwareCart($cart);
  133.         }
  134.         // always make sure that paypal express data is really cleaned
  135.         $mollieShopwareCart->clearPayPalExpress();
  136.         $cart $mollieShopwareCart->getCart();
  137.         $this->mollieCartService->persistCart($cart$salesChannelContext);
  138.         // we have to do a refresh of our page, so
  139.         // that the restored cart + the updated payment method options are updated
  140.         $request $event->getRequest();
  141.         $response = new RedirectResponse($request->getUri());
  142.         $response->send();
  143.     }
  144.     private function isPPEActive(SalesChannelContext $context): bool
  145.     {
  146.         $settings $this->settingsService->getSettings($context->getSalesChannel()->getId());
  147.         if (! $settings->isPaypalExpressEnabled()) {
  148.             return false;
  149.         }
  150.         return $this->paypal->isPaypalExpressPaymentMethodEnabled($context);
  151.     }
  152. }