支付对接 1 更新于 2026-10-13

支付渠道对接

文枢CMS 官网的支付模块采用驱动化设计:一个渠道 = 一条数据库记录 + 一个驱动类。后台可随时新增渠道,无需改代码。

一、支持的协议

驱动标识说明
码支付(多财)duocai官方对接渠道,接口地址 https://pay.1kexiu.xyz/
易支付(通用)epay兼容标准易支付协议,只需填网关地址 + PID + KEY
码支付(通用)codepay兼容常见码支付平台,字段名可在扩展参数中映射
余额支付balance站内余额直接扣款,即时到账
本地沙箱sandbox仅开发调试,不产生真实资金

二、签名算法(易支付 / 码支付通用)

  1. 把本次实际发送的全部参数按参数名 ASCII 升序排列
  1. 排除 sign、sign_type、a、c、m、s,以及值为空字符串或 null 的字段
  1. 按 key=value 用 & 连接(值保持原样,不要 URL 编码)
  1. 在参数串末尾直接追加支付对接密钥
  1. 计算 32 位小写 MD5
function makeSign(array $params, string $key): string
{
    unset($params['sign'], $params['sign_type'],
          $params['a'], $params['c'], $params['m'], $params['s']);

    $params = array_filter($params, fn($v) => $v !== '' && $v !== null);
    ksort($params, SORT_STRING);

    $pairs = [];
    foreach ($params as $name => $value) {
        $pairs[] = $name . '=' . $value;
    }

    return md5(implode('&', $pairs) . $key);
}

⚠️ 末尾是直接拼接密钥,不是 &key=密钥。

官方测试向量

用这组参数校验你的实现是否正确:

pay_key = test_pay_key_20260813
pid = M1234567890
type = alipay
out_trade_no = ORDER202608130001
notify_url = https://shop.example.com/pay/notify?channel=alipay&version=2
return_url = https://shop.example.com/pay/return?order=ORDER202608130001&source=pay
name = 测试订单
money = 1.00

正确结果:

beddd35092c3afea54c5218de0872502

注意:notify_url / return_url 里的 & 必须原样参与签名,不要先转成 &;验签时也不要 trim、不要格式化金额、不要二次 URL 解码。

三、下单接口

3.1 页面支付(推荐)

服务端签名后渲染自动提交表单,跳到收银台:

<form id="payForm" action="https://pay.1kexiu.xyz/submit.php" method="post">
  <input type="hidden" name="pid"          value="M1234567890">
  <input type="hidden" name="type"         value="alipay">
  <input type="hidden" name="out_trade_no" value="WS20261010ABCDEF">
  <input type="hidden" name="notify_url"   value="https://example.com/pay/notify/duocai">
  <input type="hidden" name="return_url"   value="https://example.com/pay/return/duocai">
  <input type="hidden" name="name"         value="墨白 · 极简博客模板">
  <input type="hidden" name="money"        value="9.90">
  <input type="hidden" name="sign"         value="SERVER_GENERATED_SIGN">
  <input type="hidden" name="sign_type"    value="MD5">
</form>

3.2 API 下单

POST {网关}mapi.php,成功返回:

{ "code": 1, "msg": "下单成功", "trade_no": "5090058146920009728",
  "payurl": "https://pay.1kexiu.xyz/gateway/Submit/pay?trade_no=..." }

或二维码模式:

{ "code": 1, "msg": "下单成功", "trade_no": "...", "qrcode": "https://qr.alipay.com/..." }

接入端应同时兼容 payurl 与 qrcode,优先取实际非空字段。

失败时 code = -1,响应里会带请求编号,便于向服务商排查。

四、参数说明

参数必填说明
pid是商户 PID
type是alipay / wxpay / qqpay
out_trade_no是商户订单号,仅允许字母、数字及 `. _ - \`,同 PID 内唯一
notify_url是异步通知地址,必须公网可访问的 HTTPS,允许带查询参数
return_url是同步跳转地址,新版必须传
name是商品标题
money是金额(元),0.01 ~ 99999999.99,建议固定两位小数字符串
sign是32 位小写 MD5
sign_type是固定 MD5
param否业务扩展参数,回调时原样返回,不要放敏感信息
clientip否付款用户 IP,非空时参与签名
device否pc / mobile / wechat / alipay / qq,发送时参与签名

五、异步通知(发货依据)

支付成功后平台会 POST 到 notify_url:

参数说明
pid商户 PID
trade_no平台订单号
out_trade_no商户订单号
type支付方式
name商品名称
money金额,固定两位小数(如 1.00)
trade_status只有精确等于 TRADE_SUCCESS 才表示成功
param下单时的扩展参数
sign / sign_type验签字段

处理顺序(务必按这个顺序)

1. 先验签           用收到的原始参数验签,失败立即拒绝
2. 再核订单         核对 PID、订单号、金额与本地待支付记录
3. 幂等入账         以 trade_no 或 out_trade_no 加唯一约束,重复通知不重复发货
4. 最后应答         成功返回纯文本小写 success(不要附带 HTML 或 JSON)

PHP 骨架:

$params = array_replace($_GET, $_POST);   // POST 覆盖同名 GET
if (!hash_equals(makeSign($params, $payKey), (string) ($params['sign'] ?? ''))) {
    http_response_code(400);
    exit('fail');
}
if (($params['trade_status'] ?? '') !== 'TRADE_SUCCESS') {
    http_response_code(400);
    exit('fail');
}
// 事务中锁定订单 → 核对金额 → 只把「未支付」改为「已支付」
// 处理成功后才 return 'success'

严禁只凭浏览器跳转发货。return_url 可能被关闭、重复访问甚至伪造,同步页只用于展示结果。文枢CMS 的 Core\Pay\Pay::settle() 已按上述顺序实现幂等入账。

六、订单查询

POST {网关}api.php,用 pid + 支付对接密钥鉴权:

动作参数返回
商户状态act=query&pid=&key=code、active、money、username、type
单笔订单act=order&pid=&key=&out_trade_no=trade_no、status、money、pay_time
订单列表act=orders&pid=&key=&limit=20&page=1total、data

status 含义:0 未支付 / 1 支付成功 / 2 已超时。

curl --request POST 'https://pay.1kexiu.xyz/api.php' \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'act=order' \
  --data-urlencode 'pid=M1234567890' \
  --data-urlencode 'key=YOUR_PAY_KEY' \
  --data-urlencode 'out_trade_no=WS20261010ABCDEF'

请求超时不要盲目重复下单:先用原 out_trade_no 查单,查到就继续用原平台订单;查不到等几秒再查。当前接口不承诺下单幂等。

七、在官网后台配置渠道

后台 → 支付渠道 → 新增/编辑:

字段说明
渠道标识唯一 code,用于回调地址 /pay/notify/<code>
驱动选择协议类型
网关地址如 https://pay.1kexiu.xyz/(保留末尾斜杠)
商户 PID商户中心显示的 PID
支付对接密钥仅用于签名与验签,不要用登录密码或软件密钥
支付方式可用通道,逗号分隔
扩展参数JSON,如 {"mode":"api"} 切换为 API 下单

配置保存后可在列表点「检测」按钮,程序会调用 act=query 校验商户状态与可用通道。

八、安全红线

  • 密钥只存服务端,绝不下发到浏览器、不可写入日志
  • 生产环境务必开启「强制回调验签」
  • notify_url 不能填 localhost 或内网地址,且路由不要 301/302 跳转
  • 回调应答只能是纯文本 success
  • 汇率 / 金额一律用整数分存储与比对,避免浮点误差