PHP(Thinkphp5.1)简单实现微信支付和微信退款

PHP(Thinkphp5.1)简单实现微信支付和微信退款

插件下载

去官网下载easyWechat(我下的是4.x版本)
composer require overtrue/wechat:~4.0 -vvv

插件使用方式

代码封装

开始使用,先封装代码

public function init()  // 支付配置初始化    {
        $config = [
            // 必要配置
            'app_id' => config('xcx_appid'),
            'mch_id' => config('mch_id'),
            'key' => config('pay_secret'),   // API 密钥

            // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
            'cert_path' => '/www/wwwroot/项目名/extend/cert/apiclient_cert.pem', // XXX: 绝对路径!!!!
            'key_path' => '/www/wwwroot/项目名/extend/cert/apiclient_key.pem',      // XXX: 绝对路径!!!!

            'notify_url' => '域名/callback',     // 你也可以在下单时单独设置来想覆盖它        ];

        $app = Factory::payment($config);
        return $app;
    }

    //写日志
    public function logs($msg, $type = 'info')
    {
        Log::init([
            'type' => 'File',
            'path' => Env::get('root_path') . 'testLog',
            'max_files' => 20,
        ]);
        Log::write($msg, $type);
        Log::close();
    }

支付功能

前端请求pay 接口

public function pay()      // 统一支付接口    {
        $app = $this->init();

        $orderId = time();
        $result = $app->order->unify([      // H5 支付,公众号支付,扫码支付,支付中签约,全部都是用这个接口下单。

            'body' => '测试支付',
            'out_trade_no' => $orderId,     // 商户订单号
            'total_fee' => 1,               // 金额 分
            'trade_type' => 'JSAPI',        // 请对应换成你的支付方式对应的值类型
            'openid' => '你的openId',
            //'spbill_create_ip' => '123.12.12.123', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
            //'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如果不设置则会使用配置里的默认地址        ]);

        $res = Order::create(['orderId' => $orderId, 'status' => 0,'userId'=>random_int(1,10000)]);    // 生成未支付的订单

        if ($result['return_code'] != 'SUCCESS' || $result['result_code'] != 'SUCCESS')
            return json(['code' => 1, 'msg' => '获取支付订单失败']);

        else {
            if ($res) {             // 返回给前端,生成支付页面
                $jssdk = $app->jssdk;
                $config = $jssdk->bridgeConfig($result['prepay_id'], false);
                return ($config);

            } else
                return json(['code' => 1, 'msg' => '创建订单失败!']);
        }
    }

    //支付回调
    public function callBack()
    {
        $app = $this->init();
        $response = $app->handlePaidNotify(function ($message, $fail) use ($app){     // 回调

            $order = Order::where(['orderId' => $message['out_trade_no']])->find()->toArray();
            if (!$order || $order['status'] == 1)   // 如果订单不存在 或者 订单已经支付过了
                return true;                        // 告诉微信,我已经处理完了,订单没找到,别再通知我了

            //$res = $app->order->queryByOutTradeNumber($message['out_trade_no']);    // 订单查询

            if ($message['return_code'] === 'SUCCESS' ) { // return_code 表示通信状态,不代表支付状态

                if ($message['result_code'] === 'SUCCESS') {    // 支付成功
                    $order['status'] = 1;
                    $this->logs('商户订单号:'.$message['out_trade_no'].' 支付成功');

                } else{         // 支付失败
                    $order['status'] = -1;
                    $this->logs('商户订单号:'.$message['out_trade_no'].' 支付失败');
                }

                Order::update($order,['orderId'=>$message['out_trade_no']]);     // 更新数据
            } else              // 通讯失败
                return $this->create([],'connect fail');

            return true;        // 返回处理完成        });
        return $response;
    }

前端调用

pay: function () {
    wx.request({
      url: 'http://域名/pay',
      header: {
        "X-Requested-With": " XMLHttpRequest"
      },
      data: {
      },
      success(res) {
        console.log(res.data)
        let ress = res.data
         //let ress = JSON.parse(res.data)
        // console.log(ress.data)
        wx.requestPayment({    // 生成支付页面的参数
          "timeStamp": ress.timeStamp,
          "nonceStr": ress.nonceStr,
          "package": ress.package,
          "signType": ress.signType,
          "paySign": ress.paySign,
          'appId': ress.appId,
          
          "success": function (res) {
            console.log(res)
          },
          "fail": function (res) {
            console.log(res)
          },
          "complete": function (res) {
            console.log(res)
          }
        })
      }
    })
  },

退款功能,

可以通过接口工具请求,传入支付的订单号即可

//退款
    public function refund()
    {
        $out_trade_no = '1628739348';   // 商户订单号
        $app = $this->init();
        // 参数分别为:商户订单号、商户退款单号、订单金额、退款金额、其他参数
        $result = $app->refund->byOutTradeNumber($out_trade_no, uniqid(), 1, 1, [

            'refund_desc' => '退款',
            'notify_url'    => 'http://域名/refundBack',
        ]);
        
        if ($result['return_code'] == 'SUCCESS')
            return true;
        else{
            $this->logs('退款失败','error');
            return false;
        }
    }

    //退款回调
    public function refundBack(){

        $app = $this->init();
        $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail) {
            // 其中 $message['req_info'] 获取到的是加密信息
            // $reqInfo 是解密后的信息
            
            $order = Order::where(['orderId' => $reqInfo['out_trade_no']])->find()->toArray();
            if (!$order || $order['status'] == 2)   // 如果订单不存在 或者 订单已经退款了
                return true;                        // 告诉微信,我已经处理完了,订单没找到,别再通知我了

            if($message['return_code']=='SUCCESS'){     // 通信成功

                if($reqInfo['refund_status']=='SUCCESS'){

                    $order['status'] = 2;
                    $this->logs('商户订单号:'.$reqInfo['out_trade_no'].' 退款成功');
                }else{
                    $order['status'] = -2;
                    $this->logs('商户订单号:'.$reqInfo['out_trade_no'].' 退款失败');
                }

                Order::update($order,['orderId'=>$reqInfo['out_trade_no']]);     // 更新数据
            } else              // 通讯失败
                return $this->create([],'connect fail');

            return true; // 返回 true 告诉微信“我已处理完成”
            // 或返回错误原因 $fail('参数格式校验错误');        });

        return $response;
    }
上一篇:Qt6 QML Book/网络设置/Web Sockets


下一篇:fastadmin支付插件