💳 支付系统 API 文档
接口地址
接口基础地址:https://pay.xiaoil.com
后台地址:/admin/(默认账号:admin,密码:123456)
商户中心:/user/(支持自助注册)
1. 创建订单
POST
https://pay.xiaoil.com/submit.php
请求参数
| 参数 | 必填 | 说明 |
| pid | 是 | 商户ID |
| type | 是 | 支付方式:alipay(支付宝) / wxpay(微信) / qqpay(QQ钱包) |
| out_trade_no | 是 | 商户订单号(唯一) |
| notify_url | 是 | 异步通知地址 |
| return_url | 否 | 支付后跳转地址 |
| name | 是 | 商品名称 |
| money | 是 | 金额(元,保留两位小数) |
| param | 否 | 自定义参数(原样返回) |
| sign | 是 | 签名 |
| sign_type | 否 | 签名类型,默认MD5 |
返回示例
{
"code": 1,
"msg": "订单创建成功",
"data": {
"trade_no": "20250102123456789012",
"payurl": "https://pay.xiaoil.com/pay/cashier.php?trade_no=xxx",
"qrcode": "https://pay.xiaoil.com/pay/cashier.php?trade_no=xxx&qrcode=1"
}
}
提示:POST请求默认会跳转到支付页面,如需返回JSON请添加参数 format=json 或使用GET请求。
1.1 MAPI接口(API模式)
POST
https://pay.xiaoil.com/mapi.php
MAPI接口专门用于API模式对接,直接返回JSON格式的支付二维码或支付链接,不会跳转页面。
请求参数
| 参数 | 必填 | 说明 |
| pid | 是 | 商户ID |
| type | 是 | 支付方式:alipay(支付宝) / wxpay(微信) / qqpay(QQ钱包) |
| out_trade_no | 是 | 商户订单号(唯一) |
| notify_url | 是 | 异步通知地址 |
| return_url | 否 | 支付后跳转地址 |
| name | 是 | 商品名称 |
| money | 是 | 金额(元,保留两位小数) |
| clientip | 否 | 客户端IP地址 |
| device | 否 | 设备类型:pc/mobile/wechat/alipay |
| param | 否 | 自定义参数(原样返回) |
| sign | 是 | 签名 |
| sign_type | 否 | 签名类型,默认MD5 |
返回示例
// 返回二维码
{
"code": 1,
"trade_no": "20250102123456789012",
"qrcode": "https://qr.alipay.com/xxx"
}
// 返回支付链接
{
"code": 1,
"trade_no": "20250102123456789012",
"payurl": "https://xxx/pay"
}
提示:MAPI接口始终返回JSON,适合需要自定义收银台页面的场景。返回的 qrcode 可直接生成二维码,payurl 可跳转或嵌入iframe。
2. 查询订单
GET
https://pay.xiaoil.com/api/query.php
请求参数
| 参数 | 必填 | 说明 |
| pid | 是 | 商户ID |
| trade_no | 否 | 系统订单号(与out_trade_no二选一) |
| out_trade_no | 否 | 商户订单号 |
| sign | 是 | 签名 |
返回示例
{
"code": 1,
"msg": "查询成功",
"data": {
"trade_no": "20250102123456789012",
"out_trade_no": "商户订单号",
"type": "alipay",
"pid": "1001",
"money": "0.01",
"realmoney": "0.01",
"name": "商品名称",
"status": 1,
"addtime": "2025-01-02 12:34:56",
"endtime": "2025-01-02 12:35:00",
"sign": "xxx",
"sign_type": "MD5"
}
}
订单状态说明
| status | 说明 |
| 0 | 待支付 |
| 1 | 已支付 |
| 3 | 已冻结 |
| 4 | 已退款 |
3. 订单状态检查
GET
https://pay.xiaoil.com/api/check.php
前端轮询用接口,会主动向支付宝查询订单状态。
请求参数
返回示例
// 已支付
{"status": 1}
// 未支付
{"status": 0}
// 订单不存在
{"status": -1, "msg": "order not found"}
提示:此接口无需签名,适合前端JS轮询检查支付状态。如果订单未支付,系统会主动向支付宝查询订单状态并自动更新。
4. 异步通知
支付成功后,系统会向 notify_url 发送POST请求:
通知参数
| 参数 | 说明 |
| pid | 商户ID |
| trade_no | 系统订单号 |
| out_trade_no | 商户订单号 |
| type | 支付方式 |
| name | 商品名称 |
| money | 金额 |
| trade_status | 交易状态:TRADE_SUCCESS |
| sign | 签名 |
| sign_type | 签名类型 |
重要:商户验签成功后,请返回纯文本 success(不含引号),否则系统会重复通知。
通知验签示例
<?php
// 接收通知参数
$params = $_POST;
$sign = $params['sign'] ?? '';
$key = '你的商户密钥';
// 验证签名
unset($params['sign'], $params['sign_type']);
ksort($params);
$str = '';
foreach ($params as $k => $v) {
if ($v !== '') {
$str .= $k . '=' . $v . '&';
}
}
$calcSign = md5(rtrim($str, '&') . $key);
if ($sign === $calcSign) {
// 验签成功,处理业务逻辑
// ...
echo 'success';
} else {
echo 'fail';
}
?>
5. 签名算法
签名采用MD5方式,步骤如下:
- 将参数按key字母升序排序
- 拼接成
key=value& 格式(排除sign、sign_type和空值)
- 去掉末尾的
&,拼接商户密钥
- 对整个字符串进行MD5加密
PHP示例
<?php
function createSign($params, $key) {
ksort($params);
$str = '';
foreach ($params as $k => $v) {
if ($k != 'sign' && $k != 'sign_type' && $v !== '') {
$str .= $k . '=' . $v . '&';
}
}
return md5(rtrim($str, '&') . $key);
}
// 示例
$params = [
'pid' => '1001',
'type' => 'alipay',
'out_trade_no' => '202501021234',
'notify_url' => 'https://example.com/notify',
'name' => '测试商品',
'money' => '0.01',
];
$key = '你的商户密钥';
$params['sign'] = createSign($params, $key);
$params['sign_type'] = 'MD5';
?>
签名字符串示例
// 排序后的参数
money=0.01&name=测试商品¬ify_url=https://example.com/notify&out_trade_no=202501021234&pid=1001&type=alipay
// 拼接密钥后
money=0.01&name=测试商品¬ify_url=https://example.com/notify&out_trade_no=202501021234&pid=1001&type=alipay你的商户密钥
// MD5加密得到签名
6. 错误码
| code | 说明 |
| 1 | 成功 |
| -1 | 缺少必要参数 |
| -2 | 商户不存在或已禁用 / 商户收款功能已关闭 |
| -3 | 签名验证失败 |
| -4 | 支付方式不存在 |
| -5 | 暂无可用支付通道 |
| -6 | 风控拦截(IP频率/金额限制等) |
7. 对接示例
PHP发起支付
<?php
// 签名函数
function createSign($params, $key) {
ksort($params);
$str = '';
foreach ($params as $k => $v) {
if ($k != 'sign' && $k != 'sign_type' && $v !== '') {
$str .= $k . '=' . $v . '&';
}
}
return md5(rtrim($str, '&') . $key);
}
// 构建参数
$params = [
'pid' => '1001',
'type' => 'alipay',
'out_trade_no' => date('YmdHis') . mt_rand(1000, 9999),
'notify_url' => 'https://你的网站/notify.php',
'return_url' => 'https://你的网站/return.php',
'name' => '测试商品',
'money' => '0.01',
];
$key = '你的商户密钥';
$params['sign'] = createSign($params, $key);
$params['sign_type'] = 'MD5';
// 方式1:跳转支付
header('Location: https://pay.xiaoil.com/submit.php?' . http_build_query($params));
// 方式2:获取支付链接
$result = json_decode(file_get_contents('https://pay.xiaoil.com/submit.php?' . http_build_query($params)), true);
if ($result['code'] == 1) {
$payUrl = $result['data']['payurl'];
$qrcodeUrl = $result['data']['qrcode'];
}
?>
前端轮询检查支付状态
<script>
// 轮询检查支付状态
var tradeNo = '订单号';
var checkTimer = setInterval(function() {
fetch('https://pay.xiaoil.com/api/check.php?trade_no=' + tradeNo)
.then(response => response.json())
.then(data => {
if (data.status == 1) {
clearInterval(checkTimer);
alert('支付成功!');
// 跳转到成功页面
location.href = '/success.php?trade_no=' + tradeNo;
}
});
}, 3000); // 每3秒检查一次
</script>
异步通知处理
<?php
// notify.php - 异步通知处理
// 签名函数
function createSign($params, $key) {
ksort($params);
$str = '';
foreach ($params as $k => $v) {
if ($k != 'sign' && $k != 'sign_type' && $v !== '') {
$str .= $k . '=' . $v . '&';
}
}
return md5(rtrim($str, '&') . $key);
}
// 接收参数
$params = $_POST;
$sign = $params['sign'] ?? '';
$key = '你的商户密钥';
// 验证签名
$calcSign = createSign($params, $key);
if ($sign !== $calcSign) {
exit('fail');
}
// 验证交易状态
if ($params['trade_status'] !== 'TRADE_SUCCESS') {
exit('fail');
}
// 获取订单信息
$outTradeNo = $params['out_trade_no'];
$money = $params['money'];
// TODO: 查询本地订单,验证金额,更新订单状态
// ...
// 返回成功
echo 'success';
?>
返回首页 | 管理后台 | 商户中心