- Issue created by @nicolas bouteille
- 🇫🇷France nicolas bouteille
After digging a little bit more into that topic, this is what I think I understand:
Stripe.php (ie Card Element) executes the payment in ajax in commerce_stripe.review.js using stripe.handleCardPayment(). Only when this ajax call is over, form.submit() is called which I assume goes to the next checkout step PaymentProcess which calls $this->createPayment in order to create the Commerce Payment inside the database. A few lines below, $payment_gateway_plugin->createPayment($payment, $this->configuration['capture']) calls Stripe.php->createPayment() and eventually the order will be placed / completed.
StripePaymentElement.php (Payment Element) executes the payment in ajax as well in commerce_stripe.payment_element.js using stripe.confirmPayment({}) when choosing a new payment method. stripe.confirmPayment uses a return_url parameter that will redirect to PaymentCheckoutController->returnPage() which will call StripePaymentElement->onReturn() to create the payment method in our database and then call $checkout_flow_plugin->redirectToStep($redirect_step_id); to make us reach the PaymentProcess step, etc.
Back to commerce_stripe.payment_element.js, in case we've selected a stored credit card, we fire stripe.confirmCardPayment() that does not need a return_url since we don't need to create the payment method afterwards because it already exists. Instead $form.submit(); makes us go to the Payment Process step.
Conclusion: in all these situations, if the customer's session gets killed after the ajax call of stripe.handleCardPayment(), stripe.confirmPayment({}) or stripe.confirmCardPayment(), and we never reach the PaymentProcess step, no information about the successful payment is stored inside the database, and the order never gets completed either.
To prevent this type of scenario from happening, we can / should plug Stripe's events to custom webhooks / api endpoints / urls instead.
https://stripe.com/docs/payments/accept-a-payment-deferred?platform=web&...
https://stripe.com/docs/webhooks
With this solution, even if the user session gets closed right after the ajax payment, Stripe would still communicate with our website and we would still be able to finalize the order no matter what.
Disavantage: for local testing, I guess this requires to have a local url accessible from the outside using something like ngrok.What do you guys think?
- 🇫🇷France nicolas bouteille
Because this is issue is too long, I'll just keep it a support request and we could create a cleaner, shorter, separate feature request...
- Status changed to Closed: works as designed
5 months ago 10:20am 14 November 2024 - 🇫🇷France nicolas bouteille
Closing this because Stripe Webhooks have actually been added in version 1.2 in a submodule that makes use of Avanced Queue.
This is actually a great implementation and queueing webhooks instead of calling processWebhook immediately ensures that these Stripe's recommandations are followed:
1/ respond to Stripe with a 200 code ASAP.
2/ makes us more inclined to receive lots of events simultaneously on our endpoint. For example all subscription renewals triggered at the same time.
3/ makes it possible to process a webhook again that could have failed with no need to ask Stripe to send it again
Thank you for you great work on this guys!