Describe the bug
Scenario:
- 2 customers, and only 1 item that they both have in their cart
- They start checking out at the same time
- I do a stock level check before creating the payment intent, it passes for both customers and I show the Stripe element
- Customer 1 is slower than Customer 2 at entering the credit card info and completing the payment
- Customer 2 finishes payment first, according to the code above the webhook is called with payment_intent.success and the item is allocated and is no longer available
- Customer 1 finishes the Stripe payment step after Customer 2, gets charged successfully, webhook is called with payment_intent.success but then item state change fails because the item stock is zero at this point
Outcome:
- The Stripe payment goes through and then moving the order to ArrangingPayment step fails because between the final stock level check on the payment page and completing the Stripe payment, the stock for one of the variants in the order went to zero.
- The order remains in an AddingItems state.
- The order also gets into an inconsistent state because the intent that was created for the order was already fulfilled so even if the out of stock items are removed from the order, Stripe will not process the order anymore or send a success message to the Webhook.
- The Stripe Plugin will not create a new intent for the same order code either
- The only way to get out of this state is to manually cancel the order and issue a refund on Stripe
To Reproduce
Steps to reproduce the behavior:
- Create a product with a variant that only has 1 item in stock
- Have 2 different customers put the same variant in their cart
- Use Stripe to checkout
- Get both customers to the checkout flow where they have to enter their credit card information
- One customer finishes first, then the second customer will see that the payment will go through but the order will not move to Arranging Payment because the item is out of stock, order remains in adding items state.
- Order is now stuck. Stripe Intent is already used and completed and cannot be reused, Stripe Plugin will not create a new intent for that same order code.
- Customer is charged but the order cannot be fulfilled
Expected behavior
A clear and concise description of what you expected to happen.
- Ideally this is what I think would handle this race condition gracefully - Separate authorization and capture (https://docs.stripe.com/payments/accept-a-payment?platform=web&ui=stripe-hosted#auth-and-capture)
- Stock check before creating intent
- Create intent and show the Stripe element
- Only authorize, dont charge the customer and update the webhook to listen to the authorization event
- On authorize, attempt to change item to allocated, this will fail if another customer grabbed the item first, in that case cancel the authorization with a message, unsure how to propagate the error to the storefront
- If stock exists and allocation can be successfully updated, then call the Stripe API to capture the payment for the same intent, which should then redirect to the URL
Environment (please complete the following information):
- @vendure/core version: 3.0.2
- Nodejs version: 20
- Database (mysql/postgres etc): MariaDB
Additional context
Add any other context about the problem here.




Describe the bug
Scenario:
Outcome:
To Reproduce
Steps to reproduce the behavior:
Expected behavior
A clear and concise description of what you expected to happen.
Environment (please complete the following information):
Additional context
Add any other context about the problem here.