标准答案
- 验证来源时应校验 HMAC 签名、时间戳、密钥版本、证书或 mTLS,并使用原始请求体参与验签,防止解析或重编码后签名不一致。
- 以事件 ID、事件来源和事件类型建立持久化去重记录。重复事件应返回成功或已处理状态,而不是再次执行业务副作用。
- 收到回调后优先快速确认,并将可靠处理放入队列或后台任务;长时间同步处理会触发对方超时并导致更多重试。
- 事件可能乱序到达,应以事件时间、版本号、资源当前状态或向源系统查询的权威状态决定是否应用,不能只按到达顺序覆盖。
- 需要记录原始事件的安全摘要、处理结果、失败原因和重放能力,以便对账和故障恢复。
题目解析
Webhook 不是可靠的数据库同步通道。网络失败、供应商重试、重复投递和事件丢失都需要在业务层通过查询、对账或补偿处理。
验签只验证事件来自某个密钥持有方,不代表事件在当前业务状态下仍应被执行;状态机和幂等仍然必要。
代码示例
验签、去重和异步入队应在接收入口完成,业务副作用由后续可重试处理器执行。
TypeScript
verifyHmac(rawBody, headers.signature, secret)
assertFreshTimestamp(headers.timestamp)
const inserted = await events.insertIfAbsent(headers.eventId)
if (inserted) await queue.publish({ eventId: headers.eventId })
return { status: 204 }常见误区
- 只校验来源 IP 或只信任一个可伪造 Header。
- 同步执行完整业务后才返回 2xx,导致供应商不断重试。
- 按收到顺序直接覆盖资源状态,不处理重复和乱序。