当 webhook 一直没有送达
按顺序排查:投递日志、事件名称、防火墙、签名。Deliveries 标签页会告诉你 Didit 是否发送过它,这一步能立刻把问题范围缩小一半。
先从目的地的 Deliveries 标签页看起。 如果 Didit 从未尝试投递,那是订阅或目的地配置的问题。 如果尝试过但失败了,响应码会告诉你原因:404 表示你的路由在该 URL 上不可达,签名不匹配表示你哈希了错误的字节内容。
#第一步:Didit 是否尝试发送过
在 API & Webhooks 中打开对应目的地,查看 Deliveries 标签页。 每一次尝试都会连同响应结果被单独记录下来。

- Last sent 会告诉你 Didit 是否尝试过发送。
- View stats 显示该目的地的尝试次数和失败次数。
- 一次测试投递能把你的端点和事件本身区分开。
- 持续失败的目的地可以先禁用,等修复好再启用。
这一个检查就能把问题分成两半:
- 没有记录到任何尝试 → 该目的地从未生成过这个事件。前往第二步。
- 记录到尝试,但失败了 → Didit 发送过,但你这边拒绝了它,或者没有收到。前往第三步。
- 记录到尝试,且是 2xx → 投递成功了。问题出在你的处理逻辑里,而不是投递环节。
#第二步:没有记录到任何尝试
按可能性从高到低排列:
- 事件没有被订阅。 没有通配符,每个事件系列都必须显式列出。一个不存在的事件名(例如
session.status.updated、kyc.completed)会静默地什么都收不到。对照事件列表检查一下。 - 应用不对。 目的地属于某个应用。如果你的会话运行在与该目的地不同的应用下,事件永远不会到达。这是配置看起来一切正常时最常见的原因。
- 确实没有变化。 webhook 只在变化时触发。一个没有移动过的会话,或者一次没有发现超过阈值命中的 AML 重新筛查,正确地不会产生事件。
- 你等待的状态还没有发生。 处于进行中的会话还没有完成。参见当会话一直没有完成。
#第三步:尝试过投递但失败了
404 表示请求到达了某处,但那里没有你的路由。请检查:
- 完整路径是否正确,包括结尾的斜杠。会把
/hook重定向到/hook/的框架,可能把一个正常工作的端点变成 404 或丢失请求体。 - URL 是否可公开访问。本地或预发布环境如果无法从公网访问,就会出现这种失败。
- 应用前面的代理、负载均衡器或基于路径的路由,是否把这个路径转发到了别处。
5xx 表示你的处理逻辑抛出了异常。在解析之前先记录原始请求体,这样你才能看到它实际收到了什么。
超时 表示你没有及时响应。应先返回 2xx,再进行处理。
完全没有响应 / 连接被拒绝 表示你的边界拦截了它。
Didit 从静态 IP 18.203.201.92 发送请求,User-Agent 为 DiditWebhook/2.0。
如果你在 Cloudflare 或采用默认拒绝策略的 WAF 后面,请为接收主机名放行这个 IP。
#常见情况:自动投递 404,但 Resend 却成功
这种情况足够常见,值得单独说明。 自动投递以 404 失败,随后在同一事件上点击 Resend 却成功了。
出现这种组合说明负载和你的端点都没有问题,差异在于时机或路径,而不是内容。请检查:
- 发生原始投递那一刻正好在部署或重启。 之后 Resend 之所以成功,是因为应用已经恢复运行。
- 冷启动超出了平台的超时时间,这在无服务器架构且首次调用较慢时很常见。
- 两次尝试之间基于路径的路由发生了变化,或者某条规则只匹配部分请求。
- 边界的速率限制或机器人防护,让单独到达的手动重发通过了,而突发到达的自动投递没有通过。
Deliveries 标签页记录了两次尝试各自的时间戳,可以拿它们和你自己那一分钟的部署与错误日志做对比。
#签名验证失败
几乎总是以下三种情况之一:
- 你对重新序列化后的 JSON 做了哈希。 应该对原始请求体字节做 HMAC,完全按接收到的样子,而不是解析后再重新字符串化的版本。解析再重新拼接会改变空白和键的顺序,签名就会对不上。大多数框架需要显式配置才能拿到原始请求体。
- 密钥不对。 签名密钥是按目的地分配的,并不是你的 API 密钥。两个目的地会有两个不同的密钥。
- 编码方式假设错误。 如果你不确定密钥应该按字面字符串使用还是需要先解码,不要猜测,严格按照签名验证参考文档操作,并在调试时记录原始请求体以便对比。
永远不要通过跳过验证来"修复"签名不匹配的问题。 一个未经验证的 webhook 端点,会接受任何找到该 URL 的人伪造的批准信息,这会把一个调试上的权宜之计变成账号接管的攻击路径。
#两次重试不等于一个队列
在遇到 5xx、404、超时或连接失败时,Didit 会重试两次,大约在 1 分钟后和之后再过 4 分钟,之后就会丢弃这次投递。 如果你的端点宕机时间超过这个窗口,那些事件就永久丢失了。
请搭建一条对账路径:在启动时,针对所有没有终态状态记录的会话轮询决策接口。 把 webhook 当作快速通道,把轮询当作兜底方案。
#无需运行验证即可测试
目的地页面上的 Try Webhook 会发送一个你选择类型的完整事件(已批准、已拒绝、审核中、KYB、实体、交易等场景)到你的端点。 用它可以在真实会话依赖它之前,验证你的端点、签名校验和处理逻辑是否正常工作。
沙盒是另外一半:沙盒会话会发出带有 "environment": "sandbox" 的真实 webhook,因此你可以免费端到端地演练整条路径。
参见在沙盒中测试。
