操作指南 · 附来源的解答

Resend Webhook 的工作原理

Resend Webhook 的工作方式是:当发生邮件、联系人、域名或抑制相关事件时,向您注册的端点发送一个带有 JSON 事件负载的 HTTPS POST 请求。您的端点应基于原始请求体验证签名,以幂等方式处理事件,并及时返回成功响应。

Resend Webhook 的工作流程

首先,您需要创建一个公开的 HTTPS 端点,并在 Resend 中注册该端点及应用所需的事件类型。当发生匹配的事件时,Resend 会发送一个包含 JSON 负载的 POST 请求。负载中包含 type(例如 email.sent、email.delivered、email.bounced 或 email.complained)、创建时间以及该事件特有的数据。请按 type 字段分派处理逻辑,不要假设每个负载的结构都相同。

处理之前先验证请求

以原始文本形式读取请求,并使用 Webhook 签名密钥以及 svix-id、svix-timestamp 和 svix-signature 头进行验证。请在解析负载或据此执行任何操作之前完成这一步。先解析 JSON 再重新序列化可能会改变字节内容,导致合法签名验证失败。拒绝未通过验证的请求,并将签名密钥保存在密钥管理器或受保护的环境变量中,而不是写在源代码里。

实现幂等的事件处理

Resend 在文档中说明其采用至少一次投递,因此同一事件可能不止一次到达您的端点。请以唯一性约束存储 svix-id,并在该标识已处理过时跳过业务逻辑。也不要依赖到达顺序,因为重试和网络延迟可能打乱事件顺序。在顺序很重要时使用事件的 created_at 值,并对状态变更进行建模,避免较早的事件意外覆盖较新的状态。

快速确认,安全处理

在事件完成验证并被持久化记录后返回 HTTP 200,然后通过队列或后台 worker 执行耗时较长的工作。超时或非成功响应会触发再次投递,因此冗长的同步处理程序会造成本可避免的重复。将事件接收与副作用分开,例如更新抑制记录、通知客服或记录退信。每个副作用本身也应可安全重复执行,或通过已存储的事件标识加以保护。

测试重试、重放和故障恢复

在上线生产环境之前,请使用有代表性的事件类型测试端点,包括无效签名、重复标识、乱序时间戳和数据库临时故障。Resend 会按照退避计划重试失败的投递,并允许您重放失败和成功的 Webhook 消息。可以利用重放在故障后恢复,或验证更新后的处理代码,但请保持去重逻辑处于启用状态,以免恢复过程重复触发面向客户的副作用。

团队常问的问题

Resend Webhook 端点应返回什么响应?

在请求通过验证且事件已被持久化接收后返回 HTTP 200。耗时的工作应异步继续执行,以免服务商因超时而重试。

为什么必须保留原始请求体?

签名覆盖的是原始请求字节。解析 JSON 后再重新序列化可能会改变这些字节,导致即使请求合法也会验证失败。

Resend Webhook 事件会被投递多次吗?

会。Resend 在文档中说明其采用至少一次投递,因此处理程序必须对事件去重,通常做法是在执行业务副作用之前先存储唯一的 svix-id。

Resend Webhook 事件会按顺序投递吗?

不会。网络延迟和重试可能改变到达顺序。当应用必须重建可靠的事件顺序时,请使用事件时间戳和状态转换规则。

如何恢复投递失败的 Resend Webhook?

Resend 会自动重试失败的投递,也支持手动重放。请先修复端点,再重放需要的事件,同时保持幂等检查处于启用状态。

一手资料