插件窝 干货文章 如何使用 EasyWeChat 在 Laravel 框架中轻松封装微信支付和支付宝支付?

如何使用 EasyWeChat 在 Laravel 框架中轻松封装微信支付和支付宝支付?

支付 return payment PaymentService 776    来源:    2025-04-01

在 Laravel 中使用 EasyWeChat 封装微信支付和支付宝支付

EasyWeChat 是一个优秀的 PHP 微信 SDK,同时也支持支付宝支付。下面我将介绍如何在 Laravel 框架中封装这两种支付方式。

1. 安装 EasyWeChat

首先安装 EasyWeChat 包:

composer require overtrue/wechat -vvv

2. 配置支付服务

微信支付配置

config/services.php 中添加微信支付配置:

'wechat_payment' => [
    'app_id'        => env('WECHAT_PAYMENT_APPID'),
    'mch_id'        => env('WECHAT_PAYMENT_MCH_ID'),
    'key'           => env('WECHAT_PAYMENT_KEY'),
    'cert_path'     => env('WECHAT_PAYMENT_CERT_PATH', 'path/to/cert/apiclient_cert.pem'),
    'key_path'      => env('WECHAT_PAYMENT_KEY_PATH', 'path/to/cert/apiclient_key.pem'),
    'notify_url'    => env('WECHAT_PAYMENT_NOTIFY_URL', 'your.domain.com/wechat/notify'),
],

支付宝支付配置

同样在 config/services.php 中添加:

'alipay' => [
    'app_id'         => env('ALIPAY_APP_ID'),
    'ali_public_key' => env('ALIPAY_PUBLIC_KEY'),
    'private_key'    => env('ALIPAY_PRIVATE_KEY'),
    'notify_url'     => env('ALIPAY_NOTIFY_URL', 'your.domain.com/alipay/notify'),
    'return_url'     => env('ALIPAY_RETURN_URL', 'your.domain.com/alipay/return'),
    'log'            => [
        'file' => storage_path('logs/alipay.log'),
    ],
],

3. 创建支付服务类

创建一个 PaymentService 类来封装支付逻辑:

<?php

namespace App\Services;

use EasyWeChat\Factory;
use EasyWeChat\Payment\Application as PaymentApp;
use EasyWeChat\Pay\Application as PayApp;

class PaymentService
{
    protected $wechatPayment;
    protected $alipay;

    public function __construct()
    {
        // 初始化微信支付
        $this->wechatPayment = Factory::payment(config('services.wechat_payment'));

        // 初始化支付宝支付
        $this->alipay = Factory::alipay(config('services.alipay'));
    }

    /**
     * 微信支付 - JSAPI支付
     */
    public function wechatJsapiPay(array $orderData)
    {
        $result = $this->wechatPayment->order->unify([
            'body'         => $orderData['body'],
            'out_trade_no' => $orderData['out_trade_no'],
            'total_fee'    => $orderData['total_fee'], // 单位:分
            'trade_type'   => 'JSAPI',
            'openid'       => $orderData['openid'],
            'notify_url'   => config('services.wechat_payment.notify_url'),
        ]);

        if ($result['return_code'] === 'SUCCESS' && $result['result_code'] === 'SUCCESS') {
            $config = $this->wechatPayment->jssdk->bridgeConfig($result['prepay_id']);
            return $config;
        }

        throw new \Exception('微信支付下单失败: '.json_encode($result));
    }

    /**
     * 支付宝支付 - 网页支付
     */
    public function alipayWebPay(array $orderData)
    {
        $order = [
            'out_trade_no' => $orderData['out_trade_no'],
            'total_amount' => $orderData['total_amount'], // 单位:元
            'subject'      => $orderData['subject'],
            'product_code' => 'FAST_INSTANT_TRADE_PAY',
        ];

        return $this->alipay->web->pay($order);
    }

    /**
     * 处理微信支付回调
     */
    public function handleWechatNotify()
    {
        $response = $this->wechatPayment->handlePaidNotify(function($message, $fail) {
            // 你的业务逻辑
            $order = Order::where('order_no', $message['out_trade_no'])->first();

            if (!$order) {
                return $fail('订单不存在');
            }

            if ($order->paid_at) {
                return true; // 已经处理过了
            }

            // 支付成功
            if ($message['result_code'] === 'SUCCESS') {
                $order->paid_at = now();
                $order->status = 'paid';
                $order->save();

                // 其他业务逻辑...

                return true;
            }

            return $fail('支付失败');
        });

        return $response;
    }

    /**
     * 处理支付宝回调
     */
    public function handleAlipayNotify()
    {
        $data = $this->alipay->verify();

        try {
            $order = Order::where('order_no', $data->out_trade_no)->first();

            if (!$order) {
                throw new \Exception('订单不存在');
            }

            if ($order->paid_at) {
                return true; // 已经处理过了
            }

            // 交易状态
            if (in_array($data->trade_status, ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
                $order->paid_at = now();
                $order->status = 'paid';
                $order->save();

                // 其他业务逻辑...

                return true;
            }
        } catch (\Exception $e) {
            // 记录错误日志
            \Log::error('支付宝回调处理失败: '.$e->getMessage());
            return false;
        }

        return $this->alipay->success();
    }
}

4. 创建支付控制器

<?php

namespace App\Http\Controllers;

use App\Services\PaymentService;
use Illuminate\Http\Request;

class PaymentController extends Controller
{
    protected $paymentService;

    public function __construct(PaymentService $paymentService)
    {
        $this->paymentService = $paymentService;
    }

    /**
     * 微信JSAPI支付
     */
    public function wechatJsapiPay(Request $request)
    {
        $orderData = [
            'body' => '测试商品',
            'out_trade_no' => time().rand(1000, 9999),
            'total_fee' => 100, // 1元
            'openid' => $request->user()->wechat_openid,
        ];

        try {
            $config = $this->paymentService->wechatJsapiPay($orderData);
            return view('payment.wechat', compact('config'));
        } catch (\Exception $e) {
            return back()->withErrors($e->getMessage());
        }
    }

    /**
     * 支付宝网页支付
     */
    public function alipayWebPay(Request $request)
    {
        $orderData = [
            'out_trade_no' => time().rand(1000, 9999),
            'total_amount' => 0.01, // 0.01元测试
            'subject' => '测试商品',
        ];

        try {
            return $this->paymentService->alipayWebPay($orderData);
        } catch (\Exception $e) {
            return back()->withErrors($e->getMessage());
        }
    }

    /**
     * 微信支付回调
     */
    public function wechatNotify()
    {
        return $this->paymentService->handleWechatNotify();
    }

    /**
     * 支付宝回调
     */
    public function alipayNotify()
    {
        return $this->paymentService->handleAlipayNotify();
    }
}

5. 添加路由

routes/web.php 中添加:

Route::middleware('auth')->group(function () {
    Route::post('/payment/wechat/jsapi', [PaymentController::class, 'wechatJsapiPay']);
    Route::post('/payment/alipay/web', [PaymentController::class, 'alipayWebPay']);
});

// 支付回调路由
Route::post('/payment/wechat/notify', [PaymentController::class, 'wechatNotify']);
Route::post('/payment/alipay/notify', [PaymentController::class, 'alipayNotify']);

6. 前端集成

微信支付前端示例

<!-- resources/views/payment/wechat.blade.php -->
<!DOCTYPE html>
<html>
<head>
    <title>微信支付</title>
    <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
</head>
<body>
    <button id="payButton">支付</button>

    <script>
        document.getElementById('payButton').addEventListener('click', function() {
            wx.chooseWXPay({
                timestamp: '{{ $config["timestamp"] }}',
                nonceStr: '{{ $config["nonceStr"] }}',
                package: '{{ $config["package"] }}',
                signType: '{{ $config["signType"] }}',
                paySign: '{{ $config["paySign"] }}',
                success: function (res) {
                    alert('支付成功');
                    // 跳转到成功页面
                    window.location.href = '/payment/success';
                },
                fail: function (res) {
                    alert('支付失败: ' + JSON.stringify(res));
                }
            });
        });
    </script>
</body>
</html>

支付宝支付前端

支付宝支付会直接返回一个表单,自动提交跳转到支付宝页面,无需额外处理。

7. 测试支付

  • 微信支付测试需要真实的微信支付商户号和配置
  • 支付宝支付可以使用沙箱环境测试

8. 注意事项

  1. 安全性:支付回调接口需要验证签名,确保请求来自微信/支付宝
  2. 幂等性:支付回调可能会多次触发,业务逻辑需要处理重复通知
  3. 日志记录:所有支付请求和回调都应该记录日志
  4. 异常处理:支付过程中可能出现的各种异常需要妥善处理
  5. 退款处理:考虑添加退款功能

通过以上步骤,你可以在 Laravel 中轻松集成微信支付和支付宝支付功能。根据实际业务需求,你可以进一步扩展 PaymentService 类,添加更多支付方式和功能。