GEO Source Tracker Webhook API

SOURCE EVENT INTEGRATION · V1

Webhook API 文档

业务系统在用户注册、充值或支付完成后调用此接口。服务可使用本地 SQLite 中的 click_id 将转化事件关联到来源访问。

POST/webhooks/events

接入流程

  1. GEO 在本地 SQLite 中为每次访问生成 click_id,但不会把它附加到目标 URL。
  2. 业务方如通过其他受控机制取得该值,可沿用到注册、充值和支付记录。
  3. 业务事件完成后,使用双方共享的签名密钥调用 Webhook。
  4. 收到 202200 即可停止重试。

未知但格式正确的 click_id 仍会接收,响应中的 matched_clickfalse,便于排查归因链路。

请求字段

字段类型说明
event_idstring事件唯一 ID,最长 128 字符;用于幂等。
event_typeenumuser.registeredwallet.rechargedorder.paid
occurred_atdate-time事件实际发生时间,必须包含时区。
click_idUUIDGEO 本地访问记录中的归因 ID;不会通过目标 URL 传递。
user_idstring外部业务系统用户 ID,最长 128 字符。
dataobject可选业务字段,例如订单号、金额和币种;不得放入密码或访问令牌。
{
  "event_id": "evt_01J5EXAMPLE",
  "event_type": "user.registered",
  "occurred_at": "2026-08-20T10:00:00.000Z",
  "click_id": "0f62d3c3-38c2-4db5-8451-8db1cabb2f0d",
  "user_id": "user_12345",
  "data": { "registration_source": "web" }
}

签名规则

请求必须包含 X-GEO-TimestampX-GEO-Signature。签名输入是时间戳、英文句点和未经重新格式化的原始请求体:

signed_payload = timestamp + "." + raw_body
signature = "v1=" + hex(HMAC-SHA256(WEBHOOK_SIGNING_SECRET, signed_payload))

服务采用常量时间比较,并拒绝与服务器时间相差超过 300 秒的请求。

Node.js 调用示例

import { createHmac } from 'node:crypto';

const secret = process.env.WEBHOOK_SIGNING_SECRET;
const timestamp = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify(event);
const signature = 'v1=' + createHmac('sha256', secret)
  .update(timestamp + '.')
  .update(body)
  .digest('hex');

const webhookUrl = new URL('/webhooks/events', process.env.GEO_BASE_URL);
const response = await fetch(webhookUrl, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-GEO-Timestamp': timestamp,
    'X-GEO-Signature': signature
  },
  body
});

响应与重试

{ "status": "accepted", "event_id": "evt_01J5EXAMPLE", "matched_click": true }
状态含义与处理
202新事件已保存,不要重试。
200同一事件已保存,幂等成功,不要重试。
400/401/409/413/415/426请求需要修正,不应原样重试。
5xx使用指数退避重试;复用同一个 event_id

同一个 event_id 携带不同内容会返回 409。请勿为重试生成新的事件 ID。

安全约束

  • 生产环境仅接受 HTTPS。
  • 签名密钥至少 32 字符,不得与管理员密码或访客 HMAC 密钥复用。
  • 请求体最大 64 KiB,顶层不接受未定义字段。
  • 服务不会记录原始 IP;事件数据写入同一 SQLite 持久化卷。