Yii2博客实战教程——微信扫码登陆的实现

随着微信的普及,越来越多的网站开始支持微信扫描二维码登录的方式,大大降低了用户的使用注册成本,提高了用户体验。下面我们就来讲讲如何使用微信的扫一扫功能实现用户登录。

首先,我们必须有微信公众账号,并且拥有oauth授权接口的权限,如果没有的话,还有个办法就是申请一个微信公众号的测试账号,完成开发功能后再切换到正式账号上使用。具体步骤参考微信公众平台及开发文档。我们这里着重讲解下YII2下的开发。整个登陆的流程如下所示:

f1d8c4e751-2016-09-2915-52-14

第一步,用户访问网站登录页面,页面提供二维码。这里我们需要使用php生成二维码供用户使用,我们采用的是第三方的phpqrcode库来生成。在wechat控制器中增加auth-qr的action这样我们就可以通过wechat/auth-qr来获取二维码图片了。

public function actionAuthQr()
    {
        Yii::$app->response->format = Response::FORMAT_RAW;
        $code = HttpHelper::getParams('task_id', CommonHelper::guid()); 
        Yii::$app->redis->setex('wechatLogin:'.$code, ((int)Yii::getAlias('@wechatQrTimer'))/60,$code);
        $url = Yii::getAlias('http://域名/wechat/auth-request/?task_id='.$code);
        QRcode::png($url,false, 'Q',4, 2);
    }

前台登陆页面的渲染如下:

<img id="qrimg" src="/wechat/auth-qr?task_id=<?= \common\helper\CommonHelper::guid()?>">

我们可以看到,每次访问我们会生成一个新的task_id存入redis里面,并且设置好过期时间。当用户使用手机扫描二维码时会自动跳转到二维码的内容url即/wechat/auth-request上,这里我们会向微信服务器发起认证。

public function actionAuthRequest()
    {
        $task_id = HttpHelper::getParams('task_id'); 
        $r = Yii::$app->redis->get('wechatLogin:'.$task_id);
        if(isset($task_id) &&  isset($r))
        {
            $callBack = '域名/wechat/auth-callback?';
            $parms = 'task_id='.$task_id;
            $callBack .= $parms;
            $config = [
                'app_id' => '微信app_id',
                'secret' => '微信app_secret',
                'token'  => '微信token',
                'oauth' => [
                    'scopes'   => ['snsapi_base'],
                    'callback' => $callBack,
                ],
            ];
            $app = new Application($config);
            $oauth = $app->oauth;
            $oauth->redirect()->send();
        }
        else
        {
            return $this->render('/site/error',[
                'message' => '二维码已过期,请刷新登陆页面后重新扫描登陆. <a href="/site/signin">点击重新登陆</a>',
                'name' => '二维码已过期',
            ]);
        }
    }

以上代码我们使用了第三方的微信开发库easywechat进行微信操作,具体的安装及使用请参考官方文档https://easywechat.org/zh-cn/docs/oauth.html

这样代码完成授权后回自动回调我们设置的callback网址,触发下面的代码

public function actionAuthCallback()
    {
        $config = [
                'app_id' => '微信app_id',
                'secret' => '微信app_secret',
                'token'  => '微信token' 
            ];
        $app = new Application($config);
        $oauth = $app->oauth;
        $user = $oauth->user();
        $task_id = HttpHelper::getParams('task_id'); 
        Yii::$app->redis->set('wechatLogin:'.$code.':'.'.openid',$user->id); 
    }

这样在完成授权后,回调url会自动获取用户id并写入redis缓存起来。

经过以上步骤用户的授权已经完成,接下来我们实现自动登陆的过程。一般来讲有两种方案,一种是采用前端ajax轮询的方式,每隔一段时间去query下服务器状态完成自动登陆,第二种是采用websocket主动推送的方式。本次我们就先简单的采用ajax轮询的方式实现登陆。

public function actionCheckWechatLogin()
    {
        $code = 0 ;
        $msg = "";
        $task_id= HttpHelper::getParams('task_id');
        $openid =  Yii::$app->redis->get('wechatLogin:'.$task_id.'.openid');
        if( $openid!= null)
        {
            $user = Admin::findOne(['wechat_id'=>$openid]);
            if($user != null && Yii::$app->user->login($user , 3600))
            {
                $code= 1;
                $msg= "success";
                Yii::$app->redis->del('wechatLogin:'.$task_id.'.openid');
            } else {
                $code = 0 ;
                $msg = "登陆失败,微信未绑定或找不到微信对应用户,请刷新登陆页面后重新扫码登陆";
            }
        }
        else
        {
            $code = 0 ;
            $msg = "openid不存在";
        }
        Yii::$app->response->format=Response::FORMAT_JSON;
        return ['error_code'=>$code,'msg'=>$msg];
    }

简单吧,这样前端只要写个ajax的timer一直不停请求后台,一旦回调函数写入redis了openid,那么就会出发登陆。当然更加合理的方式是采用第二种主动推送的方式,我们将在下一篇博客中继续介绍。




本文由 Leo's Blog 创作,采用 署名-非商业性使用 2.5 中国大陆 进行许可。
如需转载、引用请署名作者且注明文章出处。
2016年09月29日 4671 浏览 评论 YII2 微信 扫码登陆
上一篇:Yii2博客实战教程——用crontab和congsole控制器同步多说评论 | 下一篇:Yii2博客实战教程——基于workerman的pushserver实现消息推送