vendor/shopware/core/Checkout/Cart/SalesChannel/CartOrderRoute.php line 74

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Cart\SalesChannel;
  3. use Shopware\Core\Checkout\Cart\Cart;
  4. use Shopware\Core\Checkout\Cart\CartCalculator;
  5. use Shopware\Core\Checkout\Cart\CartPersisterInterface;
  6. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedCriteriaEvent;
  7. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  8. use Shopware\Core\Checkout\Cart\Order\OrderPersisterInterface;
  9. use Shopware\Core\Checkout\Order\OrderEntity;
  10. use Shopware\Core\Checkout\Order\SalesChannel\OrderService;
  11. use Shopware\Core\Checkout\Payment\Exception\InvalidOrderException;
  12. use Shopware\Core\Checkout\Payment\PreparedPaymentService;
  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\Plugin\Exception\DecorationPatternException;
  17. use Shopware\Core\Framework\Routing\Annotation\LoginRequired;
  18. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  19. use Shopware\Core\Framework\Routing\Annotation\Since;
  20. use Shopware\Core\Framework\Validation\DataBag\DataBag;
  21. use Shopware\Core\Framework\Validation\DataBag\RequestDataBag;
  22. use Shopware\Core\Profiling\Profiler;
  23. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  24. use Symfony\Component\Routing\Annotation\Route;
  25. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  26. /**
  27.  * @Route(defaults={"_routeScope"={"store-api"}})
  28.  */
  29. class CartOrderRoute extends AbstractCartOrderRoute
  30. {
  31.     private CartCalculator $cartCalculator;
  32.     private EntityRepositoryInterface $orderRepository;
  33.     private OrderPersisterInterface $orderPersister;
  34.     private CartPersisterInterface $cartPersister;
  35.     private EventDispatcherInterface $eventDispatcher;
  36.     private PreparedPaymentService $preparedPaymentService;
  37.     /**
  38.      * @internal
  39.      */
  40.     public function __construct(
  41.         CartCalculator $cartCalculator,
  42.         EntityRepositoryInterface $orderRepository,
  43.         OrderPersisterInterface $orderPersister,
  44.         CartPersisterInterface $cartPersister,
  45.         EventDispatcherInterface $eventDispatcher,
  46.         PreparedPaymentService $preparedPaymentService
  47.     ) {
  48.         $this->cartCalculator $cartCalculator;
  49.         $this->orderRepository $orderRepository;
  50.         $this->orderPersister $orderPersister;
  51.         $this->cartPersister $cartPersister;
  52.         $this->eventDispatcher $eventDispatcher;
  53.         $this->preparedPaymentService $preparedPaymentService;
  54.     }
  55.     public function getDecorated(): AbstractCartOrderRoute
  56.     {
  57.         throw new DecorationPatternException(self::class);
  58.     }
  59.     /**
  60.      * @Since("6.3.0.0")
  61.      * @Route("/store-api/checkout/order", name="store-api.checkout.cart.order", methods={"POST"}, defaults={"_loginRequired"=true, "_loginRequiredAllowGuest"=true})
  62.      */
  63.     public function order(Cart $cartSalesChannelContext $contextRequestDataBag $data): CartOrderRouteResponse
  64.     {
  65.         // we use this state in stock updater class, to prevent duplicate available stock updates
  66.         $context->addState('checkout-order-route');
  67.         $calculatedCart $this->cartCalculator->calculate($cart$context);
  68.         $this->addCustomerComment($calculatedCart$data);
  69.         $this->addAffiliateTracking($calculatedCart$data);
  70.         $preOrderPayment Profiler::trace('checkout-order::pre-payment', function () use ($calculatedCart$data$context) {
  71.             return $this->preparedPaymentService->handlePreOrderPayment($calculatedCart$data$context);
  72.         });
  73.         $orderId Profiler::trace('checkout-order::order-persist', function () use ($calculatedCart$context) {
  74.             return $this->orderPersister->persist($calculatedCart$context);
  75.         });
  76.         $criteria = new Criteria([$orderId]);
  77.         $criteria->setTitle('order-route::order-loading');
  78.         $criteria
  79.             ->addAssociation('orderCustomer.customer')
  80.             ->addAssociation('orderCustomer.salutation')
  81.             ->addAssociation('deliveries.shippingMethod')
  82.             ->addAssociation('deliveries.shippingOrderAddress.country')
  83.             ->addAssociation('deliveries.shippingOrderAddress.countryState')
  84.             ->addAssociation('transactions.paymentMethod')
  85.             ->addAssociation('lineItems.cover')
  86.             ->addAssociation('currency')
  87.             ->addAssociation('addresses.country')
  88.             ->addAssociation('addresses.countryState')
  89.             ->getAssociation('transactions')->addSorting(new FieldSorting('createdAt'));
  90.         $this->eventDispatcher->dispatch(new CheckoutOrderPlacedCriteriaEvent($criteria$context));
  91.         /** @var OrderEntity|null $orderEntity */
  92.         $orderEntity Profiler::trace('checkout-order::order-loading', function () use ($criteria$context) {
  93.             return $this->orderRepository->search($criteria$context->getContext())->first();
  94.         });
  95.         if (!$orderEntity) {
  96.             throw new InvalidOrderException($orderId);
  97.         }
  98.         $event = new CheckoutOrderPlacedEvent(
  99.             $context->getContext(),
  100.             $orderEntity,
  101.             $context->getSalesChannel()->getId()
  102.         );
  103.         Profiler::trace('checkout-order::event-listeners', function () use ($event): void {
  104.             $this->eventDispatcher->dispatch($event);
  105.         });
  106.         $this->cartPersister->delete($context->getToken(), $context);
  107.         Profiler::trace('checkout-order::post-payment', function () use ($orderEntity$data$context$preOrderPayment): void {
  108.             $this->preparedPaymentService->handlePostOrderPayment($orderEntity$data$context$preOrderPayment);
  109.         });
  110.         return new CartOrderRouteResponse($orderEntity);
  111.     }
  112.     private function addCustomerComment(Cart $cartDataBag $data): void
  113.     {
  114.         $customerComment ltrim(rtrim((string) $data->get(OrderService::CUSTOMER_COMMENT_KEY'')));
  115.         if ($customerComment === '') {
  116.             return;
  117.         }
  118.         $cart->setCustomerComment($customerComment);
  119.     }
  120.     private function addAffiliateTracking(Cart $cartDataBag $data): void
  121.     {
  122.         $affiliateCode $data->get(OrderService::AFFILIATE_CODE_KEY);
  123.         $campaignCode $data->get(OrderService::CAMPAIGN_CODE_KEY);
  124.         if ($affiliateCode) {
  125.             $cart->setAffiliateCode($affiliateCode);
  126.         }
  127.         if ($campaignCode) {
  128.             $cart->setCampaignCode($campaignCode);
  129.         }
  130.     }
  131. }