本文档覆盖 V1(MD5) 与 V2(RSA) 两套接口规范。所有示例已与线上代码核对,可直接运行。
登录商户后台 → 个人资料 → API 信息,复制以下字段:
| 字段 | 说明 |
|---|---|
| 接口地址 | https://pay.yunzexinda.com/ |
| 商户ID(pid) | 你的 UID(如 1008) |
| 商户 MD5 密钥(key) | V1 签名用,32 位字符串 |
| 商户私钥 | V2 签名用(只显示一次,请保存) |
| 平台公钥 | V2 验签用(固定,所有商户一样) |
⚠️ 请用后台「复制」按钮取值,手抄易错。
⚠️ 商户私钥丢失无法找回,只能重置(重置后需重新对接)。
商户后台 →「个人资料 → API 信息 → 签名方式」:
| 模式 | 值 | 含义 |
|---|---|---|
| 兼容模式 | 0 | V1(MD5)、V2(RSA)都可用 |
| 安全模式 | 1 | 只能用 V2(RSA) |
| type | 说明 |
|---|---|
| alipay | 支付宝 |
| wxpay | 微信支付 |
| qqpay | QQ 钱包 |
| bank | 银行卡 |
| usdt.trc20 | USDT(TRC20 网络) |
不传 type → 跳转收银台让用户选。
sign 和 sign_typeksort)k1=v1&k2=v2&...&kn=vn(末尾不加 &)md5() 取 32 位小写不要用http_build_query()+urldecode()!
我们的签名串是**原样拼接**,中文不做 urlencode。
正确做法:手动foreach拼$k.'='.$v.'&',然后rtrim($str, '&')。
参数:
pid=1008
type=alipay
money=1.00
name=VIP会员
out_trade_no=ORDER123
notify_url=https://yoursite.com/notify.php
return_url=https://yoursite.com/return.php
排序后签名串(sign 和 sign_type 剔除,空值剔除):
money=1.00&name=VIP会员¬ify_url=https://yoursite.com/notify.php&out_trade_no=ORDER123&pid=1008&return_url=https://yoursite.com/return.php&type=alipay
拼接 MD5 密钥后:
money=1.00&name=VIP会员&...&type=alipay你的32位密钥
MD5 取小写:
$sign = md5($signStr . $md5key);
接口:https://pay.yunzexinda.com/submit.php
方式:GET 或 POST(推荐 POST)
| 参数 | 必填 | 说明 |
|---|---|---|
| pid | ✅ | 商户 ID |
| type | ❌ | 支付方式;不传 = 跳收银台 |
| out_trade_no | ✅ | 商户订单号(字母数字下划线横线竖线,≤64 位,唯一) |
| notify_url | ✅ | 异步通知地址(服务器可访问) |
| return_url | ✅ | 同步跳转地址(用户付款完跳这) |
| name | ✅ | 商品名称(≤127 字) |
| money | ✅ | 金额(元,2 位小数) |
| clientip | ❌ | 用户 IP |
| device | ❌ | pc / mobile / wechat / alipay |
| param | ❌ | 业务扩展参数(原样回传) |
| sign | ✅ | 签名(见 2.1) |
| sign_type | ✅ | 固定 MD5 |
<?php
$pid = '1008';
$md5key = '你的32位MD5密钥';
$site = 'https://pay.yunzexinda.com/';
$params = [
'pid' => $pid,
'type' => 'alipay',
'out_trade_no' => 'ORDER_' . time(),
'notify_url' => 'https://yoursite.com/notify.php',
'return_url' => 'https://yoursite.com/return.php',
'name' => 'VIP 会员',
'money' => '1.00',
];
// 1. 剔除 sign / sign_type / 空值
$sign = $params;
unset($sign['sign'], $sign['sign_type']);
$sign = array_filter($sign, function($v){ return $v !== '' && $v !== null; });
// 2. ksort
ksort($sign);
// 3. 拼 k=v&...
$signStr = '';
foreach ($sign as $k => $v) {
$signStr .= $k . '=' . $v . '&';
}
$signStr = rtrim($signStr, '&');
// 4. MD5
$params['sign'] = md5($signStr . $md5key);
$params['sign_type'] = 'MD5';
// 5. 跳转
$url = $site . 'submit.php?' . http_build_query($params);
header('Location: ' . $url);
接口:https://pay.yunzexinda.com/mapi.php
方式:POST,返回 JSON
与 2.2 相同,另需 timestamp(Unix 秒级时间戳,±300 秒内有效)。
注意:mapi.php 走 API_INIT 模式,必须带 timestamp。
{
"code": 1,
"trade_no": "2026101703123456789",
"payurl": "https://pay.yunzexinda.com/pay/xxx",
"qrcode": "https://pay.yunzexinda.com/qr/xxx.png",
"urlscheme": "alipays://...",
"img": "data:image/png;base64,..."
}
方式:GET 到你填写的 notify_url
业务参数:pid / trade_no / out_trade_no / type / name / money / trade_status / param
成功标志:trade_status = TRADE_SUCCESS
你需要返回:纯文本 success(不带空格、不带换行),否则平台会**重复推送 5 次**
<?php
// notify.php
$md5key = '你的32位MD5密钥';
$data = $_GET;
$sign = $data['sign'] ?? '';
unset($data['sign'], $data['sign_type']);
// 剔除空值
$data = array_filter($data, function($v){ return $v !== '' && $v !== null; });
// 排序 + 拼串
ksort($data);
$signStr = '';
foreach ($data as $k => $v) {
$signStr .= $k . '=' . $v . '&';
}
$signStr = rtrim($signStr, '&');
// 验签
$mySign = md5($signStr . $md5key);
if ($mySign !== $sign) {
file_put_contents('notify.log', date('c') . " sign error\n", FILE_APPEND);
exit('sign error');
}
// 校验状态
if (($data['trade_status'] ?? '') !== 'TRADE_SUCCESS') {
exit('fail');
}
// ────────── 业务处理 ──────────
$out_trade_no = $data['out_trade_no']; // 你的订单号
$trade_no = $data['trade_no']; // 平台订单号
$money = $data['money'];
// TODO: 检查 $out_trade_no 是否存在、金额是否匹配、是否已处理
// TODO: 更新订单状态为「已支付」
// ────────── 返回成功 ──────────
echo 'success';
后台 →「个人资料 → API 信息 → 生成 RSA 密钥对」,系统会生成:
openssl_sign 签名)k=v&)OPENSSL_ALGO_SHA256)sign_type 固定 RSA<?php
// 用商户私钥签名
function rsaSign($signStr, $privateKey) {
$key = openssl_pkey_get_private($privateKey);
if (!$key) throw new Exception('私钥无效');
openssl_sign($signStr, $signature, $key, OPENSSL_ALGO_SHA256);
return base64_encode($signature);
}
// 用平台公钥验签
function rsaVerify($signStr, $signature, $publicKey) {
$key = openssl_pkey_get_public($publicKey);
if (!$key) return false;
return openssl_verify($signStr, base64_decode($signature), $key, OPENSSL_ALGO_SHA256) === 1;
}
// 使用
$privateKey = file_get_contents('merchant_private.pem'); // 你保存的商户私钥
$params = [
'pid' => '1008',
'type' => 'alipay',
'out_trade_no' => 'ORDER_' . time(),
'notify_url' => 'https://yoursite.com/notify.php',
'return_url' => 'https://yoursite.com/return.php',
'name' => 'VIP 会员',
'money' => '1.00',
];
// 生成签名串
$sign = $params;
unset($sign['sign'], $sign['sign_type']);
$sign = array_filter($sign, function($v){ return $v !== '' && $v !== null; });
ksort($sign);
$signStr = '';
foreach ($sign as $k => $v) $signStr .= $k . '=' . $v . '&';
$signStr = rtrim($signStr, '&');
// 签名
$params['sign'] = rsaSign($signStr, $privateKey);
$params['sign_type'] = 'RSA';
// 发送到 mapi.php
$ch = curl_init('https://pay.yunzexinda.com/mapi.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$resp = curl_exec($ch);
curl_close($ch);
echo $resp; // JSON
| 项目 | V1 | V2 |
|---|---|---|
| 签名算法 | MD5 | SHA256withRSA |
| 签名密钥 | 商户 MD5 密钥 | 商户 RSA 私钥 |
| 验签密钥 | 商户 MD5 密钥 | 平台 RSA 公钥 |
| sign_type | MD5 | RSA |
| 接口地址 | submit.php / mapi.php | 同左 |
| 安全等级 | 中 | 高(推荐) |
GET https://pay.yunzexinda.com/api.php?act=query&pid=1008&key=你的MD5密钥
返回:
{
"code": 1,
"pid": 1008,
"key": "...",
"active": 1,
"money": "100.00",
"orders": 123,
"orders_today": 5,
"orders_lastday": 8
}
GET https://pay.yunzexinda.com/api.php?act=order&pid=1008&key=你的MD5密钥&trade_no=xxx
或
GET https://pay.yunzexinda.com/api.php?act=order&pid=1008&key=你的MD5密钥&out_trade_no=ORDER123
GET https://pay.yunzexinda.com/api.php?act=orders&pid=1008&key=你的MD5密钥&limit=20&offset=0
GET https://pay.yunzexinda.com/api.php?act=settle&pid=1008&key=你的MD5密钥&limit=20&offset=0
需先在后台开启「商户退款权限」。
POST https://pay.yunzexinda.com/api.php?act=refund
Content-Type: application/x-www-form-urlencoded
pid=1008&key=你的MD5密钥&trade_no=平台订单号&money=1.00
或:
pid=1008&key=你的MD5密钥&out_trade_no=你的订单号&money=1.00
{"code": 0, "msg": "退款成功!退款金额¥1.00", "money": "1.00"}
| 错误信息 | 原因 | 解决 |
|---|---|---|
签名校验失败 | 签名串算错 / 密钥不对 | 1. 检查是否用 array_filter 剔空值2. 检查是否用 ksort 排序3. 不要 http_build_query + urldecode4. 检查密钥前后是否有空格 |
该商户只能使用RSA签名类型 | 后台开了「安全模式」,但用了 MD5 | 改用 RSA 签名,或后台关闭安全模式 |
该接口只能使用RSA签名类型 | 某些接口强制 RSA | 改用 RSA |
时间戳(timestamp)字段不能为空 | mapi.php 需带 timestamp | 加 timestamp=time() |
时间戳字段不正确 | 服务器时间偏移 > 5 分钟 | 同步服务器时间(NTP) |
商户不存在 | pid 填错 | 检查后台 pid |
商户已被封禁 | 账号异常 | 联系客服 |
| 返回 404 | URL 拼错 | 检查是 submit.php 还是 mapi.php |
| 支付成功后没收到异步通知 | notify_url 不可达 / 返回的不是 "success" | 1. 确认 URL 公网可访问 2. 返回纯文本 success(无空格、无换行、无 JSON) |
| 重复收到异步通知 | 没返回 success | 返回 success 后即停;业务处理要做幂等 |
<?php
// pay.php —— 发起支付
$pid = '1008';
$md5key = '你的32位密钥';
$site = 'https://pay.yunzexinda.com/';
$params = [
'pid' => $pid,
'type' => 'alipay',
'out_trade_no' => 'T' . date('YmdHis') . rand(1000,9999),
'notify_url' => 'https://yoursite.com/notify.php',
'return_url' => 'https://yoursite.com/return.php',
'name' => '测试商品',
'money' => '0.01',
];
$sign = $params;
unset($sign['sign'], $sign['sign_type']);
$sign = array_filter($sign, function($v){ return $v !== '' && $v !== null; });
ksort($sign);
$s = '';
foreach ($sign as $k => $v) $s .= $k . '=' . $v . '&';
$s = rtrim($s, '&');
$params['sign'] = md5($s . $md5key);
$params['sign_type'] = 'MD5';
header('Location: ' . $site . 'submit.php?' . http_build_query($params));
<?php
// notify.php —— 接收异步通知
$md5key = '你的32位密钥';
$data = $_GET;
$sign = $data['sign'] ?? '';
unset($data['sign'], $data['sign_type']);
$data = array_filter($data, function($v){ return $v !== '' && $v !== null; });
ksort($data);
$s = '';
foreach ($data as $k => $v) $s .= $k . '=' . $v . '&';
$s = rtrim($s, '&');
if (md5($s . $md5key) !== $sign) exit('sign error');
if (($data['trade_status'] ?? '') !== 'TRADE_SUCCESS') exit('fail');
// TODO: 幂等处理 —— 检查 out_trade_no 是否已处理
// TODO: 校验金额是否匹配
// 更新订单
// ...
echo 'success';
亚泰支付 · 商户对接文档 · 返回帮助中心