适用于自研系统的 RESTful JSON API,支持创建订单、查询状态、回调通知。端到端直付,资金不经平台,直达您的钱包。
Base URL:https://api2.188pay.top
Content-Type:所有请求与响应均使用 application/json
鉴权:请在商户后台的 API 密钥 页面获取 merchantId 和 secretKey
统一响应格式:{"code": 0, "msg": "success", "data": {...}} — code=0 成功,code=-1 失败
提交订单信息,获取收款钱包地址与实际应付金额。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| merchantId | string | 是 | 商户 ID |
| merchantOrderId | string | 是 | 商户订单号(您系统的唯一 ID) |
| amount | number | 是 | 订单金额(系统币种计价,如 CNY / USD / USDT) |
| coinType | string | 否 | 币种:usdt(默认)/ trx / fiat_alipay(支付宝收款) |
| notifyUrl | string | 否 | 回调地址(不填则使用钱包配置的地址) |
| returnUrl | string | 否 | 支付完成后跳转地址 |
| subject | string | 否 | 订单标题 |
| sign | string | 是 | MD5 签名(见 签名算法) |
curl -X POST https://api2.188pay.top/pay/address \
-H "Content-Type: application/json" \
-d '{
"merchantId": "YOUR_MERCHANT_ID",
"merchantOrderId": "ORDER_20260220001",
"amount": 100,
"coinType": "usdt",
"notifyUrl": "https://你的网站/callback",
"sign": "签名值"
}'
{
"code": 0,
"msg": "success",
"data": {
"orderId": "20260220143215123456",
"walletAddress": "TRx1234...abcd",
"actualAmount": 15.67,
"expireAt": "2026-02-20T14:52:15.123Z",
"cashierUrl": "https://api2.188pay.top/cashier?id=20260220143215123456"
}
}
| 字段 | 说明 |
|---|---|
| orderId | 平台订单号 |
| walletAddress | 收款钱包地址(引导用户转账到此地址) |
| actualAmount | 实际应付链上金额(含防碰撞微调,以此为准) |
| expireAt | 订单过期时间(ISO 8601 UTC) |
| cashierUrl | 托管收银台页面链接(可直接跳转展示给用户) |
{
"code": -1,
"msg": "错误信息"
}
根据平台订单号查询订单状态。此接口无需鉴权,为公开接口。
{
"code": 0,
"data": {
"id": "20260220143215123456",
"status": "CREATED",
"terminalReason": null,
"amount": 100,
"actualAmount": 15.67,
"coinType": "usdt",
"walletAddress": "TRx1234...abcd",
"expireAt": "2026-02-20T14:52:15.123Z",
"returnUrl": "https://你的网站/return"
}
}
| 状态值 | 说明 |
|---|---|
| CREATED | 等待支付中 |
| PROCESSING | 链上交易已匹配,等待确认 |
| SUCCESS | 链上已确认,支付成功 |
| FAILED | 支付失败 |
| CANCELED | 订单已终止(可通过 terminalReason 区分原因:EXPIRED / USER_CANCELED / ADMIN_CANCELED / CLOSED / REFUNDED / SYSTEM_FAILED) |
支付成功后,系统将以 POST JSON 方式向 notifyUrl 发送回调通知。
| 字段 | 类型 | 说明 |
|---|---|---|
| trade_no | string | 平台订单号 |
| out_trade_no | string | 商户订单号(创建时传入的 merchantOrderId) |
| amount | number | 订单原始金额 |
| actual_amount | number | 实际链上到账金额 |
| coin_type | string | 收款币种(usdt / trx) |
| status | string | 订单状态,回调时固定为 SUCCESS |
| tx_hash | string | 链上交易哈希 |
| sign | string | MD5 签名 |
| sign_type | string | 签名类型,固定为 MD5 |
处理要求:
out_trade_no 找到对应订单并处理业务逻辑success 或 ok(否则视为失败,触发重试)签名验证方式:排除 sign 和 sign_type 字段,其余参数过滤空值后按 key 字母序排序,拼接为 k=v&k=v 格式,末尾追加 &key=YOUR_KEY,对整体做 MD5 取小写。
标准模式签名。参与签名的字段:merchantId、merchantOrderId、amount、coinType、notifyUrl(过滤空值后参与)
amount=100&coinType=usdt&merchantId=YOUR_ID&merchantOrderId=ORDER_001¬ifyUrl=https://...
// 完整签名字符串
amount=100&coinType=usdt&merchantId=YOUR_ID&merchantOrderId=ORDER_001¬ifyUrl=https://...&key=YOUR_SECRET_KEY
// 结果
sign = MD5(完整字符串).toLowerCase()
标准模式 vs EPay 模式签名区别
标准模式末尾追加 &key=YOUR_KEY(含 &key= 前缀);EPay 兼容模式直接追加密钥本身(无任何前缀)。两者不可混用,请根据接入方式选择正确的签名方法。
$content = file_get_contents('php://input');
$data = json_decode($content, true);
$receivedSign = $data['sign'];
unset($data['sign'], $data['sign_type']);
$data = array_filter($data, function($v) { return $v !== '' && $v !== null; });
ksort($data);
$str = '';
foreach ($data as $k => $v) {
$str .= $k . '=' . $v . '&';
}
$str = rtrim($str, '&');
$str .= '&key=YOUR_SECRET_KEY';
$sign = md5($str);
if ($receivedSign === $sign) {
echo 'success';
} else {
echo 'fail';
}
const crypto = require('crypto');
function verifyCallback(body, secretKey) {
const { sign, sign_type, ...params } = body;
const sortedStr = Object.keys(params)
.sort()
.filter(k => params[k] !== '' && params[k] != null)
.map(k => `${k}=${params[k]}`)
.join('&');
const computedSign = crypto
.createHash('md5')
.update(sortedStr + '&key=' + secretKey)
.digest('hex');
return computedSign === sign;
}
app.post('/callback', (req, res) => {
if (verifyCallback(req.body, 'YOUR_SECRET_KEY')) {
res.send('success');
} else {
res.send('fail');
}
});
import hashlib
def verify_callback(body: dict, secret_key: str) -> bool:
received_sign = body.pop('sign', '')
body.pop('sign_type', None)
filtered = {k: v for k, v in body.items() if v not in ('', None)}
sorted_str = '&'.join(f'{k}={filtered[k]}' for k in sorted(filtered))
sign_str = sorted_str + '&key=' + secret_key
computed_sign = hashlib.md5(sign_str.encode()).hexdigest()
return computed_sign == received_sign
@app.route('/callback', methods=['POST'])
def callback():
data = request.get_json()
if verify_callback(data.copy(), 'YOUR_SECRET_KEY'):
return 'success'
return 'fail'
若回调接口未返回 success 或 ok,系统将按指数退避策略(min(15s × 2^(n-1), 30min))自动重发通知,最多重试 6 次。
| 次数 | 间隔 | 累计时间 |
|---|---|---|
| 1 | 15 秒后 | 约 15 秒 |
| 2 | 30 秒后 | 约 45 秒 |
| 3 | 1 分钟后 | 约 1.75 分钟 |
| 4 | 2 分钟后 | 约 3.75 分钟 |
| 5 | 4 分钟后 | 约 7.75 分钟 |
| 6 | 8 分钟后 | 约 15.75 分钟 |
全部 6 次重试失败后,可在商户后台订单详情页手动重发回调通知。