幂等与重试
request_id 是你为一次业务写入生成的唯一请求编号。它解决的是:请求已在平台执行,但你的服务因超时、断线或进程重启没收到结果,再次提交时不应重复创建、重复修改策略时间或重复开启通知轮次。
哪些接口需要
| 接口 | request_id |
|---|---|
POST /open/v1/wallets | 必填,放在 JSON 请求体 |
POST /open/v1/sweeps | 必填,放在 JSON 请求体 |
POST /open/v1/settings/addresses/collection | 必填,设置归集地址 |
POST /open/v1/settings/automation | 必填,设置自动策略 |
POST /open/v1/settings/webhook | 必填,设置回调配置 |
POST /open/v1/webhooks/{id}/redeliver | 必填,开启新的推送轮次 |
POST /open/v1/wallets/selection、/wallets/preview、/sweeps/estimate | 不需要;只读操作 |
| GET 查询接口 | 不需要 |
| 获取 accessToken | 不需要;再次成功获取会替换旧令牌 |
当前开放接口不接受 Idempotency-Key 请求头。也不要把 request_id 放到 URL 查询参数中。
如何生成
使用服务端 UUID,例如:
js
import { randomUUID } from 'node:crypto';
const requestId = randomUUID();
// 首次提交前,把 requestId 与原请求参数一起保存到你的数据库。python
import uuid
request_id = str(uuid.uuid4())
# 首次提交前,把 request_id 与原请求参数一起保存到你的数据库。服务端检查长度为 16~128。建议使用 ASCII 字母、数字、连字符组成的请求编号,标准 UUID 为 36 个字符,符合要求。底层按 UTF-8 字节计数,不要用中文或 emoji 构造临界长度编号。
同一个业务请求,重试保持原编号
json
{
"custom_id": "customer-1001",
"request_id": "85d6621e-720b-45c2-8b59-a6e8a78a3ca1"
}| 再次提交 | 结果 |
|---|---|
| 同一租户、同一接口操作、同一 request_id,业务参数一致 | 返回已保存的原结果 |
| 相同 request_id,修改 custom_id、钱包集合或归集金额等业务参数 | HTTP 409 冲突 |
| request_id 相同但属于另一个租户或另一个业务操作 | 独立记录,不共用结果 |
| 换一个新 request_id | 视为新的业务操作,不能用来“重试”未知结果 |
幂等比对的是解析后的业务参数。JSON 的字段排序和空格不参与该比对;数组顺序仍属于请求内容。签名则针对本次实际 JSON 字节,两者不要混淆。
超时后的正确处理
- 保留原 request_id 和全部业务参数。
- 查询是否已有可确认的业务结果。
- 若需要重新提交,使用当前有效 accessToken、新时间戳和重新计算的签名。
- 请求体仍使用原 request_id 与原业务参数。
重新计算签名不会改变业务请求编号。不要因为 401、429、503 或网络超时就生成另一个 request_id。
js
import { Client } from './client.mjs';
const client = new Client(
process.env.GUIJI_BASE_URL,
process.env.GUIJI_APP_ID,
process.env.GUIJI_APP_SECRET
);
// 该对象应来自你已持久化的原始提交记录。
const original = {
custom_id: 'customer-1001',
request_id: '85d6621e-720b-45c2-8b59-a6e8a78a3ca1'
};
const result = await client.call(
process.env.GUIJI_ACCESS_TOKEN,
'POST', '/open/v1/wallets', {}, original
);
console.log(JSON.stringify(result, null, 2));批量归集要检查逐项结果
创建归集返回的是任务提交结果,HTTP 200 不表示链上转账已经成功。批量请求可能包含不同钱包的成功和失败项,应逐钱包保存返回结果,再通过归集详情和结果通知跟踪。
同 request_id 重试会返回原提交结果,不会重新执行原来失败的项。确认旧请求结果并决定发起一项新的业务操作时,再使用新的 request_id。
幂等与回调去重是两件事
request_id:由你生成,防止重复创建钱包/任务、重复修改配置和重复开启推送轮次。event_id:由平台生成,防止收到同一到账/归集通知时重复处理。
回调的每次尝试和人工重新推送都会保留原 event_id。接收方按 event_id 持久化去重,不按密文、nonce 或推送次数去重。
设置与通知重推
设置或通知重推响应丢失时,保留原 request_id 和业务参数重试,返回原操作结果。不要通过新编号重试同一操作。
相同地址的新操作通常不会递增配置版本,但自动策略重新保存会更新时间边界,重推会创建新轮次。因此不要把新request_id当作网络重试。查询最新配置/最新轮次使用GET,幂等重放始终返回原操作结果。