API 文档

公开可查的接入文档:认证与签名、接口参考、错误码与 Webhook 回调。

开始前

接入流程

网关只做两件事:按你的请求创建账单,并在链上到账确认后回调你。资金全程经收款合约直达你的归集地址,不经手网关。

账单收款
你的服务器 → 网关: POST /v1/invoice           创建账单,拿到 pay_url
买家        → 网关: 打开 pay_url,选链选币并付款
网关        → 你的服务器: Webhook 回调(账单完成,confirmed=true)
你的服务器  → 网关: 返回 200 且响应体为 ok
充值收款
你的服务器 → 网关: GET /v1/deposit/address?uid=xxx&chain=base&crypto=USDC
网关       → 你的服务器: 返回 deposit_address(同一 uid + 链固定不变)
用户       → 区块链: 向该地址转账
网关       → 你的服务器: Webhook 回调(充值到账)
  • 账单收款是定额、限时的一次性账单,适合下单、订阅计费。
  • 充值收款是给每个用户分配的专属地址,可长期反复转入,适合钱包、交易所式入金。
  • 金额一律用字符串传输;时间一律为 ISO 8601 UTC。
  • 所有接口路径不带尾部斜杠。

获取凭据

每个项目有独立的 AppID 与 HMAC 密钥,用于接口鉴权与签名。密钥只显示一次,请存入密钥管理服务;一旦泄露,立即在设置页重置。

前往设置查看 AppID 与 HMAC 密钥
接口调用还受项目配置约束:IP 白名单、通知地址、收款地址未配置完整时,网关会拒绝创建账单并返回 1004。

网关地址与规则

本控制台对应的网关地址:

http
https://pay.usdzova.com
  • 接口路径形如 /v1/invoice,不带尾部斜杠。
  • 币种符号一律大写,如 USDT、USDC。
  • 链码用小写,如 ethereum、bsc、base、tron,完整列表见下方「链与币种」。
  • 账单的计价法币与买家实际支付的币种是两件事:currency 决定 amount 的计价单位,买家付什么由 methods 决定。

认证与签名

请求头

除公开接口(查询账单、支付页)外,所有 /v1 接口都要带这四个头。

请求头说明
XC-Appid项目 AppID
XC-TimestampUnix 秒;与服务器时间相差不得超过 300 秒
XC-Nonce随机串,必填;同一 AppID 下 300 秒内不可重复
XC-SignatureHMAC-SHA256 签名,小写十六进制

签名算法

签名内容为「nonce + 时间戳 + 原始请求体」,用 HMAC 密钥做 HMAC-SHA256。

http
message   = XC-Nonce + XC-Timestamp + request_body
signature = HMAC-SHA256(message, hmac_key)  # 小写十六进制
request_body 必须是实际发送的原始字节:先签名、再由 HTTP 库自动序列化 body,是最常见的 1003 错误来源。GET 请求没有请求体,签名内容里的 body 部分为空字符串,查询参数不参与签名。

签名接口按固定顺序校验,命中即返回,便于定位问题:

  • 1001 AppID 无效 → 1002 IP 不在白名单 → 1004 项目未就绪 → 1008 时间戳缺失或超窗
  • 1003 签名错误(签名校验在时间戳之后)
  • 缺少 Nonce 返回 1000,Nonce 在 300 秒内重复返回 1009

各语言示例

示例一:法币计价——创建一笔 29.99 USD 的账单,买家按汇率折算后支付。

import hashlib
import hmac
import json
import time
import uuid

import requests

base = "https://pay.usdzova.com"
appid = "XC-A3BK7NMG"
secret = "your_hmac_key"

payload = {
    "out_no": "order-20260602-001",
    "title": "Premium Plan",
    "currency": "USD",
    "amount": "29.99",
}
# separators 去掉空格:签名与发送必须是同一串字节
body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)
timestamp = str(int(time.time()))
nonce = uuid.uuid4().hex

signature = hmac.new(
    secret.encode(),
    f"{nonce}{timestamp}{body}".encode(),
    hashlib.sha256,
).hexdigest()

resp = requests.post(
    f"https://pay.usdzova.com/v1/invoice",
    data=body.encode("utf-8"),  # 传原始字节,不要用 json=payload
    headers={
        "XC-Appid": appid,
        "XC-Timestamp": timestamp,
        "XC-Nonce": nonce,
        "XC-Signature": signature,
        "Content-Type": "application/json",
    },
    timeout=10,
)
print(resp.status_code, resp.json())

示例二:币本位计价——要求买家直接支付 10 USDT,金额不经过汇率换算。与上面的差异只有 payload 里的 pricing_type / currency / amount。

import hashlib
import hmac
import json
import time
import uuid

import requests

base = "https://pay.usdzova.com"
appid = "XC-A3BK7NMG"
secret = "your_hmac_key"

# 币本位:直接以币数计价,不做汇率换算
payload = {
    "out_no": "order-20260701-002",
    "title": "Premium Plan",
    "pricing_type": "crypto",
    "currency": "USDT",
    "amount": "10",
}
body = json.dumps(payload, separators=(",", ":"), ensure_ascii=False)
timestamp = str(int(time.time()))
nonce = uuid.uuid4().hex

signature = hmac.new(
    secret.encode(),
    f"{nonce}{timestamp}{body}".encode(),
    hashlib.sha256,
).hexdigest()

resp = requests.post(
    f"https://pay.usdzova.com/v1/invoice",
    data=body.encode("utf-8"),
    headers={
        "XC-Appid": appid,
        "XC-Timestamp": timestamp,
        "XC-Nonce": nonce,
        "XC-Signature": signature,
        "Content-Type": "application/json",
    },
    timeout=10,
)
print(resp.status_code, resp.json())

接口参考

接口列表

方法路径说明签名限流
POST/v1/invoice创建账单收款需要256/分钟,按 IP
GET/v1/invoice/{sys_no}查询账单收款不需要120/分钟,按单号 + IP
GET/v1/deposit/address获取充值收款地址需要60/分钟,按项目 + IP
GET/pay/{sys_no}托管支付页(给买家打开)不需要—

响应格式

成功时直接返回业务 JSON。失败时返回统一结构,HTTP 状态码随错误码变化。

错误响应
{
  "code": "1001",
  "message": "AppID无效",
  "detail": ""
}
必须以 code 判断错误类型,不要依赖 message 文案:message 会随请求语言本地化,detail 可能是字符串,也可能是各字段的错误详情对象。框架级错误(404 资源不存在、405 方法不对、429 触发限流)返回 {"detail": "..."}。

错误码

以 code 判断错误类型,HTTP 状态码随错误码变化。只列商户调用会遇到的错误码。

错误码说明HTTP
1000参数错误400
1001AppID 无效400
1002IP 不在白名单403
1003签名错误403
1004项目未配置完整,detail 会列出缺哪项400
1005无访问权限403
1006手续费不足403
1007out_no 已存在但参数不一致400
1008时间戳缺失或超出 300 秒400
1009Nonce 重复400
2000 / 2001 / 2002无效链 / 无效币种 / 该链不支持此币种400
2003 / 2005地址非校验和格式 / 链与币种设置不匹配400
3006金额精度超过该链上代币支持的小数位400
4000 / 4001无效 uid / 未配置该链类型的归集地址400
5000不支持的计价法币400
5003 / 5005账单时间错误 / 无效 sys_no400
5007 / 5008不允许的链与币种 / 无可用账单收款方式400
5009待支付账单过多,请勿滥用400
5011 / 5012账单不存在 / 账单已过期400
5014计价币种缺少可用价格源400

创建账单收款

POST /v1/invoice(需要签名)。创建成功后返回 pay_url,把买家引导到该地址完成选链、选币与付款。

字段类型必填说明
out_nostring是商户订单号,最长 32 位,项目内唯一
titlestring是账单标题,最长 32 位
pricing_typestring否计价方式:fiat(默认,法币计价)/ crypto(币本位,amount 即应付币数)
currencystring是计价单位:法币代码(如 USD、CNY);pricing_type=crypto 时填币种符号(如 USDT)
amountstring是计价金额,0.00000001 – 1000000,最多 8 位小数;币本位时是应付币数
durationinteger否有效期分钟数,5 – 30,默认 10
methodsobject否限定收款方式,形如 {"USDT": ["ethereum"]}
notify_urlstring否账单级回调地址,优先于项目默认通知地址
return_urlstring否支付完成后买家同步跳回的地址
  • methods 不传时使用项目当前全部可用组合;传了必须是子集,否则报 5008(未知币种 2001、未知链 2000)。
  • 付款数量以响应中的 pay_amount 为准。它由汇率换算得出,钱包直收模式下还可能带区分账单的尾差;链上到账必须与 pay_amount 完全相等才会结单,少付、多付都不会自动完成。
  • out_no 幂等:已存在且 title、currency、amount、notify_url、return_url 与旧账单一致时返回原账单(HTTP 200),不一致返回 1007。
  • 项目待支付账单达到 100 笔时拒绝新建,返回 5009。
  • 如果最终只剩一个收款组合,创建时就会自动选定,chain、crypto、pay_address、pay_amount 直接有值。

币本位计价:把 pricing_type 设为 crypto,currency 填币种符号,amount 就是应付的币数——不经过汇率换算,链上到账必须精确等于该数量。

币本位请求示例
{
  "out_no": "order-20260701-001",
  "title": "Premium Plan",
  "pricing_type": "crypto",
  "currency": "USDT",
  "amount": "10",
  "methods": { "USDT": ["ethereum", "tron"] }
}
  • 直收与合约收款都支持:直收按精确金额匹配、不加尾差,同金额并发受直收地址数量限制(地址耗尽返回 5008)。
  • 金额必须能被该链上代币的最小单位精确表示,否则返回 3006。
  • 计价币种必须有价格源(稳定币按 1:1,其他币需行情),否则返回 5014;该估值只用于计费与风控,不影响应付币数。
请求示例
{
  "out_no": "order-20260602-001",
  "title": "Premium Plan",
  "currency": "USD",
  "amount": "29.99",
  "duration": 15,
  "methods": {
    "USDT": ["ethereum", "base"]
  },
  "notify_url": "https://merchant.example.com/pay/webhook",
  "return_url": "https://merchant.example.com/pay/success"
}
响应示例(HTTP 201)
{
  "appid": "XC-A3BK7NMG",
  "sys_no": "INV2606028X7K2P9Q",
  "out_no": "order-20260602-001",
  "title": "Premium Plan",
  "pricing_type": "fiat",
  "pricing_crypto": null,
  "currency": "USD",
  "amount": "29.99",
  "methods": { "USDT": ["ethereum", "base"] },
  "chain": null,
  "crypto": null,
  "crypto_address": null,
  "pay_address": null,
  "pay_amount": null,
  "pay_url": "https://pay.example.com/pay/INV2606028X7K2P9Q",
  "started_at": "2026-06-02T12:00:00.123456Z",
  "created_at": "2026-06-02T12:00:00.123456Z",
  "expires_at": "2026-06-02T12:15:00.123456Z",
  "notify_url": "https://merchant.example.com/pay/webhook",
  "return_url": "https://merchant.example.com/pay/success",
  "payment": null,
  "status": "waiting",
  "risk_level": null,
  "risk_score": null
}
未传的 notify_url / return_url 返回空字符串。链、币、收款地址在买家选定后才写入,因此创建时可能为 null;payment 会在链上出现匹配转账后出现。

查询账单收款

GET /v1/invoice/{sys_no}(公开,无需签名),用于账单页或你的服务器轮询对账。该接口不返回 appid、out_no、notify_url 等商户内部信息;账单不存在返回 404。

字段说明
sys_no系统单号,形如 INV + 日期 + 随机串
pricing_type / currency计价方式与计价单位:fiat + 法币代码,或 crypto + 币种符号
chain / crypto买家选定的链与币,未选时为 null
pay_address收款地址
pay_amount买家应付数量(以该值为准)
payment匹配到的链上转账:hash、block、from/to、amount、status、confirm_progress
payment_uriEVM 链的 EIP-681 支付 URI,非 EVM 或无法精确编码时为 null
statuswaiting / completed / expired
risk_level / risk_scoreAML 风险等级与分数(LOW / MODERATE / HIGH / SEVERE)
  • waiting:待支付。链上已出现匹配转账但未达确认数时,payment 有值、status 仍是 waiting(控制台展示为「确认中」)。
  • completed:已确认,终态。
  • expired:已过期,但不是终态——过期前已上链的付款在确认后仍会转为 completed 并发送回调。
  • 账单价值低于项目「快速确认阈值」(默认 10 USD)时,观察到付款即确认,不等待区块确认数。

获取充值收款地址

GET /v1/deposit/address(需要签名)。为你的用户分配专属充值地址:同一项目、同一 uid、同一链会稳定返回同一地址。

字段类型必填说明
uidstring是用户标识,1 – 128 位,仅字母、数字、下划线、中划线
chainstring是链码,如 ethereum、base、tron
cryptostring是币种符号,如 USDT
请求示例(GET 不参与签名,签名串 body 部分为空)
GET https://pay.usdzova.com/v1/deposit/address?uid=user-10001&chain=base&crypto=USDC
响应示例
{
  "deposit_address": "0xAbCd1234..."
}
虽然 EVM 各链对同一 uid 返回相同地址,仍请按每个「链 + 币」组合调用一次本接口:EVM 原生币(ETH、BNB、POL 等)必须用 crypto=原生币 调用过,系统才会部署该地址的合约,部署前收到的原生币要等部署完成后才入账。
  • 请求的链、币种与链上币种关系都必须已启用,且项目属性(测试 / 主网)与链匹配。
  • 必须已配置该链类型的归集地址,否则返回 4001。
  • EVM 原生币充值地址是合约,付款方转账的 gas limit 需高于 21000(钱包自动估算即可)。
  • 常见错误:4000 uid 非法;2000 链不可用;2001 币种不可用;2002 该币未在此链启用。

Webhook 回调

投递与验签

账单完成或充值到账后,网关向你投递 POST application/json 请求,带与接口调用相同的 HMAC 头。账单事件优先发到账单级 notify_url,为空时用项目通知地址;充值事件只用项目通知地址。

请求头说明
XC-Appid项目 AppID
XC-Timestamp本次投递的发送时间(Unix 秒)
XC-Nonce同一事件的多次重试保持不变,用它做幂等去重
XC-SignatureHMAC-SHA256,算法与接口调用一致
  • 验签必须用收到的原始请求体,不要解析后再序列化。
  • 成功条件:HTTP 200,且响应体去掉首尾空白后等于 ok(区分大小写)。
  • 单次投递超时 5 秒;网络错误、5xx、408、425、429 视为可重试,其余状态码判为失败不再重试。
  • 默认最多投递 5 次(含首次),指数退避约 4 / 8 / 16 / 32 秒,单次退避上限 120 秒。
  • 项目通知开关关闭或地址为空时,事件挂起并每 10 分钟重试一次,同样计入投递次数。
  • 默认只允许投递到 HTTPS 公网地址;http、localhost、内网地址直接判失败。
  • 重试窗口有限,账单状态请用查询接口兜底对账,不要只依赖回调。

账单事件

账单进入 completed 后发送一次。

http
{
  "type": "invoice",
  "data": {
    "sys_no": "INV2606028X7K2P9Q",
    "out_no": "order-20260602-001",
    "crypto": "USDT",
    "chain": "ethereum",
    "pay_address": "0xAbCd1234...",
    "pay_amount": "29.870001",
    "hash": "0xabc123...",
    "block": 12345678,
    "confirmed": true,
    "risk_level": null,
    "risk_score": null
  }
}

充值事件

充值对应转账达到确认要求后发送一次;已停用的币种到账只入账、不发回调。

http
{
  "type": "deposit",
  "data": {
    "sys_no": "DXC2606026K9P2QWX",
    "uid": "user-10001",
    "chain": "base",
    "block": 12345678,
    "hash": "0xabc123...",
    "crypto": "USDC",
    "amount": "500",
    "confirmed": true,
    "risk_level": null,
    "risk_score": null
  }
}
risk_level / risk_score 是发送时的快照。AML 筛查在确认之后异步执行,因此回调里通常为 null,筛查完成后不会补发通知;需要风险数据请以查询接口或风险评估记录为准。

链与币种

公链

Usdzova 当前支持的链如下,chain 参数直接使用「链码」列。

名称链码类型原生币
EthereumethereumEVMETH
BNB Smart ChainbscEVMBNB
Polygon PoSpolygonEVMPOL
Arbitrum Onearbitrum-oneEVMETH
OptimismoptimismEVMETH
BasebaseEVMETH
Avalanche C-ChainavalancheEVMAVAX
LinealineaEVMETH
ScrollscrollEVMETH
TrontronTronTRX

币种

crypto 参数使用币种符号,一律大写。实际可用的「链 + 币」组合以创建账单时的校验结果为准。

符号名称类型说明
USDTTether USDstablecoinERC-20 / TRC-20
USDCUSD CoinstablecoinERC-20
DAIDaistablecoinERC-20
ETHEthernativeEthereum / Arbitrum / Optimism / Base
BNBBNBnativeBNB Smart Chain
POLPolygonnativePolygon PoS
TRXTRONnativeTron

计价法币

账单的计价法币,区分大小写。

代码货币
USD美元
CNY人民币
EUR欧元
JPY日元
HKD港币