业务需求:
用户点击网站登陆,弹出二维码,用户打开微信扫描二维码登陆,如果用户没有关注,先关注微信公众号再登陆
技术:
微信生成带参数临时二维码
微信事件推送(用户扫码就是一个扫码事件)
微信公众号获取用户信息
推送事件里的FromUserName 就是用户的openid
设计实现:
1.用户点击网站微信登陆,微信请求后端接口,后端生成一个带随机场景值的二维码(这里我用的rand(1000000,9999999)生成随机sence_id),将二维码链接和sence_id一起返回前端
$sence_id = rand(1000000,9999999);//100W到999W之间的数字为网站登陆场景 todo:随机值重复情况没有做处理 $wxConfig = new WxConfig(); $img = $wxConfig->getQrCode(60,'temp',$sence_id,true); $redis = Cache::store('redis')->handler(); $redis->setex('77dj_wx:user:'.$sence_id,120,0);//已sence_id为键 return wx_successReturn(['img'=>$img,'sence_id' => $sence_id]);
2.网站展示二维码并一直轮询后台获取用户信息,参数为sence_id,根据返回的信息判断用户是否扫码登陆
$redis = Cache::store('redis')->handler(); $key = '77dj_wx:user:'.$data['sence_id'];//todo:key前缀加到配置里面 $exists = $redis->exists($key); if(!$exists) return wx_errorReturn(null,-1,'二维码已过期'); $user_id = $redis->get($key); if($user_id) { $user_info = Db::name('user')->find($user_id); $redis->del('77dj_wx:user:'.$data['sence_id']); return wx_successReturn(['user_info'=>$user_info]); } else { return wx_successReturn(['user_info'=>null]); }
3.用户扫码,如果用户没有没有关注公众号,会先关注,然后再执行登陆逻辑,如果关注过,会直接进入登陆逻辑
/** * 推送的事件处理 */ private function doEvent($postObj) { switch ($postObj->Event) { case 'subscribe' : $this->doSubscribe($postObj); break;//关注事件 case 'unsubscribe' : $this->unSubscribe($postObj); break; //取消关注 case 'CLICK' : //TODO... 菜单按钮需要重做 // $this->menuClick($postObj); break;//菜单点击事件 case 'SCAN' : $this->dealScan($postObj); break;//扫码事件 } } /** * 订阅关注 */ private function doSubscribe($postObj) { $eventKey = $postObj->EventKey; $sence_id = explode('_', $eventKey)[1]; if ($sence_id > 1000000) {//用户登陆 $postObj->EventKey = $sence_id; $this->createUser($postObj); } } /** * 扫码事件 */ private function dealScan($postObj) { if ($postObj->EventKey > 1000000) {//用户登陆 $this->createUser($postObj); } } /** * */ private function createUser($postObj) { $user = new User(); $access_token = $this->getToken(); $userArr = $user->createUser('','','dj_pc','PC',$postObj->FromUserName,$access_token); if(isset($userArr['app_session'])) { $session = $userArr['app_session']; //用户信息 $userInfo = getAppUserInfo($session, true); } $redis = Cache::store('redis')->handler(); $prefix = config('const.redis_prefix'); $key = $prefix['user_token']; $redis->hset($key,$userArr['c_session'],$userArr['id']); $redis->setex('77dj_wx:user:'.$postObj->EventKey,3600,$userArr['id']); }
问题:
按照文档说的, 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。但是我这边如果没关注,点了关注之后登录逻辑就不会走,所以在订阅事件里面也把扫码登陆的逻辑加上了