^

微信公众号扫码登录开发指南

前言

花了三百在陈哥的帮助下认证了一个服务号,为什么要认证服务号呢,就只是为了他的扫码登录网站而已。

其实也可以用微信开发者自带的那个打开一个地址进行oauth认证,那样的话写代码简直不要太简单,但是考虑到都是300块,公众号还有模版消息这种比较舒服的功能,还是选择了后者。

开发

网上的教程参差不齐,每次搜索弹出来的都是微信开放平台的扫码登录,微信公众号扫码登录我知道一定可以,因为以前做过修罗bbs的公众号扫码登录并且p神的代码审计知识星球也是用的公众号扫码登录。

可能是我不会百度吧,每次都是搜索出一大堆和公众号无关的教程文章,但是但是最终还是让我摸透了她整个业务流程,我就用简单的文字来描述一下吧。

流程

#1 生成accesstoken

公众号使用appid+appsecret来获取accesstoken。这里这个accesstoken可以理解为高级接口使用鉴权,但是这个token只有自产生开始两个小时的使用时间。

#2 获取ticket

使用accesstoken来获取ticket,php代码如下

    public function qrcode($id){
    	$data = '{"expire_seconds":"60","action_name": "QR_STR_SCENE", "action_info": {"scene": {"scene_str": '.$id.'}}}';
    	$ret = $this->p_post('https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token='.$this->at(),$data);
    	$ret = json_decode($ret,true);
    	return $ret['ticket'];
    }

这里解释一下相关的代码,$data是使用accesstoken下,对接口需要请求的一些重要请求体,里面包含了一些参数。

expire_seconds 表示二维码有效时间,单位是秒。QR_STR_SCENE表示当前为生成字符串场景。相应地,需要用到scene_str这个键,还有一种是生成id场景,他的键名就不是scene_str了,而是scene_id了,而这个键的范围就是1-100000了,比较有限制。我们的需要是,用户访问页面,会生成一个唯一ticket的二维码,如果是前面用id做内容传值,有可能会产生两个用户同时访问到同一个票据,从而产生一个同样的二维码。

所以,我的$id值为时间戳拼接硬编码然后md5,会动态改变,从而使得系统每时每刻产生一个不一样的二维码。

最后返回ticket。

#3 前端生成二维码

只需要从接口获取ticket,拼接https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=  即可

#4 用户扫码后发生的一些事

用户扫码这个由公众号产生的二维码后,发生了一些事,这需要我们明确。

首先扫码后,微信会判断这个二维码是否过期,过期了就告知过期,否则就对公众号后台配置的接口发送一个scan的event事件,并携带openid、ticket这两个重要标志(如果用户扫码后没关注,会在关注后发送一个subscribe的订阅事件,依然会传递tikcet和openid)。所以我们后台的接口,可以对事件处理时,判断是否存在ticket,如果有ticket那么就代表此openid的微信用户一定他妈的去扫码了。

此时通过api,我们可以把openid和ticket保存在数据库里,例如我后台做了个应用,专门储存到这时的扫码状态。

6127d05da1fae.png

#5 通知前端

用户扫码了,我怎么告诉前端呢?

所以这时候,轮询就显得非常重要了。因为在当前界面产生了一个ticket,而在步骤4我们储存了ticket在数据库,一开始用户没有扫码的时候,数据库是没有这个ticket的。我们可以写一个接口,根据ticket去检索,如果存在ticket,显示状态1,代表用户扫码了,存储在数据库了。如果找不到,那就是状态0,代表没有扫码。

前端使用当前界面产生的ticket,不断对接口做查询。但这还没完,我们在前面产生ticket的时候,设置了过期时间,假如二维码过期了,前端没告知,用户扫码发现过期,这是一个非常影响用户体验的体验。

所以,根据二维码过期时间,我们每两秒轮询一次,那么轮询30次之后就是一分钟,记时器计数30,那么前端就停止轮询了,告诉用户二维码过期了。

6127d1c012240.png

#6 扫码之后登陆

如果用户扫码了,前端轮询发现状态码为1,前端js会停止轮询,跳转到一个回调地址,并携带当前的ticket去处理,此时我们又可以在那个储存ticket和openid的表中做查询,根据这个票据提取出openid,然后删掉这个记录(我也不知道为啥要删,其实不删也可以,但是我不喜欢数据很多的后台)。

拿到openid之后,就很好办了。

用openid去后台用户表找这个openid对应的人,然后做常规的登录即可。

效果

略。