PHP项目如何对接聚合支付接口?

wen PHP项目 21

本文目录导读:

PHP项目如何对接聚合支付接口?

  1. 核心步骤(五步走)
  2. 代码实战(PHP + cURL)
  3. 重要提醒(坑点汇总)
  4. 推荐使用的工具/库
  5. 对接成功后的测试清单

在PHP项目中对接聚合支付接口(如PayJS、虎皮椒、甚至一些开源聚合支付网关),通常遵循标准的第三方HTTP API对接流程(构建参数 -> 签名 -> 发送请求 -> 接收回调)。

以下是一个通用的、标准化的对接步骤和代码示例,以通用的聚合支付网关(假设支持 支付宝微信支付QQ钱包 等)为例。


核心步骤(五步走)

  1. 获取配置:在聚合支付平台注册账号,获得 商户ID商户密钥(AppSecret/API Key)。
  2. 封装请求参数:根据官方文档,组装订单号、金额、支付方式、异步通知地址等。
  3. 生成签名:这是最关键的步骤,防止数据被篡改(通常使用 MD5 或 HMAC-SHA256)。
  4. 发起HTTP请求:使用 cURLGuzzle 发送 POST 请求到支付网关。
  5. 处理异步通知:接收支付平台 POST 过来的回调数据,验证签名并更新订单状态。

代码实战(PHP + cURL)

准备配置类 (config.php)

<?php
// 聚合支付配置
return [
    'merchant_id' => '10086',            // 商户ID
    'merchant_key' => 'xxxxxxxxxxxxxxx', // 商户密钥(API Key)
    'gateway_url' => 'https://api.juhepay.com/gateway', // 支付网关地址
    'notify_url' => 'https://yourdomain.com/notify.php', // 异步通知地址
    'return_url' => 'https://yourdomain.com/return.php', // 同步跳转地址
];
?>

发起支付请求 (pay.php)

<?php
require_once 'config.php';
// 1. 接收前端参数
$pay_type = $_POST['pay_type'] ?? 'alipay'; // alipay, wechat, qq
$amount = $_POST['amount'] ?? 0.01;
$order_id = 'ORD_' . time() . rand(1000, 9999); // 生成商户订单号
// 2. 构建请求参数(具体字段参考聚合支付文档)
$params = [
    'merchant_id' => $config['merchant_id'],
    'order_id'   => $order_id,
    'amount'     => $amount * 100, // 通常单位为分
    'pay_type'   => $pay_type,
    'notify_url' => $config['notify_url'],
    'return_url' => $config['return_url'],
    'timestamp'  => time(),
];
// 3. 生成签名
$params['sign'] = generateSign($params, $config['merchant_key']);
// 4. 通过cURL发送请求
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $config['gateway_url']);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params)); // 或 json_encode
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 生产环境建议开启验证
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$response = curl_exec($ch);
curl_close($ch);
// 5. 处理返回结果(通常是JSON)
$result = json_decode($response, true);
if ($result['code'] == 'SUCCESS') {
    // 跳转到支付页面(URL在 result['pay_url'] 或 result['qrcode'])
    header('Location: ' . $result['pay_url']);
    exit;
} else {
    echo '支付请求失败:' . $result['msg'];
}
// 签名函数
function generateSign($data, $key) {
    // 1. 去除 sign 字段
    unset($data['sign']);
    // 2. 按ASCII排序
    ksort($data);
    // 3. 拼接成字符串
    $str = '';
    foreach ($data as $k => $v) {
        if ($v !== '' && $v !== null) {
            $str .= $k . '=' . $v . '&';
        }
    }
    $str = trim($str, '&');
    // 4. 拼接密钥
    $str .= '&key=' . $key;
    // 5. 生成签名(大部分使用MD5)
    return strtoupper(md5($str));
}
?>

处理异步通知 (notify.php)

注意:这是最关键的部分,必须验证签名,且只处理 POST 请求。

<?php
require_once 'config.php';
// 只处理POST请求
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    exit('Request method error');
}
// 1. 获取回调数据
$data = $_POST; // 或 file_get_contents('php://input') 如果是JSON
// 2. 验证签名(同生成签名逻辑)
$expected_sign = generateSign($data, $config['merchant_key']);
if ($data['sign'] !== $expected_sign) {
    // 签名验证失败,可能是伪造请求
    exit('sign error');
}
// 3. 验证订单金额(可选)和订单状态
if ($data['status'] !== 'SUCCESS') {
    // 支付失败,记录日志
    exit('fail');
}
// 4. 业务处理:更新订单状态
$order_id = $data['order_id'];
$pay_amount = $data['pay_amount']; // 实际支付金额
// 伪代码:查询本地订单,更新状态
// $order = $db->get('orders', ['order_id' => $order_id]);
// if ($order && $order['status'] == 0) {
//     $db->update('orders', ['status' => 1, 'pay_time' => time()], ['order_id' => $order_id]);
// }
// 5. 通知支付平台处理成功(必须返回 success,否则平台会重复通知)
echo 'success';
exit;
?>

同步跳转处理 (return.php)

<?php
// 用户支付完成后跳转的页面
// 注意:此页面不可靠,仅作为用户提示,不要在这里更新订单状态
echo '支付成功,正在跳转...';
// 等待3秒后跳转到订单详情页
header('refresh:3;url=/order_detail.php?order_id='.$_GET['order_id']);
?>

重要提醒(坑点汇总)

类别 常见问题 正确做法
签名算法 拼接顺序错乱、未按文档处理空值 严格按照官方文档: 去除空值 -> 按ASCII排序 -> 拼接key -> MD5
金额单位 直接传元(如 00 大部分接口以 为单位,需 * 100
通知处理 直接在 return.php 更新订单 只在 notify.php 更新订单(服务端互信)
幂等性 未判重,导致重复发货 notify.php 先查本地订单状态,已处理则不再处理
编码 中文乱码导致签名失败 全部使用 UTF-8 编码
调试 签名校验失败找不到问题 在签名前后 var_dump 拼接字符串,与官方文档示例对比

推荐使用的工具/库

  1. Guzzle(推荐)
    composer require guzzlehttp/guzzle
  2. 直接 cURL(原生无依赖,如上代码所示)
  3. 开源聚合支付 SDK(如:yansongda/pay,Pay.js 官方 SDK)

对接成功后的测试清单

  • [ ] 生成一个1分钱的订单,扫码支付后确认用户余额减少。
  • [ ] 查看本地数据库,notify.php 更新了订单状态。
  • [ ] 模拟伪造的 notify.php 请求(修改金额),确认签名验证拦截。
  • [ ] 断网后重发通知,确认幂等性处理。

如果你能提供你具体对接的聚合支付平台名称(如 PayJS、易支付、USDT支付等),我可以给你提供更针对性的代码示例。

抱歉,评论功能暂时关闭!