错误码与排查
程序判断 error_code,开发者查看 message,平台用 trace_id 定位日志。 不要解析错误文案,不要看到401就循环获取令牌。
统一响应
json
{
"code": 401,
"error_code": "INVALID_SIGNATURE",
"message": "request signature verification failed",
"trace_id": "0123456789abcdef0123456789abcdef"
}| 字段 | 类型 | 含义 |
|---|---|---|
| code | integer | 与 HTTP 状态相同;成功为0 |
| error_code | string | 稳定的错误分类,见下表 |
| message | string | 本次失败说明,参数错误通常指出字段;内容可能细化,不作为枚举 |
| trace_id | string | 本次 HTTP 请求追踪编号,与响应头 X-Trace-Id 相同 |
错误没有 data。trace_id 由平台自动生成,你无需传入;它不同于写操作的 request_id。合法业务请求的404/405也使用此 JSON 格式。反向代理、网关或断网仍可能产生非 JSON 响应,客户端不能把解析失败当作成功。
错误码和下一步
| HTTP | error_code | 含义 | 接入方处理 |
|---|---|---|---|
| 400 | INVALID_ARGUMENT | 业务字段、JSON、路径、类型或格式错误 | 按 message 和接口参数表修改,重新签名 |
| 400 | COLLECTION_ADDRESS_MANAGED | 归集目标是平台内的钱包,可能造成循环归集 | 换成由你控制的平台外 TRON 地址后重新签名;当前租户和其他租户的钱包均禁止,不要原样重试 |
| 400 | INVALID_AUTH_HEADER | 认证头缺失或重复 | 每个认证头只发送一次;不要重复附加 |
| 401 | INVALID_SIGNATURE | 请求签名不匹配,或 appID/密钥组合无效 | 检查密钥和签名输入;不要刷新令牌掩盖签名错误 |
| 401 | TIMESTAMP_OUT_OF_RANGE | 时间戳与服务器相差超过300秒 | 校准服务端时间,使用当前秒级时间戳重新签名 |
| 401 | TOKEN_INVALID_OR_EXPIRED | 令牌缺失、过期、被替换、撤销或与当前 appID 不匹配 | 先读共享缓存中的最新令牌;必要时由单一刷新流程获取 |
| 403 | TENANT_UNAVAILABLE | 租户停用、删除或到期 | 联系平台处理租户状态,停止重试 |
| 404 | RESOURCE_NOT_FOUND | 当前租户下没有该对象 | 检查 ID、所属账户及所用的 API 域名;不会透露其他租户资源 |
| 404 | ROUTE_NOT_FOUND | 接口地址不存在 | 使用平台提供的 API 域名及 /open/v1 路径,核对接口目录 |
| 405 | METHOD_NOT_ALLOWED | HTTP 方法错误 | 按接口页使用 GET 或 POST |
| 409 | IDEMPOTENCY_CONFLICT | 同一 request_id 已用于不同业务参数 | 找回原请求;重试用原编号和原参数,新业务才用新编号 |
| 409 | BUSINESS_CONFLICT | 当前状态不允许操作或记录已存在 | 查看 message,先查询当前状态,再决定是否发起新业务 |
| 413 | PAYLOAD_TOO_LARGE | 请求体超过1 MiB | 减小批次;不要把同一请求拆分后继续复用旧编号 |
| 429 | RATE_LIMITED | 获取令牌或业务请求超过限频 | 按 Retry-After 指定的秒数等待,再重新签名 |
| 503 | SERVICE_BUSY | 服务并发已满 | 按 Retry-After 等待,减少并行请求 |
| 503 | SERVICE_UNAVAILABLE | 当前业务依赖不可用 | 保存错误,稍后查询状态;必要时提供 trace_id 给平台 |
| 504 | REQUEST_TIMEOUT | 服务器处理超时,写入结果可能未知 | 先查询结果;重试必须保持原 request_id 和参数 |
| 500 | INTERNAL_ERROR | 内部操作失败 | 保存 trace_id 和请求时间;不要改编号重复发起支出 |
批量接口的 HTTP200/code0 不代表每项都成功。查看 items[].status 和 reason。任务的 failed 与 HTTP 请求错误是两层结果,详见状态与处理。
签名错误
按顺序检查:
- appID 和密钥是否属于同一租户,是否刚重置过密钥。
- 使用 HMAC-SHA256,输出64位小写十六进制。
- 方法使用大写;路径完整包含 /open/v1,不包含域名、查询串或末尾斜杠。
- 七行末尾均为 LF,最后一行也有 LF;不是 CRLF 或两个字符的反斜杠 n。
- 签名使用的 token 原文与 Authorization 中一致,不把 Bearer 放进签名。
- 查询串键排序,空格用 %20,加号用 %2B;请求体只序列化一次。
- secret 按 UTF-8 使用,不做 hex 解码;空请求体按空字节做 SHA-256。
先运行离线测试。不要上传密钥、完整 token 或签名原文;trace_id 足以协助平台查日志。
令牌问题
新令牌立即撤销旧令牌。若多个服务同时获取令牌,它们会互相使令牌失效。统一缓存并使用互斥锁刷新;收到 TOKEN_INVALID_OR_EXPIRED 时,先确认共享缓存是否已有更新值。
签名错误和时间错误不需要重新申请 token。修正问题后重新生成当前请求签名即可。SDK 不自动刷新或重新执行资金操作,避免重复支出。
写操作超时如何处理
没有收到成功响应,并不能证明写入失败。保留原 request_id 和业务参数,先查已有结果;需要重试时只更新 token、时间戳和签名,业务编号与内容不变。返回过的批量受理结果会按原样重放,查询任务详情才能获得最新状态。
限频和响应头
| 范围 | 当前规则 |
|---|---|
| 获取令牌,同一IP | 60次 / 300秒 |
| 获取令牌,同一appID | 20次 / 300秒 |
| 业务请求,同一租户 | 600次 / 60秒 |
| 请求繁忙 | 收到 SERVICE_BUSY 时按 Retry-After 等待,并减少并行请求 |
429携带 Retry-After。并发限制触发的 SERVICE_BUSY 也携带 Retry-After;不是所有503都会带此头。
示例客户端的错误属性
Node.js ApiError 提供 status、errorCode、traceId、retryAfter、response;Python 对应 status、error_code、trace_id、retry_after、response。
js
import { Client, ApiError } from './client.mjs';
const client = new Client(
process.env.GUIJI_BASE_URL,
process.env.GUIJI_APP_ID,
process.env.GUIJI_APP_SECRET
);
try {
const data = await client.call(
process.env.GUIJI_ACCESS_TOKEN, 'GET', '/open/v1/wallets',
{ page: '1', page_size: '20' }, null
);
console.log(JSON.stringify(data, null, 2));
} catch (error) {
if (error instanceof ApiError) {
console.error({
http: error.status, error_code: error.errorCode,
message: error.message, trace_id: error.traceId,
retry_after: error.retryAfter
});
} else {
console.error('请求未取得结果,请保留原业务编号并先查询状态。');
}
}仍无法解决时提供什么
提供:trace_id、请求时间及所在时区、HTTP方法、接口路径、HTTP状态和完整错误响应。写操作另提供 request_id、相关钱包或任务ID。不要提供密钥或 token。