上周接 Stripe 的支付回调,测试环境怎么都不触发。本地没有公网 IP,自己 curl 模拟的报文又和平台发的不一样——差一个 Stripe-Signature 头,来回耗掉一个下午。后来先用临时地址把真实回调接住,对着报文补本地验签,10 分钟就通了。
先说结论
- 生成一个临时回调地址(600 秒有效),填进 GitHub、Stripe 的 webhook 设置,真实报文先进来再说。
- 页面每约 2 秒拉一次:方法、来源 IP、请求头、正文都在,JSON 自动格式化。
- 任何一条都能复制成 cURL,回本地复现,不用猜平台到底发了什么。
- 服务器只是临时落盘,10 分钟后自动清掉;本机只存 token 和未读计数。
一、先接住,再对报文
Webhook 联调最大的信息差,是你看不见对面真正发了什么。文档写的是一回事,平台实际发的常是另一回事:签名头叫什么名字、事件体嵌了几层、重试间隔多久,文档经常滞后。
自己模拟报文,等于拿猜的数据调真接口。我踩过这个坑:本地验签死活不过,查到半夜才发现平台发的是 x-signature 而文档写的 X-Signature,大小写、前缀都对不上。先把真实回调原样接住,一切就变成填空题。
二、从生成到复现,一共三步
点「生成回调地址」,拿到一个带独立 token 的 URL。填进 GitHub 仓库的 Webhooks、Stripe 的 Endpoints,或者任何支持自定义回调的系统,等事件触发。
页面上每约 2 秒自动拉取一次,新请求插到最上面并高亮。点开「请求头」看白名单字段和全部 X- 头;正文是 JSON 会自动格式化缩进。
对完报文,点「复制为 cURL」得到一条可执行的命令,贴回终端立刻复现这条请求。验签逻辑不对,就改参数重放,不用等平台下一次触发。
三、几条边界,心里有数
每个地址 600 秒 有效,到期服务器连同记录一起清掉,点「续期」可以再加 600 秒。每个地址最多保留 50 条 请求,超出丢最旧的;单条正文最多 256KB,超长截断并标记。
请求头只记常见字段加全部 X- 开头的,单值超过 4KB 截断。我认为这些边界不是缺陷——调试要的是「看得清」,不是「存得多」,50 条足够覆盖一次完整联调。
还有一条要提醒:别在调试期把生产密钥配进 webhook。签名对不上时,先用这里的原始报文比对,确认逻辑没问题再上真密钥。
常见疑问
回调地址能用多久?
每个地址生成后 600 秒(10 分钟)有效,到期后服务器连同已捕获的请求一起清掉。调试中途点「续期」可以再延长 600 秒;刷新页面不续期,剩余时间在页面顶部随时能看到。
我发的内容安全吗?
回调的内容会由服务器临时保存约 10 分钟,到期自动清除,请勿发送真实密钥或敏感数据。本机只存 token 和未读计数(localStorage),想删掉点页脚「清空我的数据」,会先二次确认。
一条回调能看到哪些信息?
HTTP 方法、时间、来源 IP、URL query、请求头(常见字段加全部 X- 头,单值最长 4KB)和请求正文(最长 256KB,超长截断并标记)。任何一条都能一键复制成 cURL,回本地复现。
新回调要等多久才能看到?
约 2 秒。页面每隔约 2 秒向服务器拉一次,没有用长连接方案,服务器端只是极简的落盘暂存。页面切到后台会暂停轮询,回到前台立刻拉一次。
English version: https://www.9314.cn/tools/webhook-debugger/en/