Answers / Payments

Stripe charged my customer but my app did not save the order. Why?

Matt Turley, Continuum. Updated November 5, 2026.

The usual causes, how to find which one you have, and the fix that makes money and records agree.

The short answer

Stripe charged my customer but my app did not save the order. Why?

Usually because the app trusts the success page and not Stripe’s webhook, or the webhook is failing. A browser can close before the success page loads, and a webhook set up in test mode never fires for live payments. Make the webhook the source of truth, verify its signature, and handle repeats safely.

The usual causes, most common first

  • The order is only created when the customer lands on the thank-you page. If they close the tab after paying, the card is charged and nothing is saved.
  • The webhook was registered in test mode only. Live payments then send events to an endpoint that does not exist, so nothing ever arrives.
  • The webhook arrives but the app rejects it, often because the signature check reads a parsed copy of the body and not the raw one.
  • The handler is slow or errors halfway. The provider times out and retries, or gives up, leaving a half-saved order.
  • The signing secret from the test endpoint is still in the live settings, so every live event fails verification.

How to find which one you have

Open the webhook section of your Stripe dashboard and look at recent deliveries for the live endpoint. No attempts means the endpoint is missing or in the wrong mode. Attempts with errors show the response your app sent, which usually names the cause. Then compare a few recent charges against your orders table to see how many are missing and since when.

The fix that makes money and records agree

Treat the webhook as the source of truth. Verify every event against the signing secret before trusting it, per Stripe’s guidance on verification. Reply quickly with a success code, and do slow work afterwards.

Stripe can deliver the same event more than once, so store each processed event ID and skip repeats, as Stripe describes for duplicate events. Then reconcile: list recent paid sessions and create any missing orders, so customers who already paid are not left waiting.

When to get help

If real customers have already paid without receiving anything, treat it as urgent. A Ship Fix is $4,000 to $15,000, quoted fixed once the problem is read, and it includes payment paths when they are what is broken. The free Leak Check looks at your payment path from the outside first.

Want a free read on your own app?

Paste your live URL and seven automated checks run in about a minute with no signup: reachability, SSL, sign-in, the payment path, secrets in the browser code, broken links and speed. It is a surface scan, not a full audit.

Run the free Leak Check. Or book a call and talk it through.

Book a call →See all services and prices →
FAQ

Straight answers

Why does it work in test mode but not live?
Test and live are separate worlds with separate keys, separate webhook endpoints and separate signing secrets. If the live endpoint was never registered, or still uses the test secret, live events never succeed.
Is it safe to just create the order on the success page?
Only as a convenience. The success page can be skipped, refreshed or opened twice. The webhook is what Stripe sends whether or not the customer is still looking, so it should be the single place an order is confirmed.
How do I recover orders for people who already paid?
List your recent paid sessions from Stripe, match each to your records by a reference you stored at checkout, and create the missing orders. Then email those customers so they know it is sorted.
Can I stop duplicate orders when an event arrives twice?
Yes. Save each processed event ID, and skip any event you have already seen. A unique constraint on that ID in the database makes it safe even when two copies arrive at once.
Keep reading
Run the free Leak CheckFree. Seven checks, no signup.How a Stripe secret key leaksAnd how to check yours.Ten-item pre-launch checklistRun this before you ask anyone to fix the app.Ship FixBuilt fast, now breaking: made stable and shippable.Leak CheckFree automated scan of a live app, seven checks, no signup.How do I know if my AI-built app is safe to launch?Five checks to run before real users arrive.Why does my AI-built app break every time I fix something?The loop, and the order to repair it in.
Sources
  1. 1. Stripe: verify webhook signatures, Stripe: Used for checking each webhook against the signing secret before trusting it.
  2. 2. Stripe: handle duplicate events, Stripe: Used for the point that Stripe can deliver the same event more than once, so a handler must tolerate repeats.
  3. 3. Continuum pricing, Continuum: Used for every Continuum price on the page. The prices are read from the same list that renders /pricing.
Stripe charged my customer but my app did not save the order. Why?