签名认证
所有 /v1/** 接口都用 HMAC-SHA256 签名认证,没有登录态、没有 token。
请求头
| 请求头 | 说明 |
|---|---|
X-Api-Key | API key |
X-Timestamp | 当前时间,Unix 毫秒。与服务器相差超过 ±30 秒拒绝(REQUEST_EXPIRED) |
X-Nonce | 16–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 |
PATH | URL 路径,不含域名和查询串,按实际发送的(已百分号编码的)形式,如 /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, 待签名串))两个最常见的坑
- 签的 body 必须就是发出去的字节。先把 JSON 序列化成字符串,用这个字符串算哈希并作为请求体发送;不要签一份、HTTP 库再序列化一份。
- 直接把规范化后的查询串作为 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¬e=a%2Bb%21规范化查询串:
text
chain_code=TRON¬e=a%2Bb%21&status=CONFIRMED&status=PENDING&user_id=u%201待签名串:
text
GET
/v1/deposits
chain_code=TRON¬e=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。
鉴权错误
| reason | HTTP | 原因 |
|---|---|---|
MERCHANT_AUTH_FAILED | 401 | 缺少签名请求头、key 不存在或已停用、商户已停用 |
SIGNATURE_INVALID | 401 | 签名不对:对照上面的示例逐段检查待签名串 |
REQUEST_EXPIRED | 401 | 时间戳缺失、不是毫秒、或与服务器相差超过 30 秒(检查服务器时钟 / NTP) |
NONCE_REPLAYED | 401 | nonce 重复,或长度不在 16–64 |
IP_NOT_ALLOWED | 403 | 来源 IP 不在白名单 |
PERMISSION_DENIED | 403 | key 没有接口需要的权限范围 |