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

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