Express.js中Stripe Webhook出现400 Bad Request错误求助
解决Express + Stripe Webhook 400 Bad Request错误
你的400错误来自Stripe Webhook的签名验证失败,以下是针对性的排查和修复方案:
1. 确认Webhook签名密钥正确
- 你当前硬编码了
endpointSecret,首先要确保这个值是Stripe后台对应Webhook端点的签名密钥(不是API密钥)。 - 测试环境和生产环境的签名密钥是分开的,不要混淆。建议把密钥放到
.env文件中,通过环境变量读取,避免硬编码:const endpointSecret = process.env.STRIPE_WEBHOOK_SECRET;
2. 防止请求体被重复解析
Express的全局express.json()中间件会把请求体解析为JSON对象,但Stripe的Webhook需要原始的二进制请求体来验证签名。如果你的app.use(express.json())在app.use("/api/stripe", stripeRouter)之前执行,会导致request.body已经被解析,无法通过签名验证。
修复方案:
- 调整中间件顺序,让Webhook路由优先使用
express.raw()解析,跳过全局的express.json():// index.js // 先单独挂载Webhook路由,使用raw解析 app.use( "/api/stripe/webhook", express.raw({ type: "application/json" }), stripeRouter ); // 再挂载全局json解析和其他Stripe路由 app.use(express.json()); app.use("/api/stripe", stripeRouter);
3. 检查Webhook转发配置(测试阶段)
如果你用Stripe CLI测试Webhook,确保:
- 转发命令的端点路径和代码完全一致,比如:
stripe listen --forward-to localhost:3000/api/stripe/webhook - 确认CLI使用的是对应环境的API密钥(测试环境用测试密钥,生产用生产密钥),可通过
--api-key参数指定。
4. 确保签名请求头完整传递
如果你的应用部署在反向代理(如Nginx)或托管平台上,要确保stripe-signature请求头没有被修改或丢弃。比如Nginx需要配置proxy_set_header stripe-signature $http_stripe_signature;来传递该头。
额外优化建议
- 用Checkout流程时,更推荐监听
checkout.session.completed事件(而非payment_intent.succeeded),因为这个事件包含完整的Checkout会话信息,更适合处理订单逻辑:switch (event.type) { case "checkout.session.completed": const checkoutSession = event.data.object; // 在这里处理订单创建、通知用户等逻辑 break; // ...其他事件 }
内容的提问来源于stack exchange,提问作者Can Do
相关产品推荐
相关产品推荐

