个人网站实现微信扫码登录

分类首页前端日期1年前访问1135评论0

先看文章,了解做法和思路
https://mdnice.com/writing/3fb83abf28d4486c8ce03ba89c668a8b
https://blog.csdn.net/IT_rookie_newbie/article/details/130510852

以下代码只是提供思路,并不能直接使用,如有不懂处可以有偿联系作者,Q:528772568

先看流程图

获取getAccessToken

  //获取wxgetAccessToken
   public function getAccessToken(){
       $appid = config('wx_lite')['appid'];
        $appsecret = config('wx_lite')['appSecret'];
        $token_file = Config('extraconfig');//适用于TP5.0,获取extra下面的extraconfig.php配置文件,不需要手动创建,用extraconfig方法创建
        
        if(empty($token_file['wx_expiretime'])||(int) $token_file['wx_expiretime']<time()){
            $TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $appid . "&secret=" . $appsecret;
            $json = file_get_contents($TOKEN_URL);
            $result = json_decode($json);
            if(empty($result->access_token)){
                $this->error($result->errmsg);
            }
            $ACC_TOKEN = $result->access_token;
            $this->extraconfig(['wx_expiretime'=>time()+7000,'wx_token'=>$ACC_TOKEN]);
        }else{
            $ACC_TOKEN = $token_file['wx_token'];
        }
        
        return $ACC_TOKEN;
   }
//保存token文件
   private function extraconfig($arr = [], $file = 'extraconfig')
    {
        
        if (is_array($arr)) {
            $filename = $file . EXT;
            
            $filepath = APP_PATH . 'extra/' . $filename;
            if (!file_exists($filepath)) {
                $conf = "<?php return [];";
                file_put_contents($filepath, $conf);
            }
            
            $conf = include $filepath;
            foreach ($arr as $key => $value) {
                $conf[$key] = $value;
            }
    
            $time = date('Y/m/d H:i:s');
            $str = "<?php\r\n/**\r\n * 由config建立.\r\n * $time\r\n */\r\nreturn [\r\n";
            foreach ($conf as $key => $value) {
                $str .= "\t'$key' => '$value',";
                $str .= "\r\n";
            }
            $str .= '];';
    
            file_put_contents($filepath, $str);
            
            return true;
        } else {
            return false;
        }
    }

生成二维码

//获取不限制的小程序码
   public function getUnlimitedQRCode(){
       $keyUuid = Random::uuidrd();
    //   $id = Cache::get($key);
       $url = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$this->getAccessToken();
       $res = Curl::curl_request($url,json_encode(['scene'=>$keyUuid,'page'=>'pages/index/index','env_version'=>'develop']),'post',false);
       
       $json = json_decode($res,true);
       if(is_array($json)&&!empty($json['errcode'])){
           $this->error($json['errmsg']);
       }
       $name = 'wxcode'.time().mt_rand(1, 100).'.jpg';
        $file = fopen("xcxcode/".$name,"w");//创建件准备写入,文件名xcxcode/wxcode1.jpg为自定义
        fwrite($file,$res);//写入
        fclose($file);
        $cacheData = ['key'=>$keyUuid,'is_webLogin'=>0];
        Cache::set($keyUuid,$cacheData,600);
        $request = Request::instance();
        $this->success('',['loginUrl'=>$request->domain().'/xcxcode/'.$name,'key'=>$keyUuid]);
        
   }

轮询获取扫码状态


public function wxLoginQuery($key){
        $userinfo = Cache::get($key);  
		//这里的状态和缓存自己写逻辑,用redis或其他,由wxlogin接口登录成功后会返回unionid值 
		if($userinfo&&!empty($userinfo['wxunionid'])){
            $user = model('User')->where('wxunionid',$userinfo['wxunionid'])->find();
            Cache::pull($key);
            if($user){
                //直接登录会员
                $this->success('登录成功!',['type'=>1,'key'=>$key]);
            }else{
                $this->success('未注册!',['type'=>2,'key'=>$key]);
            }
        }else{
            $this->error('未扫码或已过期!');
        }
    }


微信登录
 /**
     * 微信小程序登录
     *
     * @ApiMethod (GET)
     * @Author XiaoLiu wen@zmmz.com
     * @DateTime 2022-04-11 12:52:08 
     * @param string $code 微信登录code
     * @param string $avatar 微信头像
     * @param string $nickName 微信昵称
     * @return void
     */
    public function wxlogin($code = '', $avatar = '', $nickName = '',$loginKey='')
    {
        if (!$code) {
            $this->error('请填写正确的code');
        }
		//判断是否是扫码登录,判断是否是通过扫码进入
        if($loginKey){
            $cacheData = Cache::get($loginKey);
            if(!$cacheData){
                $loginKey = '';
                $this->error('二维码已过期!');
            }
        }
        $avatar = $this->request->get('avatar', '', 'trim,strip_tags,htmlspecialchars');
        $config =config('wx_lite');
        $appid = $config['appid'];
        $appsecret = $config['appSecret'];
        $grant_type = $config['grant_type'];
        $url = "https://api.weixin.qq.com/sns/jscode2session?" . "appid=" . $appid . "&secret=" . $appsecret . "&js_code=" . $code . "&grant_type=" . $grant_type;
        $res = json_decode(Curl::curl_request($url), true);
        
        if (!empty($res['errcode'])) {
            $this->error('code解析失败');
        }
      
        $wx_unionid = '';
        $wx_openid = $res['openid']; 
        
        if(!empty($res['unionid'])){
           $wx_unionid = $res['unionid']; 
           $user = model('User')->field('id,wxopenid,wxunionid')->where('wxunionid', $wx_unionid)->find();
        }else{
           $user = model('User')->field('id,wxopenid')->where('wxopenid', $wx_openid)->find();  
        }
       
        $time = time();
        
        if($user){
             if($avatar){
                model('User')->where('id',$user['id'])->update(['avatar'=>$avatar]);
            }
            if(!$user['wxopenid']){
                model('User')->where('id',$user['id'])->update(['wxopenid'=>$wx_openid]);
            }
            //模拟一次登录
            $this->auth->direct($user['id']);
            $data = $this->auth->getUserinfo();
            
            if($loginKey){
                $Keydata = Cache::pull($loginKey);
                $data['is_webLogin'] = 1;
                
                Cache::set($loginKey,$data,600);
            }
            $this->success('登录成功', $data);
        }
        
     //如果未注册执行注册,注册逻辑不展示,根据实际业务自行编写
       Db::startTrans();
        $register_user= $this->register($avatar,$nickName,$wx_unionid,$wx_openid);//model('Third')->create($values);
        if (!$register_user) {
            Db::rollback();
            $this->error("登录失败,请重试");
        } 
        
        Db::commit();
        //模拟一次登录
        $this->auth->direct($register_user);
        $data = $this->auth->getUserinfo();
        if($loginKey){
            $Keydata = Cache::pull($loginKey);
            $data['is_webLogin'] = 1;
            Cache::set($loginKey,$data,600);
        }
        $this->success('登录成功', $data);
    }

小程序扫码判断二维码是否过期

//获取二维码信息
   public function getSceneInfo($key=''){
       $cacheData = Cache::get($key);
       if(!$cacheData){
           $this->error('二维码过期!');
       }
        $this->success('',$cacheData);
   }

前端代码


  {layout name='/layout/layout'/}
    <div class="app-main-post">
        <div class="login-form" style="box-shadow: 8px 8px 20px 0 rgb(55 99 170 / 10%), -8px -8px 20px 0 #fff;text-align: center;padding: 50px 0;padding-bottom:50%">
            <img id="profile-img" class="profile-img-card" src="__CDN__/assets/img/avatar.png" style="display: none;"/>
            <div style="text-align: center;font-size: 23px;">扫码登录</div>
            <p id="profile-name" class="profile-name-card"></p>
            <img src="__CDN__/assets/img/736c88b1bbfed3528ec3b2900b75de5a.gif" id='loginurl' alt="" style="width: 55%;height:350px" />
        </div>
                
            <!--------------------------------------------------->
    </div>
    <script>
    $(function(){
      
        let loginkey = '';
        $.ajax({
			url: '/api/v1/Wxutils/getUnlimitedQRCode',
			type: 'GET', // 指定请求类型为POST
			data: {}, // 要发送的数据
			success: function(res) {
			    console.log(res)
				if(res.code){
					$('#loginurl').attr('src',res.data.loginUrl)
					loginkey = res.data.key
				}else{
					alert(res.msg);
				}
			},
			error: function(jqXHR, textStatus, errorThrown) {
				 if (jqXHR.status === 401) {
					 alert(jqXHR.responseJSON.msg);
				 }
			},
			dataType: 'jsonp' // 预期的服务器响应类型
		});
		
		var myIntval;
        var myIntval = setInterval(function(){
            $.ajax({
    			url: '/api/v1/wxutils/wxLoginQuery',
    			type: 'POST', // 指定请求类型为POST
    			data: {key:loginkey}, // 要发送的数据
    			success: function(res) {
    			    console.log(res)
    				if(!res.code){
    				   return true;
    				}
    				if(res.data.type==1){
                        clearInterval(myIntval);
                        // alert(res.msg);
                        // window.location.href = '/'
                        window.location.href = '/index/user/login?key='+res.data.key;
                    }else if(res.data.type==3){
                        window.location.href = '/index/login?key='+res.data.key;
                        // location.reload();
                    }else{
                        alert(res.msg);
                        // location.reload();
                    }
					console.log(res)
    			},
    			error: function(jqXHR, textStatus, errorThrown) {
    				 if (jqXHR.status === 401) {
    					 alert(jqXHR.responseJSON.msg);
    				 }
    			},
    			dataType: 'jsonp' // 预期的服务器响应类型
    		});
        }, 2000);
        console.log(1231)
    })
</script>