Stripe Webhook签名匹配失败求助(版本v6.19)
Stripe Webhook 400错误(签名验证失败)排查方案
我来帮你搞定这个Webhook签名验证失败的问题,从你的代码和描述来看,有几个核心问题和常见坑需要逐一排查:
1. 核心问题:全局body解析中间件冲突
你的代码里犯了一个典型错误:全局注册了bodyParser.json(),同时又在Webhook路由里用bodyParser.raw()。
Express的中间件是按顺序执行的,当请求到达/webhook路由时,全局的bodyParser.json()已经把请求体解析成了JSON对象,而Stripe的签名验证必须依赖原始的未解析的请求体Buffer。这时候request.body已经不是原始内容,自然匹配不上签名。
修正方案:
删掉全局的JSON解析中间件(只给需要的业务路由单独使用),确保Webhook路由拿到原始请求体:
// 只引入一次body-parser,避免重复加载 const bodyParser = require('body-parser'); const express = require('express'); const app = express(); // ❌ 删掉全局的JSON和urlencoded解析,不要影响Webhook路由 // app.use(bodyParser.json()); // app.use(bodyParser.urlencoded({ extended: false })); const stripe = require('stripe')('sk_test_VPw...'); const endpointSecret = 'whsec_...'; // ✅ Webhook路由单独使用raw解析,确保拿到原始Buffer app.post('/webhook', bodyParser.raw({type: 'application/json'}), (request, response) => { const sig = request.headers['stripe-signature']; let event; try { event = stripe.webhooks.constructEvent(request.body, sig, endpointSecret); } catch (err) { console.error('Webhook验证失败:', err.message); return response.status(400).send(`Webhook Error: ${err.message}`); } if (event.type === 'checkout.session.completed') { const session = event.data.object; console.log('处理结账会话:', session.id); // handleCheckoutSession(session); } response.json({received: true}); });
2. 版本兼容性问题
你使用的Stripe v6.19是比较老旧的版本(当前最新稳定版已到v10+),虽然核心签名逻辑变化不大,但可能存在一些隐藏的兼容性问题,比如对Buffer处理、请求头解析的差异。
建议升级到较新的稳定版本:
npm install stripe@latest
3. 最后再核对几个细节
虽然你说已经核对过密钥,但还是要再确认:
- 确保使用的是Webhook端点的签名密钥(
whsec_开头),而非API密钥(sk_test_开头) - 如果你的服务在反向代理(Nginx、Cloudflare等)后面,要确保代理没有修改请求体或请求头(比如自动压缩body),这会导致原始内容变化,签名验证失败
- 可以在catch块里打印
typeof request.body,如果输出是object而非buffer,说明还是被其他中间件提前解析了,需要检查中间件注册顺序
内容的提问来源于stack exchange,提问作者Magnus
相关产品推荐
相关产品推荐

