UPG 充值网关 API 文档 (v1)
版本:v1.2 · 更新日期:2026-09-14 本服务面向支持加密货币支付的国家/地区的商户系统,不面向中国大陆地区提供服务。
1. 概述
UPG(USDT Payment Gateway)提供加密货币充值收款能力。商户系统通过 API 创建充值订单,获得一个本订单专属的收款地址;用户向该地址转账后,平台完成链上确认后即回调支付成功,资金风控审核结论随后单独给出。
- 支持:USDT,链支持 TRC20(TRON)、ERC20(以太坊)、BEP20(BSC)。
- 每笔订单独立收款地址(HD 派生),无需靠金额尾数区分订单。
- 支付与风控解耦:链上到账确认即回调支付成功,不被风控阻塞;资金来源的风控结论单独通过
review_status返回。命中风控的资金照常入账,但不进入平台归集池,支持人工复核后放行或退款。
环境
| 环境 | Base URL | 链 |
|---|---|---|
| 生产 | https://www.aicanpay.com |
TRON / 以太坊 / BSC 主网 |
所有接口路径均以此 Base URL 为前缀,例如创建订单的完整地址为
https://www.aicanpay.com/v1/deposit/orders。请求一律使用 HTTPS。
链参数总览
| chain | 链 | 地址格式 | 确认数(约耗时) | 单笔最低充值 |
|---|---|---|---|---|
TRC20 |
TRON | Base58,T 开头 |
19 块(约 1 分钟) | 1 USDT |
ERC20 |
以太坊 | Hex,0x 开头 |
12 块(约 3 分钟) | 10 USDT |
BEP20 |
BSC | Hex,0x 开头 |
15 块(约 1 分钟) | 1 USDT |
ERC20 最低充值额较高是因为以太坊主网矿工费显著高于其他链,小额充值会被归集成本吞没。低于最低额的入账会被累计到
paid_amount,但建议商户在收银页做前置校验。
2. 通用约定
- 请求与响应均为
application/json; charset=utf-8。 - 金额一律使用字符串,最多 6 位小数(USDT 精度),例如
"100.5"。禁止使用浮点数。 - 时间使用 ISO 8601 UTC 格式,例如
"2026-08-30T08:12:33Z"。 - 所有接口需要签名认证(见第 3 节)。
统一响应结构
{
"code": 0,
"message": "ok",
"request_id": "req_9f8a7b6c",
"data": { }
}
code = 0 表示成功;非 0 见错误码表(第 9 节)。request_id 用于排查问题,请在联系技术支持时提供。
3. 认证与签名
商户开通后获得三项凭证:
| 凭证 | 说明 |
|---|---|
merchant_id |
商户号,形如 M100001 |
api_key |
请求标识,放在请求头 |
api_secret |
签名密钥,只用于本地计算签名,绝不放入请求 |
请求头
| Header | 说明 |
|---|---|
X-Api-Key |
商户 api_key |
X-Timestamp |
Unix 时间戳(秒)。与服务器时间偏差超过 ±300 秒拒绝 |
X-Nonce |
随机字符串(≤36 字符),5 分钟内不得重复 |
X-Signature |
签名,计算方式如下 |
签名算法
sign_payload = timestamp + "\n" + nonce + "\n" + HTTP方法(大写) + "\n" + 请求路径(含query) + "\n" + 请求body(GET为空字符串)
X-Signature = lowercase(hex(HMAC-SHA256(api_secret, sign_payload)))
示例(创建订单):
1756540353
a1b2c3d4e5
POST
/v1/deposit/orders
{"merchant_order_no":"ORD20260830001","amount":"100","currency":"USDT","chain":"TRC20"}
body 必须使用发送时的原始字节参与签名,不要重新序列化。
4. 充值订单
4.1 订单状态机
支付状态与风控审核状态相互独立,这是对接时最重要的一点:
status(支付维度)——只要链上到账并确认,立即变为SUCCESS并回调,不受风控影响。商户据此即可判定"用户付款成功"。review_status(审核维度)——平台对资金来源的风控审核结果,单独返回,不会阻塞或回退支付状态。
支付维度: PENDING ──► CONFIRMING ──► SUCCESS (到账确认即成功)
└──► EXPIRED (超时未付款)
审核维度: PENDING ──► PASS (来源干净)
└──► REVIEWING ──► PASS (人工复核放行)
├──► REFUNDED (退款完成)
└──► FROZEN (被 Tether 官方冻结)
status |
含义 | 终态 |
|---|---|---|
PENDING |
订单已创建,等待用户付款 | 否 |
CONFIRMING |
已检测到链上转账,等待区块确认(各链确认数见"链参数总览") | 否 |
SUCCESS |
支付成功。链上已到账且确认数达标 | 是 |
EXPIRED |
有效期内未收到任何付款 | 是 |
REFUNDED |
资金已退款(详见第 6 节) | 是 |
FROZEN |
地址资金被 Tether 官方冻结,无法操作 | 是 |
review_status |
含义 |
|---|---|
PENDING |
风控审核进行中(通常数秒内完成) |
PASS |
审核通过,资金来源干净 |
REVIEWING |
命中风控或来源无法溯源,转人工复核。订单照常入账,仅该笔资金不归集 |
status = SUCCESS即代表用户付款成功,商户可据此给用户上账。review_status供商户知悉资金审核进展;若为REVIEWING,平台会另行处置并通过deposit.reviewed回调告知最终结果。
4.2 创建充值订单
POST /v1/deposit/orders
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
merchant_order_no |
string | 是 | 商户侧订单号,商户内唯一,作为幂等键。重复提交返回原订单 |
amount |
string | 是 | 期望充值金额(USDT),上限 1000000,下限按链见"链参数总览" |
currency |
string | 是 | 固定 USDT |
chain |
string | 是 | TRC20 / ERC20 / BEP20,决定收款地址所在链,创建后不可更改 |
notify_url |
string | 否 | 本订单回调地址(https)。不传则使用商户后台配置的默认地址 |
expire_seconds |
int | 否 | 订单有效期(秒),默认 1800,范围 300 – 86400 |
attach |
string | 否 | 透传字段(≤255 字符),回调时原样返回 |
响应 data:
{
"order_no": "D2026083012000001",
"merchant_order_no": "ORD20260830001",
"status": "PENDING",
"amount": "100",
"currency": "USDT",
"chain": "TRC20",
"deposit_address": "TXk9vP3rF2mQ8sLwYhNc41GaJdBiUeZoK7",
"expired_at": "2026-08-30T08:42:33Z",
"created_at": "2026-08-30T08:12:33Z"
}
必须告知用户的注意事项(建议展示在商户收银页):
- 必须使用订单指定的链转账(订单是哪条链就走哪条链),转错链无法找回。ERC20 与 BEP20 地址格式相同(
0x开头),用户极易在钱包里选错网络,收银页必须醒目标注链名称。 - 必须在
expired_at之前完成转账;过期后向该地址付款会成为异常入账,需人工处理(见 4.5)。 - 地址为本订单专属,请勿保存复用。
4.3 查询充值订单
GET /v1/deposit/orders/{order_no} —— 按平台单号查询
GET /v1/deposit/orders/by-merchant-no/{merchant_order_no} —— 按商户单号查询
响应 data:
{
"order_no": "D2026083012000001",
"merchant_order_no": "ORD20260830001",
"status": "SUCCESS",
"amount": "100",
"paid_amount": "100",
"payment_status": "PAID",
"currency": "USDT",
"chain": "TRC20",
"deposit_address": "TXk9vP3rF2mQ8sLwYhNc41GaJdBiUeZoK7",
"review_status": "PASS",
"risk_level": "LOW",
"risk_score": 3,
"transactions": [
{
"tx_hash": "7b2e6f...c91d",
"from_address": "TXahG5...pQr2",
"amount": "100",
"confirmations": 19,
"received_at": "2026-08-30T08:15:02Z"
}
],
"attach": "",
"expired_at": "2026-08-30T08:42:33Z",
"created_at": "2026-08-30T08:12:33Z",
"finished_at": "2026-08-30T08:16:40Z"
}
4.4 金额差异处理(重要)
入账以链上实收金额 paid_amount 为准,不以订单期望金额 amount 为准。
订单何时进入终态:到账交易的区块确认数达标后立即转 SUCCESS 并回调,不等风控、不等待补足差额、也不等到有效期截止——少付同样即时结单。有效期截止仍分文未收才转 EXPIRED。风控审核结果随后通过 review_status 与 deposit.reviewed 回调给出。
payment_status 字段(回调与查询均返回,商户无需自行比较金额):
| 值 | 含义 |
|---|---|
UNPAID |
尚未收到任何转账 |
PAID |
实收 = 应付 |
UNDERPAID |
实收 < 应付(常见于交易所提现扣除手续费) |
OVERPAID |
实收 > 应付 |
其他规则:
- 入账即定格:订单结单后再向该地址转账(包括想"补差价"的转账),不会并入本单,会进入异常入账流程人工处置。请勿引导用户分多笔付款。
- 多付 / 少付:商户系统必须按
paid_amount入账,差异部分按payment_status结合自身业务规则处理(补差、退差、按实收记账)。 - 精度:各链 USDT 合约精度不同(TRC20/ERC20 为 6 位小数,BEP20 为 18 位),平台统一按 6 位小数记账,超出部分向下截断。
- 收银页建议:向用户醒目提示「交易所提现会扣手续费,请用『到账数量』模式或多转手续费部分」,可显著减少少付。
4.5 异常入账
订单进入终态后(或过期后)向该地址的付款,不再关联任何订单,记录为异常入账,商户可在商户后台查看并申请人工处理。API 层面首期不开放,避免误用。
5. 风控(黑U识别)
平台在每笔到账后,调用链上反洗钱数据服务(MistTrack 等)对付款来源地址进行筛查。
筛查不影响支付状态——订单在到账确认时已是 SUCCESS,筛查结果只决定 review_status:
| risk_level | 分值区间 | review_status |
|---|---|---|
LOW |
0–30 | PASS |
MODERATE |
31–70 | PASS,标记留痕 |
HIGH |
71–90 | REVIEWING,人工复核 |
SEVERE |
91–100 | REVIEWING,人工复核(涉制裁/被盗资金等) |
分值与等级由风控数据服务(MistTrack)给出,档位对齐其官方口径;平台采信其
risk_level。复核阈值为HIGH及以上,可按风险偏好在后台调整。 另有一种情况也会转REVIEWING:付款来源地址无法溯源(例如仅通过余额对账发现的到账),此时无从筛查,一律转人工复核。
REVIEWING 的订单照常入账计费、照常计入商户余额,差别只有一处:资金不进入平台归集池,停留在原充值地址,直到审核结论产生——放行(review_status 转 PASS,随即归集)、退款(见第 6 节)或遭遇 Tether 官方冻结(status 转 FROZEN)。
5.1 查询风控详情
GET /v1/deposit/orders/{order_no}/risk
{
"order_no": "D2026083012000001",
"risk_level": "HIGH",
"risk_score": 72,
"labels": ["gambling", "mixer-exposure"],
"provider": "misttrack",
"screened_at": "2026-08-30T08:16:35Z"
}
labels 为风险标签(英文枚举,如 stolen-funds、sanctioned-entity、mixer-exposure、gambling、scam、darknet),可能为空数组。
6. 退款
仅 review_status = REVIEWING 的订单(及平台人工同意的特殊情况)可发起退款。
重要:退款不会自动原路退回付款地址——付款方若使用交易所提币,
from_address是交易所热钱包,原路退回将导致资金丢失。商户必须向最终用户收集退款地址后提交。平台会对退款地址再次做风控筛查,命中高风险将拒绝。
6.1 申请退款
POST /v1/refunds
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
merchant_refund_no |
string | 是 | 商户退款单号,幂等键 |
order_no |
string | 是 | 原充值订单号(平台单号) |
refund_address |
string | 是 | 收款地址,必须与原订单同链(TRC20 为 T 开头 Base58;ERC20/BEP20 为 0x 开头 Hex) |
reason |
string | 否 | 退款原因(≤255 字符) |
响应 data:
{
"refund_no": "R2026083015000001",
"merchant_refund_no": "REF20260830001",
"order_no": "D2026083012000001",
"status": "REFUND_PENDING",
"refund_amount": "100",
"refund_address": "TQm3xW...k8Yd",
"network_fee": "0",
"created_at": "2026-08-30T10:02:11Z"
}
network_fee 为从退款中扣除的矿工费(TRC20/BEP20 恒为 "0"),用户实际到账 = refund_amount − network_fee。
退款金额为该订单隔离的全部实收金额。链上矿工费:TRC20 / BEP20 由平台承担;ERC20 因以太坊主网矿工费较高,从退款金额中扣除实际矿工费(以 network_fee 列明)。退款只在原链进行,不支持跨链退款。
6.2 退款状态
| 状态 | 含义 |
|---|---|
REFUND_PENDING |
已受理,等待平台审核与处理 |
REFUND_PROCESSING |
已上链广播,等待确认 |
REFUND_SUCCESS |
退款完成(含 tx_hash),原订单转 REFUNDED |
REFUND_FAILED |
退款被拒绝或失败(含 fail_reason),原订单 review_status 保持 REVIEWING |
6.3 查询退款
GET /v1/refunds/{refund_no} —— 响应结构同 6.1,外加 tx_hash、fail_reason、finished_at。
7. 回调通知(Webhook)
订单发生关键状态变化时,平台向 notify_url 发起 POST 请求(JSON body),并携带与请求接口相同规则的签名头(X-Api-Key / X-Timestamp / X-Nonce / X-Signature,用商户 api_secret 签名)。商户必须验签,否则任何人都可伪造回调。
回调验签时,签名 payload 的各段取值:HTTP 方法固定为 POST;请求路径为 notify_url 的路径部分(含 query,不含域名);body 为收到的原始字节(不要先解析再重新序列化)。
7.1 事件类型
| event | 触发时机 |
|---|---|
deposit.confirming |
首次检测到链上转账(可用于前端展示"已检测到付款") |
deposit.success |
支付成功——链上到账且确认数达标即推送,不等风控。商户以此为准给用户上账 |
deposit.reviewed |
风控审核出结论,review_status 变为 PASS 或 REVIEWING。仅作知会,不影响已成功的支付 |
deposit.expired |
订单超时未付款 |
refund.success |
退款完成 |
refund.failed |
退款失败 |
7.2 回调 body
{
"event": "deposit.success",
"event_id": "evt_5c1d9e2a",
"occurred_at": "2026-08-30T08:16:40Z",
"data": { /* 与对应查询接口的 data 结构一致 */ }
}
7.3 应答与重试
- 商户返回 HTTP
2xx即视为成功,响应 body 不做要求。 - 以商户返回 2xx 为唯一送达确认,未确认即视为失败并持续重试:先按
15s / 30s / 1m / 2m / 5m / 10m / 15m / 30m密集重试,之后固定每 30 分钟一次,直到收到确认为止(最长约 4 天)。期间平台会告警提示运营介入,仍可在后台手动重推。 - 因此商户接口务必做到幂等:同一
event_id可能被推送多次,重复收到不应重复上账。 - 回调可能重复、可能乱序(
event_id唯一,可用于去重)。商户务必:- 按
event_id幂等处理; - 收到回调后以查询接口的实时状态为准再入账(防伪造、防乱序的双保险);
- 回调处理逻辑不要超过 10 秒,先应答再异步处理。
- 按
8. 限频
默认每商户 20 QPS(创建订单)/ 50 QPS(查询),超出返回错误码 40001。轮询查询建议间隔 ≥5 秒,以回调为主、查询兜底。
9. 错误码
| code | 说明 |
|---|---|
0 |
成功 |
10001 |
参数缺失或非法 |
10002 |
签名错误 |
10003 |
时间戳超出允许偏差 |
10004 |
nonce 重复 |
10005 |
api_key 无效或商户被禁用 |
20001 |
订单不存在 |
20002 |
商户单号已存在且参数不一致(幂等冲突) |
20003 |
当前订单状态不允许该操作 |
30001 |
退款地址格式非法 |
30002 |
退款地址风控筛查未通过 |
30003 |
该订单不满足退款条件 |
40001 |
请求频率超限 |
50000 |
系统内部错误,请携带 request_id 联系技术支持 |
10. 对接自检清单
- 金额全程使用字符串/定点数处理,无浮点运算
- 回调做了验签
- 回调按
event_id幂等去重 - 上账以
deposit.success+ 查询接口双重确认,按paid_amount入账(review_status仅作知会,不要用它判断是否上账) - 处理了多付/少付/一单多笔场景
- 收银页向用户明示:订单指定的链(醒目标注,防止 ERC20/BEP20 选错网络)、地址一次性、有效期
- 创建订单前按链校验最低充值额
- 退款流程向用户收集退款地址(不默认原路退回)
- 生产与沙箱凭证隔离,api_secret 不落前端、不进日志