deposit.credited
链上入金已确认并记进会员可用余额
何时发
Cobo 确认到账、入账凭证过账成功之后(不是收到链上通知那一刻)。
收到它时余额已经能查到了。
⚠ 只覆盖链上入金。你用 POST /v1/deposits 上报的入金不发这条事件 ——
那条接口是同步的,201 返回时钱已经记上了,再发一条事件只是回声。
⚠ status_version 恒为 0(入金没有状态机,只有「已入账」这一态)。
⚠ data.id 是我方入金流水号(纯数字),与 GET /v1/deposits 列表里的
dep_<你的 reference> 不是同一套标识。
这条事件不由任何 API 调用发起
只覆盖链上入金(由 Cobo 回调触发)。你用 POST /v1/deposits 上报的入金不触发这条事件 —— 那条路径不调通知。
事件体
{
"event_id": "evt_9d2b6f4013ae4c78b5910c3e7d84a2f1",
"event_type": "deposit.credited",
"created_at": "2026-08-12T12:44:03Z",
"merchant_id": "acme",
"livemode": true,
"data": {
"object": "deposit",
"id": "184203",
"external_member_id": "u_88123",
"status": "credited",
"status_version": 0
}
}
事件体字段
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 去重用这个。evt_…,同一事件重投时不变。 |
type | string | 固定为 deposit.credited |
created_at | string | 事件产生时刻(RFC3339)。不是投递时刻 —— 重投时它不变。 |
data.object | string | 对象类型,决定 data.id 该拿去查哪个端点 |
data.id | string | 对象 ID,拿它回查详情 |
data.status | string | 认不出的值按未知处理并告警,不要 fallback 成「处理中」 |
data.status_version | number | 单调递增,用它把慢到的旧状态丢掉 |
验签与去重
验签用原始请求体字节,不要先解析再重新序列化 —— 你的 JSON 库与我方的键顺序、空格几乎一定不同,重新序列化出来的签名一定对不上, 而那个错误长得像「密钥配错了」。
// Node · 放在解析 JSON 之前
const raw = await readRawBody(req); // Buffer / string,别用已解析的 req.body
const expect = crypto.createHmac("sha256", WEBHOOK_SECRET).update(raw).digest("hex");
const got = req.headers["z-signature"]; // 形如 t=<unix>,v1=<hex>
if (!timingSafeEqual(expect, parseV1(got))) return res.status(400).end();
// 去重:用信封的 id,不是 data.id
if (await seen(JSON.parse(raw).id)) return res.status(200).end();
完整做法(含时间戳容差与重投语义)见 Webhook 指南。