Stripe
Stripe Checkout not working
Either the server never created a Checkout Session, or it did and the browser never arrived at checkout.stripe.com. Those are different bugs with the same blank button.
Symptoms
- The button does nothing, reloads the page, or opens a 404.
- Stripe shows a session id in the logs, and the browser stays on your site.
- Checkout opens in test mode, or for a price you do not sell.
- The API returns “No such price.”
Common causes
Price id and secret key are from different modes
A price_ id from test mode only exists for the test secret key. Live keys return no such price. Generated apps copy the id from whichever mode the chat used.
Publishable key and secret key are from different accounts
The client token and the server key have to belong to the same Stripe account. A sample key left in the frontend produces a session the page cannot open.
The session exists and the redirect is blocked
Browsers enforce Content-Security-Policy form-action on the redirect that follows a form POST. If checkout.stripe.com is not allowed, the 303 is dropped and the tab stays on your billing page. The session is sitting in Stripe, unused.
The button targets a route this deploy deleted
A regeneration renamed /api/checkout or removed the server action. The page still shows the button. The request 404s.
Success and cancel URLs point at the preview
Checkout opens, payment works, and Stripe returns the customer to a host that no longer exists. It looks like checkout “lost” the order.
The price is archived, or live charges are not enabled
An archived price and an account that has not finished live activation both fail at session creation. The UI often shows a generic error, or none.
Fix it
Reproduce in a private window
Click the button and note the URL that is requested. A 404 is a routing bug. A 500 is in the handler. A 303 toward checkout.stripe.com that never navigates is a browser policy or a JavaScript router eating the redirect.
Find the session id
In the server log or the Stripe Dashboard, see whether a cs_test_ or cs_live_ session was created. No session means the failure is before Stripe. A session means the failure is between your response and the browser.
Read the session
Open it in the Dashboard. Check the mode, the price, the amount, and the success and cancel URLs. Fix the price id and the keys so they belong to that same mode and account.
Allow the Checkout host in form-action
If you set Content-Security-Policy, form-action needs https://checkout.stripe.com. The customer portal needs https://billing.stripe.com. A policy of form-action 'self' blocks the redirect even when the session was created.
Click it on a phone
A control below the fold, or under a cookie banner, never submits. The desktop screenshot will not show that.
Hit the URL you published
After a deploy, test the production domain. The preview can still have the old keys and the old route.
Catch it automatically
Map the checkout on a domain you verified. Production mode stops when the payment page is on screen and checks the price. Staging, on a preview you own, may type Stripe's published test card and nothing else. That catches a deleted route and a wrong price without charging anyone.
Watch the next break before a customer does.
Map the path once. The next publish does not get to fail in private.
Questions
The Dashboard shows a session, but the customer saw nothing. Where is the bug?
The session was created. Look at the redirect from your site to checkout.stripe.com. A Content-Security-Policy form-action, a client-side router, or a success URL on a dead host will do this.
Why does test mode work?
The price id, the secret key, and the webhook endpoint are all per mode. A working test checkout says nothing about the live price id or the live endpoint.
Can FunnelWatch finish a real payment?
No. Production checks stop on the payment page. Any card number other than Stripe's published test card is rejected before it is typed, and only on staging.