Shopware 6: Easy errors/validation on checkout and flash message
Fabian Blechschmidt
One of our customers needs sometimes a file uploaded on the checkout. In our other checkout posts, we explained, how to change the checkout and why it is so easy in Shopware <3
I don’t want to dive into details of the upload, if you want to read about it, leave a comment or drop us an email! I want to write about errors and validation, after diving with my colleague Bruno into it.
Create order
To create an order on Shopware, we have the CheckoutController::order
, the important part of the method looks like this:
// \Shopware\Storefront\Controller\CheckoutController::order
#[Route(path: '/checkout/order', name: 'frontend.checkout.finish.order', options: ['seo' => false], methods: ['POST'])]
public function order(RequestDataBag $data, SalesChannelContext $context, Request $request): Response
{
if (!$context->getCustomer()) {
return $this->redirectToRoute('frontend.checkout.register.page');
}
try {
$this->addAffiliateTracking($data, $request->getSession());
$orderId = Profiler::trace('checkout-order', fn () => $this->orderService->createOrder($data, $context));
} catch (ConstraintViolationException $formViolations) {
return $this->forwardToRoute('frontend.checkout.confirm.page', ['formViolations' => $formViolations]);
} catch (InvalidCartException|Error|EmptyCartException) {
$this->addCartErrors(
$this->cartService->getCart($context->getToken(), $context)
);
return $this->forwardToRoute('frontend.checkout.confirm.page');
} catch (UnknownPaymentMethodException|CartException $e) {
if ($e->getErrorCode() === CartException::CART_PAYMENT_INVALID_ORDER_STORED_CODE && $e->getParameter('orderId')) {
return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $e->getParameter('orderId'), 'changedPayment' => false, 'paymentFailed' => true]);
}
$message = $this->trans('error.' . $e->getErrorCode());
$this->addFlash('danger', $message);
return $this->forwardToRoute('frontend.checkout.confirm.page');
}
try {
$finishUrl = $this->generateUrl('frontend.checkout.finish.page', ['orderId' => $orderId]);
$errorUrl = $this->generateUrl('frontend.account.edit-order.page', ['orderId' => $orderId]);
$response = Profiler::trace('handle-payment', fn (): ?RedirectResponse => $this->paymentService->handlePaymentByOrder($orderId, $data, $context, $finishUrl, $errorUrl));
return $response ?? new RedirectResponse($finishUrl);
} catch (PaymentProcessException|InvalidOrderException|PaymentException|UnknownPaymentMethodException) {
return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $orderId, 'changedPayment' => false, 'paymentFailed' => true]);
}
}
As you can see you have three catch blocks. The third is the important and interesting for us. But to use it, we need to make sure to NOT throw a
- ConstraintViolationException
- InvalidCartException
- EmptyCartException
- \Error
But throw a CartException
!
} catch (UnknownPaymentMethodException|CartException $e) {
if ($e->getErrorCode() === CartException::CART_PAYMENT_INVALID_ORDER_STORED_CODE && $e->getParameter('orderId')) {
return $this->forwardToRoute('frontend.checkout.finish.page', ['orderId' => $e->getParameter('orderId'), 'changedPayment' => false, 'paymentFailed' => true]);
}
$message = $this->trans('error.' . $e->getErrorCode());
$this->addFlash('danger', $message);
return $this->forwardToRoute('frontend.checkout.confirm.page');
}
The easiest way to achieve the above conditions is to implement your own CartException
.
<?php
namespace Agency\Project\Exception;
class SomethingWentWrongOnCartValidationException extends \Shopware\Core\Checkout\Cart\CartException
{
public function __construct()
{
parent::__construct(0, 'SOMETHING_WENT_WRONG', 'Something went wrong.');
}
}
This way you can easily throw new SomethingWentWrongOnCartValidationException()
anywhere during order creation in our case during CartConvertedEvent
.
Lost in Translation
As you can see above, then your exception is catch, the error code (in our example SOMETHING_WENT_WRONG
) is run through translation as error.SOMETHING_WENT_WRONG
, then added as flash message and the visitor is redirected back to the last step of the checkout.
Other articles from this category