生产 API
HMAC 身份验证
精确的请求头、规范化请求内容和稳定的 HMAC-SHA256 测试向量。
本页内容
除 GET /v1/time 外,所有接口都需要 HMAC-SHA256。API 签名密钥不会随请求发送,只用于签署规范化请求内容。
必需请求头
Authorization: HMAC-SHA256 {api_key}:{base64_signature}
X-Request-Timestamp: {unix_seconds}
带请求体的调用还需要 Content-Type: application/json。
规范化请求内容
{timestamp}\n{METHOD}\n{path}\n{query}\n{bodyHash}
规则如下:
METHOD使用大写;path只包含请求路径,例如/v1/energy/orders;query是实际发送的完整查询字符串,包含开头的?;没有查询时为空;bodyHash是对原始 UTF-8 字节计算出的 SHA-256 摘要的小写十六进制值;请求没有请求体时,它是空字符串;- 签名完成后不要重新序列化 JSON。
没有请求体的请求,最后一段签名为空。 不要对空字符串求哈希:SHA-256("") 是一个固定的非空摘要(e3b0c442…),服务端据此得到的规范化内容与你的不同,签名会被拒绝。每个 GET、DELETE 以及不带请求体发送的 POST 都适用此规则。
因此 GET /v1/balance 签名的正是下面这串——五个字段,最后一个为空,字符串以换行结尾:
1784376000\nGET\n/v1/balance\n\n
签名为 base64(HMAC-SHA256(api_secret, canonical_payload))。
Node.js 示例
import crypto from 'node:crypto';
export function sign(secret, timestamp, method, path, query = '', body = '') {
const bodyHash = body
? crypto.createHash('sha256').update(Buffer.from(body, 'utf8')).digest('hex')
: '';
const canonical = `${timestamp}\n${method.toUpperCase()}\n${path}\n${query}\n${bodyHash}`;
return crypto.createHmac('sha256', secret).update(canonical, 'utf8').digest('base64');
}
稳定测试向量
使用时间戳 1784376000 和秘密 rtn_sk_live_0123456789abcdefghijklmnopqrstuvwxyzABCDEFG。
| 请求 | 预期签名 |
|---|---|
GET /v1/balance |
MAcY78Aad0bL9LGIJGMHR4plQ9jZH3TPUrYEJIMnSFY= |
使用下方请求体的 POST /v1/energy/orders |
4+nngnu7C6PVGfCs3zPJ34PWylIZdkdNSw8wmoywnTk= |
{"client_request_id":"order-1042","address":"TJRabPrwbZy45sbavfcjinPJC18kjpRTv8","energy":65000,"duration_minutes":60,"expected_total_trx":"3.200000"}
若测试向量不匹配,请先修正序列化、查询处理或换行符,再发送正式请求。
身份验证失败
无效的认证方案、密钥、签名、时间戳或 IP 允许列表会按错误格式返回 401。连续失败可能得到 429;请遵守 Retry-After。
Rentron