版本 1.0

对外支付 API 接口文档

适用于无开发能力的网站方快速接入支付 · 南阳市儒谦商贸有限公司提供

快速开始(3 步完成对接)

  1. 复制下方「完整 PHP 示例」代码,替换 3 个配置项(商户ID、密钥、通知地址)
  2. 上传到你的服务器,访问该文件即可发起支付
  3. 看到跳转支付宝即对接成功

支付链路架构(双层验签)

本系统存在两套独立的验签流程,商户只需关注第一套:

第一层:商户 ↔ 平台(MD5)

  • 商户下单时用商户密钥对参数做 MD5 签名
  • 平台验证签名后受理订单
  • 支付成功后,平台用同一密钥签名并 GET 通知商户的 notify_url
  • 商户收到通知后用同一密钥验签确认

第二层:平台 ↔ 支付宝(RSA2)

  • 平台用应用私钥对支付宝请求做 RSA2 签名
  • 支付宝支付成功后回调平台的 alipay-notify 接口
  • 平台用支付宝公钥验证回调签名(RSA2)
  • 验签通过后平台更新订单状态,再转发通知给商户

商户无需对接支付宝、无需配置支付宝密钥,只需与平台完成 MD5 验签即可。支付宝的 notify_url 由平台内部管理,商户传入的 notify_url 仅用于接收平台转发的支付结果通知。

1. 接口地址与请求头

POST https://baas-api.wanwang.xin/supabase/proxy/WS20260801233620000001/functions/v1/external-api

Content-Type: application/x-www-form-urlencoded 或 application/json(两种均支持)

每个请求必须携带以下 3 个请求头(直接复制,所有商户通用):

Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InBvbGFyZGIiLCJpYXQiOjE3ODQ2MTQ2MTgsImV4cCI6MjA5OTk3NDYxOH0.StbzHSCkim8How6H3eZWH-RKMiIXqNc1QSm0LKZi_Vg

apikey: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InBvbGFyZGIiLCJpYXQiOjE3ODQ2MTQ2MTgsImV4cCI6MjA5OTk3NDYxOH0.StbzHSCkim8How6H3eZWH-RKMiIXqNc1QSm0LKZi_Vg

Referer: https://www.ruqianshop.cn

这是平台网关的固定认证信息,无需理解其含义,直接复制即可。

2. 请求参数

字段名变量名必填类型示例值描述
商户IDpid是Int1001由平台分配的商户ID
支付方式type是Stringalipay固定为 alipay
商户订单号out_trade_no是String20160806151343349商户系统内部唯一订单号
异步通知地址notify_url是Stringhttps://yourdomain.com/notify支付成功后接收 GET 通知
同步跳转地址return_url否Stringhttps://yourdomain.com/return支付完成后用户跳转地址
商品名称name是StringVIP会员不超过 127 字节
商品金额money是String1.00单位元,最多两位小数
用户 IPclientip是String192.168.1.100用户发起支付的 IP
设备/场景类型device否Stringpc可选 qr(或 scan)、pc、mobile。qr 为扫码场景,会把后台标记为「仅扫码」的通道(如当面付)纳入可选池;pc 为电脑网页场景;mobile 为手机网页场景。不传时平台按请求 User-Agent 自动识别 pc/mobile;UA 也认不出终端(服务端 curl/PHP/Java 等)则归入「未识别兜底」(web)场景。服务端发起的请求强烈建议显式传参,详见 2.2 常见问答
业务扩展参数param否Stringabc123支付后原样返回
签名字符串sign是Stringmd5 计算结果见下方签名算法
签名类型sign_type是StringMD5固定为 MD5

2.1 设备/场景类型与通道选择

平台按以下优先级确定本次下单的场景,并据此筛选支付通道:

优先级判定依据说明
1显式传入 device=qr / scan / pc / mobile最高优先级,大小写不敏感;qr 与 scan 等价,均表示扫码场景;其他值视为未传
2请求头 User-Agent 自动识别含 Android/iPhone/iPad/MicroMessenger 等判为 mobile,其余浏览器 UA 判为 pc;订单备注标记 device_src:ua
3无法判定(UA 为空或为服务端客户端)curl / PHP / Java / Python / okhttp / Go-http-client 等归为「未识别兜底」(web)场景,只在勾选了该标签或未限定场景的通道中按权重随机

device=qr 扫码场景

  • 返回 qrcode + urlscheme,payurl 为平台收银台中间页
  • 后台被设为「不进大轮询 + 仅扫码」的通道(如当面付)在此场景被优先独占使用
  • 存在这类专属通道时,其他不限场景的通用轮询通道不再参与本场景分配;没有专属通道时才按权重随机

device=pc 可选通道

  • 订单码(order_code):返回 qrcode + urlscheme,收银台页展示二维码
  • 当面付(precreate / face):返回 qrcode + urlscheme,同上
  • 电脑网站支付(page):返回 payurl,跳转支付宝原生收银台

device=mobile 可选通道

  • 手机网站支付(wap):返回 payurl,手机浏览器内唤起支付宝 App
  • 订单码 / 当面付:返回 qrcode + urlscheme,可直接用 urlscheme 唤起支付宝
  • 不会分配电脑网站支付(page),避免手机端跳到 PC 收银台无法付款

已对接商户升级说明(接口完全向下兼容,不改也能正常收款)

  • 签名算法、请求地址、请求头、返回结构、异步通知格式均无变化,无需重新对接
  • 服务端发起下单(PHP/curl/Java 等)请务必显式传 device:PC 站点传 pc,手机站或 H5 传 mobile,需要走扫码收银台传 qr;不传时因 UA 为服务端客户端,会归为「未识别兜底」场景,可能分配不到你期望的通道
  • 本次升级仅新增 device=qr / scan 可选值与平台内部的通道场景筛选规则,签名算法、请求地址、请求头、返回结构、异步通知格式均无变化;已按 pc / mobile 对接的商户无需修改代码
  • 平台侧可为通道配置「是否参与通用大轮询」与「适用场景」(扫码/电脑网页/手机网页/未识别兜底):不参与大轮询但显式勾选了当前场景的通道属于场景专属通道,该场景的订单会优先只分配给它,因此商户传对 device 直接决定走哪个通道
  • 预下单遇到通道致命错误(如未签约产品、无权限 ACCESS_FORBIDDEN)时,平台会自动切换到其他可用通道重试(最多 3 次)并回写实际通道,商户侧无感知;全部失败才返回 code=-101,订单标记为 failed
  • 由浏览器直接调用下单接口的场景可不传 device,平台按 UA 自动识别
  • 新增可选参数 device 参与签名:传了就按普通参数一起排序签名,不传则不参与(空值不签名规则不变)
  • 返回字段新增 pay_method(实际使用的通道支付方式),可用于前端判断展示二维码还是跳转 payurl;旧代码忽略该字段不受影响
  • 扫码类通道(订单码/当面付)返回 qrcode 与 urlscheme,payurl 为平台收银台中间页;网页类通道(wap/page)返回 payurl 与 ready=true,qrcode 为空。建议按「qrcode 是否有值」分支处理,而不是按固定模式写死
  • 异步通知时机为资金确认到账后发送(小额自动确认,大额等待结算通知或人工确认),商户侧仍需保持幂等处理与返回 success

2.2 常见问答

Qdevice=qr 适合什么场景?和 pc / mobile 有什么区别?▶

你的页面需要展示二维码、让用户拿手机扫码付款时传 qr(scan 与 qr 完全等价)。

此时平台会把后台标记为「仅扫码」的通道(如当面付)纳入可选池,同时保留不限场景的通用通道,一起按权重随机分配。

返回 qrcode 与 urlscheme,payurl 为平台收银台中间页;pc / mobile 场景则不会分配「仅扫码」通道。

Q不传 device 时平台怎么判断?▶

读取请求头 User-Agent:含 Android / iPhone / iPad / MicroMessenger 等判为 mobile,其余浏览器 UA 判为 pc,订单备注会标记 device_src:ua。

浏览器直接调用下单接口时可以不传,由平台自动识别。

QUA 识别失败(未识别兜底)是什么情况,会有什么影响?▶

服务端发起的请求(curl / PHP / Java / Python / okhttp / Go-http-client 等)UA 认不出终端,平台归入 web 兜底场景,订单 device 字段为空。

兜底场景只在「未限定场景」或显式勾选了「未识别兜底」的通道中按权重随机;标记为「仅扫码」的通道不会被选中。

若某场景下没有任何通道命中,平台会回退到全部可用通道,保证订单不会因场景筛选而失败。

因此服务端对接请务必显式传 device,否则可能分配不到你期望的通道。

Q通道被设为「不参与通用大轮询」后还能被选中吗?▶

能,而且会被优先使用:当下单场景显式命中它勾选的适用场景标签时,该场景的订单只分配给这类专属通道,其他通用通道不再参与随机。

例如某当面付通道关闭大轮询且只勾「扫码」,则 device=qr 的订单全部走它,pc / mobile / 兜底场景都不会命中它。

若同一场景勾选了多个专属通道,则在这些专属通道之间按权重随机。

Q传了 device 之后签名要怎么算?▶

device 是普通可选参数:传了就和其他参数一起按参数名 a-z 排序参与 MD5 签名,不传则不参与(空值不签名规则不变)。

注意大小写不敏感(PC / pc 均可),但签名请使用你实际发送的原始值。

Q预下单遇到通道错误会自动换通道吗?▶

会。遇到未签约产品、无权限(ACCESS_FORBIDDEN)等致命错误时,平台自动切换到同场景下的其他可用通道重试,最多 3 个通道,并回写实际使用的通道,商户侧无感知。

全部失败才返回 code=-101,订单标记为 failed,请勿高频重试。

3. 签名算法

签名规则(务必严格遵守):

  1. 去掉 sign 和 sign_type 两个参数
  2. 去掉值为空的参数(空字符串不参与签名)
  3. 剩余参数按参数名 a-z 排序
  4. 拼接为 key1=value1&key2=value2 格式(值不做 URL 编码)
  5. 末尾直接拼接商户密钥(不加 & 符号)
  6. 对整个字符串计算 MD5(32位小写)

验签常见踩坑(务必注意):

  • 不要对值做 URL 编码/解码:签名使用原始值拼接,不要 urlencode 也不要 urldecode
  • 不要引入多余空格:key=value 之间、& 前后、密钥前后都不能有空格
  • 末尾无 &:最后一个参数值后面直接拼密钥,不加 & 分隔符
  • MD5 必须 32 位小写:不要大写,不要 16 位截取
  • 空值参数不参与:值为空字符串的参数直接跳过,不是拼 key=

4. 返回结果(JSON)

字段名变量名必填类型示例值描述
返回状态码code否Int11 成功,其它为失败
返回信息msg否Stringsuccess失败原因
订单号trade_no否String20160806151343349商户订单号(原样返回)
支付跳转链接payurl否Stringhttps://...wap/page 通道为支付宝收银台地址,直接跳转;扫码类通道为平台收银台中间页(页内展示二维码,移动端可自动唤起支付宝)
二维码链接qrcode否Stringhttps://qr.alipay.com/xxx扫码支付模式返回,可用于生成二维码
支付宝 schemeurlscheme否Stringalipays://platformapi/...扫码支付模式返回,APP 内唤起支付宝用
就绪标记ready否Booleantrue网页/手机支付模式返回 true,表示可直接跳转 payurl
通道支付方式pay_method否Stringorder_code本次实际使用的通道类型:order_code 订单码、precreate/face 当面付、wap 手机网站支付、page 电脑网站支付。可用于前端判断展示二维码还是跳转 payurl

code=1 表示成功,此时 payurl 必有值,将用户跳转至 payurl 即可完成支付。扫码模式额外返回 qrcode 和 urlscheme;网页/手机模式额外返回 ready=true。

5. 异步通知(GET)

支付宝确认收款后,平台先通过 RSA2 验签确认支付宝回调,待资金实际到账确认后(即时到账自动确认,延迟到账需等待结算通知),再用商户密钥(MD5)签名并向你的 notify_url 发送 GET 请求:

字段名变量名必填类型示例值描述
商户IDpid否Int1001固定值
系统订单号trade_no否String2026081234567890支付宝交易号
商户订单号out_trade_no否String20160806151343349商户订单号
支付方式type否Stringalipay固定值
商品名称name否StringVIP会员下单时传入的商品名
商品金额money否String1.00订单金额
支付状态trade_status否StringTRADE_SUCCESS仅此值表示成功
业务扩展参数param否Stringabc123下单时传入则原样返回;未传入则通知中不包含此字段
签名字符串sign否Stringmd5 值按签名算法验证
签名类型sign_type否StringMD5固定值

收到通知后:1. 按相同签名算法验证 sign;2. 确认 trade_status=TRADE_SUCCESS;3. 更新订单状态;4. 返回 HTTP 200 且响应体包含 success(不区分大小写)。若未满足条件,系统最多重试 3 次。

异步通知验签示例(PHP)
<?php
// notify.php - 异步通知接收
$md5Key = '你的商户密钥';

$params = $_GET;
$sign = $params['sign'];
unset($params['sign']);
unset($params['sign_type']);
ksort($params);
$str = '';
foreach ($params as $k => $v) {
    if ($v === '' || $v === null) continue;
    $str .= $k . '=' . $v . '&';
}
$expected = md5(rtrim($str, '&') . $md5Key);

if ($expected === $sign && $_GET['trade_status'] === 'TRADE_SUCCESS') {
    // 验签通过,更新你的订单状态
    // $outTradeNo = $_GET['out_trade_no'];
    // $money = $_GET['money'];
    http_response_code(200);
    echo 'success';  // 必须返回 success,否则系统认为通知失败会重试
} else {
    http_response_code(400);
    echo 'fail';
}

6. 错误码

code说明
1成功
-1缺少必要参数
-2仅支持 MD5 签名
-3签名验证失败
-4金额无效
-5无效的 notify_url
-6订单号已存在(重复)
-7当前IP付款次数已达上限,请稍后再试
-100数据库错误
-101业务错误(如支付通道异常)。HTTP 状态码仍为 200,请以 body 中的 code 为准;平台已内置通道致命错误自动切换(最多重试 3 个通道),仍返回 -101 说明当前无可用通道,请勿高频重试

7. 查询单个订单接口

用于查询支付订单状态,签名算法与支付接口完全一致。

GET https://baas-api.wanwang.xin/supabase/proxy/WS20260801233620000001/functions/v1/query-order

支持 GET 和 POST 请求,需携带与下单接口相同的 Authorization、apikey、Referer 请求头(见第1节)。

注意:GET 请求参数放在 URL query string 中;POST 请求参数以 JSON 格式放在 body 中(Content-Type: application/json)。

7.1 请求参数

字段名变量名必填类型示例值描述
操作类型act是Stringorder固定值 order
商户IDpid是Int1001由平台分配的商户ID;必传,且只能查到归属本商户ID的订单
商户订单号out_trade_no二选一String20160806151343349与 trade_no 二选一
系统订单号trade_no二选一String20160806151343312优先使用此参数
签名字符串sign是StringMD5计算结果见支付接口签名算法
签名类型sign_type是StringMD5固定为 MD5

7.2 返回结果(JSON)

字段名变量名必填类型示例值描述
返回状态码code-Int11 成功,其它为失败
返回信息msg-String查询成功失败原因
系统订单号trade_no-String2026081234567890支付宝交易号(未支付时回退为商户订单号)
商户订单号out_trade_no-String20160806151343349商户订单号
第三方订单号api_trade_no-String2026081234567890支付宝交易号(未支付为空字符串)
支付方式type-Stringalipay固定值
商户IDpid-Int1001商户ID
创建订单时间addtime-String2026-08-06 22:55:52订单创建时间
完成交易时间endtime-String2026-08-06 22:55:52支付成功时间(未支付为空字符串)
商品名称name-StringVIP会员下单时商品名
商品金额money-String1.00订单金额
支付状态status-Int11 已支付,0 未支付
业务扩展参数param-Stringabc123下单时传入的 param 原样返回(未传则为空字符串)
支付者账号buyer-String当前留空

7.3 错误码

code说明
1成功
-1无效操作
-2缺少商户ID
-3缺少订单号
-4缺少签名
-5签名验证失败
-6订单不存在(订单号不存在,或该订单不归属当前 pid)
-100数据库错误
-101系统错误

7.4 示例请求

GET 示例
https://baas-api.wanwang.xin/supabase/proxy/WS20260801233620000001/functions/v1/query-order?act=order&pid=1001&out_trade_no=order_1786533221877324&sign=xxx&sign_type=MD5

说明:pid 为必传参数,服务端按 pid 精确匹配订单归属,商户仅可查询自己名下订单,查询他人订单号统一返回 -6 订单不存在;sign 按第 3 节签名算法,使用参与请求的参数(不含 sign、sign_type)加商户密钥计算。

8. 完整 PHP 示例(复制即用)

将以下代码保存为 pay.php,替换前 3 行配置后上传到你的服务器即可使用:

pay.php - 完整下单示例
<?php
// ===== 只需修改这 3 项 =====
$pid = 1001;                                    // 你的商户ID
$md5Key = '你的商户密钥';                        // 平台分配的密钥
$notifyUrl = 'https://你的域名/notify.php';     // 你的异步通知地址

// ===== 以下无需修改 =====
$apiUrl = 'https://baas-api.wanwang.xin/supabase/proxy/WS20260801233620000001/functions/v1/external-api';
$anonKey = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoiYW5vbiIsImlzcyI6InBvbGFyZGIiLCJpYXQiOjE3ODQ2MTQ2MTgsImV4cCI6MjA5OTk3NDYxOH0.StbzHSCkim8How6H3eZWH-RKMiIXqNc1QSm0LKZi_Vg';

function isMobileUA($ua) {
    return (bool) preg_match('/android|iphone|ipod|ipad|windows phone|harmonyos|micromessenger|mobile/i', $ua);
}

function buildSign($params, $key) {
    unset($params['sign']);
    unset($params['sign_type']);
    ksort($params);
    $str = '';
    foreach ($params as $k => $v) {
        if ($v === '' || $v === null) continue;
        $str .= $k . '=' . $v . '&';
    }
    return md5(rtrim($str, '&') . $key);
}

$params = [
    'pid'          => $pid,
    'type'         => 'alipay',
    'out_trade_no' => 'order_' . time(),
    'notify_url'   => $notifyUrl,
    'return_url'   => 'https://你的域名/return.php',
    'name'         => '测试商品',
    'money'        => '0.01',
    'clientip'     => $_SERVER['REMOTE_ADDR'],
    // 服务端发起请求必须显式传 device:PC 站点传 pc,手机站/H5 传 mobile
    // 若希望走扫码收银台(含仅扫码场景可用的通道,如当面付),传 qr
    // 不传时平台只能读到 curl 的 UA,无法识别终端类型,会归为网页端场景
    'device'       => isMobileUA($_SERVER['HTTP_USER_AGENT'] ?? '') ? 'mobile' : 'pc',
    'sign_type'    => 'MD5',
];
$params['sign'] = buildSign($params, $md5Key);

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL            => $apiUrl,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => http_build_query($params),
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYPEER => false,
    CURLOPT_TIMEOUT        => 15,
    CURLOPT_REFERER        => 'https://www.ruqianshop.cn',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $anonKey,
        'apikey: ' . $anonKey,
    ],
]);
$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
if ($data['code'] == 1) {
    header('Location: ' . $data['payurl']);
} else {
    echo '错误:' . $data['msg'];
}

接入流程

  1. 联系平台运营获取商户ID(pid)与商户密钥。
  2. 复制上方完整 PHP 示例,替换配置项。
  3. 将用户跳转至返回的 payurl 完成支付。
  4. 在 notify_url 接收异步通知并验签,更新订单状态。

商户信息与本站经营资质见 关于我们。