老莫的笔记本  
  
查看: 317|回复: 0

普通的H5 网页作微信公众号菜单,获取微信授权、jssdk

[复制链接]

662

主题

878

帖子

5145

积分

超级版主

Rank: 8Rank: 8

积分
5145
发表于 2022-6-24 17:26:29 | 显示全部楼层 |阅读模式
本帖最后由 周大胖子 于 2022-7-5 14:55 编辑

我的血泪史啊,

先提一个 坑爹的点: 注意事项: 拿完网页微信配置后,比如说获取微信收货地址,在调试器中就会报错、必须在真实环境中测 才可以正常运行。

第一步    单纯在该网页中获取微信授权   

               这就是获取code 别问我啥是CODE 我也不晓得 ,但是存起来用就可以获取到用户的一些信息

             1.1 判断是不是微信浏览器

             function is_weixin() {
                       var ua = navigator.userAgent.toLowerCase();
                    if (ua.match(/MicroMessenger/i) == "micromessenger") { return true; } else { return false; }
            }
     
            if (is_weixin()) {
               // console.log('这是微信浏览器')

            } else {
               // console.log('不是')
            }


            1.2 获取授权的code    利用code 获取openid 只能获取一次  




  1.             let appid = "***"; //微信APPid
  2.             let local = window.location.href;
  3.             let code = getUrlCode().code; //是否存在code

  4.            if (code == null || code === "") {

  5.                
  6.                     //不存在就打开上面的地址进行授权
  7.                     window.location.href =
  8.                     "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
  9.                     appid +
  10.                     "&redirect_uri=" +
  11.                     encodeURIComponent(local) +
  12.                     "&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect";

  13.             } else {
  14.                   
  15.                     console.log(code)   // 这就是获取到了code
  16.                   
  17.             }


  18.         function getUrlCode() {
  19.             // 截取url中的code方法
  20.             var url = location.search;
  21.             var theRequest = new Object();
  22.             if (url.indexOf("?") != -1) {
  23.                 var str = url.substr(1);
  24.                 var strs = str.split("&");
  25.                 for (var i = 0; i < strs.length; i++) {
  26.                     theRequest[strs[i].split("=")[0]] = strs[i].split("=")[1];
  27.                 }
  28.             }
  29.             console.log(theRequest);
  30.             return theRequest;
  31.         }



复制代码




第二步    获取用户的openid    利用code 获取openid 只能获取一次,code 不能重复利用  

               
               这是一个前后台配合的操作  :   

            2.1 前台把code 传给 后台 ,后台向微信发出请求 获得 结果

                    前台简单的一个AJAX 就可以  例如




  1. api('api/home/use/getwx',  {'code': localStorage.getItem('wxcode')}, 'GET').then((e) => {
  2.                     // console.log(e)
  3.                     if (e.status == 200) {
  4.                         $("input[name=wxid]").val(e.data.data.openid);

  5.                      
  6.                     }
  7.            });
复制代码


          2.2 后台请求微信token,并把需要的值传回给前台






  1.     // 根据CODE 获取 access_token 和 用户信息
  2.     public function getwx( Request $request )
  3.     {
  4.         if(!$request->param('code')){
  5.             return app('json')->fail('没收到code');
  6.         }
  7.         $code = $request->param('code');
  8.         $timeout=array(
  9.             'https'=>array(
  10.                 'timeout'=>5000
  11.             )
  12.         );
  13.         $ctx=stream_context_create($timeout);
  14.         $text=file_get_contents('https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx79d8025aa45db24e&secret=ec81fc6d2381da603d64af2e3f6d9272&code='.$code.'&grant_type=authorization_code',0,$ctx);
  15.         
  16.         $m = array(
  17.             'data'=> json_decode($text)
  18.         );
  19.         $text = json_decode($text);

  20.         Cache::set('wxtoken', $text->access_token ,3600);
  21.       
  22.         return app('json')->success(  $m  );
  23.     }

  24.    

复制代码



第三步    获取调用支付、获取地址等功能

    3.1 首先明白一个事情, 要想调用微信的API 就需要 在当前页面 获取他的签名  ,

     3.1.1  获取签名在前台, 要获取签名 就需要引入微信的文件,才能使用 wx.什么什么

              
  1.   <script src="https://res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>  
复制代码


     3.1.2  然后直接发起请求,并且把 当前页面的链接传到后台 [ 这里其实有个问题就是关于 code获取时的链接地址 后面有个= 后面还有别的什么,我个人不喜欢,所以之前把code 存在了前端的缓存中,然后每次刷新页面除了读url 中的code, 还读缓存中是否有没过期的code 。有效期两小时 ,这样我就可以保证URL的纯净,等于把授权的code 藏起来了 ]

        


  1.        // 获取微信的配置
  2.         function weixinConfigFun(){

  3.            api('api/home/use/getSignature', {
  4.                     'url': location.href
  5.                 }, 'GET').then((e) => {
  6.                     // console.log(e)
  7.                     if (e.status == 200){
  8.                         // alert(1)
  9.                         wx.config({
  10.                             debug: false, // 开启调试模式,调用的所有 api 的返回值会在客户端 alert 出来,若要查看传入的参数,可以在 pc 端打开,参数信息会通过 log 打出,仅在 pc 端时才会打印。
  11.                             appId: e.data.appId, // 必填,公众号的唯一标识
  12.                             timestamp: e.data.timestamp, // 必填,生成签名的时间戳
  13.                             nonceStr: e.data.nonceStr, // 必填,生成签名的随机串
  14.                             signature: e.data.signature,// 必填,签名
  15.                             jsApiList: [  
  16.                             'editAddress',  
  17.                             'checkJsApi',
  18.                             'openAddress',
  19.                             ] // 必填,需要使用的 JS 接口列表
  20.                             // “openProductViewWithPid”,“batchAddCard”,“chooseCard”,“batchViewCard”,“editAddress”,“checkJsApi”
  21.                         });
  22.                         
  23.                         wx.openAddress({
  24.                             success: function (res) {
  25.                                 console.log(res)
  26.                             }
  27.                         });
  28.                     }
  29.                 });
  30.                
  31.         }

  32.         
复制代码


         注意 只要配置成功,后面的API调用在微信开发者工具中 很可能出问题,建议真机尝试   




   3.2  PHP 获取微信的签名 配置 注意配置获取 直接访问 getSignature

   


  1.    
  2.     // 获取微信的access_token
  3.     public function getWxAccessToekn(){

  4.         if(Cache::get('wxtoken')){

  5.             return Cache::get('wxtoken');

  6.         }else{
  7.             
  8.             $timeout=array(
  9.                 'https'=>array(
  10.                     'timeout'=>5000
  11.                 )
  12.             );
  13.             $ctx=stream_context_create($timeout);
  14.             // $text=file_get_contents('https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx79d8025aa45db24e&secret=ec81fc6d2381da603d64af2e3f6d9272&code='.$code.'&grant_type=authorization_code',0,$ctx);
  15.             $text=file_get_contents('https://api.weixin.qq.com/cgi-bin/token?appid=wx79d8025aa45db24e&secret=ec81fc6d2381da603d64af2e3f6d9272&&grant_type=client_credential',0,$ctx);
  16.             
  17.             $text = json_decode($text);

  18.             Cache::set('wxtoken', $text->access_token ,3600);

  19.             return Cache::get('wxtoken');
  20.         }
  21.     }


  22.    
  23.     /**
  24.      * 微信签名获取  
  25.      */
  26.     public function getSignature( Request $request )
  27.     {
  28.         // 先判断cache
  29.         $jsapiTicket =$this->getTicket() ;
  30.         
  31.         $nonceStr = $this->createNonceStr();
  32.         
  33.         $timestamp = time();
  34.         
  35.         // var test = window.location.href; 这样就可以获取当前页面url,最近我写个微信功能也这样取的。[我的想法是前端的URL当前页,传给后台]
  36.         // 签名用的url必须是调用JS接口页面的完整URL”
  37.         // 注意 URL 一定要动态获取,不能 hardcode.
  38.         // $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
  39.         // $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
  40.         
  41.         $url = $request->param('url');
  42.         //  $url = $request->param('url');
  43.         // 这里参数的顺序要按照 key 值 ASCII 码升序排序
  44.         $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
  45.         
  46.         $signature = sha1($string);
  47.         // dd($config['app_id']);

  48.         $signPackage = array(
  49.           "appId"     => '*******',
  50.           "nonceStr"  => $nonceStr,
  51.           "timestamp" => $timestamp,
  52.           "url"       => $url,
  53.           "signature" => $signature,
  54.           "rawString" => $string,
  55.           "jsapiTicket"=>$jsapiTicket
  56.         );
  57.         // return [
  58.         //     'code'=>0,
  59.         //     'message'=> '获取微信配置成功',
  60.         //     'data'=>$signPackage
  61.         // ];
  62.         // return $signPackage;
  63.          return app('json')->success(  $signPackage  );

  64.     }



  65.     public function getTicket()
  66.     {
  67.         if(Cache::get('ticket')){

  68.             return Cache::get('ticket');

  69.         }else{
  70.             
  71.             // $config = $this->sendConfig();

  72.             // $app = Factory::officialAccount($config);
  73.    
  74.             $accessToken = $this->getWxAccessToekn();

  75.             $url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token='. $accessToken.'&type=jsapi';
  76.             
  77.             //初始化
  78.             $ticketArr = $this->curl_get($url);
  79.             
  80.             $ticket = $ticketArr['ticket'];

  81.             Cache::set('ticket', $ticket ,3600);
  82.         
  83.             return $ticket;

  84.         }
  85.       
  86.     }


  87.     public function curl_get($url)
  88.     {
  89.        $headerArray =array("Content-type:application/json;","Accept:application/json");
  90.         $ch = curl_init();
  91.         curl_setopt($ch, CURLOPT_URL, $url);
  92.         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  93.         curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  94.         curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  95.         curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
  96.         $output = curl_exec($ch);
  97.         curl_close($ch);
  98.         $output = json_decode($output,true);
  99.         return $output;
  100.     }
  101.    
  102.     /**
  103.      *  生成随机数  
  104.     */
  105.    
  106.     public function createNonceStr($length = 16) {
  107.         $returnStr='';

  108.         $pattern = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';

  109.         for($i = 0; $i < $length; $i ++) {
  110.             
  111.             $returnStr .= $pattern {mt_rand ( 0, 61 )};

  112.         }
  113.         return $returnStr;
  114.     }




  115.    
复制代码





回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表