跳到主要内容

确认回调

确认回调是 Gregor 服务器在有人确认提醒时向你的服务发出的 HTTPS 请求。可以用它关闭事件单、停止升级流程或记录由谁接手,而不必轮询回执。

是否发送回调由确认的人决定。回调永远不会从对方的设备上发出。

回调按频道配置,由频道所有者或管理员设置。

  1. 在频道页打开频道的发送链接。
  2. 在确认回调下选择配置回调。
  3. 填写回调 URL。必须是公网可访问的 https 地址,固定查询参数会被保留。
  4. 保存后,这里会显示回调已启用和回调签名密钥。
  5. 选择查看密钥,复制密钥并存入你的服务的密钥存储。不要放进脚本、日志或客户端。

在提醒中加上 "callback": true。提醒必须是可以确认的,即 urgent、设置了 require_ack 或设置了 receipt;其他提醒带上回调后会变为需要确认。

终端窗口
curl -X POST "$SEND_URL" \
-H 'Content-Type: application/json' \
-d '{"alert": {"title": "数据库不可用"}, "level": "urgent", "callback": true}'

如果频道没有启用回调,请求会以 callback_not_configured 拒绝,不会接受一个永远不会触发的回调。

有人确认提醒时,应用会询问:仅确认,还是确认并发送回调。只有第一次确认有效,之后在其他设备上再确认不会改变结果。

POST /talaria/ack HTTP/1.1
Content-Type: application/json
User-Agent: Receipt-Callback/1
X-Webhook-Event-Id: cb1…
X-Webhook-Key-Id: ck1…
X-Webhook-Timestamp: 1792311330
X-Webhook-Attempt: 1
X-Webhook-Signature: v1=5d41402abc4b2a76b9719d911017c592…
{
"event_id": "cb1…",
"type": "receipt.acknowledged",
"occurred_at": "2026-10-27T08:15:30Z",
"channel_id": "ch1…",
"receipt_id": "rcp_9a02…",
"message_id": "msg_4f1c…",
"status": "acked",
"acknowledged": true,
"acknowledged_at": "2026-10-27T08:15:30Z",
"acknowledged_by": { "user_id": "…", "device_address": "dv1…" }
}

请求体不包含提醒的标题、正文或 payload。请用 message_id 或 receipt_id 对应到你自己的记录。

在信任一个回调之前:

  1. 按 X-Webhook-Key-Id 找到对应的密钥。
  2. 如果 X-Webhook-Timestamp 与你的时钟相差超过五分钟,拒绝它。
  3. 用从应用中复制的原样密钥,对 timestamp + "." + 原始请求体 计算 HMAC-SHA256,并与 v1= 之后的十六进制值做常量时间比较。
  4. 忽略已经处理过的 X-Webhook-Event-Id。
  5. 事件保存好之后,再返回任意 2xx 状态码。
import hashlib, hmac, time
def verify(headers, raw_body: bytes, key: str) -> bool:
timestamp = headers["X-Webhook-Timestamp"]
if abs(time.time() - int(timestamp)) > 300:
return False
expected = hmac.new(key.encode(), f"{timestamp}.".encode() + raw_body, hashlib.sha256).hexdigest()
received = headers["X-Webhook-Signature"].removeprefix("v1=")
return hmac.compare_digest(expected, received)

请在解析 JSON 之前,对收到的原始字节计算签名。

投递至少一次,同一个事件可能到达多次,请按事件 ID 去重。

  • 网络错误、超时、408、429 和 5xx 响应会重试:第一次重试在一分钟后,之后间隔逐渐加长,最长一小时。会遵守 Retry-After 响应头。
  • 其他 4xx 响应会停止重试,因为这通常说明接收端配置有误。
  • 确认 24 小时后停止重试。

回执中会显示回调的 status、attempt_count 和 delivered_at。

  • 轮换密钥会生成新的签名密钥。新的回调立即使用新密钥;已排队的回调仍使用创建时的密钥,旧密钥在 24 小时内继续有效。请在这段时间内把新密钥部署到你的服务,并按 X-Webhook-Key-Id 选择密钥。
  • 停用回调后,新提醒不能再请求回调。已排队的回调仍会投递。