本文目录导读:

我来详细说明PHP项目对接支付接口的完整流程,以最常用的支付宝和微信支付为例。
对接支付接口的基本流程
整体架构
用户浏览器 → 你的PHP服务器 → 支付平台API
↓ ↓
支付页面 ← 支付结果异步通知 ← 处理支付结果
基础准备工作
// 配置支付参数(通常在config/payment.php)
return [
'alipay' => [
'app_id' => '你的APP_ID',
'merchant_private_key' => '商户私钥',
'alipay_public_key' => '支付宝公钥',
'notify_url' => 'https://yourdomain.com/notify/alipay',
'return_url' => 'https://yourdomain.com/return/alipay',
],
'wechat' => [
'app_id' => '微信公众号APPID',
'mch_id' => '商户号',
'key' => 'API密钥',
'notify_url' => 'https://yourdomain.com/notify/wechat',
],
];
支付宝支付对接示例
安装SDK
composer require alipaysdk/easysdk # 或 composer require yansongda/pay
发起支付请求
<?php
namespace App\Services;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Log;
class AlipayService
{
protected $config;
public function __construct()
{
$this->config = config('payment.alipay');
}
/**
* 创建支付宝支付
*/
public function createOrder($order)
{
$alipay = Pay::alipay($this->config);
try {
$result = $alipay->web([
'out_trade_no' => $order['order_no'], // 订单号
'total_amount' => $order['amount'], // 金额
'subject' => $order['subject'], // 订单标题
'timeout_express' => '30m', // 超时时间
]);
// 返回支付链接或表单
return $result->getContent(); // HTML表单
} catch (\Exception $e) {
Log::error('支付宝支付请求失败', [
'message' => $e->getMessage(),
'order' => $order
]);
throw $e;
}
}
}
异步通知处理
<?php
namespace App\Http\Controllers;
use Yansongda\Pay\Pay;
class NotifyController extends Controller
{
public function alipayNotify()
{
$alipay = Pay::alipay(config('payment.alipay'));
try {
// 验证签名
$data = $alipay->verify();
// 获取订单信息
$orderNo = $data->out_trade_no;
$tradeNo = $data->trade_no;
$totalAmount = $data->total_amount;
$tradeStatus = $data->trade_status;
// 判断交易状态
if ($tradeStatus == 'TRADE_SUCCESS') {
// 处理订单逻辑
$this->processOrder($orderNo, $tradeNo, $totalAmount);
// 返回成功标识
return $alipay->success();
}
} catch (\Exception $e) {
Log::error('支付宝通知验证失败', [
'message' => $e->getMessage()
]);
return 'fail';
}
}
private function processOrder($orderNo, $tradeNo, $amount)
{
// 更新订单状态
// 添加支付记录
// 发送通知等
\DB::transaction(function () use ($orderNo, $tradeNo, $amount) {
Order::where('order_no', $orderNo)
->update(['status' => 'paid', 'trade_no' => $tradeNo]);
PaymentLog::create([
'order_no' => $orderNo,
'trade_no' => $tradeNo,
'amount' => $amount,
'pay_time' => date('Y-m-d H:i:s')
]);
});
}
}
微信支付对接示例
安装SDK
composer require wechatpay/wechatpay # 或 composer require yansongda/pay
发起支付请求
<?php
namespace App\Services;
use Yansongda\Pay\Pay;
class WechatService
{
protected $config;
public function __construct()
{
$this->config = config('payment.wechat');
}
/**
* 微信JSAPI支付(公众号)
*/
public function createJsapiOrder($order, $openid)
{
$wechat = Pay::wechat($this->config);
$result = $wechat->mp([
'out_trade_no' => $order['order_no'],
'body' => $order['body'],
'total_fee' => intval($order['amount'] * 100), // 微信金额单位是分
'openid' => $openid,
'spbill_create_ip' => request()->getClientIp(),
]);
// 返回JSAPI参数
return $result->getContent(); // json数据
}
/**
* 微信扫码支付(Native)
*/
public function createNativeOrder($order)
{
$wechat = Pay::wechat($this->config);
$result = $wechat->scan([
'out_trade_no' => $order['order_no'],
'body' => $order['body'],
'total_fee' => intval($order['amount'] * 100),
'time_expire' => date('YmdHis', time() + 1800), // 30分钟
]);
// 获取二维码链接
$codeUrl = $result->code_url;
// 生成二维码图片
return $codeUrl;
}
/**
* H5支付
*/
public function createH5Order($order)
{
$wechat = Pay::wechat($this->config);
$result = $wechat->wap([
'out_trade_no' => $order['order_no'],
'body' => $order['body'],
'total_fee' => intval($order['amount'] * 100),
'spbill_create_ip' => request()->getClientIp(),
]);
return $result->getContent(); // 重定向URL
}
}
微信异步通知处理
<?php
namespace App\Http\Controllers;
use Yansongda\Pay\Pay;
class NotifyController extends Controller
{
public function wechatNotify()
{
$wechat = Pay::wechat(config('payment.wechat'));
try {
// 验证签名
$data = $wechat->verify();
// 处理订单
$orderNo = $data->out_trade_no;
$transactionId = $data->transaction_id;
$totalFee = $data->total_fee / 100; // 转换为元
// 更新订单状态
$this->processOrder($orderNo, $transactionId, $totalFee);
// 返回成功响应
return $wechat->success();
} catch (\Exception $e) {
Log::error('微信通知处理失败', [
'message' => $e->getMessage()
]);
return 'FAIL';
}
}
}
订单查询与退款
订单查询
// 支付宝
$alipay = Pay::alipay($config);
$result = $alipay->query(['out_trade_no' => '订单号']);
// 微信
$wechat = Pay::wechat($config);
$result = $wechat->find('订单号');
退款处理
// 支付宝退款
$alipay = Pay::alipay($config);
$result = $alipay->refund([
'out_trade_no' => '原订单号',
'refund_amount' => '退款金额',
'out_request_no' => '退款请求号'
]);
// 微信退款
$wechat = Pay::wechat($config);
$result = $wechat->refund([
'out_trade_no' => '原订单号',
'out_refund_no' => '退款单号',
'total_fee' => '原订单金额',
'refund_fee' => '退款金额'
]);
安全注意事项
签名验证
// 必须验证回调签名
public function verifySign($data, $sign, $key)
{
// 排序
ksort($data);
// 拼接字符串
$str = '';
foreach ($data as $k => $v) {
if ($v !== '' && $k !== 'sign') {
$str .= $k . '=' . $v . '&';
}
}
$str .= 'key=' . $key;
// 验证签名
return md5($str) === $sign;
}
防止重复通知
// 幂等性检查
public function processOrder($orderNo, $tradeNo, $amount)
{
// 先查询是否已经处理过
$log = PaymentLog::where('trade_no', $tradeNo)->first();
if ($log) {
return; // 已处理过,直接返回
}
// 处理订单...
}
金额校验
// 验证金额一致性
$orderAmount = Order::where('order_no', $data['out_trade_no'])->value('amount');
if (abs($orderAmount - $data['total_amount']) > 0.01) {
Log::warning('金额不一致', $data);
return false;
}
最佳实践建议
- 使用统一的支付网关类:封装所有支付逻辑
- 日志记录完整:记录每次请求和响应
- 异步通知重试机制:处理网络问题
- 事务处理:确保数据一致性
- 监控告警:监控支付成功率
推荐支付SDK
- yansongda/pay - 支持支付宝、微信支付等多种支付方式
- thephpleague/omnipay - 强大的支付抽象库
这就是PHP项目对接支付接口的完整方案,生产环境中务必做好安全防护和异常处理。