# Webhook 接入

Webhook 把组织业务变化发送到你的 HTTPS 接收端。回调只携带必要的资源 ID 和状态，具体记录由 API 按组织权限读取。

## 配置流程

1. 部署一个公网 HTTPS 接收端，仅使用默认 443 端口。
2. 在个人中心 **API & Webhooks → 添加回调** 中选择组织、名称、地址和事件。
3. 验证账号密码和已启用的 2FA。保存只显示一次的 `whsec_...` 签名密钥。
4. 将密钥放进接收端服务端环境变量，部署下述验证处理逻辑。
5. 点击 **验证并启用**。平台发送 `webhook.verification`；接收端先验签，再原样返回挑战值。
6. 验证通过后才开始投递新的业务事件。使用“发送测试”确认你的日志和告警链路。

每账号和每组织各最多 10 个未停用的回调，组织额度由所有管理员共享。每个回调只绑定一个组织；只能由该组织的实际管理员创建。停止或轮换时，创建并验证新回调，更新接收配置，再停用旧回调。创建、验证、测试与重发还受[操作频率限制](/conventions/)约束。

## 地址限制

只允许完整 HTTPS 域名地址，禁止 HTTP、非 443 端口、IP 字面量、用户名/密码、URL 片段、本地及保留域名、本站域名。每次验证和投递均重新检查 DNS 的公网地址；回调不会跟随 HTTP 重定向，也不会转发站点 Cookie、API Key 或内部服务凭证。

第三方机器人平台的普通消息 Webhook 往往不支持本协议的挑战和验签；请先部署你自己的接收服务，再由它调用机器人平台。

## 请求头与签名

```http
Content-Type: application/json
User-Agent: Screenshare-Webhooks/1.0
X-Screenshare-Event-Id: evt_EXAMPLE
X-Screenshare-Timestamp: 1790305200
X-Screenshare-Signature: v1=<64位小写十六进制HMAC>
```

签名算法是 HMAC-SHA256。密钥是创建时显示的**完整 `whsec_...` 字符串的 UTF-8 字节**，不要去掉前缀，不要把后面的十六进制字符先解码成二进制。

签名输入：

```text
timestamp + "." + 原始HTTP请求体字节
```

接收端应：

1. 限制请求体大小，例如 64 KiB。
2. 读取原始 body，在 JSON 解析或重新序列化之前计算签名。
3. 校验时间戳为整数 Unix 秒，建议允许与当前时钟相差不超过 300 秒。
4. 对十六进制签名进行固定长度校验后，使用恒定时间比较。
5. 解析 JSON，确认 body.id 等于 `X-Screenshare-Event-Id`，partner_id 与此接收配置一致。
6. 按事件 ID 持久化去重，处理成功或可靠入队后返回 2xx。

重试会保留相同事件 ID 和业务载荷，时间戳和签名会重新生成。不要用签名作为业务去重键。

## 验证接收端

```json
{
  "id":"evt_EXAMPLE",
  "type":"webhook.verification",
  "api_version":"v1",
  "partner_id":"ORGANIZATION_ID",
  "created_at":"2026-09-25T03:00:00.000Z",
  "data":{"challenge":"RANDOM_CHALLENGE"}
}
```

先完成正常验签，再返回 HTTP 200 和如下 JSON，响应不超过 1024 字节：

```json
{"challenge":"RANDOM_CHALLENGE"}
```

仅返回 200 而没有正确挑战值不会启用回调。`webhook.test` 不需要回显挑战，验签后返回 2xx 即可。

## 重试、重发与顺序

业务事件持久化后进入投递队列，后台约每分钟处理。每次 HTTP 投递超时为 8 秒。任何非 2xx（包括 3xx）和连接错误都会视为失败。

最多自动尝试 8 次。前七次失败后分别等待至少 1 分钟、5 分钟、15 分钟、1 小时、3 小时、6 小时、12 小时，再进行下一次尝试。实际时间受调度和队列负载影响。

最终失败后，可在个人中心的“投递记录”手动重发。已送达事件也可重发；因此必须正确处理重复事件。不同事件不保证按业务发生顺序送达，同一事件可能因确认丢失而再次投递。

每条投递每日最多手动重发 3 次；账号和组织也有共享重发限制。后台每轮最多启动 10 次业务投递，并发最多 3 个，失败只按上述有限次数退避，防止失效接收端和重复点击放大外发流量。

推荐先把事件 ID 和载荷写入你自己的数据库或可靠队列，提交成功后立即响应，再异步执行耗时业务。不要先返回 200 再仅保存在进程内存中。

## 日志与权限

界面显示最近 50 条业务投递，包括事件 ID、状态、尝试次数和 HTTP 结果。验证和测试不计入业务投递列表。业务投递及 API 调用日志按 30 天保留策略清理。

每次投递会重新检查创建账号、组织状态和当前管理员成员资格。失权或停用后，尚未发送的投递会取消；已经到达接收端的数据无法撤回，正在发送的请求也可能先于撤销完成。

Webhook 适合及时通知，不能代替定期 API 核对。外部工单存储与事件入队是不同服务，极端中断或最终失败时仍可能遗漏通知；接收方应保留低频的状态核对任务。
