美文网首页
esaywechat 微信公众号jsapi支付

esaywechat 微信公众号jsapi支付

作者: 中v中 | 来源:发表于2020-01-09 00:01 被阅读0次

    esaywechat 对应各框架版本
    laravel =》overtrue/laravel-wechat
    tp =》 naixiaoxin/think-wechat
    yii 和 symfony等等
    以laravel 为例
    //安装

    composer require "overtrue/laravel-wechat:~4.0"
    

    在 config/app.php 注册 ServiceProvider 和 Facade (Laravel 5.5 无需手动注册)

    'providers' => [
        // ...
        Overtrue\LaravelWeChat\ServiceProvider::class,
    ],
    'aliases' => [
        // ...
        'EasyWeChat' => Overtrue\LaravelWeChat\Facade::class,
    ],
    

    创建配置文件:

    php artisan vendor:publish --provider="Overtrue\LaravelWeChat\ServiceProvider"
    

    修改应用根目录下的 config/wechat.php 中对应的参数即可。
    参数在微信公众平台配置和查看
    同时设置号 域名 白名单 等
    demo

    /*
         * 公众号
         */
    。。。。
        'official_account' => [
            'default' => [
                'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', 'wxe4f459877777'),         // AppID
                'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', '2323233uewuwuewueyue'),    // 
                'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', 'weee'),           // Token
                'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', '23333333'),
                /*
                 * OAuth 配置
                 *
                 * scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login
                 * callback:OAuth授权完成后的回调页地址(如果使用中间件,则随便填写。。。)
                 */
                // ],
            ],
        ],
    。。。。。
    //支付所需参数 微信商家平台里获取对应参数
        'pay_config' => [
                // 必要配置
                'app_id' => '同上',
                'mch_id' => '368779###',
                'secret' => '3b1e348d68610d07wqwqwqw3ee',
                'key'    => 'ecipa2018wxhuwqwqwqw0',   // API 密钥
                // 如需使用敏感接口(如退款、发送红包等)需要配置 API 证书路径(登录商户平台下载 API 证书)
                'cert_path' => '../cert/apiclient_cert.pem', // XXX: 绝对路径!!!!
                'key_path'  => '../cert/apiclient_key.pem',      // XXX: 绝对路径!!!!
                //'notify_url' => 'http://'.$_SERVER['HTTP_HOST'].'/api/WeChatNotify',     // 默认的订单回调地址,你也可以在下单时单独设置来想覆盖它
                //其他参数
        ],
    

    证书 微信公众平台有下载地址
    ···

    配置完成后
    开始使用

    use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
    use EasyWeChat\Payment\Kernel\BaseClient;
    use EasyWeChat\Factory;
    ...
    //用户点击支付 生成预支付订单
    public function PrepayOrder(Request $request,$order_sn) {
    ....
    $config = config('wechat.pay_config');
    $app = Factory::payment($config);
    $jssdk = $app->jssdk;
    //微信以分为单位 注意订单价格
    $actualPrice = $order['actual_price']*100;
               //生成预付单
               $host = $_SERVER['HTTP_HOST'];
                try {
                    $result = $app->order->unify([
                        'body' => $order['name'],
                        'out_trade_no' => $order['order_sn'],
                        'total_fee' => $actualPrice,//todo
                        'attach' => $order['id'],
                        'spbill_create_ip' => '', // 可选,如不传该参数,SDK 将会自动获取相应 IP 地址
                        //'notify_url' => $config['notify_url'], // 支付结果通知网址,如果不设置则会使用配置里的默认地址
                        'notify_url' => 'http://'.$_SERVER['HTTP_HOST'].'/api/WeChatNotify',
                        'trade_type' => 'JSAPI',//支付方式
                        'openid' => $openid,
                    ]);
                } catch (InvalidConfigException $e) {
                }
                //预支付订单号prepayId, 生成支付 JS 配置
               $prepayId = $result['prepay_id'];
               $jsApiParameters = $jssdk->bridgeConfig($prepayId);
            $arr = [
                'error'=>0,
                'jsApiParameters'=>$jsApiParameters,
            ];
            return $arr;
    

    //页面调起微信支付js

    <script src="{{ asset('jq/jquery-1.11.3.min.js') }}"></script>
    <script>
    //下单
        var jsApiParameters = '';
        $("footer").on("click", "#payNow", function callpay(event) {
            
            $.ajax({
                  url: "/api/PrepayOrder/{{ $order['order_sn'] }}",
                  type: 'post',
                  dataType: 'json',
                  cache: false,
              })
              .done(function(respones) {
                  if(respones.error==0){
                      jsApiParameters = JSON.parse(respones.jsApiParameters);
                      callPay();
                  }else{
                      alert(respones.msg);
                  }
              })
              .fail(function() {
                  alert('网络错误,请稍后再试!');
    
              })
        });
    
    
    
        function callPay() {
            if (typeof WeixinJSBridge == "undefined"){
                if( document.addEventListener ){
                    document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
                }else if (document.attachEvent){
                    document.attachEvent('WeixinJSBridgeReady', jsApiCall);
                    document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
                }
            }else{
                jsApiCall();
            }
        }
    
        function jsApiCall()
        { 
          WeixinJSBridge.invoke(
            'getBrandWCPayRequest',jsApiParameters,
            function(res){
              //WeixinJSBridge.log(res.err_msg);
              if (res.err_msg == "get_brand_wcpay_request:ok") {
                alert('支付成功')
                   //可以进行查看订单,等操作
              } else {
                    alert('支付失败!');
              }
              //alert(res.err_code+res.err_desc+res.err_msg);
            }
          );
        }
    
    </script>
    

    支付后的回调-》 预支付notify_url

    use EasyWeChat\Kernel\Exceptions\Exception;
    use EasyWeChat\Factory;
    use EasyWeChat\Payment\Kernel\BaseClient;
    ...
    //支付结果
        public function notify()
        {
            // 判断是否支付成功
            $config = config('wechat.pay_config');
            $app = Factory::payment($config);
            try {
                BaseClient::setDefaultOptions([
                    'curl' => [
                        CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
                    ],
                    'verify'=>false               //不开启CURLOPT_SSL_VERIFYPEER, 这里后来线上ssl报错加的,原因忘了
                ]);
                $response = $app->handlePaidNotify(function ($message, $fail) {
                    $orderSn = $message['out_trade_no'];
                    //开启事务并上锁
                    DB::beginTransaction();
                  检查价格 {
                        //订单不是待付款 或者金额不对直接结束//todo价格*100
                        DB::rollBack();
                        return true;
                    }
                    // 用户是否支付成功
                    if ($message['return_code'] === 'SUCCESS' && array_get($message, 'result_code') === 'SUCCESS') {
                        // return_code 表示通信状态,不代表支付状态
                        // 成功后修改订单已支付
                        data_set($orderInfo,'status',1);     //支付成功
                        data_set($orderInfo,'out_order_sn',array_get($message, 'transaction_id'));     //支付单号
                        data_set($orderInfo,'pay_status',1);     //支付成功
                        data_set($orderInfo,'pay_time',date("Y-m-d H:i:s"));     //支付时间
                        data_set($orderInfo,'attributes',json_encode([]));//清空预支付订单id
                        if($orderInfo->save()){
                            DB::commit();
                        }else{
                            //纪录错误日志。。
                           
                            $error   = new ErrorLogModel($data);
                            $error->save();
                            DB::rollBack();
                        }
                    }else{
                        //支付失败直接结束
                        DB::rollBack();
                        return true;
                    }
                    
                    }
                    // 添加账单 --无账单处理
                    //微信和短信通知支付成功
                    $goods = new GoodsModel;
                    //获取商品详情
                    $goodsDetails = $goods->getGoodsById($message['attach']);
                    //微信通知
                    ExamNotify::notifyWechat($goodsDetails,$orderInfo->user_id, $message['openid']);
                    // 短信通知to或邮件通知
                    $phone = UserModel::query()->where('id', $orderInfo->user_id)->value('phone');
                    if ($phone) {
                        ExamNotify::notifySms($goodsDetails,$orderInfo->user_id);
                    }else{
                        ExamNotify::notifyEmail($goodsDetails,$orderInfo->user_id);
                    }
                });
    
                return $response;
    
            } catch (Exception $e) {
                // 纪录日志
                $data = [
                    'note' => '微信通知异常',
                    'params' => json_encode($e),
                    'user_id' => 0,
                    'code' => 'wechat_notify',
                    'ip' => ip2long(request()->ip()),
                ];
                $error   = new ErrorLogModel($data);
                $error->save();
            }
    

    写的比较粗略,只是一个支付的大致流程
    easywechat 文档链接https://www.easywechat.com/

    以上为参考代码:(下文为实际项目代码片段)

    public function notify(Request $request)
        {
            $notify = $this->getNotify();
            $options = [
                // 必要配置
                'app_id'             => config('common.wxapp.app_id'),
                'mch_id'             => config('common.wxapp.mch_id'),
                'key'                => config('common.wxapp.key'),
                'notify_url'         => config('common.wxapp.notify_url'),
            ];
            $app = Factory::payment($options);
            logger('回调数据 =====');
            logger($notify->toArray());
            // 查询微信订单,确认支付状态
            $result = $app->order->queryByTransactionId($notify['transaction_id']);
            logger('查询订单result=====');
            logger($result);
            if($result['result_code'] === 'SUCCESS'){} else {
                return true;
            }
            logger('支付回调中。。。');
            $response = $app->handlePaidNotify(function ($message, $fail)
            {
                // 根据返回的订单号查询订单数据
                $order = Order::where('order_sn', $message['out_trade_no'])->first();
                if (!$order) {
                    // 订单不存在
                    return true;
                }
                if ($order->status != 0 ) {
                    // 不是待支付状态均不处理,包含取消和失败
                    return true;
                }
                // 支付成功后的业务逻辑
                if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态,不代表支付状态
                    // 用户是否支付成功
                    if (array_get($message, 'result_code') === 'SUCCESS') {
                        // 变更状态
                        $order->status = 1;
                        $order->paid_at = date('Y-m-d H:i:s');
                        $order->pay_sn = $message['transaction_id'];
                    } elseif (array_get($message, 'result_code') === 'FAIL') {
                        // 用户支付失败
                        $order->status = 3;
                    }
                    if($order->save()){
                        return true;
                        // 更新prepay_id (意义不大,原本是用来再支付次数限制的)
    //                    WxPrepayId::where('order_id')
                    } else {
                        logger('订单更新失败'.$order->id);
                        $fail('更新失败');
                    }
                } else {
                    return $fail('通信失败,请稍后再通知我');
                }
            });
            logger('支付回调处理完成 order='.$result['out_trade_no']);
            return $response;
        }
    
        private function getNotify(Request $request = null)
        {
            $request = Request::createFromGlobals();
            try {
                $xml = XML::parse(strval($request->getContent()));
            } catch (\Throwable $e) {
                throw new Exception('Invalid request XML: ' . $e->getMessage(), 400);
            }
    
            if (!is_array($xml) || empty($xml)) {
                throw new Exception('Invalid request XML.', 400);
            }
            return new Collection($xml);
        }
    

    相关文章

      网友评论

          本文标题:esaywechat 微信公众号jsapi支付

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