使用ngrok对接Stripe Webhook时出现签名验证失败问题
必须获取原始请求体,禁止提前解析JSON
很多后端框架(如Express、NestJS)默认会自动解析JSON请求体,这会破坏Stripe签名依赖的原始字节结构。以Express为例,要替换express.json()中间件为:app.use('/webhooks/stripe', express.raw({ type: 'application/json' }));确保后续处理时直接使用原始Buffer或字符串,而非解析后的JSON对象。
检查ngrok是否篡改请求细节
启动ngrok时添加日志参数,查看请求流转细节:ngrok http <port> --log=stdout重点对比本地和ngrok转发请求的
Stripe-Signature头、Content-Length值,以及请求体的字节长度。如果ngrok开启了压缩,尝试禁用:ngrok http <port> --no-gzip确认Stripe CLI转发配置与Secret匹配
执行stripe listen时,会输出类似Webhook signing secret: whsec_xxx的内容,确保代码中使用的webhookSecret完全一致。同时检查转发地址是否正确,避免多余斜杠或参数:stripe listen --forward-to https://<准确的ngrok域名>/webhooks/stripe触发事件后,查看Stripe CLI日志是否显示“Forwarded event to xxx”,无额外报错。
验证请求编码与字节一致性
在代码中打印原始请求体的字节长度,对比本地和ngrok转发的结果:console.log('Request body length:', req.body.length);若长度不一致,说明代理或框架修改了请求体编码(如转码为非UTF-8),需排查中间件或代理配置。
尝试绕过Stripe CLI直接配置Webhook
登录Stripe Dashboard,添加ngrok地址作为Webhook端点,选择payment_intent.succeeded事件,获取对应的Webhook Secret替换到代码中,用真实支付事件测试。若此方法成功,说明问题出在Stripe CLI,尝试更新CLI到最新版本:stripe update
内容的提问来源于stack exchange,提问作者tim bits

