During checkout, it is possible to create duplicate orders by clicking the Continue button again immediately after the initial order has been processed but before the browser redirects to the next checkout step.
The button is correctly disabled while the request is being processed. However, it becomes active again briefly before the redirect takes place.
A second click during this interval triggers another checkout.confirmPayment request and creates an additional order.
- Add a product to the cart and proceed to checkout.
- Complete the required checkout information.
- Click Continue to submit the order.
- Wait until the loading indicator disappears and the button becomes active again.
- Click Continue a second time before the browser redirects.
Actual result: Two separate orders are created from the same checkout process.
Expected result: Once an order has been successfully submitted, the checkout button must remain disabled until the redirect is completed. Repeated submissions must not create additional orders.
Technical findingsThe checkout template calls hideLoading(btn) before processing the redirect:
.then(function(json) { hideLoading(btn); // ... if (json.redirect) { window.location.href = json.redirect;}
The hideLoading() function sets btn.disabled = false, making the button clickable again.
Additionally, the payment submission function does not appear to have an independent in-flight guard against repeated calls.
Suggested fix- Keep the checkout button disabled after successful order submission until navigation is completed.
- Re-enable the button only if validation or request processing fails and another submission is required.
- Add a submission guard to prevent concurrent calls to handlePaymentSubmit().
- Consider server-side idempotency protection to prevent duplicate order creation from repeated HTTP requests.
The relevant checkout submission logic is implemented directly in the Bootstrap 5 checkout template.
While this allows the issue to be addressed through a Joomla template override without modifying J2Commerce core files, essential checkout functionality such as submission locking and duplicate-order prevention should ideally be handled centrally rather than depending on the active frontend template.