The steps below illustrate my problem with Stripe's PaymentIntent flow, but you could come up with something similar for the other payment gateways I've looked at where the final notification of a successful payment is sent asynchronously from the payment gateway to the merchant site.
- Customer adds 10 x item A to their shopping cart, total now $100
- Customer goes to checkout page. Server creates a Stripe PaymentIntent for the $100 total and sends the 'client_secret' to the browser.
- Customer's browser displays the checkout page, showing $100 total, and Stripe's payment form.
- Customer opens a new tab, and adds 10 x item B to their shopping cart, total now $200.
- Customer returns to checkout tab, and completes $100 payment with Stripe (nothing the site can do to prevent this - it's all happening client side)
- Asynchronously, Stripe notifies the site via webhooks that we've got a $100 payment. What do we do now?
The payment total no longer matches the cart total. Do we have to refund the payment and cancel the order? How do we notify the customer? We've probably already shown them an 'order complete - thank you' page, because we had no way of knowing the total was wrong until the asynchronous notification arrived. The customer's probably left our site already. What do we do with their shopping cart?
-- Some further background to all this:
I used to always turn to Stripe whenever my clients wanted to take online payments on their websites, because Stripe's synchronous model made my code nice and easy. The customer would enter their card details, Stripe would then return a token representing the payment, finally my server side code would check all the details were correct, use Stripe's API to collect the money, and return a 'thank you' message to the customer's browser.
But now it seems Stripe are moving away from this model to an asynchronous model (PaymentIntents), where your server is supposed to listen for notifications for completed payments, before fulfilling orders. In Stripe's terminology, we should set up 'webhooks' listening for the 'payment_intent.succeeded' event.
All the other payment gateways I've used in the past also have an asynchronous model, in the sense that your webserver has to wait for some kind of callback from the gateway notifying us of the payment, before we can safely start processing the order. PayPal calls it 'Instant Payment Notification', Worldpay called it 'Order Webhooks', Adflex called it 'Server2ServerNotification'... etc.
Where I'm struggling, is trying to cope with things that might happen during the gap between checkout starting, and payment notification being received. Given that these payment gateways are all using these kind of asynchronous models, there must be a simple solution to this (and similar) problems, but I'm really stuck - any suggestions would be much appreciated.