EasyWeChat利用临时二维码实现在电脑浏览器上的微信扫码登陆功能

知识技术 2022-05-02 11:28 1774
转载请务必注明: 来源:《建站管家》https://www.df81.com/news/340.html

这个方法最开始用在还没有“微信开放平台”的时候,现在也有不少网站在用,简单说就是生成一个临时二维码放到服务器,然后微信扫描二维码后将该值传递给服务器进行比对,实现登陆,和手机动态码登陆思路类似。

流程说明

先把我们要实现的步骤说下:

用户访问微信登陆页面,程序生成一个临时二维码。

用户使用微信扫描刚生成的二维码。

扫码后微信发送二维码所含内容给网站程序。

客户端每隔N秒(或填写)将第一步的二维码内容和网站从微信接收的二维码内容比对,如果找到则登陆成功。


准备工作

因临时二维码生成和扫码操作需要用到公众账号通讯接口,因此我们先配置它(微信相关页面)。首先在@app/controllers/下新建一个名为WxController.php的控制器文件并且定义一个actionIndex来处理和微信之间的交互,如下面代码:

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {

    /**
     * 服务器与微信通讯处理接口
     * @author abei<abei@nai8.me>
     */
    public function actionIndex(){
        /*
         * 'WECHAT'=>[
         *      'appId'=>'xxx',
         *      'appSecret'=>'xxxxx',
         *      'token'=>'nai8_me'
         * ]
         */
        $options = Yii::$app->params['WECHAT'];
        $app = new Application($options);

        $response = $app->server->serve();
        $response->send();
    }
}


根据微信文档,首先我们需要通过服务器验证。

$response = $app->server->serve();
$response->send();


这段代码就是处理和微信响应的,我们在测试平台填写action的url和token


当配置验证通过后,我们再对微信服务器发过来的各种请求做相应处理,比如传过来一个文本,比如一次二维码扫描,比如一个地理位置,比如等等。关于EasyWechat对于和微信服务器交互的文档可以查看如下地址。

https://easywechat.org/zh-cn/...
https://easywechat.org/zh-cn/...


接下来我们来处理微信发过来的请求,在本文档里我们要处理的是扫描二维码后的接收事件,当然扫描二维码根据当前微信是否关注公众号返回的是不同的,因篇幅问题,我们只说关注后的情况。

增加功能后的代码如下

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {

    public $wxApp;

    /**
     * 服务器与微信通讯处理接口
     * @author abei<abei@nai8.me>
     */
    public function actionIndex(){
        $options = Yii::$app->params['WECHAT'];
        $app = new Application($options);

        $server = $app->server;
        $this->wxApp = $app;

        $server->setMessageHandler(function ($message) {
            switch ($message->MsgType) {
                case 'event':// SCAN & subscribe
                    return $this->doEvent($message);
                    break;
            }
        });

        $response = $server->serve();
        $response->send();
    }

    /**
     * 处理事件
     * @param $message
     * @author abei<abei@nai8.me>
     */
    protected function doEvent($message){
        switch ($message->Event) {
            case 'SCAN':
                return $this->doScan($message);
                break;
        }
    }

    /**
     * 处理具体扫描事件
     * @param $message
     * @author abei<abei@nai8.me>
     */
    protected function doScan($message){
        $key = $message->EventKey;
        $openId = $message->FromUserName;
        return $openId;
    }
}


为防止函数过长,我们拆分为几个小方法处理,同时增加一个叫做$wxApp的变量代表本次交互,串联每个函数。

我们准备工作暂时到这里,下面用到的时候再说。

生成临时二维码

现在我们通过 EasyWeChat 来生成一个临时二维码,那就定义一个叫做 actionQrcode 的函数吧。

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {
    public $wxApp;

    ...

    public $enableCsrfValidation = false;

    /**
     * 生成一个临时二维码
     * @author abei<abei@nai8.me>
     */
    public function actionQrcode(){
        $options = Yii::$app->params['WECHAT'];
        $app = new Application($options);
        $qrcode = $app->qrcode;

        $rand = mt_rand(100000,999999);
        $result = $qrcode->temporary($rand, 6 * 24 * 3600);
        $ticket = $result->ticket;// 或者 $result['ticket']
        $url = $qrcode->url($ticket);
    
        return $this->render('qrcode',[
            'url'=>$url,
            'rand'=>$rand
        ]);
    }
}


actionQrcode 方法将一个随机的6位数字放到了临时二维码中,这里要说明有两点

$url 即为二维码图片地址,在视图里直接用img 标签接收即可。

除了微信服务器验证为GET请求,其他的事件均为POST请求,但是yii2默认对于POST提交是进行crsf验证的,因此为了有效的接收微信服务器给我们的推送信息,我们需要关闭crsf验证。

public $enableCsrfValidation = false; // 我就是用来关闭crsf验证滴


这样我们就生成了一个含有$rand值的二维码,对于如何使用完成登陆方法很多,我这里使用浏览器请求方式,在actionQrcode的视图内,我填写如下代码

<img src="<?= $url;?>" alt="">
<script>
    //todo 每隔N秒钟向程序发起一次请求,询问一个叫做wx_qrcode的数据表是否有含有$rand的记录,如果有则php完成登陆,浏览器跳转到比如个人中心等页面
</script>


那么接下来就是这个叫做wx_qrcode的表如何设计以及记录如何产生的问题了。


重要的wx_qrcode表

如果你看了微信文档一定知道,当我们使用微信扫描临时二维码的时候,微信除了告诉我们服务器二维码所代表的$rand随机数字外,还有一个叫做$openId的标识,它代表扫码微信的唯一身份,因此我们设计了wx_qrcode表,里面含有open_id和rand。


思路是这样的

扫码后程序接到微信传递过来的open_id和rand随机码,进行会员初始化工作,同时往wx_qrcode表内存此记录。

程序接到浏览器请求,根据请求中的rand随机码来查询wx_qrcode,如果找到记录,则找到了open_id,也就找到了此会员,然后使用Yii::$app->user->login()方法进行登录授权,然后删除该记录后返给浏览器登录成功,否则返回失败,继续让浏览器N秒后询问。

也就是说我们需要修改第一步里的微信扫码处理程序,做简单处理。

namespace app\controllers;

use Yii;
use yii\web\Controller;
use EasyWeChat\Foundation\Application;// 引入EasyWeChat

class WxController extends Controller {

    public $wxApp;

    public $enableCsrfValidation = false;

    ...

    /**
     * 处理具体扫描事件
     * @param $message
     * @author abei<abei@nai8.me>
     */
    protected function doScan($message){
        $key = $message->EventKey;
        $openId = $message->FromUserName;
        
        $user = User::find()->where(['open_id'=>$openId])->one();
        if($user == false){
            //todo 新建会员
        }
        
        $wxQrcode = new WxQrcode();
        $wxQrcode->open_id = $openId;
        $wxQrcode->rand = $key;
        $wxQrcode->save();
    }
}


这只是一个思路,各位兄弟根据自己系统的情况需要更加完善这块的逻辑,反正这个扫描的接收,我们需要填充wx_qrcode记录,让浏览器来询问。

ok,接下来我再说下PHP如何处理浏览器咨询的逻辑

    public function actionAsk(){
        $rand = Yii::$app->request->get('key');
        $check = WxQrcode::find()->where(['rand'=>$rand])->one();
        if($check){
            $user = User::find()->where(['open_id'=>$check->open_id)->one();
            Yii::$app->user->login($user);
            
            $check->delete();
            
            return Json::encode(['done'=>true]);
        }else{
            //todo 不做什么,让浏览器继续问。
        }
    }


总结一下

扫码登陆有很多,比如生成二维码后不进行视图的循环,而是扫码后以动态码形式用模板消息等发给微信,微信在页面添加动态码实现验证登陆,就像兄弟连的微信登陆一样。

方法很多,核心就一条,就是利用二维码的内容进行PC和微信之间的传递。


点赞 (0)

收藏 (0)

本站部分信息来源网络,如有侵权,请联系QQ:1062129401删除。

上一篇: 《建站管家》二次开发文档

下一篇: PHP实现执行定时任务的几种思路详解

请先登录后,再发表评论 ~ ~
发表评论
发表评论
发表帖子
广告位招租( ¥5 / 天 )
点击咨询
相关帖子

如果要判断文件是否存在,用函数 is_file(),如果要判断目录是否存在,用函数 is_dir()
用宝塔安装TP程序后,网站前台可以访问,后台无法访问,不是程序问题,而是web服务器环境配置问题(PHP配置),出现这种问题,一般是windows主机安装宝塔造成的,linux安装宝塔不会出现此错误
广告位招租( ¥3 / 天 )
点击咨询
广告位招租( ¥2 / 天 )
点击咨询
广告位招租( ¥1 / 天 )
点击咨询
最新帖子

小朋友,你爸爸是谁啊?这很单纯的,就像我们碰到别人会问:你吃过饭了吗?类似;许多人初次相识,经常会问:你是做什么的啊?你做什么,好像决定你收入的高低,你,资产的范围
1、升级框架到ThinkPHP8.0.3【要求PHP8.1+环境,推荐PHP8.1】 2、启用/禁用调试模式等小细节改进
后台点击生成站点地图 一直转圈圈没有反应,
在线客服