Skip to content

签名认证 ​

所有 /v1/** 接口都用 HMAC-SHA256 签名认证,没有登录态、没有 token。

请求头 ​

请求头说明
X-Api-KeyAPI key
X-Timestamp当前时间,Unix 毫秒。与服务器相差超过 ±30 秒拒绝(REQUEST_EXPIRED)
X-Nonce16–64 位随机串,同一个 key 5 分钟内不能重复(NONCE_REPLAYED)。建议 16 字节随机数的 hex
X-Signature签名,见下文,hex 小写
Content-Type有请求体时为 application/json

待签名串 ​

用 \n(换行,0x0A)把 6 段连起来,末尾没有换行:

text
METHOD
PATH
CANONICAL_QUERY
TIMESTAMP
NONCE
hex(sha256(BODY))
段规则
METHOD大写,如 GET、POST
PATHURL 路径,不含域名和查询串,按实际发送的(已百分号编码的)形式,如 /v1/wallets/u_10001/addresses
CANONICAL_QUERY查询参数规范化:按 key 排序,同 key 按 value 排序;key 与 value 按 RFC 3986 编码(只保留 A-Z a-z 0-9 - _ . ~,空格编码为 %20 而不是 +);用 & 连接。没有查询参数时为空串
TIMESTAMP与 X-Timestamp 相同
NONCE与 X-Nonce 相同
hex(sha256(BODY))请求体原始字节的 SHA-256,hex 小写。没有请求体(如 GET)时是空串的哈希 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
text
X-Signature = hex(HMAC-SHA256(API secret, 待签名串))

两个最常见的坑

  1. 签的 body 必须就是发出去的字节。先把 JSON 序列化成字符串,用这个字符串算哈希并作为请求体发送;不要签一份、HTTP 库再序列化一份。
  2. 直接把规范化后的查询串作为 URL 的查询部分发送,就不会出现「签的和发的顺序 / 编码不一致」。

示例 ​

API secret 为 test-secret,X-Timestamp: 1762650000000,X-Nonce: 0123456789abcdef0123:

http
GET /v1/deposits?user_id=u%201&chain_code=TRON&status=PENDING&status=CONFIRMED&note=a%2Bb%21

规范化查询串:

text
chain_code=TRON&note=a%2Bb%21&status=CONFIRMED&status=PENDING&user_id=u%201

待签名串:

text
GET
/v1/deposits
chain_code=TRON&note=a%2Bb%21&status=CONFIRMED&status=PENDING&user_id=u%201
1762650000000
0123456789abcdef0123
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

签名:d474bb4c8ff89a37f214d8c39c3d17a502d54b64c1822024a86480c248bcbc86

带请求体(POST /v1/withdraws,同样的时间戳和 nonce):

json
{"user_id":"u1","chain_code":"TRON","token_code":"USDT","to_address":"TXYZ","amount":"12.5","biz_id":"order-1"}

签名:381b9e20fc9b2e0cd97ecb003686acd472db596757b674e56df9e038d708867c

用这两组数据可以校验自己的实现。

权限范围与 IP 白名单 ​

每个 API key 有权限范围,接口需要的范围写在 接口参考 里:

范围能做什么
read所有查询接口、重发事件
deposit创建充值地址、补单
withdraw发起提现

缺少范围返回 PERMISSION_DENIED;请求来源 IP 不在 key 的白名单里返回 IP_NOT_ALLOWED。建议发起提现用单独的 withdraw key,并只放行服务器出口 IP。

鉴权错误 ​

reasonHTTP原因
MERCHANT_AUTH_FAILED401缺少签名请求头、key 不存在或已停用、商户已停用
SIGNATURE_INVALID401签名不对:对照上面的示例逐段检查待签名串
REQUEST_EXPIRED401时间戳缺失、不是毫秒、或与服务器相差超过 30 秒(检查服务器时钟 / NTP)
NONCE_REPLAYED401nonce 重复,或长度不在 16–64
IP_NOT_ALLOWED403来源 IP 不在白名单
PERMISSION_DENIED403key 没有接口需要的权限范围