DEVELOPER DOCUMENTATION · API V1

从签名到入账,
每一步都有明确答案。

本文档覆盖平台鉴权、充值地址、提现订单和 Webhook 验签。示例 Base URL 为 https://wallet.example.com

REST / JSONHMAC-SHA256USDT · 6 DECIMALS

01 · QUICKSTART

快速开始

管理员先在后台创建接入平台并配置 HTTPS 回调地址。系统会一次性返回App IDAPI SecretWebhook Secret

密钥只显示一次

立即保存至 Secret Manager。不要写入代码仓库、日志、浏览器或客户端应用。

1创建平台配置回调 URL
2保存密钥服务端安全存储
3导入地址TRON 公开地址池
4发送请求携带 HMAC 签名

02 · AUTHENTICATION

请求鉴权

所有 /v1/* 请求必须携带以下四个请求头:

X-App-Id平台 App ID
X-TimestampUnix 秒级时间戳,允许前后 300 秒
X-Nonce每个请求唯一的随机字符串
X-Signature64 位小写十六进制 HMAC 签名

待签名字符串

{timestamp}\n{nonce}\n{HTTP_METHOD}\n{path_with_query}\n{sha256(raw_body)}

最终签名为 hex(HMAC-SHA256(api_secret, canonical_request))。 GET 请求体是空字节;存在查询参数时必须按实际发送顺序签入。

Python 示例

import hashlib, hmac, json, secrets, time

method = "POST"
path = "/v1/deposit-addresses"
body = json.dumps(
    {"external_user_id": "user-10001"},
    separators=(",", ":"),
).encode()
timestamp = str(int(time.time()))
nonce = secrets.token_hex(16)

canonical = "\n".join([
    timestamp,
    nonce,
    method,
    path,
    hashlib.sha256(body).hexdigest(),
])
signature = hmac.new(
    API_SECRET.encode(),
    canonical.encode(),
    hashlib.sha256,
).hexdigest()
原始字节必须一致

签名完成后不要重新格式化 JSON,也不要重新排序或编码查询参数。

03 · DEPOSITS

充值接口

POST/v1/deposit-addresses

为平台用户获取固定充值地址。同一平台、同一用户重复请求会返回同一地址。

POST /v1/deposit-addresses
Content-Type: application/json
X-App-Id: app_xxx
X-Timestamp: 1785388800
X-Nonce: 9f21e8...
X-Signature: 6dc70e...

{
  "external_user_id": "user-10001"
}
200 RESPONSE
{
  "external_user_id": "user-10001",
  "network": "TRON",
  "asset": "USDT",
  "address": "T..."
}
GET/v1/deposits

按用户 ID 或交易哈希查询充值列表,最多返回 200 条。

GET/v1/deposits/{deposit_id}

按网关系统充值 ID 查询单笔确认记录。

何时入账?

仅在收到 deposit.confirmed 且 Webhook 验签通过后入账。使用事件顶层 id 做幂等键。

04 · WITHDRAWALS

提现接口

POST/v1/withdrawals

创建待审核提现。金额必须是十进制字符串,最多 6 位小数,禁止使用浮点数计算。

POST /v1/withdrawals
Content-Type: application/json
X-App-Id: app_xxx
X-Timestamp: 1785388800
X-Nonce: 504ceb...
X-Signature: dcd085...

{
  "platform_order_id": "wd-20260730-00001",
  "external_user_id": "user-10001",
  "to_address": "T...",
  "amount": "12.500000"
}

platform_order_id 是幂等键。相同订单号和参数会返回原订单; 同订单号但参数不同返回 409

提现状态

REVIEWING等待管理员审核冻结用户余额
APPROVED / SIGNING批准并开始签名继续等待
BROADCASTED已广播,等待固化确认继续等待
SUCCESS链上成功正式扣减
REJECTED管理员拒绝解除冻结
SIGN_FAILED / ONCHAIN_FAILED签名或链上失败人工核查
GET/v1/withdrawals/{withdrawal_id}

按系统 ID 查询。

GET/v1/withdrawals/by-order/{platform_order_id}

按平台业务单号查询,建议用于超时后的状态确认。

05 · WEBHOOKS

Webhook 验签

网关向平台配置的回调地址发送 JSON,并携带:

X-Webhook-Id投递 ID
X-Webhook-TimestampUnix 秒级时间戳
X-Webhook-SignatureWebhook Secret 签名
const expected = crypto
  .createHmac("sha256", WEBHOOK_SECRET)
  .update(timestamp + "." + rawBody)
  .digest("hex");

if (!crypto.timingSafeEqual(
  Buffer.from(expected),
  Buffer.from(signature)
)) throw new Error("invalid webhook signature");

签名消息为 timestamp + "." + 原始请求体。 业务事务提交成功后返回任意 2xx,否则网关会指数退避重试。

充值deposit.confirmed
提现withdrawal.successwithdrawal.rejectedwithdrawal.sign_failedwithdrawal.onchain_failed

06 · ERRORS

错误处理

401App ID、签名或管理员令牌无效;时间戳过期
404资源不存在或不属于当前平台
409Nonce 重放、幂等冲突、地址池不足或状态冲突
422参数、金额精度或 TRON 地址格式错误
500先以原业务单号查询状态,再决定是否重试

07 · GO-LIVE

上线检查

平台与网关服务器均启用 NTP,避免签名时间偏差。

API、管理后台与 Webhook 全部使用 HTTPS。

两个 Secret 存储在服务端 Secret Manager。

Webhook 事件 ID 建立数据库唯一键,并与入账处于同一事务。

提现私钥隔离至 KMS、HSM 或独立签名服务。

先以小额真实 USDT 演练充值、重复通知和提现故障。

为地址池、热钱包 USDT/TRX、Worker、DEAD 回调和备份设置告警。

准备好发出第一个请求了吗?

返回接入流程