Skip to content

Commit 57bb766

Browse files
authored
Add early returns when processing already created order when returning from PayPal to Sylius (#372)
| Q | A | --------------- | ----- | Branch? | 1.7 | Bug fix? | yes | New feature? | no | Related tickets | This PR introduces early return conditions in the checkout flow to handle a specific edge case involving PayPal payments: When a customer starts a PayPal payment and then returns to Sylius in a different browser tab, they may complete the checkout again, either by going through the entire process or by paying again via PayPal. If they then switch back to the original tab (where the PayPal flow was first initiated) and try to complete the order again, it may result in errors because the order is already completed. To prevent this, we now short-circuit the flow with early returns if the order has already been placed and there is no payment in the `cart` state, ensuring the customer cannot proceed further in such cases.
2 parents 6c37b20 + 8efb003 commit 57bb766

File tree

1 file changed

+13
-3
lines changed

1 file changed

+13
-3
lines changed

src/Controller/ProcessPayPalOrderAction.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use Sylius\Abstraction\StateMachine\WinzouStateMachineAdapter;
2020
use Sylius\Component\Core\Factory\AddressFactoryInterface;
2121
use Sylius\Component\Core\Model\CustomerInterface;
22+
use Sylius\Component\Core\Model\OrderInterface;
2223
use Sylius\Component\Core\Model\PaymentInterface;
2324
use Sylius\Component\Core\Model\PaymentMethodInterface;
2425
use Sylius\Component\Core\OrderCheckoutTransitions;
@@ -87,9 +88,18 @@ public function __invoke(Request $request): Response
8788
{
8889
$orderId = $request->request->getInt('orderId');
8990
$order = $this->orderProvider->provideOrderById($orderId);
90-
/** @var PaymentInterface $payment */
91+
92+
if ($order->getState() !== OrderInterface::STATE_NEW) {
93+
return new JsonResponse(['orderID' => $orderId]);
94+
}
95+
96+
/** @var PaymentInterface|null $payment */
9197
$payment = $order->getLastPayment(PaymentInterface::STATE_CART);
9298

99+
if (null === $payment) {
100+
return new JsonResponse(['orderID' => $orderId]);
101+
}
102+
93103
$data = $this->getOrderDetails((string) $request->request->get('payPalOrderId'), $payment);
94104

95105
/** @var CustomerInterface|null $customer */
@@ -144,13 +154,13 @@ public function __invoke(Request $request): Response
144154
} catch (PaymentAmountMismatchException) {
145155
$this->paymentStateManager->cancel($payment);
146156

147-
return new JsonResponse(['orderID' => $order->getId()]);
157+
return new JsonResponse(['orderID' => $orderId]);
148158
}
149159

150160
$this->paymentStateManager->create($payment);
151161
$this->paymentStateManager->process($payment);
152162

153-
return new JsonResponse(['orderID' => $order->getId()]);
163+
return new JsonResponse(['orderID' => $orderId]);
154164
}
155165

156166
private function getOrderCustomer(array $customerData): CustomerInterface

0 commit comments

Comments
 (0)