接入准备
先完成商户、套餐和收款账户配置,再开始联调。
开通商户获取商户 UID 与 API 密钥
购买套餐套餐有效且无手续费欠费
配置账户填写并启用至少一个收款账户
服务端签名密钥只保存在服务端
接收通知验签、入账并返回 success
正式接入前请先在商户中心使用“检测配置/测试连接”确认账户可用。测试金额应使用小额,真实支付验收放在全部配置完成以后进行。
公共约定
| 项目 | 约定 | 说明 |
|---|---|---|
| 商户标识 | pid | 商户中心显示的 UID,不要写死平台测试账号。 |
| 支付方式 | type | 使用商户“支付插件”页面显示的调用值;只提交已配置、已启用的方式。 |
| 商户订单号 | out_trade_no | 同一商户内保持唯一,仅允许字母、数字及 ._-|。 |
| 金额 | money | 大于 0 的数字,建议固定为两位小数。 |
| 请求方式 | POST 优先 | 签名和下单均应由商户服务器发起。 |
签名规则
默认使用 MD5;签名计算必须在商户服务端完成。
- 移除
sign、sign_type、数组值和空值。 - 按参数名 ASCII 升序排序,拼接为
key=value&key=value。 - 在拼接结果末尾直接追加商户 API 密钥。
- 计算 32 位小写 MD5,得到
sign;同时提交sign_type=MD5。
<?php
function makeSign(array $data, string $merchantKey): string
{
unset($data['sign'], $data['sign_type']);
$data = array_filter($data, static function ($value) {
return !is_array($value) && $value !== null && trim((string)$value) !== '';
});
ksort($data);
$pairs = [];
foreach ($data as $key => $value) {
$pairs[] = $key . '=' . $value;
}
return md5(implode('&', $pairs) . $merchantKey);
}编码一致性签名时参与计算的值必须与实际提交值完全一致。不要在签名后再次修改金额、商品名称、语言或 URL;传入
lang 时也必须参与签名。网页跳转下单
适合普通网站收银台,平台完成下单后直接展示或跳转支付页面。
POST https://yatai.usdt-ai.vip/submit.php
请求参数
| 参数 | 必填 | 说明 |
|---|---|---|
pid | 必填 | 商户 UID |
type | 可选 | 支付方式调用值;为空时进入平台收银台选择。 |
out_trade_no | 必填 | 商户订单号 |
notify_url | 必填 | 服务器异步通知地址,必须是完整 HTTP/HTTPS URL。 |
return_url | 必填* | 浏览器支付成功返回地址;请求未传时读取商户中心默认值。 |
timeout_url | 可选 | 支付超时后的浏览器返回地址;请求未传时读取商户中心默认值。 |
name | 必填 | 商品名称,最长按 127 字节处理。 |
money | 必填 | 订单金额 |
param | 可选 | 商户自定义透传参数,支付成功通知时原样返回。 |
lang | 可选 | 页面语言;支持 zh-CN、zh-TW、en-US、ja-JP。未传时默认简体中文,并且该参数需要参与签名。 |
sign | 必填 | 按本页签名规则生成。 |
sign_type | 必填 | 默认 MD5。 |
<form method="post" action="https://yatai.usdt-ai.vip/submit.php">
<input type="hidden" name="pid" value="YOUR_MERCHANT_UID">
<input type="hidden" name="type" value="PAY_TYPE">
<input type="hidden" name="out_trade_no" value="ORDER_202608270001">
<input type="hidden" name="notify_url" value="https://merchant.example.com/pay/notify">
<input type="hidden" name="return_url" value="https://merchant.example.com/pay/success">
<input type="hidden" name="timeout_url" value="https://merchant.example.com/pay/timeout">
<input type="hidden" name="lang" value="en-US">
<input type="hidden" name="name" value="测试商品">
<input type="hidden" name="money" value="1.00">
<input type="hidden" name="sign_type" value="MD5">
<input type="hidden" name="sign" value="GENERATED_SIGN">
<button type="submit">立即支付</button>
</form>JSON 下单
适合 APP、前后端分离或由商户自行控制跳转的场景。
POST https://yatai.usdt-ai.vip/mapi.php
基础参数与网页跳转下单一致,并额外要求 clientip。常用控制参数如下:
| 参数 | 必填 | 说明 |
|---|---|---|
clientip | 必填 | 付款用户真实 IP,必须是合法 IPv4/IPv6。 |
method | 必填 | 常用值:web、jump、jsapi、scan。 |
device | 可选 | 默认 pc;可传 mobile、wechat、alipay、app。 |
sub_openid | 条件必填 | method=jsapi 时必填。 |
auth_code | 条件必填 | method=scan 时必填。 |
curl -X POST 'https://yatai.usdt-ai.vip/mapi.php' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'pid=YOUR_MERCHANT_UID' \
--data-urlencode 'type=PAY_TYPE' \
--data-urlencode 'out_trade_no=ORDER_202608270001' \
--data-urlencode 'notify_url=https://merchant.example.com/pay/notify' \
--data-urlencode 'return_url=https://merchant.example.com/pay/success' \
--data-urlencode 'lang=en-US' \
--data-urlencode 'name=测试商品' \
--data-urlencode 'money=1.00' \
--data-urlencode 'clientip=203.0.113.10' \
--data-urlencode 'method=jump' \
--data-urlencode 'device=pc' \
--data-urlencode 'sign_type=MD5' \
--data-urlencode 'sign=GENERATED_SIGN'{
"code": 1,
"trade_no": "PLATFORM_TRADE_NO",
"payurl": "https://payment.example/redirect"
}不同插件可能返回
payurl、qrcode、urlscheme 或其他支付信息。业务端应先判断 code,再按实际返回字段处理。订单查询
用于主动确认支付状态,不应只依赖浏览器返回页。
GET https://yatai.usdt-ai.vip/api.php?act=order
| 参数 | 必填 | 说明 |
|---|---|---|
pid | 必填 | 商户 UID |
key | 必填 | 商户 API 密钥;仅允许从服务端请求。 |
trade_no | 二选一 | 平台订单号 |
out_trade_no | 二选一 | 商户订单号 |
curl 'https://yatai.usdt-ai.vip/api.php?act=order&pid=YOUR_MERCHANT_UID&key=YOUR_API_KEY&out_trade_no=ORDER_202608270001'状态判断返回
code=1 表示查询成功;订单字段 status=1 表示已支付,status=0 表示未支付。最终入账还应结合验签通过的异步通知,并保证幂等。支付结果通知
支付成功后,平台向 notify_url 发送异步 GET 通知。
异步通知
notify_url
服务器到服务器通知。验签、核对金额并完成业务入账后,响应纯文本 success。
浏览器返回
return_url
用于给付款用户展示支付结果,不应将它作为唯一入账依据。
成功通知参数
| 参数 | 说明 |
|---|---|
pid | 商户 UID |
trade_no | 平台订单号 |
out_trade_no | 商户订单号 |
type | 实际支付方式调用值 |
name | 商品名称 |
money | 订单金额 |
trade_status | 成功时固定为 TRADE_SUCCESS |
param | 下单时传入的透传参数,未传时不返回。 |
sign / sign_type | 通知签名与签名类型 |
<?php
$params = $_GET;
$receivedSign = $params['sign'] ?? '';
if (($params['trade_status'] ?? '') !== 'TRADE_SUCCESS') {
http_response_code(400);
exit('fail');
}
if (!hash_equals(makeSign($params, 'YOUR_API_KEY'), $receivedSign)) {
http_response_code(403);
exit('fail');
}
// 1. 按 out_trade_no 查询本地订单
// 2. 核对 pid、money 与本地订单
// 3. 使用数据库事务和唯一约束保证只入账一次
// 4. 完成业务处理后返回 success
exit('success');自动重试首次通知失败后,系统会按计划任务再次通知。商户回调必须支持重复请求;只有业务处理完成后才返回
success。超时返回
仅处理付款页面倒计时结束后的浏览器跳转。
支付超时
timeout_url
配置后,订单倒计时结束会携带签名参数返回该地址;未配置时显示平台统一超时页面。
| 参数 | 说明 |
|---|---|
pid | 商户 UID |
trade_no | 平台订单号 |
out_trade_no | 商户订单号 |
trade_status | 固定为 TRADE_TIMEOUT |
sign / sign_type | 返回签名与签名类型 |
不要直接关闭订单超时页只说明支付会话已结束,不代表链上或第三方绝对未到账。商户应先查询订单;发现实际到账时,以平台最终支付状态为准。
常见问题
按返回信息定位配置、签名和业务状态。
-3 / 签名校验失败检查参数排序、空值过滤、字符编码和 API 密钥。
-4 / 参数缺失检查 pid、订单号、金额、通知地址和 JSON 下单的 clientip。
-6 / 套餐不可用商户未购买有效套餐或套餐已到期。
-7 / 手续费欠费先在商户中心补缴套餐手续费,再重新创建订单。
商户余额不足商户直清通道手续费从余额扣除,需要先充值余额。
订单号已存在同一订单号参数不可变化;需要修改金额或回调地址时请生成新订单号。
没有可用通道确认支付插件已分配、账户配置完整、状态启用且套餐有效。
通知反复重试确认通知地址公网可访问,验签成功后响应纯文本 success。
上线前安全检查
真实支付前逐项确认,避免密钥泄露和重复入账。
- API 密钥只保存在商户服务端,不写入网页、APP 或公开代码仓库。
- 回调地址使用 HTTPS,验签前不更新本地订单状态。
- 同时核对
pid、out_trade_no、money与本地订单。 - 以商户订单号建立唯一约束,回调处理必须幂等。
- 记录平台订单号、通知时间和处理结果,但日志不得保存完整密钥。
- 先完成未支付订单与模拟回调检查,最后再进行小额真实支付验收。
推荐验收顺序签名自检 → 创建未支付订单 → 查询订单 → 回调验签 → 超时页 → 小额真实支付 → 核对余额手续费与业务入账。