接口说明及规范
本文档面向接入 聚合支付平台 的商户开发者,覆盖签名规则、支付、退款、订单查询、异步通知、商户信息与代付等全部公开接口。所有接口采用统一的签名与返回结构,建议先阅读「签名规则」再对接业务接口。
协议规则#
application/x-www-form-urlencodedJSONUTF-8SHA256WithRSAV2 升级说明
- V2 接口全面使用 RSA 签名算法;V1 接口使用 MD5 签名算法。
- V2 接口改用全新的接口地址,支持退款、代付等功能;V1 接口使用
submit.php和mapi.php提交订单。 - V2 接口新增
timestamp入参和返回值用于校验时间戳。
获取 RSA 密钥对
在 商户后台 → 个人资料 → API 信息 页面,点击【生成商户 RSA 密钥对】,生成后注意保存【商户私钥】。对接接口时只需要用到 平台公钥 与 商户私钥。
签名规则#
签名步骤
- 获取请求报文所有非空请求参数(不包括数组、字节类型参数,如文件、字节流),剔除
sign、sign_type字段,并按第一个字符的键值 ASCII 码递增排序(字母升序),若遇到相同字符则按第二个字符递增排序,以此类推。 - 将排序后的参数和对应值组合成
参数=参数值的格式,并用&连接,生成待签名字符串。 - 使用商户私钥对待签名字符串计算 RSA 签名(SHA256WithRSA),得到
sign。
验签步骤
- 参照签名步骤第 1~2 步,得到待签名字符串。
- 使用平台公钥,根据签名字符串
sign对待签名字符串进行 RSA 验签(SHA256WithRSA)。
签名示例
/**
* 生成待签名字符串并按 ASCII 升序排序
* @param array $params 业务参数(不含 sign / sign_type)
*/
function buildSignSource(array $params): string
{
// 1. 剔除 sign、sign_type 与空值
unset($params['sign'], $params['sign_type']);
$params = array_filter($params, function ($v) {
return $v !== '' && $v !== null;
});
// 2. 按键名 ASCII 升序排序
ksort($params, SORT_STRING);
// 3. 拼接成 参数=参数值&参数=参数值
$pairs = [];
foreach ($params as $k => $v) {
$pairs[] = $k . '=' . $v;
}
return implode('&', $pairs);
}
/** SHA256WithRSA 签名,返回 Base64 字符串 */
function rsaSign(array $params, string $merchantPrivateKey): string
{
$source = buildSignSource($params);
openssl_sign($source, $sign, $merchantPrivateKey, OPENSSL_ALGO_SHA256);
return base64_encode($sign);
}
/** 平台公钥验签 */
function rsaVerify(array $params, string $sign, string $platformPublicKey): bool
{
$source = buildSignSource($params);
return openssl_verify($source, base64_decode($sign), $platformPublicKey, OPENSSL_ALGO_SHA256) === 1;
}
import java.security.*;
import java.security.spec.*;
import java.util.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class SignUtil {
public static String buildSource(Map<String, String> params) {
params.remove("sign");
params.remove("sign_type");
TreeMap<String, String> sorted = new TreeMap<>();
for (Map.Entry<String, String> e : params.entrySet()) {
String v = e.getValue();
if (v != null && !v.isEmpty()) sorted.put(e.getKey(), v);
}
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> e : sorted.entrySet()) {
if (sb.length() > 0) sb.append('&');
sb.append(e.getKey()).append('=').append(e.getValue());
}
return sb.toString();
}
public static String sign(Map<String, String> params, String privateKey) throws Exception {
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(loadPrivateKey(privateKey));
signature.update(buildSource(params).getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(signature.sign());
}
}
import base64
from urllib.parse import urlencode
def build_source(params: dict) -> str:
"""剔除 sign / sign_type 与空值,按 ASCII 升序拼接"""
data = {k: v for k, v in params.items()
if k not in ("sign", "sign_type") and v not in (None, "")}
return urlencode(sorted(data.items()))
def rsa_sign(params: dict, merchant_private_key: str) -> str:
"""SHA256WithRSA 签名(依赖 cryptography)"""
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
key = serialization.load_pem_private_key(merchant_private_key.encode(), password=None)
signature = key.sign(build_source(params).encode("utf-8"),
padding.PKCS1v15(), hashes.SHA256())
return base64.b64encode(signature).decode()
def rsa_verify(params: dict, sign: str, platform_public_key: str) -> bool:
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.exceptions import InvalidSignature
key = serialization.load_pem_public_key(platform_public_key.encode())
try:
key.verify(base64.b64decode(sign), build_source(params).encode("utf-8"),
padding.PKCS1v15(), hashes.SHA256())
return True
except InvalidSignature:
return False
支付方式列表#
接口中的 type、refund 等字段取值如下;type 不传时跳转到收银台,由用户自行选择。
| 调用值 | 描述 | 图标 |
|---|---|---|
alipay | 支付宝 | |
wxpay | 微信支付 | |
qqpay | QQ 钱包 | |
bank | 云闪付 / 银联 | |
jdpay | 京东支付 | |
ecny | 数字人民币 | |
douyinpay | 抖音支付 |
实际可用支付方式以商户后台「支付通道」中已开通的为准;未开通的方式调用后会返回对应错误码。V1 旧版接口使用同一套取值(另有 paypal,不含 ecny),详见 V1 支付方式与设备类型。
页面跳转支付#
此接口可用于用户前台直接发起支付,使用 form 表单跳转或拼接成 URL 跳转。
https://pay.ya92.com/api/pay/submit
亦支持 GET(推荐 POST,不容易被劫持)
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 支付方式 | type | 是 | String | alipay | 见支付方式列表 |
| 商户订单号 | out_trade_no | 是 | String | 20160806151343349 | 商户侧唯一 |
| 异步通知地址 | notify_url | 是 | String | http://www.pay.com/notify_url.php | 服务器异步通知地址 |
| 跳转通知地址 | return_url | 是 | String | http://www.pay.com/return_url.php | 页面跳转通知地址 |
| 商品名称 | name | 是 | String | VIP会员 | 超过 127 个字节会自动截取 |
| 商品金额 | money | 是 | String | 1.00 | 单位:元,最大 2 位小数 |
| 业务扩展参数 | param | 否 | String | 没有请留空 | 支付后原样返回 |
| 自定义进件商户 ID | merchant_id | 否 | Int | 对应进件商户列表的 ID,未进件请勿传 | |
| 自定义通道 ID | channel_id | 否 | Int | 对应自定义子通道的 ID | |
| 买家身份证号 | cert_no | 否 | String | 可限制指定买家,仅支持支付宝官方接口 | |
| 买家真实姓名 | cert_name | 否 | String | 可限制指定买家,仅支持支付宝官方接口 | |
| 买家最小年龄 | min_age | 否 | Int | 可限制买家年龄,仅支持支付宝官方接口 | |
| 手续费承担方 | fee_mode | 否 | Int | 0 / 1 | 0:商家承担,1:买家承担;不传以商户后台配置为准 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
示例代码
<!-- 页面跳转支付:表单自动提交 -->
<form id="payForm" action="https://pay.ya92.com/api/pay/submit" method="post">
<input type="hidden" name="pid" value="1001">
<input type="hidden" name="type" value="alipay">
<input type="hidden" name="out_trade_no" value="20160806151343349">
<input type="hidden" name="notify_url" value="http://www.pay.com/notify_url.php">
<input type="hidden" name="return_url" value="http://www.pay.com/return_url.php">
<input type="hidden" name="name" value="VIP会员">
<input type="hidden" name="money" value="1.00">
<input type="hidden" name="timestamp" value="1721206072">
<input type="hidden" name="sign" value="商户私钥签名结果">
<input type="hidden" name="sign_type" value="RSA">
</form>
<script>document.getElementById('payForm').submit();</script>
$params = [
'pid' => 1001,
'type' => 'alipay',
'out_trade_no' => '20160806151343349',
'notify_url' => 'http://www.pay.com/notify_url.php',
'return_url' => 'http://www.pay.com/return_url.php',
'name' => 'VIP会员',
'money' => '1.00',
'timestamp' => (string) time(),
];
$params['sign'] = rsaSign($params, $merchantPrivateKey);
$params['sign_type'] = 'RSA';
// 方式一:服务端渲染自动提交表单
echo '<form id="f" method="post" action="https://pay.ya92.com/api/pay/submit">';
foreach ($params as $k => $v) {
echo '<input type="hidden" name="' . htmlspecialchars($k) . '" value="' . htmlspecialchars($v) . '">';
}
echo '</form><script>document.getElementById("f").submit();</script>';
// 方式二:直接拼接 URL 跳转(GET)
// header('Location: https://pay.ya92.com/api/pay/submit?' . http_build_query($params));
curl -X POST 'https://pay.ya92.com/api/pay/submit' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'pid=1001' \
--data-urlencode 'type=alipay' \
--data-urlencode 'out_trade_no=20160806151343349' \
--data-urlencode 'notify_url=http://www.pay.com/notify_url.php' \
--data-urlencode 'return_url=http://www.pay.com/return_url.php' \
--data-urlencode 'name=VIP会员' \
--data-urlencode 'money=1.00' \
--data-urlencode 'timestamp=1721206072' \
--data-urlencode 'sign=商户私钥签名结果' \
--data-urlencode 'sign_type=RSA'
其他说明
- 支付方式(
type)不传会跳转到收银台支付。 - 该接口为浏览器跳转型接口,无 JSON 返回值,提交后直接进入收银台。
统一下单接口#
此接口可用于服务器后端发起支付请求,返回支付二维码链接、支付跳转 URL 等。代码需根据返回的 pay_type 展示对应支付页面。
https://pay.ya92.com/api/pay/create
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 接口类型 | method | 是 | String | web | 见接口类型列表 |
| 设备类型 | device | 否 | String | pc | 仅通用网页支付需要传,见设备类型列表 |
| 支付方式 | type | 是 | String | alipay | 见支付方式列表 |
| 商户订单号 | out_trade_no | 是 | String | 20160806151343349 | |
| 异步通知地址 | notify_url | 是 | String | http://www.pay.com/notify_url.php | 服务器异步通知地址 |
| 跳转通知地址 | return_url | 否 | String | http://www.pay.com/return_url.php | 页面跳转通知地址 |
| 商品名称 | name | 是 | String | VIP会员 | 超过 127 个字节会自动截取 |
| 商品金额 | money | 是 | String | 1.00 | 单位:元,最大 2 位小数 |
| 用户 IP 地址 | clientip | 是 | String | 192.168.1.100 | 用户发起支付的 IP 地址 |
| 业务扩展参数 | param | 否 | String | 没有请留空 | 支付后原样返回 |
| 被扫支付授权码 | auth_code | 否 | String | 仅被扫支付需要传 | |
| 用户 Openid | sub_openid | 否 | String | 仅 JSAPI 支付需要传 | |
| 应用 AppId | sub_appid | 否 | String | 仅 JSAPI 支付(微信)需要传 | |
| 是否小程序 | is_applet | 否 | Int | 1 | 仅 JSAPI 支付需要传,1:是小程序 |
| 自定义进件商户 ID | merchant_id | 否 | Int | 对应进件商户列表的 ID,未进件请勿传 | |
| 自定义通道 ID | channel_id | 否 | Int | 对应自定义子通道的 ID | |
| 买家身份证号 | cert_no | 否 | String | 可限制指定买家,仅支持支付宝官方接口 | |
| 买家真实姓名 | cert_name | 否 | String | 可限制指定买家,仅支持支付宝官方接口 | |
| 买家最小年龄 | min_age | 否 | Int | 可限制买家年龄,仅支持支付宝官方接口 | |
| 手续费承担方 | fee_mode | 否 | Int | 0 / 1 | 0:商家承担,1:买家承担 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 错误信息 | msg | String | 失败时返回原因 | |
| 平台订单号 | trade_no | String | 20160806151343349 | 平台内部的订单号 |
| 发起支付类型 | pay_type | String | jump | 见发起支付类型说明 |
| 发起支付参数 | pay_info | String | weixin://wxpay/bizpayurl?pr=04IPMKM | 根据不同的发起支付类型,返回内容也不一样 |
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
返回示例
{
"code": 0,
"trade_no": "20160806151343349",
"pay_type": "qrcode",
"pay_info": "weixin://wxpay/bizpayurl?pr=04IPMKM"
}
{
"code": 0,
"trade_no": "20160806151343349",
"pay_type": "jump",
"pay_info": "https://qr.alipay.com/bax00000"
}
{
"code": 0,
"trade_no": "20160806151343351",
"pay_type": "jsapi",
"pay_info": "{\"appId\":\"wx2421b1c4370ec43b\",\"timeStamp\":\"1395712654\",\"nonceStr\":\"e61463f8efa94090b1f366cccfbbb444\",\"package\":\"prepay_id=up_wx21201855730335ac86f8c43d1889123400\",\"signType\":\"RSA\",\"paySign\":\"oR9d8PuhnIc+YZ8cBHFCwfgpaK9gd7vaRvkYD7rthRAZ\"}"
}
{
"code": 0,
"trade_no": "2024072320222180092",
"pay_type": "scan",
"pay_info": "{\"type\":\"wxpay\",\"trade_no\":\"2024072320222180092\",\"api_trade_no\":\"4200002345202407238253501450\",\"buyer\":\"o9uAcc6VlZxhcujpKIqQuWWoDQc\",\"money\":\"1.00\"}"
}
示例代码
$params = [
'pid' => 1001,
'method' => 'jump', // 直接返回跳转 url,最简单
'type' => 'alipay',
'out_trade_no' => '20160806151343349',
'notify_url' => 'http://www.pay.com/notify_url.php',
'return_url' => 'http://www.pay.com/return_url.php',
'name' => 'VIP会员',
'money' => '1.00',
'clientip' => '192.168.1.100',
'timestamp' => (string) time(),
];
$params['sign'] = rsaSign($params, $merchantPrivateKey);
$params['sign_type'] = 'RSA';
$ch = curl_init('https://pay.ya92.com/api/pay/create');
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);
$result = json_decode($resp, true);
if (($result['code'] ?? -1) === 0 && rsaVerify($result, $result['sign'], $platformPublicKey)) {
header('Location: ' . $result['pay_info']); // pay_type = jump
exit;
}
exit('下单失败:' . ($result['msg'] ?? '未知错误'));
Map<String, String> params = new HashMap<>();
params.put("pid", "1001");
params.put("method", "jump");
params.put("type", "alipay");
params.put("out_trade_no", "20160806151343349");
params.put("notify_url", "http://www.pay.com/notify_url.php");
params.put("name", "VIP会员");
params.put("money", "1.00");
params.put("clientip", "192.168.1.100");
params.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
params.put("sign", SignUtil.sign(params, merchantPrivateKey));
params.put("sign_type", "RSA");
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://pay.ya92.com/api/pay/create"))
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString(toForm(params)))
.build();
String body = client.send(request, HttpResponse.BodyHandlers.ofString()).body();
import json, time, requests
params = {
"pid": 1001,
"method": "jump",
"type": "alipay",
"out_trade_no": "20160806151343349",
"notify_url": "http://www.pay.com/notify_url.php",
"name": "VIP会员",
"money": "1.00",
"clientip": "192.168.1.100",
"timestamp": str(int(time.time())),
}
params["sign"] = rsa_sign(params, merchant_private_key)
params["sign_type"] = "RSA"
resp = requests.post("https://pay.ya92.com/api/pay/create", data=params, timeout=15)
result = resp.json()
assert rsa_verify(result, result["sign"], platform_public_key), "验签失败"
print(result["pay_info"]) # 跳转地址
const crypto = require('crypto');
const axios = require('axios');
function buildSource(params) {
const obj = {};
Object.keys(params).forEach(k => {
if (k === 'sign' || k === 'sign_type') return;
if (params[k] === '' || params[k] === null) return;
obj[k] = String(params[k]);
});
return Object.keys(obj).sort()
.map(k => `${k}=${obj[k]}`).join('&');
}
const params = {
pid: 1001, method: 'jump', type: 'alipay',
out_trade_no: '20160806151343349',
notify_url: 'http://www.pay.com/notify_url.php',
name: 'VIP会员', money: '1.00',
clientip: '192.168.1.100',
timestamp: String(Math.floor(Date.now() / 1000)),
};
params.sign = crypto.sign('sha256', Buffer.from(buildSource(params)),
merchantPrivateKey).toString('base64');
params.sign_type = 'RSA';
const { data } = await axios.post('https://pay.ya92.com/api/pay/create',
new URLSearchParams(params).toString(), { timeout: 15000 });
console.log(data.pay_info);
curl -X POST 'https://pay.ya92.com/api/pay/create' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'pid=1001' \
-d 'method=jump' \
-d 'type=alipay' \
-d 'out_trade_no=20160806151343349' \
-d 'notify_url=http://www.pay.com/notify_url.php' \
-d 'name=VIP会员' \
-d 'money=1.00' \
-d 'clientip=192.168.1.100' \
-d 'timestamp=1721206072' \
-d 'sign=商户私钥签名结果' \
-d 'sign_type=RSA'
接口类型列表
| 调用值 | 描述 |
|---|---|
web | 通用网页支付(会根据 device 判断,自动返回跳转 url / 二维码 / 小程序跳转 url 等) |
jump | 跳转支付(仅会返回跳转 url) |
jsapi | JSAPI 支付(小程序内支付使用,仅返回 JSAPI 参数,需传入 sub_openid 和 sub_appid) |
app | APP 支付(iOS/安卓 APP 内支付使用,仅返回 APP 支付参数,或 APP 拉起微信小程序参数) |
scan | 付款码支付(需传入 auth_code 参数,支付成功后返回订单信息) |
applet | 小程序支付(微信小程序内使用,返回微信小程序插件参数或跳转小程序参数) |
设备类型列表
| 调用值 | 描述 |
|---|---|
pc | 电脑浏览器(默认) |
mobile | 手机浏览器 |
qq | 手机 QQ 内浏览器 |
wechat | 微信内浏览器 |
alipay | 支付宝客户端 |
douyin | 抖音 APP |
发起支付类型说明
| 发起支付类型 | 描述 |
|---|---|
jump | 返回支付跳转 url |
html | 返回 html 代码,用于支付跳转 |
qrcode | 返回支付二维码 |
urlscheme | 返回微信/支付宝小程序跳转 url scheme |
jsapi | 返回用于发起 JSAPI 支付的参数 |
app | 返回用于发起 APP 支付的参数 |
scan | 付款码支付成功,返回支付订单信息 |
wxplugin | 返回要拉起的微信小程序插件参数,用于未开通支付能力的小程序发起支付 |
wxapp | 返回要拉起的微信小程序和路径,用于 APP 内拉起微信小程序支付 |
其他说明
- 代码中需根据接口返回的
pay_type值来展示具体的支付页面(如扫码页面)。若不想自行处理,可在method传入jump,此时pay_type只会返回jump,直接跳转支付即可。 - 付款码支付可不传支付类型
type字段,会根据auth_code的数字自动判断支付类型。 - 微信小程序插件支付,不同支付平台拉起支付的方式不一样,可联系客服获取对接小程序插件的文档。
订单查询#
https://pay.ya92.com/api/pay/query
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 平台订单号 | trade_no | 二选一 | String | 20160806151343349 | 与商户订单号必传其一 |
| 商户订单号 | out_trade_no | 二选一 | String | 20160806151343351 | 与平台订单号必传其一 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 错误信息 | msg | String | 失败时返回原因 | |
| 平台订单号 | trade_no | String | 20160806151343349 | |
| 商户订单号 | out_trade_no | String | 20160806151343351 | |
| 接口订单号 | api_trade_no | String | 40001249985198893 | 微信/支付宝返回的单号 |
| 支付方式 | type | String | alipay | 见支付方式列表 |
| 支付状态 | status | Int | 1 | 见支付状态列表 |
| 商户 ID | pid | Int | 1001 | |
| 订单创建时间 | addtime | String | 2024-07-01 16:47:32 | |
| 订单完成时间 | endtime | String | 2024-07-01 16:49:24 | 仅完成才返回 |
| 商品名称 | name | String | ||
| 商品金额 | money | String | 1.00 | |
| 已退款金额 | refundmoney | String | 仅部分退款情况才返回 | |
| 业务扩展参数 | param | String | ||
| 支付用户标识 | buyer | String | 一般为 openid | |
| 支付用户 IP | clientip | String | ||
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
支付状态列表
| 状态值 | 描述 |
|---|---|
0 | 未支付 |
1 | 已支付 |
2 | 已退款 |
3 | 已冻结 |
4 | 预授权 |
示例代码
$params = [
'pid' => 1001,
'out_trade_no' => '20160806151343349',
'timestamp' => (string) time(),
];
$params['sign'] = rsaSign($params, $merchantPrivateKey);
$params['sign_type'] = 'RSA';
$ch = curl_init('https://pay.ya92.com/api/pay/query');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if ($result['code'] === 0 && $result['status'] == 1) {
// 订单已支付,可在此发货
echo '已支付,金额:' . $result['money'];
}
curl -X POST 'https://pay.ya92.com/api/pay/query' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'pid=1001' \
-d 'out_trade_no=20160806151343349' \
-d 'timestamp=1721206072' \
-d 'sign=商户私钥签名结果' \
-d 'sign_type=RSA'
支付结果通知#
支付成功后,平台会向商户提交订单时传入的 notify_url 推送异步通知,同时向 return_url 发起页面跳转通知。
{商户 notify_url}
平台 → 商户
通知参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 商户 ID | pid | Int | 1001 | |
| 平台订单号 | trade_no | String | 20160806151343349 | |
| 商户订单号 | out_trade_no | String | 20160806151343351 | |
| 接口订单号 | api_trade_no | String | 40001249985198893 | 微信/支付宝返回的单号 |
| 支付方式 | type | String | alipay | 见支付方式列表 |
| 交易状态 | trade_status | String | TRADE_SUCCESS | 固定为 TRADE_SUCCESS |
| 订单创建时间 | addtime | String | 2024-07-01 16:47:32 | |
| 订单完成时间 | endtime | String | 2024-07-01 16:49:24 | 仅完成才返回 |
| 商品名称 | name | String | ||
| 商品金额 | money | String | 1.00 | |
| 业务扩展参数 | param | String | ||
| 支付用户标识 | buyer | String | 一般为 openid | |
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
success(纯文本),否则平台会按策略重复推送。notify_url 处理示例
// notify_url.php —— 必须校验签名与 trade_status
$params = $_GET; // 平台以 GET 推送
$sign = $params['sign'] ?? '';
unset($params['sign'], $params['sign_type']);
if (!rsaVerify($params, $sign, $platformPublicKey)) {
exit('sign error'); // 验签失败,不处理
}
if (($params['trade_status'] ?? '') !== 'TRADE_SUCCESS') {
exit('success'); // 非成功状态直接应答,避免重复推送
}
// 幂等:以 out_trade_no 为准,重复通知只处理一次
$order = findOrderByOutTradeNo($params['out_trade_no']);
if ($order && $order['status'] != 1 && $order['money'] == $params['money']) {
markOrderPaid($params['out_trade_no'], $params['trade_no']);
}
exit('success'); // 关键:必须输出 success
其他说明
- 商户系统代码内务必对返回的签名
sign进行校验,并且判断trade_status的值是否等于TRADE_SUCCESS。 - 支付平台可能会增加回调字段,验证签名时必须支持增加的扩展字段(即验签时不要写死字段白名单)。
- 异步通知需保证幂等:同一
out_trade_no可能收到多次通知。
订单退款#
需要先在商户后台开启「订单退款 API 接口」开关,才能调用该接口发起订单退款。
https://pay.ya92.com/api/pay/refund
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 平台订单号 | trade_no | 二选一 | String | 20160806151343349 | 与商户订单号必传其一 |
| 商户订单号 | out_trade_no | 二选一 | String | 20160806151343351 | 与平台订单号必传其一 |
| 退款金额 | money | 是 | String | 1.00 | 单位:元 |
| 商户退款单号 | out_refund_no | 否 | String | 20160806151343391 | 可避免出现重复请求退款 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 返回信息 | msg | String | 失败或成功时返回提示 | |
| 平台退款单号 | refund_no | String | 20160806151343349 | |
| 商户退款单号 | out_refund_no | String | 20160806151343351 | |
| 平台订单号 | trade_no | String | 20160806151343349 | |
| 退款金额 | money | String | ||
| 扣减商户余额 | reducemoney | String | ||
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
订单退款查询#
https://pay.ya92.com/api/pay/refundquery
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 平台退款单号 | refund_no | 二选一 | String | 20160806151343349 | 与商户退款单号必传其一 |
| 商户退款单号 | out_refund_no | 二选一 | String | 20160806151343351 | 与平台退款单号必传其一 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 错误信息 | msg | String | 失败时返回提示 | |
| 平台退款单号 | refund_no | String | 20160806151343349 | |
| 商户退款单号 | out_refund_no | String | 20160806151343351 | |
| 平台订单号 | trade_no | String | 20160806151343349 | |
| 商户订单号 | out_trade_no | String | 20160806151343351 | |
| 退款金额 | money | String | ||
| 扣减商户余额 | reducemoney | String | ||
| 退款状态 | status | Int | 1 | 0:失败,1:成功 |
| 退款时间 | addtime | String | 2024-07-01 16:47:32 | |
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
订单关闭#
https://pay.ya92.com/api/pay/close
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 平台订单号 | trade_no | 二选一 | String | 20160806151343349 | 与商户订单号必传其一 |
| 商户订单号 | out_trade_no | 二选一 | String | 20160806151343351 | 与平台订单号必传其一 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 返回信息 | msg | String | 失败或成功时返回提示 | |
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
只有部分支付插件支持关闭订单操作。
查询商户信息#
https://pay.ya92.com/api/merchant/info
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 返回信息 | msg | String | 失败或成功时返回提示 | |
| 商户 ID | pid | Int | 1001 | |
| 商户状态 | status | Int | 1 | 0:已封禁,1:正常,2:待审核 |
| 支付状态 | pay_status | Int | 1 | 0:关闭,1:开启 |
| 结算状态 | settle_status | Int | 1 | 0:关闭,1:开启 |
| 商户余额 | money | String | 50.00 | 单位:元 |
| 结算方式 | settle_type | Int | 1 | 见结算方式列表 |
| 结算账户 | settle_account | String | alipay@alipay.com | |
| 结算账户姓名 | settle_name | String | 张三 | |
| 订单总数量 | order_num | Int | 10 | |
| 今日订单数量 | order_num_today | Int | 3 | |
| 昨日订单数量 | order_num_lastday | Int | 2 | |
| 今日订单收入 | order_money_today | String | 45.00 | 单位:元 |
| 昨日订单收入 | order_money_lastday | String | 35.00 | 单位:元 |
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
结算方式列表
| 状态值 | 描述 |
|---|---|
1 | 支付宝 |
2 | 微信 |
3 | QQ 钱包 |
4 | 银行卡 |
查询订单列表#
查询订单列表可用于对账或同步订单状态等。
https://pay.ya92.com/api/merchant/orders
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 查询偏移 | offset | 是 | Int | 0 | 从 0 开始 |
| 每页条数 | limit | 是 | Int | 50 | 最大不能超过 50 |
| 过滤订单状态 | status | 否 | Int | 1 | 0:未支付,1:已支付 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
转账发起#
平台需开通代付功能,且在商户后台开启「代付 API 接口」开关,才能调用本接口发起转账。
https://pay.ya92.com/api/transfer/submit
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 转账方式 | type | 是 | String | alipay | 见转账方式列表 |
| 收款方账号 | account | 是 | String | alipay@alipay.com | 支付宝账号 / 微信 OpenId / 银行卡号 |
| 收款方姓名 | name | 否 | String | 张三 | 传入则校验账号与该姓名是否匹配 |
| 转账金额 | money | 是 | String | 1.00 | 单位:元 |
| 转账备注 | remark | 否 | String | ||
| 转账交易号 | out_biz_no | 否 | String | 2016080615134334917 | 传入后可避免出现重复请求转账 |
| 安全发账本 ID | bookid | 否 | String | 仅支付宝安全发转账可以传入 | |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 错误信息 | msg | String | 失败时返回转账失败原因 | |
| 转账状态 | status | Int | 1 | 0:正在处理,1:转账成功 |
| 系统交易号 | biz_no | String | 2016080615134334917 | |
| 商户交易号 | out_biz_no | String | 2016080615134334917 | 可用于后续转账查询 |
| 接口转账单号 | orderid | String | 40001283951815782 | 支付宝/微信返回的转账单号 |
| 转账完成时间 | paydate | String | 2024-07-01 16:47:32 | |
| 转账花费金额 | cost_money | String | 从商户可用余额扣减的金额 | |
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
转账方式列表
| 状态值 | 描述 |
|---|---|
alipay | 支付宝 |
wxpay | 微信支付 |
qqpay | QQ 钱包 |
bank | 银行卡 |
如果返回的转账状态 status=0,则需稍后调用转账查询接口查询转账状态。
转账查询#
https://pay.ya92.com/api/transfer/query
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 系统交易号 | biz_no | 二选一 | String | 2016080615134334919 | 与商户交易号必传其一 |
| 商户交易号 | out_biz_no | 二选一 | String | 2016080615134334919 | 与系统交易号必传其一 |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 返回信息 | msg | String | 成功或失败时返回提示 | |
| 转账状态 | status | Int | 1 | 0:正在处理,1:转账成功,2:转账失败 |
| 转账失败原因 | errmsg | String | 收款方账户异常 | status=2 时才返回 |
| 系统交易号 | biz_no | String | 2016080615134334917 | |
| 商户交易号 | out_biz_no | String | 2016080615134334917 | |
| 接口转账单号 | orderid | String | 40001283951815782 | 支付宝/微信返回的转账单号 |
| 转账完成时间 | paydate | String | 2024-07-01 16:47:32 | |
| 转账金额 | amount | String | 单位:元 | |
| 转账花费金额 | cost_money | String | 从商户可用余额扣减的金额 | |
| 转账备注 | remark | String | ||
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
可用余额查询#
https://pay.ya92.com/api/transfer/balance
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 当前时间戳 | timestamp | 是 | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | 是 | String | 参考签名规则 | |
| 签名类型 | sign_type | 是 | String | RSA | 默认为 RSA |
返回参数
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它值为失败 |
| 返回信息 | msg | String | 成功或失败时返回提示 | |
| 商户可用余额 | available_money | String | 1.00 | 单位:元 |
| 转账手续费率 | transfer_rate | String | 3 | % |
| 当前时间戳 | timestamp | String | 1721206072 | 10 位整数,单位秒 |
| 签名字符串 | sign | String | 参考签名规则 | |
| 签名类型 | sign_type | String | RSA | 默认为 RSA |
V1 协议规则与签名#
/submit.php、/mapi.php、/api.php,仅覆盖支付与查询类功能。新接入请直接使用 V2 接口(RSA 签名,支持退款、代付等完整能力)。application/x-www-form-urlencodedJSONUTF-8MD5MD5 签名算法
- 将发送或接收到的所有参数按照参数名 ASCII 码从小到大排序(a-z);
sign、sign_type和空值不参与签名。 - 将排序后的参数拼接成 URL 键值对格式,例如
a=b&c=d&e=f,参数值不要进行 URL 编码。 - 再将拼接好的字符串与商户密钥 KEY 进行 MD5 加密,得出
sign:sign = md5(拼接字符串 + KEY)。
公式里的「+」是各语言的字符串拼接符,不是字面量字符;MD5 结果取小写。具体签名与发起支付的完整示例可下载 SDK 查看。
/** V1 旧版 MD5 签名 */
function epaySign(array $params, string $key): string
{
// 1. 剔除 sign / sign_type 与空值
unset($params['sign'], $params['sign_type']);
$params = array_filter($params, function ($v) {
return $v !== '' && $v !== null;
});
// 2. 键名 ASCII 升序
ksort($params, SORT_STRING);
// 3. 拼接成 k=v&k=v(值不做 URL 编码)后与密钥一起 md5
$pairs = [];
foreach ($params as $k => $v) {
$pairs[] = $k . '=' . $v;
}
return strtolower(md5(implode('&', $pairs) . $key));
}
import hashlib
from urllib.parse import quote
def epay_sign(params: dict, key: str) -> str:
"""V1 旧版 MD5 签名"""
data = {k: v for k, v in params.items()
if k not in ("sign", "sign_type") and v not in (None, "")}
source = "&".join(f"{k}={v}" for k, v in sorted(data.items()))
return hashlib.md5((source + key).encode("utf-8")).hexdigest()
V1 页面跳转支付#
此接口可用于用户前台直接发起支付,使用 form 表单跳转或拼接成 URL 跳转。
https://pay.ya92.com/submit.php
亦支持 GET(推荐 POST,不容易被劫持或屏蔽)
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 支付方式 | type | 否 | String | alipay | 见V1 支付方式列表;不传会跳转到收银台 |
| 商户订单号 | out_trade_no | 是 | String | 20160806151343349 | |
| 异步通知地址 | notify_url | 是 | String | http://www.pay.com/notify_url.php | 服务器异步通知地址 |
| 跳转通知地址 | return_url | 是 | String | http://www.pay.com/return_url.php | 页面跳转通知地址 |
| 商品名称 | name | 是 | String | VIP会员 | 超过 127 个字节会自动截取 |
| 商品金额 | money | 是 | String | 1.00 | 单位:元,最大 2 位小数 |
| 业务扩展参数 | param | 否 | String | 没有请留空 | 支付后原样返回 |
| 签名字符串 | sign | 是 | String | 202cb962ac59075b964b07152d234b70 | 见MD5 签名算法 |
| 签名类型 | sign_type | 是 | String | MD5 | 默认为 MD5 |
示例代码
<!-- V1 页面跳转支付:表单自动提交 -->
<form id="payForm" action="https://pay.ya92.com/submit.php" method="post">
<input type="hidden" name="pid" value="1001">
<input type="hidden" name="type" value="alipay">
<input type="hidden" name="out_trade_no" value="20160806151343349">
<input type="hidden" name="notify_url" value="http://www.pay.com/notify_url.php">
<input type="hidden" name="return_url" value="http://www.pay.com/return_url.php">
<input type="hidden" name="name" value="VIP会员">
<input type="hidden" name="money" value="1.00">
<input type="hidden" name="sign" value="MD5 签名结果">
<input type="hidden" name="sign_type" value="MD5">
</form>
<script>document.getElementById('payForm').submit();</script>
$params = [
'pid' => '1001',
'type' => 'alipay',
'out_trade_no' => '20160806151343349',
'notify_url' => 'http://www.pay.com/notify_url.php',
'return_url' => 'http://www.pay.com/return_url.php',
'name' => 'VIP会员',
'money' => '1.00',
];
$params['sign'] = epaySign($params, $merchantKey);
$params['sign_type'] = 'MD5';
echo '<form id="f" method="post" action="https://pay.ya92.com/submit.php">';
foreach ($params as $k => $v) {
echo '<input type="hidden" name="' . htmlspecialchars($k) . '" value="' . htmlspecialchars($v) . '">';
}
echo '</form><script>document.getElementById("f").submit();</script>';
V1 API 接口支付#
此接口可用于服务器后端发起支付请求,会返回支付二维码链接或支付跳转 URL。
https://pay.ya92.com/mapi.php
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 支付方式 | type | 是 | String | alipay | 见V1 支付方式列表 |
| 商户订单号 | out_trade_no | 是 | String | 20160806151343349 | |
| 异步通知地址 | notify_url | 是 | String | http://www.pay.com/notify_url.php | 服务器异步通知地址 |
| 跳转通知地址 | return_url | 否 | String | http://www.pay.com/return_url.php | 页面跳转通知地址 |
| 商品名称 | name | 是 | String | VIP会员 | 超过 127 个字节会自动截取 |
| 商品金额 | money | 是 | String | 1.00 | 单位:元,最大 2 位小数 |
| 用户 IP 地址 | clientip | 是 | String | 192.168.1.100 | 用户发起支付的 IP 地址 |
| 设备类型 | device | 否 | String | pc | 根据用户浏览器 UA 判断,见V1 设备类型列表;默认为 pc |
| 业务扩展参数 | param | 否 | String | 没有请留空 | 支付后原样返回 |
| 签名字符串 | sign | 是 | String | 202cb962ac59075b964b07152d234b70 | 见MD5 签名算法 |
| 签名类型 | sign_type | 是 | String | MD5 | 默认为 MD5 |
返回结果(JSON)
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 1 | 1 为成功,其它值为失败 |
| 返回信息 | msg | String | 失败时返回原因 | |
| 订单号 | trade_no | String | 20160806151343349 | 支付订单号 |
| 支付跳转 URL | payurl | String | https://pay.ya92.com/pay/wxpay/202010903/ | 若返回该字段,则直接跳转到该 URL 支付 |
| 二维码链接 | qrcode | String | weixin://wxpay/bizpayurl?pr=04IPMKM | 若返回该字段,则根据该 URL 生成二维码 |
| 小程序跳转 URL | urlscheme | String | weixin://dl/business/?ticket=xxx | 若返回该字段,则使用 JS 跳转,可发起微信小程序支付 |
payurl、qrcode、urlscheme 三个参数只会返回其中一个。
$params = [
'pid' => '1001',
'type' => 'alipay',
'out_trade_no' => '20160806151343349',
'notify_url' => 'http://www.pay.com/notify_url.php',
'return_url' => 'http://www.pay.com/return_url.php',
'name' => 'VIP会员',
'money' => '1.00',
'clientip' => '192.168.1.100',
];
$params['sign'] = epaySign($params, $merchantKey);
$params['sign_type'] = 'MD5';
$ch = curl_init('https://pay.ya92.com/mapi.php');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($params),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
if (($result['code'] ?? 0) == 1) {
if (!empty($result['payurl'])) {
header('Location: ' . $result['payurl']); // 直接跳转支付
} elseif (!empty($result['qrcode'])) {
// 用 $result['qrcode'] 生成二维码给用户扫
} elseif (!empty($result['urlscheme'])) {
// 小程序场景:用 JS 跳转 $result['urlscheme']
}
} else {
exit('下单失败:' . ($result['msg'] ?? '未知错误'));
}
curl -X POST 'https://pay.ya92.com/mapi.php' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'pid=1001' \
-d 'type=alipay' \
-d 'out_trade_no=20160806151343349' \
-d 'notify_url=http://www.pay.com/notify_url.php' \
-d 'name=VIP会员' \
-d 'money=1.00' \
-d 'clientip=192.168.1.100' \
-d 'sign=MD5签名结果' \
-d 'sign_type=MD5'
V1 支付结果通知#
通知类型:服务器异步通知(notify_url)、页面跳转通知(return_url)。
{商户 notify_url}
平台 → 商户
通知参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 平台订单号 | trade_no | 是 | String | 20160806151343349021 | 支付系统侧订单号 |
| 商户订单号 | out_trade_no | 是 | String | 20160806151343349 | 商户系统内部的订单号 |
| 支付方式 | type | 是 | String | alipay | 见V1 支付方式列表 |
| 商品名称 | name | 是 | String | VIP会员 | |
| 商品金额 | money | 是 | String | 1.00 | |
| 支付状态 | trade_status | 是 | String | TRADE_SUCCESS | 只有 TRADE_SUCCESS 表示成功 |
| 业务扩展参数 | param | 否 | String | ||
| 签名字符串 | sign | 是 | String | 202cb962ac59075b964b07152d234b70 | 见MD5 签名算法 |
| 签名类型 | sign_type | 是 | String | MD5 | 默认为 MD5 |
success(纯文本)以表示服务器已正确接收订单通知,否则平台会重复推送。notify_url 处理示例
// V1 回调:先验签,再判断 trade_status
$params = $_GET;
$sign = $params['sign'] ?? '';
if (!hash_equals(epaySign($params, $merchantKey), $sign)) {
exit('sign error');
}
if (($params['trade_status'] ?? '') !== 'TRADE_SUCCESS') {
exit('success');
}
// 幂等处理:同一 out_trade_no 可能收到多次通知
markOrderPaid($params['out_trade_no'], $params['trade_no']);
exit('success');
V1 支付方式与设备类型#
支付方式列表
| 调用值 | 描述 |
|---|---|
alipay | 支付宝 |
wxpay | 微信支付 |
qqpay | QQ 钱包 |
bank | 银联支付 |
jdpay | 京东支付 |
paypal | PayPal |
douyinpay | 抖音支付 |
设备类型列表
| 调用值 | 描述 |
|---|---|
pc | 电脑浏览器 |
mobile | 手机浏览器 |
qq | 手机 QQ 内浏览器 |
wechat | 微信内浏览器 |
alipay | 支付宝客户端 |
douyin | 抖音 APP |
jump | 仅返回支付跳转 URL |
V1 查询商户信息#
https://pay.ya92.com/api.php?act=query&pid={商户ID}&key={商户密钥}
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 操作类型 | act | 是 | String | query | 此 API 固定值 |
| 商户 ID | pid | 是 | Int | 1001 | |
| 商户密钥 | key | 是 | String | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i |
返回结果
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 1 | 1 为成功,其它值为失败 |
| 商户 ID | pid | Int | 1001 | |
| 商户密钥 | key | String(32) | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i | |
| 商户状态 | active | Int | 1 | 1 为正常,0 为封禁 |
| 商户余额 | money | String | 0.00 | 商户所拥有的余额 |
| 结算方式 | type | Int | 1 | 1:支付宝,2:微信,3:QQ,4:银行卡 |
| 结算账号 | account | String | admin@pay.com | 结算账号 |
| 结算姓名 | username | String | 张三 | 结算姓名 |
| 订单总数 | orders | Int | 30 | 订单总数统计 |
| 今日订单 | order_today | Int | 15 | 今日订单数量 |
| 昨日订单 | order_lastday | Int | 15 | 昨日订单数量 |
V1 查询结算记录#
https://pay.ya92.com/api.php?act=settle&pid={商户ID}&key={商户密钥}
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 操作类型 | act | 是 | String | settle | 此 API 固定值 |
| 商户 ID | pid | 是 | Int | 1001 | |
| 商户密钥 | key | 是 | String | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i |
返回结果
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 1 | 1 为成功 |
| 返回信息 | msg | String | 查询结算记录成功! | |
| 结算记录 | data | Array | 结算记录列表 |
V1 查询单个订单#
https://pay.ya92.com/api.php?act=order&pid={商户ID}&key={商户密钥}&out_trade_no={商户订单号}
也可用 trade_no 传系统订单号。
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 操作类型 | act | 是 | String | order | 此 API 固定值 |
| 商户 ID | pid | 是 | Int | 1001 | |
| 商户密钥 | key | 是 | String | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i | |
| 系统订单号 | trade_no | 二选一 | String | 20160806151343312 | |
| 商户订单号 | out_trade_no | 二选一 | String | 20160806151343349 |
系统订单号与商户订单号二选一传入即可;若都传入,以系统订单号为准。
返回结果
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 1 | 1 为成功,其它值为失败 |
| 返回信息 | msg | String | 查询订单号成功! | |
| 平台订单号 | trade_no | String | 2016080622555342651 | 支付系统侧订单号 |
| 商户订单号 | out_trade_no | String | 20160806151343349 | 商户系统内部的订单号 |
| 第三方订单号 | api_trade_no | String | 20160806151343349 | 支付宝、微信等接口方订单号 |
| 支付方式 | type | String | alipay | 见V1 支付方式列表 |
| 商户 ID | pid | Int | 1001 | 发起支付的商户 ID |
| 创建订单时间 | addtime | String | 2016-08-06 22:55:52 | |
| 完成交易时间 | endtime | String | 2016-08-06 22:55:52 | |
| 商品名称 | name | String | VIP会员 | |
| 商品金额 | money | String | 1.00 | |
| 支付状态 | status | Int | 0 | 1 为支付成功,0 为未支付 |
| 业务扩展参数 | param | String | 默认留空 | |
| 支付者账号 | buyer | String | 默认留空 |
V1 批量查询订单#
https://pay.ya92.com/api.php?act=orders&pid={商户ID}&key={商户密钥}
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 操作类型 | act | 是 | String | orders | 此 API 固定值 |
| 商户 ID | pid | 是 | Int | 1001 | |
| 商户密钥 | key | 是 | String | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i | |
| 查询订单数量 | limit | 否 | Int | 20 | 最大 50 |
| 页码 | page | 否 | Int | 1 | 当前查询的页码 |
返回结果
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 1 | 1 为成功 |
| 返回信息 | msg | String | 查询结算记录成功! | |
| 订单列表 | data | Array | 订单列表,字段可参考V1 查询单个订单 |
V1 提交订单退款#
需要先在商户后台开启「订单退款 API」开关,才能调用该接口发起订单退款。
https://pay.ya92.com/api.php?act=refund
请求参数
| 字段名 | 变量名 | 必填 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|---|
| 商户 ID | pid | 是 | Int | 1001 | |
| 商户密钥 | key | 是 | String | 89unJUB8HZ54Hj7x4nUj56HN4nUzUJ8i | |
| 平台订单号 | trade_no | 二选一 | String | 20160806151343349021 | 与 out_trade_no 不能同时为空;都传时以本字段为准 |
| 商户订单号 | out_trade_no | 二选一 | String | 20160806151343349 | 下单时传入的商户订单号,须在商家系统中唯一 |
| 退款金额 | money | 是 | String | 1.50 | 少数通道需要与原订单金额一致 |
返回结果
| 字段名 | 变量名 | 类型 | 示例值 | 描述 |
|---|---|---|---|---|
| 返回状态码 | code | Int | 0 | 0 为成功,其它为失败 |
| 返回信息 | msg | String | 退款成功 |
SDK 下载与示例#
官方提供现成的接入示例包,内含完整的签名、下单、异步通知验签、订单查询、退款实现,可直接对照改造。下载地址为平台官方公开发布的资源,本站直接引用,不做二次转载。
示例包里通常包含
- 签名工具类:待签名字符串拼装、排序、加密 / 验签(V2 为 RSA,V1 为 MD5)。
- 下单示例:页面跳转支付(表单提交)与统一下单(接口返回支付地址 / 二维码)。
- 异步通知处理:验签 + 判断交易状态 + 输出
success的完整回调样例。 - 查询与退款:订单查询、退款、退款查询的请求封装。
常见问题#
签名总是验签失败怎么办?
- 确认剔除了
sign、sign_type以及所有空值参数后再拼接。 - 拼接顺序必须是键名的 ASCII 升序,且区分大小写,不要用 locale 排序。
- 待签名字符串不要做 URL 编码(编码只在最终发起 HTTP 请求时对参数做一次)。
- 确认使用的是商户私钥签名、平台公钥验签,不要用反。
- 密钥需为完整 PEM 格式(含
-----BEGIN...-----头尾)。
异步通知收不到,或收到多次?
notify_url必须是公网可直接访问的地址,不能是localhost或内网 IP。- 处理完必须输出纯文本
success,否则平台判定失败并重推。 - 收到多次属正常现象,业务侧必须做幂等(按
out_trade_no去重)。 - 务必以异步通知为准,
return_url跳转可能因用户关闭浏览器而丢失。
返回 code 非 0 如何排查?
- 先看返回的
msg文案,多数情况下已说明原因(如余额不足、通道维护、金额超限)。 - 检查
timestamp是否为 10 位秒级时间戳,与服务器时间偏差过大会被拒绝。 - 确认
pid与签名用的密钥属于同一商户。
如何快速自测?
可在测试支付页面直接发起一笔小额测试订单,验证通道是否可用(测试订单不支持退款)。