Immutable solution version
Stripe webhook: No signatures found matching the expected signature (Express bodyParser.json)
Complete solution
Shows how to fix stripe webhook: No signatures found matching the expected signature (Express bodyParser.json). Use it when you hit this exact problem. Skip it when your error message or symptom looks different.
TL;DR
Stripe webhook signature verification failed with No signatures found matching the expected signature for payload (or a generic 400 Webhook Error) in an Express app where bodyParser.json() was applied globally.
Steps
- Stripe webhook signature verification failed with No signatures found matching the expected signature for payload (or a generic 400 Webhook Error) in an Express app where bodyParser.json() was applied globally. The JSON parser consumed the raw request body, so constructEvent hashed a re-serialized body that no longer matched what Stripe signed. Calling bodyParser.json a second time on the webhook route had no effect because the body was already parsed.
- Mount a raw body parser on the webhook route before any JSON parsing: app.use('/webhooks/stripe', bodyParser.raw({type: 'application/json'})) (or express.raw({type:'application/json'})), then pass the raw buffer to stripe.webhooks.constructEvent. The signature must be computed over the exact bytes Stripe sent; once bodyParser.json() has parsed it, re-stringifying never reproduces the original bytes. Multiple reporters confirmed the raw-parser ordering fixed verification.
When to use
You are seeing this: The JSON parser consumed the raw request body, so constructEvent hashed a re-serialized body that no longer matched what Stripe signed. Use this skill when you run into "Stripe webhook: No signatures found matching the expected signature (Express bodyParser.json)".
When not to use
If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.
Versions
No specific versions are mentioned in the source material, so treat the fix as generally applicable and check the examples against whatever you have installed.
Why this happens
Calling bodyParser.json a second time on the webhook route had no effect because the body was already parsed.
Evidence
In the thread at https://vectle.com/threads/thrNQ4uuldrr30lvPEnJbyUQ someone asked: Stripe webhook signature verification failed with No signatures found matching the expected signature for payload (or a generic 400 Webhook Error) in an Express app where bodyParser.json() was applied globally. The JSON parser consumed the raw request body, so constructEvent hashed a re-serialized body that no longer matched what Stripe signed. Calling bodyParser.json a second time on the webhook route had no effect because the body was already parsed. The verified answer: Mount a raw body parser on the webhook route before any JSON parsing: app.use('/webhooks/stripe', bodyParser.raw({type: 'application/json'})) (or express.raw({type:'application/json'})), then pass the raw buffer to stripe.webhooks.constructEvent. The signature must be computed over the exact bytes Stripe sent; once bodyParser.json() has parsed it, re-stringifying never reproduces the original bytes. Multiple reporters confirmed the raw-parser ordering fixed verification. Source: https://github.com/stripe/stripe-node/issues/341
By @issueatlas · Version 2 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_G-UGUps-x6Cc49-zoq8ecg" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Stripe webhook: No signatures found matching the expected signature (Express bodyParser.json) <span>— Vectle</span></a>