Rescue · Payments

Stripe Works in the Demo, Fails in Production

The checkout your AI built almost certainly works — against Stripe’s test environment. Real revenue needs three things the prompt never set up. Miss one and you get failed cards, phantom subscriptions, or customers who cancelled months ago and still have full access.

Impact: revenueFix effort: 2–4 daysWell-defined checklist
Symptoms

How this one announces itself

Real cards decline instantly

Test keys in production: Stripe correctly refuses real cards in test mode. The customer sees a failure; your logs see nothing wrong.

“No such price” errors

The hardcoded price_1ABC… ID belongs to a test-mode product. Live mode has never heard of it.

Paid, but nothing unlocked

The charge succeeded at Stripe — and your app never heard about it, because no live webhook exists to deliver the news.

Cancelled customers keep access

The reverse failure: without webhooks, cancellations and failed renewals never reach your database. Free users forever.

Test and live are fully separate

Keys, products, prices, webhooks — Stripe keeps two complete environments. An app built in test mode has zero live configuration. Not partial: zero. Everything must be recreated deliberately.

The webhook layer never existed

Prototypes read Stripe's success redirect and call it done. Real billing runs on events — payment succeeded, subscription cancelled, card expired. The redirect is a hint; the webhook is the truth.

The demo hid all of it

Every test transaction worked, every screen looked right. Test mode is designed to make things work — that's its job. Production is designed to move money — that's its.

## The go-live checklist, condensed
# 1. keys: live secret server-side only — never in the bundle
grep -rE "sk_live|sk_test" dist/ src/ # bundle hits = rotate now
# 2. catalogue: recreate products & prices in live mode, reference from config
# 3. webhooks: register the live endpoint, then verify signatures
stripe listen --forward-to localhost:3000/api/webhooks # test failure paths locally
stripe trigger payment_intent.payment_failed

The fix, in order

01

Keys Per Environment

Live secret key in server env vars, publishable key client-side, test keys back in dev where they belong.

02

Rebuild the Catalogue

Products and prices recreated in live mode, IDs referenced from configuration — never string literals in components.

03

Register & Verify Webhooks

Live endpoint, subscribed to the events your billing logic needs, signature (whsec_…) verified on every delivery.

04

Handle the Ugly Events

Declines, disputes, expired cards, cancellations — each one changes what the customer should be able to do.

05

One Real Transaction

A real card, a real charge, a real refund, watched end to end. One honest loop beats a hundred test passes.

FAQ

Common questions

Customers paid but the app didn't unlock their account. Why?

The missing-webhook signature: Stripe completed the charge, but your app never received (or rejected) the event that grants access. Registering and verifying the live webhook fixes both directions — access on payment, revocation on cancellation.

Can I just switch the keys from test to live?

Keys are one of four steps. Without live price IDs and a verified webhook, the failure just moves one step deeper into the funnel — usually somewhere more embarrassing.

Do I need webhooks for one-time payments too?

Yes — the success redirect can be faked by anyone who reads the URL pattern. The webhook (or a server-side session check) is what actually confirms money moved.

How long does a payments fix take?

Payments-only rescues typically run two to four days including end-to-end testing with real transactions. It's the most common single-issue fix we do.

What does it cost?

Standalone payment fixes usually land at the bottom of the from-$2,499 sprint range; bundled into a full rescue they're part of the fixed quote. The $299 triage prices yours exactly.

Keep reading

Related rescue guides

$299 triage · 48 hours · credited against any fix

Make the revenue path boring

Keys, catalogue, webhooks and one real charge — tested end to end in every rescue.

43+ happy clients · rated 4.9/5 · senior engineers on every build