本页内容
Webhook
接收文件转换和 Token 生命周期事件,并使用 HMAC-SHA256 验证每次投递。
启用方式
登录客户中心,在“API Key”页面填写公网可访问的 HTTPS webhook_url 并保存;也可由管理员在总后台配置。Webhook 投递不消耗预览额度,接收端应在 5 秒内返回 2xx。
事件
| 事件 | 触发条件 | 主要 data 字段 |
|---|---|---|
conversion.ready | 文件转换完成 | job_id、token、title、source_extension、status、output_extension |
conversion.failed | 文件转换失败 | job_id、token、title、source_extension、status、error_code |
token.revoked | 单个 Token 被撤销 | token、src、title |
token.batch_revoked | 批量撤销 Token | count、tokens(每项包含 token、src、title) |
token.expired | Token 到达有效期 | token、src、title、expire_at |
token.max_views | 访问次数达到上限 | token、src、title、max_views、view_count |
请求合同
| Header | 说明 |
|---|---|
X-Djm-Event | 事件类型 |
X-Djm-Delivery | 本次投递的唯一 ID,用于幂等 |
X-Djm-Timestamp | Unix 秒级时间戳 |
X-Djm-Signature | sha256=<HMAC hex> |
json
{
"id":"0123456789abcdef0123456789abcdef",
"event":"conversion.ready",
"occurred_at":"2026-08-03T10:00:00+08:00",
"api_key_id":5,
"data":{
"job_id":"abcdef0123456789abcdef0123456789",
"token":"preview_token",
"title":"季度报告",
"source_extension":"docx",
"status":"ready",
"output_extension":"pdf"
}
}验签
签名为 sha256=<hex>,计算方式是 HMAC-SHA256(api_secret, raw_body)。必须使用收到的原始 Body,不要先解析再重新序列化 JSON。
php
$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $apiSecret);
if (!hash_equals($expected, $_SERVER['HTTP_X_DJM_SIGNATURE'])) {
http_response_code(401); exit;
}javascript
const raw = request.rawBody;
const expected = 'sha256=' + crypto.createHmac('sha256', apiSecret).update(raw).digest('hex');
const valid = expected.length === signature.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));python
raw = request.get_data(cache=False)
expected = 'sha256=' + hmac.new(api_secret.encode(), raw, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers['X-Djm-Signature']):
abort(401)go
func Verify(rawBody []byte, signature, secret string) bool {
if !strings.HasPrefix(signature, "sha256=") { return false }
received, err := hex.DecodeString(strings.TrimPrefix(signature, "sha256="))
if err != nil { return false }
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(rawBody)
return hmac.Equal(received, mac.Sum(nil))
}幂等处理
- 读取原始 Body 并验证签名。
- 校验
X-Djm-Timestamp与当前时间相差不超过 300 秒。 - 以
X-Djm-Delivery唯一插入事件表;重复键直接返回 204。 - 持久化后立即返回 204,耗时业务放入自己的异步队列。
重试规则
最多 8 次,时间为:立即、1 分钟、5 分钟、30 分钟、2 小时、8 小时、24 小时、72 小时。
网络错误以及 HTTP 408、425、429、5xx 会重试;其他 4xx 视为永久失败。目标必须解析到公网地址,逐跳重定向也会重新校验,响应读取上限为 64 KiB。