How does the Stripe Checkout flow work?
- The React client sends the cart (product ids and quantities) to your Express API.
- The server looks up prices in MongoDB, creates a Checkout Session, and returns its url. The client sets window.location.href to that URL.
- After payment, Stripe calls your webhook endpoint with a checkout.session.completed event. Only then do you mark the order as paid.
Why must the server calculate the price?
How do I create a Checkout Session in Express?
Bash
Js
Js
What should the success page show?
How do I verify a Stripe webhook in Express?
Js
Js
How do I test Stripe payments locally?
Bash
What environment variables does the integration need?
Bash
What are the common Stripe integration mistakes?
- Putting express.json() above the webhook route. The body gets parsed, the raw bytes are gone, and constructEvent fails with a signature error that looks like a wrong secret.
- Marking the order paid on the success page. A customer can type that URL by hand, or close the tab before it loads. The webhook is the only source you can trust.
- Trusting totals from the client, as described earlier.
- Doing money math with floats. In JavaScript, 0.1 + 0.2 is 0.30000000000000004. Store integer cents, and round once at the edges if you must convert.
- Forgetting the idempotent update, then sending two confirmation emails when Stripe retries.
Checklist before you go live
- Prices, tax, shipping and discounts are all computed on the server.
- The webhook route uses express.raw and sits above express.json().
- Signature verification is on, and the event handler is idempotent.
- Orders are fulfilled from the webhook, never from the success page.
- Live keys and a live webhook endpoint secret are set in your hosting environment, not in the repository.