業務需求:
用戶點擊網站登陸,彈出二維碼,用戶打開微信掃描二維碼登陸,如果用戶沒有關注,先關注微信公眾號再登陸
技術:
微信生成帶參數臨時二維碼
微信事件推送(用戶掃碼就是一個掃碼事件)
微信公眾號獲取用戶信息
推送事件里的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']); }
問題:
按照文檔說的, 如果用戶還未關注公眾號,則用戶可以關注公眾號,關注后微信會將帶場景值關注事件推送給開發者。但是我這邊如果沒關注,點了關注之后登錄邏輯就不會走,所以在訂閱事件里面也把掃碼登陸的邏輯加上了