PC端微信扫码登录,无需关注微信公众号即可登录.无需开放平台,无需甚至不需要掏每年审核费用..

常见方案有两种

1,微信开发者平台(http://open.weixin.qq.com) 的网页oauth方案. 好像需要300一年,这种方案是免关注,此方法能返回微信用户基本信息

2,微信本身有生成二维码功能,但是要想要实现扫码登陆,其实就消息机制(也就是必须关注才能),此方法也能返回微信用户基本信息.

 

为啥不用现成的

我自己不是用的这两种方法.因为我自己用了一个微信自动回复的addons  ,它已经占用了接口配置URL ,  我要使用微信扫码登录,只能修改它代码.

我还有另外一个情况就是,我的微信公众号是测试账号(申请地址) ,只能关注100个人.

自己方案

1,  用户pc访问 login.html登陆页面

2,  login.html 已经登陆的情况下,和普通登陆情况一致,直接跳转后台或者用户页面.

3,  如果未登录,那么生成 request_str 随机字符串. 并写入数据库,将字符串加入session.

3.1 此页面视图文件只是显示一个二维码 (qr.php),二维码的内容是一个网址, /wx_login.php?request_str=$request_str ;

3.2 同时pc页面login.html 轮询ajax请求 判断手机用户是否扫码成功,扫码成功就写入数据库,然后自动登录

4,  用户通过扫码访问带参数的二维码(也就是访问了wx_login.php?request_str=$request_str )

4.1 将参数中request_str加入session['wx_request_str']  ,最后回调页面需要用.

4.2 微信上自动跳转到微信oauth登陆页面.

5,  手机上oauth微信授权登陆成功跳转到回调页面login_callback,读取session['wx_request_str'],并将用户openid写入数据库

5.1 此时PC端AJAX请求判断扫码成功,登陆处理

 --- 此时 3.2 步在反复轮询,读取数据库中的到 openid 知道用户已经登陆.

6,完成登录.

一切基于thinkphp5

use EasyWeChat\Foundation\Application; //EasyWeChat 3.x 微信套件
use addons\wechat\library\Config as ConfigService; //读取微信公众号的基本配置
use \think\Request; //thinkphp 获得参数 头信息
use \think\Session; //thinkphp session 管理
use Endroid\QrCode\QrCode; //二维码生成
use app\admin\library\Auth; //fastadmin 登录类
use app\admin\model\Admin; //fastadmin 管理员模型

 

初始化部分

    protected $logined = false; //登录状态
    protected $login_url ='';  //后台登陆页面
    protected $tips_url ='';   //手机页面报错或者成功提示
    protected $config =[];
    public $app = null;

    public function _initialize()
    {
        parent::_initialize();
        
        //手机扫码回调地址
        $call_url = Request::instance()->domain().url('/addons/wxlogin/index/login_callback',['t'=>time()]);  

        //PC授权后登录的页面
        $this->login_url = Request::instance()->domain().url('/admin/index/index');   //(可以用url('','','',true) 直接生成带域名)

        //手机扫码成功/或者失败跳转的页面
        $this->tips_url = Request::instance()->domain().url('/addons/yakeblog/index');

        //读取微信appid之类的.
        $this->config = ConfigService::load();

        //修改授权方式 (因为我是测试公众号相当于认证的服务号,有snsapi_base权限)
        $this->config['oauth']['scopes'][0] = 'snsapi_base';  //snsapi_base微信认证服务号;认证订阅号snsapi_userinfo
        //修改授权为回调地址
        $this->config['oauth']['callback'] = $call_url;
        //dump($config);exit;

        //初始化 EasyWeChat
        $this->app = new Application($this->config);
    }

PC登录页面login控制器

    public function login()
    {

        $auth = Auth::instance();

        //判断是否登陆,如果登陆了直接跳转后台
        if($auth->isLogin()){
            $this->redirect($this->login_url);
            exit;
        }


        //当前时间
        $time = time();

        //读取请求字符串session ,防止反复请求.
        $request_str = Session::get('request_str');

        //如果请求字符串存在就验证数据库
        if(!empty($request_str)){
            $info = db('wxlogin')->where('request_str',$request_str)->find();
            //如果数据库存在,判断是否过期,是否已经扫码
            if(!empty($info) && ( $info['overtime'] >= $time )  && empty($info['openid']) ) {
        $request_str = $info['request_str'];
                $overtime = $info['overtime'];
            }else{
                $request_str = '';  //设置为空,后面处理
            }
        }

        //如果不存在或者过期,那么重新生成
        if(empty($request_str)){
            $request_str = $this->random(). $time ; //生成随机字符串,后面追加时间,防止相同
            Session::set('request_str',$request_str); //写入session

            $overtime = $time +60 ; //60秒有效期
            //写入数据库
            db('wxlogin')-> insert(['request_str'=>$request_str,'overtime'=>$overtime]);
        }

        $this->assign('overtime',$overtime);  //传入有效期
        return $this->view->fetch('login');
    }

此页面控制器业务逻辑相当简单,生成随机字符串,$this->random()  (是一个随机生产字符串的函数,这里不提供了,php7.0自带,我的是5.5另外找的)

判断有没有过期,没过期,没被使用就继续用.有用过就重新生成.并写入数据库,同时加入session

 

 

 

login对应的视图文件

此页面也相当简单就显示一个二维码 示例页面( https://login.getce.cn) <本站已经改成小程序扫描登陆>

js代码部分就是反复ajax请求 /addons/wxlogin/index/is_login,判断是否登录.

 

res.code 有三种情况:

-1  :错误

0 :等待用户登录信息

1:成功.

可以自己扩展

 

 

手机页面控制器

    //判断是否微信浏览器
    public function is_weixin(){
        if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false ) {
                return true;
        }
        return false;
    }

    //手机端登陆接口
    //此页面是电脑生成带参数二维码,手机扫码访问的入口
    public function wx_login()
    {

        if($this->is_weixin()){
            $time = time();
            //获取参数
      $request_str = $this->request->param('request_str/s');
            if(!empty($request_str)){
                Session::set('wx_request_str',$request_str); //写入session,加个微信wx前缀,用于回调链接使用

                //读取数据库中 access_token,access_token每日调用次数有限,防止重复请求
                $info = db('wxlogin_token')->where('app_id',$this->config['app_id'])->find();
                $accessToken = $this->app->access_token;
                //如果还在有效期
                if (!empty($info) && !empty ($info['access_token'])  && ($info['overtime'] >= $time) ){
                    $this->app['access_token']->setToken($info['access_token']);
                }else{
                    //如果已经过期
                    $token = $accessToken->getToken(true); // 强制重新从微信服务器获取 token.

                    if (!empty($token)){

            //更新或者新增记录
            if(empty($info)){
              db('wxlogin_token')-> insert(['app_id'=>$this->config['app_id'],'access_token'=>$token,'overtime'=> $time+3600]);
            }else{
              db('wxlogin_token')
                ->where('app_id',$this->config['app_id'])
                ->update(['access_token'=>$token, 'overtime'=> $time+3600]);
            }
                    }else{
                        $this->error('请求access_token错误',$this->tips_url);
                    }
                }

                  $oauth = $this->app->oauth;

                  // 未登录
                  if (empty($_SESSION['wechat_user'])) {
                    return $oauth->redirect();
                  }
            }else{
                $this->error('扫码参数错误!',$this->tips_url);
            }


        }else{
            $this->error('请微信中访问!');
        }

    }




    //手机页面.登陆回调页面,处理用户授权后登录逻辑
    public function login_callback()
    {

        $user = $this->app->oauth->user();

        $time = time();

        //获取授权参数
        $request_str = Session::get('wx_request_str');
        Session::set('wx_request_str',NULL); //清理session

        if(!empty($request_str)){
            $info = db('wxlogin')->where('request_str',$request_str)->find();
            //数据库存在,且未到有效期,并且没有写入openid的情况.
            if(!empty($info) && ( $info['overtime'] >= $time )  && empty($info['openid']) ){
                db('wxlogin')->where('id',$info['id'])->update(['openid'=>$user->id,'oktime'=>$time]);
                $this->success('授权成功,现在PC端已经登陆!',$this->tips_url);
            }else{
                $this->error('可能已经授权',$this->tips_url);
            }

        }else{
            $this->error('参数错误',$this->tips_url);
        }



    }

可以无需视图文件,我没视图文件,只有控制器

手机上就两个页面,当然你也可以自己扩展,

1,wx_login.php?request_str = xxxxxxxxxxxxx

参数是PC端生成的URL二维码传过来的.

读取数据库看有没有过期,又没被使用过这个参数.

没有使用,没过期就授权登录,当然需要将request_str参数加入session

$oauth = $this->app->oauth; 
return $oauth->redirect();

2, 授权成功回调页面 login_callback.php

读微信oauth的用户openid

然后将openid写入wxlogin表,表示已经登陆.

那么手机上就完成了全部业务