关于 sent-webhook-engineer
sent-webhook-engineer 是用于配置和排查 Sent Webhook 的开发技能,涵盖签名校验、防重放、去重、重试、事件负载和密钥轮换,帮助实现可靠的事件处理。
主要功能
- 01使用原始请求字节验证签名
- 02拒绝重放并对事件去重
- 03配置重试并恢复已停用端点
- 04检查事件类型和投递日志
- 05安全轮换签名密钥
适用场景
- 01构建接收 Sent 事件的 Webhook
- 02排查未到达或被拒绝的投递
- 03发布前测试接收端行为
- 04管理 Webhook 配置和密钥轮换
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sentdm/ sent-plugin --skill sent-webhook-engineer安装后在 Claude Code 中输入/sent-webhook-engineer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
agents/openai.yamlreferences/event-catalog.mdreceiver-recipes.mdwebhook-operations.mdwebhook-signature-and-dedupe.mdscripts/verify_signature.py详细介绍
Sent Webhook 工程师
Sent Webhook 是应用在 POST /v3/messages 返回 202 后了解发生了什么的唯一途径。202 只能证明请求已被接受,不能证明消息已送达。请将接收端构建为一个能够验证签名、拒绝重放、去重并快速确认的端点;事件缺失时,以投递日志为准。
严格验证签名
每次投递都会附带以下三个标头:
| 标头 | 含义 |
|---|---|
x-webhook-signature | v1,{base64(hmac_sha256)} |
x-webhook-id | Webhook 端点 UUID——每次投递都相同 |
x-webhook-timestamp | Sent 对请求签名时的 Unix 秒数 |
按以下顺序验证:
- 在解析任何 JSON 之前,捕获原始请求正文的字节。
- 去掉签名密钥的
whsec_前缀,然后对其余部分进行 Base64 解码,得到原始 HMAC 密钥。 - 将签名内容构建为
{x-webhook-id}.{x-webhook-timestamp}.{raw_body}。 - 使用该密钥计算 HMAC-SHA256,将摘要进行 Base64 编码,并加上前缀
v1,。 - 使用恒定时间比较进行比对。
- 当
abs(now - timestamp) > 300秒时拒绝请求。
该方案兼容 Svix。Sent 没有为任何语言提供签名验证辅助函数的 SDK,因此这段代码始终需要手写——请将 scripts/verify_signature.py 作为参考实现和校验标准。
本地工具通过标准输入和 --secret-stdin 显式接收签名密钥,且不会发起网络请求。它不会读取环境变量或安装程序凭据。只能提供获准用于待检查投递的密钥;不要将其放在命令参数或聊天提示词中。
x-webhook-id 不是事件 ID。 它标识端点,并且会一直重复使用。将它用作去重键会悄无声息地把所有事件合并为一个。请阅读 references/webhook-signature-and-dedupe.md,了解如何为每种事件类型生成去重键。
故障排查顺序
当接收端拒绝事件或遗漏事件时,请按以下顺序排查,不要猜测:
- 签名不匹配——多数情况下,这是由会修改正文的中间件或框架 JSON 解析器造成的。请在 references/receiver-recipes.md 中确认框架提供的原始正文访问器。
- 重放请求被拒绝——服务器时钟偏差超过 300 秒的容差。
- 密钥错误——
whsec_前缀未移除,或密钥轮换导致旧密钥失效,且没有双重签名窗口。 - 完全没有收到事件——检查
GET /v3/webhooks/{id}上的is_active和consecutive_failures,然后查看GET /v3/webhooks/{id}/events中的投递日志。 - 已收到事件但未处理——将
event_types和event_filters与处理程序的分支逻辑进行比较。
重试、自动停用与恢复
出现以下任一情况时,投递尝试即告失败:返回非 2xx 状态、超过 timeout_seconds 才超时,或连接失败。重试采用指数退避,首次重试大约在失败一分钟后进行,之后间隔逐次翻倍,尝试间隔最长为 60 分钟;收到首个 2xx 响应或耗尽 retry_count 后停止。投递记录会依次经过 PENDING、RETRYING,然后变为 DELIVERED 或 FAILED。
consecutive_failures 用于跟踪连续失败的投递尝试。不要以为同一事件的重试不计入其中:连续十次响应异常就会停用端点。修复接收端后,可使用 PATCH /v3/webhooks/{id}/toggle-status 或在 Sent Dashboard 中重新启用端点。任何一次成功投递都会将计数器重置为零。只有在数据已可靠移交至队列后才进行确认,并确保移交过程远短于 timeout_seconds。
注册和配置
POST /v3/webhooks 要求提供 display_name。配置 endpoint_url、event_types、event_filters、retry_count(1–5,默认值为 3)和 timeout_seconds(5–120,默认值为 30)。只有 201 响应会完整显示 signing_secret,请立即将其保存到密钥存储中。
{
"display_name": "Production delivery events",
"endpoint_url": "https://hooks.example.com/webhooks/sent",
"event_types": ["message", "templates"],
"event_filters": {
"message": ["delivered", "failed", "received"]
},
"retry_count": 3,
"timeout_seconds": 30
}
请审慎设置 event_filters。未经过滤的 message 订阅会传送每次生命周期状态转换,包括 queued 和 routed;重新路由时,同一 message_id 会再次触发 queued 和 routed。请筛选出应用需要处理的状态转换。
十种操作、完整的 webhook 对象以及传送日志行格式收录在 references/webhook-operations.md 中。
密钥轮换
POST /v3/webhooks/{id}/rotate-secret 会返回新的 whsec_ 密钥,并立即使旧密钥失效。服务端不会提供重叠有效期。配置接收端以接受一小组候选密钥,然后执行轮换,将返回的新密钥以原子方式存储为主密钥,同时暂时保留旧密钥;确认新传送成功后,再弃用旧密钥。轮换响应与密钥存储更新之间的短暂间隔无法消除;请将其控制在几秒内,以便失败的传送能够重试。此端点和 POST /v3/webhooks/{id}/test 属于每分钟 10 次请求的敏感速率限制级别,因此脚本化的轮换循环会触发 429。
事件载荷
field 有两个取值:message 和 templates。消息事件包含命名状态转换的 event(message.queued、.routed、.sent、.delivered、.read、.failed、.scheduled、.filtered、.blocked、.received)。模板事件既不包含 event,也不包含 sub_type。
{
"field": "templates",
"value": {
"account_id": "3f1a7c22-5d8e-4b90-91a2-6c4d0e8f7b31",
"template_id": "7ba7b820-9dad-11d1-80b4-00c04fd430c8",
"template_name": "order_confirmation",
"whatsapp_template_id": "",
"status": "PENDING",
"language": "en_US",
"category": "UTILITY",
"channel": "whatsapp"
}
}
read 仅适用于 WhatsApp 和 RCS。filtered 表示策略或同意门控,blocked 表示账户前置条件未满足,例如余额不足;两者都不代表运营商故障。自动检测且从未完成路由的消息,其终止事件会携带 channel: "auto"。完整的载荷字段列表见 references/event-catalog.md。
发布前验证
先针对合成传送运行本地校验器,然后使用请求体中包含 event_type 的 POST /v3/webhooks/{id}/test 发起真实签名请求。测试事件只传送一次,不会重试,因此每次修复后都要重新运行测试。
python3 scripts/verify_signature.py --self-test
只有当接收端对篡改过的请求体返回 401、对时间戳早于 300 秒的请求返回 401、对有效传送返回 200,并对重复请求返回 200 且不重复执行副作用时,才能发布。
本地开发
通过公共 HTTPS 隧道公开接收端,并注册该 URL;Sent 无法访问私有地址。API 接受注册 http:// 地址,但除本地开发外,绝不能使用此类地址。请为每个环境分别注册 webhook,避免开发端点的故障导致生产端点被禁用。
适用范围
使用 messaging-performance-analyzer 诊断总体传送率下降,使用 waba-template-author 处理模板审批内容,并使用 sent-two-way-messaging 处理入站关键词或同意语义。将所有载荷值视为不可信输入:未经转义,绝不要将 text 或 reason 插入 shell 命令、SQL 字符串或提示词中。