vendor/shopware/storefront/Controller/AccountOrderController.php line 108

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Storefront\Controller;
  3. use Shopware\Core\Checkout\Cart\Exception\OrderNotFoundException;
  4. use Shopware\Core\Checkout\Cart\Exception\OrderPaymentMethodNotChangeable;
  5. use Shopware\Core\Checkout\Customer\Exception\CustomerAuthThrottledException;
  6. use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
  7. use Shopware\Core\Checkout\Order\Exception\GuestNotAuthenticatedException;
  8. use Shopware\Core\Checkout\Order\Exception\WrongGuestCredentialsException;
  9. use Shopware\Core\Checkout\Order\OrderEntity;
  10. use Shopware\Core\Checkout\Order\SalesChannel\AbstractCancelOrderRoute;
  11. use Shopware\Core\Checkout\Order\SalesChannel\AbstractOrderRoute;
  12. use Shopware\Core\Checkout\Order\SalesChannel\AbstractSetPaymentOrderRoute;
  13. use Shopware\Core\Checkout\Order\SalesChannel\OrderService;
  14. use Shopware\Core\Checkout\Payment\Exception\PaymentProcessException;
  15. use Shopware\Core\Checkout\Payment\SalesChannel\AbstractHandlePaymentMethodRoute;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
  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\RequestDataBag;
  22. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
  23. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceInterface;
  24. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextServiceParameters;
  25. use Shopware\Core\System\SalesChannel\SalesChannel\AbstractContextSwitchRoute;
  26. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  27. use Shopware\Core\System\SystemConfig\SystemConfigService;
  28. use Shopware\Storefront\Event\RouteRequest\CancelOrderRouteRequestEvent;
  29. use Shopware\Storefront\Event\RouteRequest\HandlePaymentMethodRouteRequestEvent;
  30. use Shopware\Storefront\Event\RouteRequest\SetPaymentOrderRouteRequestEvent;
  31. use Shopware\Storefront\Framework\Routing\Annotation\NoStore;
  32. use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedHook;
  33. use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoader;
  34. use Shopware\Storefront\Page\Account\Order\AccountOrderDetailPageLoadedHook;
  35. use Shopware\Storefront\Page\Account\Order\AccountOrderDetailPageLoader;
  36. use Shopware\Storefront\Page\Account\Order\AccountOrderPageLoadedHook;
  37. use Shopware\Storefront\Page\Account\Order\AccountOrderPageLoader;
  38. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  39. use Symfony\Component\HttpFoundation\Request;
  40. use Symfony\Component\HttpFoundation\Response;
  41. use Symfony\Component\Routing\Annotation\Route;
  42. /**
  43.  * @Route(defaults={"_routeScope"={"storefront"}})
  44.  */
  45. class AccountOrderController extends StorefrontController
  46. {
  47.     private AccountOrderPageLoader $orderPageLoader;
  48.     private AbstractContextSwitchRoute $contextSwitchRoute;
  49.     private AccountEditOrderPageLoader $accountEditOrderPageLoader;
  50.     private AbstractCancelOrderRoute $cancelOrderRoute;
  51.     private AbstractSetPaymentOrderRoute $setPaymentOrderRoute;
  52.     private AbstractHandlePaymentMethodRoute $handlePaymentMethodRoute;
  53.     private EventDispatcherInterface $eventDispatcher;
  54.     private AccountOrderDetailPageLoader $orderDetailPageLoader;
  55.     private AbstractOrderRoute $orderRoute;
  56.     private SalesChannelContextServiceInterface $contextService;
  57.     private SystemConfigService $systemConfigService;
  58.     private OrderService $orderService;
  59.     public function __construct(
  60.         AccountOrderPageLoader $orderPageLoader,
  61.         AccountEditOrderPageLoader $accountEditOrderPageLoader,
  62.         AbstractContextSwitchRoute $contextSwitchRoute,
  63.         AbstractCancelOrderRoute $cancelOrderRoute,
  64.         AbstractSetPaymentOrderRoute $setPaymentOrderRoute,
  65.         AbstractHandlePaymentMethodRoute $handlePaymentMethodRoute,
  66.         EventDispatcherInterface $eventDispatcher,
  67.         AccountOrderDetailPageLoader $orderDetailPageLoader,
  68.         AbstractOrderRoute $orderRoute,
  69.         SalesChannelContextServiceInterface $contextService,
  70.         SystemConfigService $systemConfigService,
  71.         OrderService $orderService
  72.     ) {
  73.         $this->orderPageLoader $orderPageLoader;
  74.         $this->contextSwitchRoute $contextSwitchRoute;
  75.         $this->accountEditOrderPageLoader $accountEditOrderPageLoader;
  76.         $this->cancelOrderRoute $cancelOrderRoute;
  77.         $this->setPaymentOrderRoute $setPaymentOrderRoute;
  78.         $this->handlePaymentMethodRoute $handlePaymentMethodRoute;
  79.         $this->eventDispatcher $eventDispatcher;
  80.         $this->orderDetailPageLoader $orderDetailPageLoader;
  81.         $this->orderRoute $orderRoute;
  82.         $this->contextService $contextService;
  83.         $this->systemConfigService $systemConfigService;
  84.         $this->orderService $orderService;
  85.     }
  86.     /**
  87.      * @Since("6.0.0.0")
  88.      * @Route("/account/order", name="frontend.account.order.page", options={"seo"="false"}, methods={"GET", "POST"}, defaults={"XmlHttpRequest"=true, "_loginRequired"=true, "_loginRequiredAllowGuest"=true})
  89.      * @Route("/account/order", name="frontend.account.order.page", options={"seo"="false"}, methods={"GET", "POST"}, defaults={"XmlHttpRequest"=true})
  90.      * @NoStore
  91.      */
  92.     public function orderOverview(Request $requestSalesChannelContext $context): Response
  93.     {
  94.         $page $this->orderPageLoader->load($request$context);
  95.         $this->hook(new AccountOrderPageLoadedHook($page$context));
  96.         return $this->renderStorefront('@Storefront/storefront/page/account/order-history/index.html.twig', ['page' => $page]);
  97.     }
  98.     /**
  99.      * @Since("6.2.0.0")
  100.      * @Route("/account/order/cancel", name="frontend.account.order.cancel", methods={"POST"})
  101.      */
  102.     public function cancelOrder(Request $requestSalesChannelContext $context): Response
  103.     {
  104.         $cancelOrderRequest = new Request();
  105.         $cancelOrderRequest->request->set('orderId'$request->get('orderId'));
  106.         $cancelOrderRequest->request->set('transition''cancel');
  107.         $event = new CancelOrderRouteRequestEvent($request$cancelOrderRequest$context);
  108.         $this->eventDispatcher->dispatch($event);
  109.         $this->cancelOrderRoute->cancel($event->getStoreApiRequest(), $context);
  110.         if ($context->getCustomer() && $context->getCustomer()->getGuest() === true) {
  111.             return $this->redirectToRoute(
  112.                 'frontend.account.order.single.page',
  113.                 [
  114.                     'deepLinkCode' => $request->get('deepLinkCode'),
  115.                 ]
  116.             );
  117.         }
  118.         return $this->redirectToRoute('frontend.account.order.page');
  119.     }
  120.     /**
  121.      * @Since("6.2.0.0")
  122.      * @Route("/account/order/{deepLinkCode}", name="frontend.account.order.single.page", options={"seo"="false"}, methods={"GET", "POST"})
  123.      * @NoStore
  124.      */
  125.     public function orderSingleOverview(Request $requestSalesChannelContext $context): Response
  126.     {
  127.         try {
  128.             $page $this->orderPageLoader->load($request$context);
  129.             $this->hook(new AccountOrderPageLoadedHook($page$context));
  130.         } catch (GuestNotAuthenticatedException WrongGuestCredentialsException CustomerAuthThrottledException $exception) {
  131.             return $this->redirectToRoute(
  132.                 'frontend.account.guest.login.page',
  133.                 [
  134.                     'redirectTo' => 'frontend.account.order.single.page',
  135.                     'redirectParameters' => ['deepLinkCode' => $request->get('deepLinkCode')],
  136.                     'loginError' => ($exception instanceof WrongGuestCredentialsException),
  137.                     'waitTime' => ($exception instanceof CustomerAuthThrottledException) ? $exception->getWaitTime() : '',
  138.                 ]
  139.             );
  140.         }
  141.         return $this->renderStorefront('@Storefront/storefront/page/account/order-history/index.html.twig', ['page' => $page]);
  142.     }
  143.     /**
  144.      * @Since("6.0.0.0")
  145.      * @Route("/widgets/account/order/detail/{id}", name="widgets.account.order.detail", options={"seo"="false"}, methods={"GET"}, defaults={"XmlHttpRequest"=true, "_loginRequired"=true})
  146.      */
  147.     public function ajaxOrderDetail(Request $requestSalesChannelContext $context): Response
  148.     {
  149.         $page $this->orderDetailPageLoader->load($request$context);
  150.         $this->hook(new AccountOrderDetailPageLoadedHook($page$context));
  151.         $response $this->renderStorefront('@Storefront/storefront/page/account/order-history/order-detail-list.html.twig', [
  152.             'orderDetails' => $page->getLineItems(),
  153.             'orderId' => $page->getOrder()->getId(),
  154.             'page' => $page,
  155.         ]);
  156.         $response->headers->set('x-robots-tag''noindex');
  157.         return $response;
  158.     }
  159.     /**
  160.      * @Since("6.2.0.0")
  161.      * @Route("/account/order/edit/{orderId}", name="frontend.account.edit-order.page", methods={"GET"}, defaults={"_loginRequired"=true, "_loginRequiredAllowGuest"=true})
  162.      * @Route("/account/order/edit/{orderId}", name="frontend.account.edit-order.page", methods={"GET"})
  163.      * @NoStore
  164.      */
  165.     public function editOrder(string $orderIdRequest $requestSalesChannelContext $context): Response
  166.     {
  167.         $criteria = new Criteria([$orderId]);
  168.         $deliveriesCriteria $criteria->getAssociation('deliveries');
  169.         $deliveriesCriteria->addSorting(new FieldSorting('createdAt'FieldSorting::ASCENDING));
  170.         $order $this->orderRoute->load($request$context$criteria)->getOrders()->first();
  171.         if ($order === null) {
  172.             throw new OrderNotFoundException($orderId);
  173.         }
  174.         if ($context->getCurrency()->getId() !== $order->getCurrencyId()) {
  175.             $this->contextSwitchRoute->switchContext(
  176.                 new RequestDataBag([SalesChannelContextService::CURRENCY_ID => $order->getCurrencyId()]),
  177.                 $context
  178.             );
  179.             return $this->redirectToRoute('frontend.account.edit-order.page', ['orderId' => $orderId]);
  180.         }
  181.         /** @var OrderDeliveryEntity|null $mostCurrentDelivery */
  182.         $mostCurrentDelivery $order->getDeliveries()->last();
  183.         if ($mostCurrentDelivery !== null && $context->getShippingMethod()->getId() !== $mostCurrentDelivery->getShippingMethodId()) {
  184.             $this->contextSwitchRoute->switchContext(
  185.                 new RequestDataBag([SalesChannelContextService::SHIPPING_METHOD_ID => $mostCurrentDelivery->getShippingMethodId()]),
  186.                 $context
  187.             );
  188.             return $this->redirectToRoute('frontend.account.edit-order.page', ['orderId' => $orderId]);
  189.         }
  190.         $page $this->accountEditOrderPageLoader->load($request$context);
  191.         $this->hook(new AccountEditOrderPageLoadedHook($page$context));
  192.         if ($page->isPaymentChangeable() === false) {
  193.             $refundsEnabled $this->systemConfigService->get('core.cart.enableOrderRefunds');
  194.             if ($refundsEnabled) {
  195.                 $this->addFlash(self::DANGER$this->trans('account.editOrderPaymentNotChangeableWithRefunds'));
  196.             } else {
  197.                 $this->addFlash(self::DANGER$this->trans('account.editOrderPaymentNotChangeable'));
  198.             }
  199.         }
  200.         $page->setErrorCode($request->get('error-code'));
  201.         return $this->renderStorefront('@Storefront/storefront/page/account/order/index.html.twig', ['page' => $page]);
  202.     }
  203.     /**
  204.      * @Since("6.2.0.0")
  205.      * @Route("/account/order/payment/{orderId}", name="frontend.account.edit-order.change-payment-method", methods={"POST"})
  206.      */
  207.     public function orderChangePayment(string $orderIdRequest $requestSalesChannelContext $context): Response
  208.     {
  209.         $this->contextSwitchRoute->switchContext(
  210.             new RequestDataBag(
  211.                 [
  212.                     SalesChannelContextService::PAYMENT_METHOD_ID => $request->get('paymentMethodId'),
  213.                 ]
  214.             ),
  215.             $context
  216.         );
  217.         return $this->redirectToRoute('frontend.account.edit-order.page', ['orderId' => $orderId]);
  218.     }
  219.     /**
  220.      * @Since("6.2.0.0")
  221.      * @Route("/account/order/update/{orderId}", name="frontend.account.edit-order.update-order", methods={"POST"})
  222.      */
  223.     public function updateOrder(string $orderIdRequest $requestSalesChannelContext $context): Response
  224.     {
  225.         $finishUrl $this->generateUrl('frontend.checkout.finish.page', [
  226.             'orderId' => $orderId,
  227.             'changedPayment' => true,
  228.         ]);
  229.         /** @var OrderEntity|null $order */
  230.         $order $this->orderRoute->load($request$context, new Criteria([$orderId]))->getOrders()->first();
  231.         if ($order === null) {
  232.             throw new OrderNotFoundException($orderId);
  233.         }
  234.         if (!$this->orderService->isPaymentChangeableByTransactionState($order)) {
  235.             throw new OrderPaymentMethodNotChangeable();
  236.         }
  237.         if ($context->getCurrency()->getId() !== $order->getCurrencyId()) {
  238.             $this->contextSwitchRoute->switchContext(
  239.                 new RequestDataBag([SalesChannelContextService::CURRENCY_ID => $order->getCurrencyId()]),
  240.                 $context
  241.             );
  242.             $context $this->contextService->get(
  243.                 new SalesChannelContextServiceParameters(
  244.                     $context->getSalesChannelId(),
  245.                     $context->getToken(),
  246.                     $context->getContext()->getLanguageId()
  247.                 )
  248.             );
  249.         }
  250.         $errorUrl $this->generateUrl('frontend.account.edit-order.page', ['orderId' => $orderId]);
  251.         $setPaymentRequest = new Request();
  252.         $setPaymentRequest->request->set('orderId'$orderId);
  253.         $setPaymentRequest->request->set('paymentMethodId'$request->get('paymentMethodId'));
  254.         $setPaymentOrderRouteRequestEvent = new SetPaymentOrderRouteRequestEvent($request$setPaymentRequest$context);
  255.         $this->eventDispatcher->dispatch($setPaymentOrderRouteRequestEvent);
  256.         $this->setPaymentOrderRoute->setPayment($setPaymentOrderRouteRequestEvent->getStoreApiRequest(), $context);
  257.         $handlePaymentRequest = new Request();
  258.         $handlePaymentRequest->request->set('orderId'$orderId);
  259.         $handlePaymentRequest->request->set('finishUrl'$finishUrl);
  260.         $handlePaymentRequest->request->set('errorUrl'$errorUrl);
  261.         $handlePaymentMethodRouteRequestEvent = new HandlePaymentMethodRouteRequestEvent($request$handlePaymentRequest$context);
  262.         $this->eventDispatcher->dispatch($handlePaymentMethodRouteRequestEvent);
  263.         try {
  264.             $routeResponse $this->handlePaymentMethodRoute->load(
  265.                 $handlePaymentMethodRouteRequestEvent->getStoreApiRequest(),
  266.                 $context
  267.             );
  268.             $response $routeResponse->getRedirectResponse();
  269.         } catch (PaymentProcessException $paymentProcessException) {
  270.             return $this->forwardToRoute(
  271.                 'frontend.checkout.finish.page',
  272.                 ['orderId' => $orderId'changedPayment' => true'paymentFailed' => true]
  273.             );
  274.         }
  275.         return $response ?? $this->redirectToRoute(
  276.             'frontend.checkout.finish.page',
  277.             ['orderId' => $orderId'changedPayment' => true]
  278.         );
  279.     }
  280. }