本文目录导读:

在PHP项目中对接聚合支付接口(如PayJS、虎皮椒、甚至一些开源聚合支付网关),通常遵循标准的第三方HTTP API对接流程(构建参数 -> 签名 -> 发送请求 -> 接收回调)。
以下是一个通用的、标准化的对接步骤和代码示例,以通用的聚合支付网关(假设支持 支付宝、微信支付、QQ钱包 等)为例。
核心步骤(五步走)
- 获取配置:在聚合支付平台注册账号,获得
商户ID和商户密钥(AppSecret/API Key)。 - 封装请求参数:根据官方文档,组装订单号、金额、支付方式、异步通知地址等。
- 生成签名:这是最关键的步骤,防止数据被篡改(通常使用 MD5 或 HMAC-SHA256)。
- 发起HTTP请求:使用
cURL或Guzzle发送 POST 请求到支付网关。 - 处理异步通知:接收支付平台 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 拼接字符串,与官方文档示例对比 |
推荐使用的工具/库
- Guzzle(推荐)
composer require guzzlehttp/guzzle
- 直接 cURL(原生无依赖,如上代码所示)
- 开源聚合支付 SDK(如:
yansongda/pay,Pay.js 官方 SDK)
对接成功后的测试清单
- [ ] 生成一个1分钱的订单,扫码支付后确认用户余额减少。
- [ ] 查看本地数据库,
notify.php更新了订单状态。 - [ ] 模拟伪造的
notify.php请求(修改金额),确认签名验证拦截。 - [ ] 断网后重发通知,确认幂等性处理。
如果你能提供你具体对接的聚合支付平台名称(如 PayJS、易支付、USDT支付等),我可以给你提供更针对性的代码示例。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播