If you're integrating Stripe in a Node.js backend, you're likely using webhooks to handle events like checkout.session.completed. One of the common pitfalls during deployment is related to webhook signature verification failures, and recently, I ran into exactly this issue.
In this post, Iβll walk through the problem I faced, how I fixed it, and what best practices you can follow to avoid the same mistake.
app.post(
"/api/v1/webhook/stripe",
express.raw({ type: "application/json" }),
stripeWebhookHandler
);
// JSON body parser for all other routes
app.use((req, res, next) => {
if (req.originalUrl === "/api/v1/webhook/stripe") {
next(); // Skip body parsing for Stripe
} else {
express.json()(req, res, next);
}
});
This is required because Stripe needs access to the raw body to verify the signature using the stripe.webhooks.constructEvent() method.
**
β The Problem
**
After deploying to production, Stripe kept returning this error:
β "Webhook signature verification failed. No signatures found matching the expected signature for payload."
I was sure my raw body handling was correct, and the endpoint URL was accurate. Locally, everything worked using the Stripe CLI. But in production⦠webhook requests kept failing.
π The Root Cause
Turns out the issue was very simple but easy to overlook:
π I was using the Test Mode webhook signing secret (whsec_...) in production, while Stripe was sending Live Mode events.
Stripe signs test and live events with different secrets, and if you mismatch them, signature verification will always fail β even if your code is perfect.
β
The Fix: Environment-Based Configuration
To avoid this, I updated my environment variables and Stripe initialization code to handle different modes based on the environment
π§ͺ Bonus Tip: Use Stripe CLI for Local Testing
To test webhooks locally with the Stripe CLI:
stripe login
stripe listen --forward-to localhost:5000/api/v1/webhook/stripe
stripe trigger checkout.session.completed
Make sure your local environment uses the test mode secrets to match the CLIβs default behavior.
π‘ Final Thoughts
Small mistakes like using the wrong webhook secret can cost you hours of debugging. If you're getting a "Webhook signature verification failed" error, double-check your mode (test/live) and environment configuration.
If this helped you, share it with someone struggling with Stripe setup β and happy coding! β‘
Top comments (0)