PHP项目支付接口如何对接PHP项目

wen PHP项目 23

本文目录导读:

PHP项目支付接口如何对接PHP项目

  1. 对接支付接口的基本流程
  2. 支付宝支付对接示例
  3. 微信支付对接示例
  4. 订单查询与退款
  5. 安全注意事项
  6. 最佳实践建议
  7. 推荐支付SDK

我来详细说明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;
}

最佳实践建议

  1. 使用统一的支付网关类:封装所有支付逻辑
  2. 日志记录完整:记录每次请求和响应
  3. 异步通知重试机制:处理网络问题
  4. 事务处理:确保数据一致性
  5. 监控告警:监控支付成功率

推荐支付SDK

这就是PHP项目对接支付接口的完整方案,生产环境中务必做好安全防护和异常处理。

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