之前的一直想做 扫码登陆这个, 感觉很方便, 但是 我的公众微信没权限啊!!
最近弄了新的公众微信,有权限了,来做个扫码登陆!
首先, 我们需要准备:
前期准备:
网站用户已经把自己的账号与微信公众号进行了绑定了!,
具体绑定流程如下,
在微信公众号菜单上加权限,如果用户没有绑定,提示绑定, 用户点击菜单时候,开发者能拿到openid,让用户在微信里打开网址登陆页面,重新登陆一次,登陆成功后记录openid即可!
还有一种方法就是使用带参数的二维码, 用户在Pc网址登陆后,生成一张带唯一标志的二维码,使用手机扫描二维码,开发者拿到二维码携带的参数,与生成二维码的参数对应,就能知道是哪个用户,然后记录数据即可!
可以获得渠道二维码权限的微信公众号!
渠道二维码权限的公众号,我们需要使用带参数的二维码,功能生成带参数的二维码!
准备完成,开始做第一步,生成带参数的二维码,然后在网页展示二维码,让用户扫码!
首先后端工作开始!
渠道二维码在微信公众平台文档
我们的绑定操作,无需生成永久二维码,临时的即可!
临时二维码请求说明
http请求方式: POST
URL: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKENPOST数据格式:json
POST数据例子:{“expire_seconds”: 604800, “action_name”: “QR_SCENE”, “action_info”: {“scene”: {“scene_id”: 123}}}
或者也可以使用以下POST数据创建字符串形式的二维码参数:
{“expire_seconds”: 604800, “action_name”: “QR_STR_SCENE”, “action_info”: {“scene”: {“scene_str”: “test”}}}
我们还需要在前端生成一个唯一状态码,用来标识用户!
前端部分
1 2 3 |
random:function (number=1000,t = false) { return Math.round(Math.random()*number) }, |
生成一个随机数id,发送给后台接口去拿二维码
后端收到id后,把id作为生成带参数二维码的id
获取二维码成功,返回前端,前端显示二维码
1 |
{"status":1,"info":{"ticket":"gQHO8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyRExaY29WS2ljdTIxTC1zZk5wMVgAAgT_84dZAwQA6QcA","expire_seconds":518400,"url":"http:\/\/weixin.qq.com\/q\/02DLZcoVKicu21L-sfNp1X"},"url":"","title":""} |
接口调用成功,拿到二维码地址, http://weixin.qq.com/q/02DLZcoVKicu21L-sfNp1X
注意:此地址只能在微信中打开,打开后会直接打开相应的微信公众号,其他浏览器打开无效,
得到二维码地址,我们需要把地址转为二维码, 这里可以后端直接生成,也可以前端来做,为了方便,我用前端来生成,
安装了一个扩展: vue-qrcode
具体怎么用我就不细说了,
我们直接生成二维码:
二维码展示成功后, 我们需要前端启动一个定时器,每隔1秒钟请求一次后台,检查用户是否已经扫码(这里还可以使用websocket去做)!
后端,如果用户扫码成功,则在微信的消息中,会拿到一个事件类型的消息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
//事件类型消息 public function event($msg){ switch ($msg->Event) { case 'subscribe': $define = require_once wx_root.'/config/wxconfig.php'; $data = $define['guanzhu']; return $this->reply($data,'news'); break; case 'unsubscribe': return '取消了关注,回复消息用户收不到'; break; case 'CLICK': self::logger($msg->Event,'进入事件类型区域'); $event = new Event(); $evn = $event->index($msg); if(is_array($evn)){ return $this->reply($evn['info'],$evn['type']); }else{ return $evn; } break; // 扫码成功后走这里 case 'SCAN': $scan = new Scan(); return $scan->start($msg); break; default: return json_encode($msg); break; } } |
然后,我们就能在扫码成功的消息里拿到前端定义的唯一标志,用户openid等等信息!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public function login(){ $info = Db::name('user') ->where(['openid'=>$this->msgData->FromUserName]) ->field('pk_user_main,nickname,a_token') ->find(); if(empty($info)){ $msg = '抱歉,您的微信还未绑定平台账号'; cache($this->msgData->EventKey,$msg); return $msg.',请点我绑定'; }else{ $info['uid'] = $info['pk_user_main']; $info['token'] = $info['a_token']; cache($this->msgData->EventKey,$info); return '亲爱的'.$info['nickname'].',您已经登陆成功了'; } } |
如果用户已经绑定了,直接把他的个人信息缓存下来(如果是分布式,建议缓存到redis等等),
这里直接回复了客户端消息, 亲爱的 XXX ,您已经登陆成功了!
缓存成功,
前台的轮询消息这里的接口数据里,直接拿缓存的数据,如果没拿到返回false,
否则返回缓存的数据,
前端拿到数据表示登陆成功!
这样,我们的扫码登陆就已经完成了!