## The problem
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.
## What works
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