美文网首页
2021-02-24 laravel + EasyWechat

2021-02-24 laravel + EasyWechat

作者: 浩克啊12138 | 来源:发表于2021-02-24 13:40 被阅读0次

1.安装必要的第三方包

$ composer require overtrue/wechat:~5.0 -vvv
  1. 在控制器中添加微信支付调用方法
    public function payOrder(Request $request)
    {
        $memberId = $request->attributes->get('memberId');
        $orderSn = $request->get('orderSn');
        $order = Orders::where('order_sn', $orderSn)->where('status', 0)->get()->toArray();
        if (empty($order)) {
            return ['code' => 404, 'massage' => '找不到订单!'];
        }

        try {
            $config = Pay::payByWeChat(reset($order)['id'], $memberId);
            return ['code' => 200, 'data' => $config];
        } catch (\Exception $e) {
            return ['code' => 404, 'massage' => $e->getMessage()];
        }
    }

3.在模型中创建支付方法

    public static function getConfig()
    {
        $config = Configs::first()->toArray();

        return [
            // 必要配置
            'app_id' => $config['app_id'] ?? env('WECHAT_APP_ID'),
            'mch_id' => $config['mch_id'] ?? env('WECHAT_MCH_ID'),
            'key' => $config['key'] ?? env('WECHAT_KEY'),   // API 密钥

            // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
//            'cert_path' => 'path/to/your/cert.pem', // 绝对路径!!!!
//            'key_path' => 'path/to/your/key',      // 绝对路径!!!!

            'notify_url' => route('order.notify'),     // 你也可以在下单时单独设置来想覆盖它
//            'sandbox' => true, // 设置为 false 或注释则关闭沙箱模式
        ];
    }

    public static function payByWeChat($orderId, $memberId)
    {
        $goodsIds = OrderItems::where('orders_id', 11)->select('goods_id')->get()->toArray();
        $goodsIds = array_column($goodsIds, 'goods_id');
        $lastOrder = Orders::join('orders_items', 'orders_items.orders_id', '=', 'orders.id')
            ->where('orders.member_id', $memberId)
            ->where('orders.type', 0)
            ->whereIn('orders_items.goods_id', $goodsIds)
            ->where('orders.pay_time', '>=', date('Y-m-d'))
            ->orderBy('orders.pay_time', 'desc')
            ->get()
            ->toArray();

        if (!empty($lastOrder)) {
            throw new \Exception('今日该商品已达到购买上限, 支付失败!');
        }

        $order = Orders::find($orderId)->toArray();
        $member = Members::find($memberId)->toArray();

        $payment = Factory::payment(self::getConfig());
        $jssdk = $payment->jssdk;

        $result = $payment->order->unify([
            'body' => env('APP_NAME'),         // 订单说明
            'out_trade_no' => $order['order_sn'],   // 平台内部订单号
            'total_fee' => $order['price'] * 100,   // 价格, 单位为分
//            'spbill_create_ip' => '123.12.12.123', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
//            'notify_url' => 'https://pay.weixin.qq.com/wxpay/pay.action', // 支付结果通知网址,如果不设置则会使用配置里的默认地址
            'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型 小程序为JSAPI
            'openid' => $member['openid'],
        ]);

        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            $prepayId = $result['prepay_id'];

            $config = $jssdk->sdkConfig($prepayId);
//            $config['orderSn'] = $order['order_sn'];
//            $config['orderId'] = $order['id'];
            return $config;
//            return response($config);
        }

        if ($result['return_code'] == 'FAIL' && array_key_exists('return_msg', $result)) {
            throw new \Exception($result['return_msg']);
        }

        throw new \Exception($result['err_code_des']);
    }
  1. 在控制器中添加微信回调方法
    public function notify(Request $request)
    {
        $fields = $request->query->all();

        return Pay::notifyByWeChat($fields);
    }

5.在模型中创建微信回调处理方法

    public static function notifyByWeChat($fields, $notify)
    {
        $config = self::getConfig();
        $payment = Factory::payment($config);

        $response = $payment->handlePaidNotify(function ($message, $fail) use ($fields) {
            // 根据返回的订单号查询订单数据
            $order = Orders::where('order_sn', $message['out_trade_no'])->get()->toArray();
            if (!$order) {
                $fail('订单不存在!');
            }
            $order = reset($order);

            if ($order['status'] == '1') {
                return true;
            }

            // 支付成功后的业务逻辑
            if ($message['result_code'] === 'SUCCESS') {
                $order['order_sn'] = $message['out_trade_no']; // 回调订单号
                $order['pay_order_sn'] = $message['transaction_id']; // 回调流水号
                $order['verification_code'] = Pay::generateVerificationCode();
                $order['pay_time'] = date('Y-m-d H:i:s');
                $order['status'] = 1;
                $order = Orders::timestamps($order);

                Orders::where('order_sn', $order['order_sn'])->update($order);
                if ($order['type']) {
                    $card = OrderItems::where('order_id', $order['id']);
                    $timeLimit = reset($card)['time_limit'];
                    $member = Members::find($order['member_id'])->toArray();
                    $expireTime = strtotime($member['expire_time']);
                    if (empty($member['expire_time']) || $expireTime < time()) {
                        $time = date('Y-m-d', time() + $timeLimit * 86400);
                    } else {
                        $time = date('Y-m-d', $expireTime + $timeLimit * 86400);
                    }

                    $data = ['expire_time' => $time];
                    $data['status'] = 1;
                    $data['updated_at'] = date('Y-m-d H:i:s');
                    Members::where('id', $order['member_id'])->update($data);
                }
            }

            return true;
        });

        return $response;
    }

6.设置路由

Route::group([
    'middleware' => 'jwt.user',
    'prefix' => 'orders',
], function (Router $router) {
    // 订单支付
    $router->post('pay', 'OrderController@payOrder');
    // 微信支付回调
    $router->any('notify', 'OrderController@notify')->name('order.notify');
});

7.小程序端测试代码
wxml文件

<!--index.wxml-->
<view class="container">
  <view class="userinfo">
    <button wx:if="{{!hasUserInfo && canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
    <block wx:else>
      <image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
      <text class="userinfo-nickname">{{userInfo.nickName}}</text>
    </block>
  </view>
  <view class="usermotto">
    <text class="user-motto">{{motto}}</text>
  </view>
</view>
// index.js
// 获取应用实例
const app = getApp()

Page({
  data: {
    motto: 'Hello World',
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse('button.open-type.getUserInfo')
  },
  // 事件处理函数
  bindViewTap() {
    wx.navigateTo({
      url: '../logs/logs'
    })
  },
  onLoad() {
    console.log(app.globalData)
    if (app.globalData.userInfo) {
      this.setData({
        userInfo: app.globalData.userInfo,
        hasUserInfo: true
      })
    } else if (this.data.canIUse) {
      // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
      // 所以此处加入 callback 以防止这种情况
      app.userInfoReadyCallback = res => {
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true
        })
      }
    } else {
      // 在没有 open-type=getUserInfo 版本的兼容处理
      wx.getUserInfo({
        success: res => {
          app.globalData.userInfo = res.userInfo
          this.setData({
            userInfo: res.userInfo,
            hasUserInfo: true
          })
        }
      })
    }
  },
  getUserInfo(e) {
    console.log(e)
    var rawData = e.detail.rawData 
    app.globalData.userInfo = e.detail.userInfo
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true
    })

    console.log(rawData)
    wx.login({
      success:function (res){
        var code = res.code;  
        var token = null;
        wx.request({
          url: 'http://fiveyears.cc/wechat/auth', 
          header: {
            'content-type': 'application/json'
          },
          data: {
            code: code,
            rawData: rawData
          },
          success(res) {
            console.log(res)
            token = res.data.token

            console.log(token)

            wx.request({
              url: 'http://fiveyears.cc/orders/pay', 
              header: {
                'content-type': 'application/json'
              },
              data: {
                token: token,
                orderSn: 'VIP2021021908181676096'
              },
              method: 'post',
              success(res) {
                console.log(res)
                console.log(res.data)
                console.log(res.data.data.timestamp)
  
                wx.requestPayment({
                  'timeStamp':res.data.data.timestamp,//
                  'nonceStr': res.data.data.nonceStr,
                  'package': res.data.data.package,
                  'signType': 'MD5',
                  'paySign': res.data.data.paySign,
                  'success':function(res){
                      console.log(res);
                  },
                  'fail':function(res){
                      console.log('fail:'+JSON.stringify(res));
                  }
                })
              }
            })
          }
        })

      }
    })

  }
})

相关文章

网友评论

      本文标题:2021-02-24 laravel + EasyWechat

      本文链接:https://www.haomeiwen.com/subject/ehhsfltx.html