标准 JSON API · REST

188Pay API 接入文档

适用于自研系统的 RESTful JSON API,支持创建订单、查询状态、回调通知。端到端直付,资金不经平台,直达您的钱包。

BASE URL: api2.188pay.top
Content-Type: application/json
签名算法: MD5
回调重试: 最多 6 次

Base URL:https://api2.188pay.top

Content-Type:所有请求与响应均使用 application/json

鉴权:请在商户后台的 API 密钥 页面获取 merchantIdsecretKey

统一响应格式:{"code": 0, "msg": "success", "data": {...}} — code=0 成功,code=-1 失败

创建订单 POST /pay/address

提交订单信息,获取收款钱包地址与实际应付金额。

参数 类型 必填 说明
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
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": "签名值"
  }'
JSON
{
  "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 托管收银台页面链接(可直接跳转展示给用户)
JSON
{
  "code": -1,
  "msg": "错误信息"
}

查询订单 GET /pay/order/{orderId}

根据平台订单号查询订单状态。此接口无需鉴权,为公开接口。

JSON
{
  "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

处理要求:

  1. 验证签名是否正确(防止伪造回调)
  2. 根据 out_trade_no 找到对应订单并处理业务逻辑
  3. 业务处理成功后响应字符串 successok(否则视为失败,触发重试)

签名验证方式:排除 signsign_type 字段,其余参数过滤空值后按 key 字母序排序,拼接为 k=v&k=v 格式,末尾追加 &key=YOUR_KEY,对整体做 MD5 取小写。

签名算法

标准模式签名。参与签名的字段:merchantIdmerchantOrderIdamountcoinTypenotifyUrl(过滤空值后参与)

  1. 步骤 1 — 过滤空值,按 key 字母序排序后拼接参数串
    示例
    amount=100&coinType=usdt&merchantId=YOUR_ID&merchantOrderId=ORDER_001&notifyUrl=https://...
  2. 步骤 2 — 末尾追加 &key=YOUR_SECRET_KEY,对完整字符串做 MD5 取小写
    示例
    // 完整签名字符串
    amount=100&coinType=usdt&merchantId=YOUR_ID&merchantOrderId=ORDER_001&notifyUrl=https://...&key=YOUR_SECRET_KEY
    
    // 结果
    sign = MD5(完整字符串).toLowerCase()

标准模式 vs EPay 模式签名区别

标准模式末尾追加 &key=YOUR_KEY(含 &key= 前缀);EPay 兼容模式直接追加密钥本身(无任何前缀)。两者不可混用,请根据接入方式选择正确的签名方法。

PHP
$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';
}
Node.js
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');
  }
});
Python
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'

重试策略

若回调接口未返回 successok,系统将按指数退避策略(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 次重试失败后,可在商户后台订单详情页手动重发回调通知。