开发者文档

API 工作区
https://api.rentron.xyz/v1
OpenAPI 架构

身份验证

// DOC

生产 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…),服务端据此得到的规范化内容与你的不同,签名会被拒绝。每个 GETDELETE 以及不带请求体发送的 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