当前位置 : 主页 > 网络编程 > PHP >

使用ThinkPHP 6实现微信支付功能

来源:互联网 收集:自由互联 发布时间:2023-11-09
一、准备工作在开始之前,我们需要确保已经满足以下准备工作: 安装ThinkPHP 6框架:可以通过Composer进行安装,执行命令 composer create-project topthink/think=6.* project_name 即可创建一个新的

一、准备工作 在开始之前,我们需要确保已经满足以下准备工作:

  1. 安装ThinkPHP 6框架:可以通过Composer进行安装,执行命令composer create-project topthink/think=6.* project_name即可创建一个新的ThinkPHP 6项目。
  2. 获取微信支付接口:登录微信公众平台,进入开发者中心,申请并获取到微信支付的相关接口信息,包括商户号、支付密钥等。
  3. 配置微信支付参数:在ThinkPHP 6项目中,打开位于config目录下的pay.php文件,根据所获取到的微信支付接口信息,配置相应的参数。

二、创建支付控制器 在ThinkPHP 6中,我们可以通过生成器快速创建一个控制器及其相关的模板和路由。执行以下命令生成一个名为Pay的控制器:

php think make:controller Pay

生成的控制器文件位于app/controller目录下,我们可以在该文件中编写支付相关的业务逻辑。

三、实现微信支付功能

  1. 创建统一下单接口 在Pay控制器中,创建一个名为unifiedOrder的方法来处理统一下单请求,代码如下:
php
<?php

namespace app\controller;

use think\Controller;
use think\facade\Config;
use think\facade\Request;
use think\facade\View;
use think\facade\Log;
use think\facade\Db;
use think\facade\Cache;

class Pay extends Controller
{
    // 统一下单接口
    public function unifiedOrder()
    {
        // 获取统一下单所需的参数,根据业务需求自行获取
        $orderNo = Request::post('order_no');
        $totalAmount = Request::post('total_amount');
        // ...

        // 构建统一下单所需的数据
        $params = [
            'appid' => Config::get('pay.app_id'),
            'mch_id' => Config::get('pay.mch_id'),
            'nonce_str' => uniqid(), // 随机字符串,根据实际情况生成
            'body' => '订单支付', // 商品描述,根据实际情况设置
            'out_trade_no' => $orderNo, // 商户订单号,根据实际情况生成
            'total_fee' => $totalAmount * 100, // 订单总金额,单位:分,需要转换成整数
            'spbill_create_ip' => Request::ip(), // 客户端IP,根据实际情况获取
            'notify_url' => Config::get('pay.notify_url'), // 支付回调通知地址
            'trade_type' => 'JSAPI', // 交易类型,根据实际情况设置
            'openid' => $this->getOpenId(), // 用户的OpenID,根据实际情况获取
        ];

        // 生成签名并添加到请求参数中
        $params['sign'] = $this->generateSign($params);

        // 发起统一下单请求
        $responseXml = $this->postXmlCurl($this->arrayToXml($params), 'https://api.mch.weixin.qq.com/pay/unifiedorder');

        // 解析返回的XML数据
        $responseData = $this->xmlToArray($responseXml);

        if ($responseData['return_code'] == 'SUCCESS' && $responseData['result_code'] == 'SUCCESS') {
            // 统一下单成功,返回预支付订单信息给前端
            return json([
                'code' => 0,
                'msg' => '统一下单成功',
                'data' => [
                    'appId' => Config::get('pay.app_id'),
                    'timeStamp' => time(),
                    'nonceStr' => uniqid(),
                    'package' => 'prepay_id=' . $responseData['prepay_id'],
                    'signType' => 'MD5',
                    'paySign' => $this->generateSign([
                        'appId' => Config::get('pay.app_id'),
                        'timeStamp' => time(),
                        'nonceStr' => uniqid(),
                        'package' => 'prepay_id=' . $responseData['prepay_id'],
                        'signType' => 'MD5',
                    ]),
                ],
            ]);
        } else {
            // 统一下单失败
            return json([
                'code' => -1,
                'msg' => '统一下单失败',
            ]);
        }
    }

    // 支付回调接口
    public function notify()
    {
        // 获取微信支付的回调数据
        $data = file_get_contents('php://input');
        Log::write('微信支付回调数据:' . $data);

        // 解析回调数据
        $responseData = $this->xmlToArray($data);

        if ($this->checkSign($responseData)) {
            // 验证签名成功

            if ($responseData['return_code'] == 'SUCCESS' && $responseData['result_code'] == 'SUCCESS') {
                // 支付成功,处理订单逻辑,更新订单状态等
                // ...
                return 'SUCCESS';
            } else {
                // 支付失败
                return 'FAIL';
            }
        } else {
            // 验证签名失败
            return 'FAIL';
        }
    }

    // 获取用户的OpenID,根据实际情况获取
    private function getOpenId()
    {
        // ...
    }

    // 生成签名
    private function generateSign($params)
    {
        // 排序
        ksort($params);

        // 拼接字符串
        $string = '';
        foreach ($params as $key => $value) {
            if ($key != 'sign' && $value != '' && !is_array($value)) {
                $string .= $key . '=' . $value . '&';
            }
        }
        $string .= 'key=' . Config::get('pay.api_key');

        // MD5加密并转换为大写
        return strtoupper(md5($string));
    }

    // 验证签名
    private function checkSign($params)
    {
        $sign = $params['sign'];
        unset($params['sign']);
        return $sign == $this->generateSign($params);
    }

    // 数组转XML
    private function arrayToXml($data)
    {
        $xml = '<xml>';
        foreach ($data as $key => $value) {
            $xml .= "<{$key}><![CDATA[{$value}]]></{$key}>";
        }
        $xml .= '</xml>';
        return $xml;
    }

    // XML转数组
    private function xmlToArray($xml)
    {
        libxml_disable_entity_loader(true);
        return json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

    // 发送POST请求
    private function postXmlCurl($xml, $url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: text/xml']);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}
  1. 处理支付回调 在Pay控制器中,创建一个名为notify的方法来处理微信支付的异步通知回调,代码如下:
public function notify()
{
    // 获取微信支付的回调数据
    $data = file_get_contents('php://input');
    
    // 处理回调数据,如验证签名等
    // ...
    
    // 根据回调结果更新订单状态等业务逻辑
    // ...
    
    // 返回响应给微信支付平台
    return 'SUCCESS';
}

四、配置路由 在ThinkPHP 6中,可以通过编辑route目录下的route.php文件来配置路由规则。我们需要为支付接口和支付回调接口配置相应的路由规则,示例如下:

// 支付接口路由
Route::post('pay/unifiedOrder', 'Pay/unifiedOrder');

// 支付回调路由
Route::post('pay/notify', 'Pay/notify');

五、前端集成 根据业务需求,在前端页面中调用支付接口,获取到预支付订单信息后,可以使用微信JSAPI提供的支付功能进行支付操作。

上一篇:Doris安装及使用
下一篇:没有了
网友评论