Skip to content

幂等与重试

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 字节,两者不要混淆。

超时后的正确处理

  1. 保留原 request_id 和全部业务参数。
  2. 查询是否已有可确认的业务结果。
  3. 若需要重新提交,使用当前有效 accessToken、新时间戳和重新计算的签名。
  4. 请求体仍使用原 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));

下载运行该示例所需的 client.mjs

批量归集要检查逐项结果

创建归集返回的是任务提交结果,HTTP 200 不表示链上转账已经成功。批量请求可能包含不同钱包的成功和失败项,应逐钱包保存返回结果,再通过归集详情和结果通知跟踪。

同 request_id 重试会返回原提交结果,不会重新执行原来失败的项。确认旧请求结果并决定发起一项新的业务操作时,再使用新的 request_id。

幂等与回调去重是两件事

  • request_id:由你生成,防止重复创建钱包/任务、重复修改配置和重复开启推送轮次。
  • event_id:由平台生成,防止收到同一到账/归集通知时重复处理。

回调的每次尝试和人工重新推送都会保留原 event_id。接收方按 event_id 持久化去重,不按密文、nonce 或推送次数去重。

设置与通知重推

设置或通知重推响应丢失时,保留原 request_id 和业务参数重试,返回原操作结果。不要通过新编号重试同一操作。

相同地址的新操作通常不会递增配置版本,但自动策略重新保存会更新时间边界,重推会创建新轮次。因此不要把新request_id当作网络重试。查询最新配置/最新轮次使用GET,幂等重放始终返回原操作结果。