Webhooks
本页内容
订阅事件
在开发页添加 HTTPS 接收地址,默认订阅 task.succeeded、task.failed 和 task.canceled。签名密钥仅在创建时显示。接收地址必须使用标准 HTTPS,不支持私有网络和 POST 重定向。
签名验证
请求方法为 POST,消息体为 JSON。X-Jisu-Event-Id 是稳定事件 ID,X-Jisu-Timestamp 是 Unix 秒数,X-Jisu-Signature 格式为 v1=十六进制签名。用创建接收地址时得到的密钥,对「时间戳 + 英文句号 + 原始请求体」计算 HMAC-SHA256。必须使用原始字节,不能先解析 JSON 再序列化。每次投递重新签名。
以下 Node.js 示例返回签名是否有效;requestHeaders 使用小写字段名,rawBody 是解析前的 Buffer,secret 从接收端环境配置读取。
import { createHmac, timingSafeEqual } from 'node:crypto';
function verifyWebhook(requestHeaders, rawBody, secret) {
const timestamp = requestHeaders['x-jisu-timestamp'];
const signature = requestHeaders['x-jisu-signature'];
if (typeof timestamp !== 'string' || !/^[0-9]+$/.test(timestamp)) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
if (typeof signature !== 'string' || !/^v1=[a-f0-9]{64}$/.test(signature)) return false;
const expected = createHmac('sha256', secret)
.update(timestamp + '.').update(rawBody).digest();
return timingSafeEqual(expected, Buffer.from(signature.slice(3), 'hex'));
}
幂等消费
验证签名后,用消息体中的 id 去重并持久化接收结果,再返回 2xx。非 2xx、网络错误或未能确认接收结果会触发重试。同一事件可能重复到达或乱序到达;通过任务查询接口读取当前状态。事件 ID 在自动重试和手动重投中均不改变。平台不保证接收端只收到一次。
投递与重试
每轮最多尝试 8 次,失败后依次等待 30、60、120、240、480、960、1920 秒。实际投递还受 Worker 调度影响。进程中断或两分钟投递租约到期时,该次记录为「结果未知」,按重试规则继续;接收端此时可能已经收到事件。
开发页支持按接收地址和状态筛选、分页、查看累计次数与每次投递的响应或错误。每轮用尽后可手动重投,开启新的一轮;累计次数与已有记录保留。早期版本没有独立尝试记录的历史数据不会补造响应明细。
停用接收地址暂停尚未发出的投递,不影响已经发送的请求;停用期间的新事件不进入该地址队列。启用后恢复待投递队列,已失败事件仍需手动重投。
上游回调
供应商回调属于平台内部处理,不直接作为用户扣款证据。Beatra 与 Kie 回调必须通过令牌与各自的签名验证,再由服务端查询确认结果;不会把用户 Webhook 的密钥用作供应商密钥。
文档