vendor/shopware/core/Checkout/Payment/Cart/PaymentTransactionChainProcessor.php line 151

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Payment\Cart;
  3. use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
  4. use Shopware\Core\Checkout\Order\OrderEntity;
  5. use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\AsynchronousPaymentHandlerInterface;
  6. use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\PaymentHandlerRegistry;
  7. use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\SynchronousPaymentHandlerInterface;
  8. use Shopware\Core\Checkout\Payment\Cart\Token\TokenFactoryInterfaceV2;
  9. use Shopware\Core\Checkout\Payment\Cart\Token\TokenStruct;
  10. use Shopware\Core\Checkout\Payment\Exception\InvalidOrderException;
  11. use Shopware\Core\Checkout\Payment\Exception\PaymentProcessException;
  12. use Shopware\Core\Checkout\Payment\Exception\UnknownPaymentMethodException;
  13. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  15. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  16. use Shopware\Core\Framework\Log\Package;
  17. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  18. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  19. use Shopware\Core\System\StateMachine\Loader\InitialStateIdLoader;
  20. use Shopware\Core\System\SystemConfig\SystemConfigService;
  21. use Symfony\Component\HttpFoundation\RedirectResponse;
  22. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  23. use Symfony\Component\Routing\RouterInterface;
  24. #[Package('checkout')]
  25. class PaymentTransactionChainProcessor
  26. {
  27.     private TokenFactoryInterfaceV2 $tokenFactory;
  28.     private EntityRepositoryInterface $orderRepository;
  29.     private RouterInterface $router;
  30.     private PaymentHandlerRegistry $paymentHandlerRegistry;
  31.     private SystemConfigService $systemConfigService;
  32.     private InitialStateIdLoader $initialStateIdLoader;
  33.     /**
  34.      * @internal
  35.      */
  36.     public function __construct(
  37.         TokenFactoryInterfaceV2 $tokenFactory,
  38.         EntityRepositoryInterface $orderRepository,
  39.         RouterInterface $router,
  40.         PaymentHandlerRegistry $paymentHandlerRegistry,
  41.         SystemConfigService $systemConfigService,
  42.         InitialStateIdLoader $initialStateIdLoader
  43.     ) {
  44.         $this->tokenFactory $tokenFactory;
  45.         $this->orderRepository $orderRepository;
  46.         $this->router $router;
  47.         $this->paymentHandlerRegistry $paymentHandlerRegistry;
  48.         $this->systemConfigService $systemConfigService;
  49.         $this->initialStateIdLoader $initialStateIdLoader;
  50.     }
  51.     /**
  52.      * @throws InvalidOrderException
  53.      * @throws PaymentProcessException
  54.      * @throws UnknownPaymentMethodException
  55.      */
  56.     public function process(
  57.         string $orderId,
  58.         RequestDataBag $dataBag,
  59.         SalesChannelContext $salesChannelContext,
  60.         ?string $finishUrl null,
  61.         ?string $errorUrl null
  62.     ): ?RedirectResponse {
  63.         $criteria = new Criteria([$orderId]);
  64.         $criteria->addAssociation('transactions.stateMachineState');
  65.         $criteria->addAssociation('transactions.paymentMethod');
  66.         $criteria->addAssociation('orderCustomer.customer');
  67.         $criteria->addAssociation('orderCustomer.salutation');
  68.         $criteria->addAssociation('transactions.paymentMethod.appPaymentMethod.app');
  69.         $criteria->addAssociation('language');
  70.         $criteria->addAssociation('currency');
  71.         $criteria->addAssociation('deliveries.shippingOrderAddress.country');
  72.         $criteria->addAssociation('billingAddress.country');
  73.         $criteria->addAssociation('lineItems');
  74.         $criteria->getAssociation('transactions')->addSorting(new FieldSorting('createdAt'));
  75.         /** @var OrderEntity|null $order */
  76.         $order $this->orderRepository->search($criteria$salesChannelContext->getContext())->first();
  77.         if (!$order) {
  78.             throw new InvalidOrderException($orderId);
  79.         }
  80.         $transactions $order->getTransactions();
  81.         if ($transactions === null) {
  82.             throw new InvalidOrderException($orderId);
  83.         }
  84.         $transactions $transactions->filterByStateId(
  85.             $this->initialStateIdLoader->get(OrderTransactionStates::STATE_MACHINE)
  86.         );
  87.         $transaction $transactions->last();
  88.         if ($transaction === null) {
  89.             return null;
  90.         }
  91.         $paymentMethod $transaction->getPaymentMethod();
  92.         if ($paymentMethod === null) {
  93.             throw new UnknownPaymentMethodException($transaction->getPaymentMethodId());
  94.         }
  95.         $paymentHandler $this->paymentHandlerRegistry->getPaymentMethodHandler($paymentMethod->getId());
  96.         if (!$paymentHandler) {
  97.             throw new UnknownPaymentMethodException($paymentMethod->getHandlerIdentifier());
  98.         }
  99.         if ($paymentHandler instanceof SynchronousPaymentHandlerInterface) {
  100.             $paymentTransaction = new SyncPaymentTransactionStruct($transaction$order);
  101.             $paymentHandler->pay($paymentTransaction$dataBag$salesChannelContext);
  102.             return null;
  103.         }
  104.         if ($paymentHandler instanceof AsynchronousPaymentHandlerInterface) {
  105.             $paymentFinalizeTransactionTime $this->systemConfigService->get('core.cart.paymentFinalizeTransactionTime'$salesChannelContext->getSalesChannelId());
  106.             if (\is_numeric($paymentFinalizeTransactionTime)) {
  107.                 $paymentFinalizeTransactionTime = (int) $paymentFinalizeTransactionTime;
  108.                 // setting is in minutes, token holds in seconds
  109.                 $paymentFinalizeTransactionTime *= 60;
  110.             } else {
  111.                 $paymentFinalizeTransactionTime null;
  112.             }
  113.             $tokenStruct = new TokenStruct(
  114.                 null,
  115.                 null,
  116.                 $transaction->getPaymentMethodId(),
  117.                 $transaction->getId(),
  118.                 $finishUrl,
  119.                 $paymentFinalizeTransactionTime,
  120.                 $errorUrl
  121.             );
  122.             $token $this->tokenFactory->generateToken($tokenStruct);
  123.             $returnUrl $this->assembleReturnUrl($token);
  124.             $paymentTransaction = new AsyncPaymentTransactionStruct($transaction$order$returnUrl);
  125.             return $paymentHandler->pay($paymentTransaction$dataBag$salesChannelContext);
  126.         }
  127.         return null;
  128.     }
  129.     private function assembleReturnUrl(string $token): string
  130.     {
  131.         $parameter = ['_sw_payment_token' => $token];
  132.         return $this->router->generate('payment.finalize.transaction'$parameterUrlGeneratorInterface::ABSOLUTE_URL);
  133.     }
  134. }