CodeBoxCodeBox 文档

Webhooks

通过 Webhooks 实时接收二维码扫描、过期等事件通知

概述

Webhooks 让你的服务实时接收二维码相关事件通知。当事件发生时,CodeBox 会向你配置的 URL 发送 HTTP POST 请求,携带事件详情。

Webhook 地址必须使用 HTTPS 且解析到公网 IP。系统会拒绝 localhost、内网、链路本地、云主机 metadata 和其他保留地址,并对重定向后的每个目标重新检查。

事件类型

事件说明触发时机
scan.created二维码被扫描用户扫描动态二维码时触发
qrcode.expired二维码已过期二维码到达过期时间时触发

Payload 格式

所有 Webhook 请求使用 POST 方法,Content-Typeapplication/json

scan.created

{
  "event": "scan.created",
  "timestamp": "2026-03-10T08:30:00.000Z",
  "data": {
    "qrCodeId": "clxxx...",
    "scanId": "evt_xxx...",
    "eventType": "impression",
    "ip": "203.0.113.1",
    "device": "mobile",
    "browser": "Chrome",
    "os": "iOS",
    "country": "CN",
    "region": "Shanghai",
    "city": "Shanghai"
  }
}

qrcode.expired

{
  "event": "qrcode.expired",
  "timestamp": "2026-03-10T00:00:00.000Z",
  "data": {
    "qrCodeId": "clxxx...",
    "name": "营销活动码",
    "expiresAt": "2026-03-10T00:00:00.000Z"
  }
}

签名验证

每个 Webhook 请求包含 X-Webhook-SignatureX-Webhook-Timestamp Header。签名覆盖时间戳和原始请求体,接收方还应拒绝时间戳过旧的请求以防重放。

签名生成规则:

HMAC-SHA256(webhook_secret, timestamp + "." + payload)

Node.js 验证示例:

import crypto from 'crypto';

function verifyWebhookSignature(
  payload: string,
  timestamp: string,
  signature: string,
  secret: string
): boolean {
  const signedPayload = `${timestamp}.${payload}`;
  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex');

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express 中间件示例
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.headers['x-webhook-signature'] as string;
  const timestamp = req.headers['x-webhook-timestamp'] as string;
  const payload = req.body.toString();

  if (!verifyWebhookSignature(payload, timestamp, signature, process.env.WEBHOOK_SECRET!)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(payload);
  console.log(`收到事件: ${event.event}`);

  // 处理事件...

  res.status(200).send('OK');
});

务必使用 crypto.timingSafeEqual 进行签名比较,避免时序攻击。

重试策略

如果你的端点返回非 2xx 状态码,CodeBox 会自动重试:

重试次数延迟
第 1 次1 秒
第 2 次4 秒
第 3 次16 秒

共重试 3 次,采用指数退避策略。3 次重试均失败后,该事件将被丢弃。

确保你的 Webhook 端点在 10 秒内响应,超时将视为失败并触发重试。

管理 Webhooks

通过 Dashboard

Dashboard → API 管理 页面中,可以:

  • 创建新的 Webhook 端点
  • 在创建响应中查看并立即保存 Webhook Secret
  • 启用或禁用特定事件

通过 API

Webhook 管理接口使用 Session 认证(需登录状态)。

端点方法说明
/api/v1/webhooksPOST创建 Webhook
/api/v1/webhooksGET获取列表
/api/v1/webhooks/:idGET获取详情
/api/v1/webhooks/:idPATCH更新
/api/v1/webhooks/:idDELETE删除

创建请求体:

{
  "url": "https://your-server.com/webhook",
  "events": ["scan.created", "qrcode.expired"]
}

创建响应:

{
  "success": true,
  "data": {
    "id": "...",
    "url": "https://your-server.com/webhook",
    "events": ["scan.created", "qrcode.expired"],
    "secret": "whsec_xxxxxxxxxxxxxxxx",
    "status": "ACTIVE"
  }
}

创建时返回的 secret 仅显示一次,请立即保存。用于验证后续收到的 Webhook 请求签名。

On this page