Test Stripe webhooks locally without ngrok, guesswork, or pushing to staging. This is the exact loop I use to debug Stripe webhook handlers on my own machine — Stripe CLI listen + forward, signature verification on the raw body, replaying events by ID, and proving idempotency.
What you'll learn:
• Forward real Stripe test events to localhost with the Stripe CLI
• Why you must use the CLI's whsec_ secret (not the dashboard's) for local testing
• Verify Stripe signatures against the raw request body — and why parsing it too early breaks everything
• Trigger payment_intent.succeeded, charge.failed, customer.subscription.created, invoice.payment_failed
• Replay the exact same event by ID after a code fix — no more recreating checkouts
• Prove idempotency by replaying twice and watching the duplicate get skipped
The four-command loop: listen → trigger → replay → check idempotency.
Written walkthrough + code:
https://dev.to/restofstack/how-to-test-str...
CODE:
https://github.com/restofstack/stripe-webh...
Next step — once events are arriving reliably, how to query them like a database:
https://centrali.io/blog/query-stripe-webh...
Chapters:
0:00 The pain — why ngrok + guess-and-check breaks down
0:30 The local app and the dev route
1:00 Start the Stripe CLI listener
1:30 The webhook secret that matters (CLI, not dashboard)
2:10 Two common mistakes — wrong secret, parsing body too early
2:40 Log the event ID
3:00 Trigger the first event
3:40 Trigger more event types
4:20 Replay an event by ID
5:00 Prove idempotency by replaying twice
5:40 The "boring log line" — skipped duplicate
6:00 The four-command loop
6:20 Pre-production checklist
7:00 Where Centrali fits (storing + querying events after they arrive)
#stripe #webhooks #stripeintegration
stripe-cli, test stripe webhooks locally, stripe webhook tutorial, webhook signature verification, idempotency, stripe events resend, local webhook testing, stripe payment_intent, indie saas, solo dev, debug webhooks