接收 Webhook
平台发送只包含必要元数据的出站事件。签名规则如下:
| 项目 | 值 |
|---|---|
X-Signature | 小写十六进制 HMAC-SHA256 |
| 签名字节 | ${X-Webhook-Timestamp}.${原始请求体} 的 UTF-8 字节 |
X-Webhook-Timestamp | Unix 秒 |
X-Webhook-Event-Id | 稳定 UUID 幂等键 |
X-Webhook-Sequence | AppClient 范围内单调递增的正整数 |
必须按此顺序处理
- 在大小限制内读取原始请求字节,不要先解析 JSON。
- 校验必需请求头与时间窗口;官方 SDK 默认允许 300 秒时钟偏差。
- 从 Secret Manager 读取签名 secret,对精确字节计算 HMAC-SHA256,并用恒定时间比较。
- 签名成功后才解析 JSON,并确认正文
event_id与请求头一致。 - 在产生业务效果前,用持久存储原子认领事件 ID。重复事件返回 2xx,不重复执行效果。
- 在 10 秒内完成安全工作或入队并返回 2xx。
ts
const event = await verifier.verify(request.headers, rawBody)
await enqueueSafeEffect(event.event_id, event.type)
return new Response(null, { status: 204 })TypeScript SDK 的内存重放存储只适合本地测试;生产环境必须实现持久且原子的 claim(eventID)。轮换期间只在明确的到期时间前接受上一把 secret。
非 2xx、连接失败与超时会触发指数退避重试,最长 24 小时;重放会保留原事件 ID 与序列号。不要在错误响应、日志、队列或崩溃报告中复制 secret、签名或完整事件正文。