微信扫码关注公众号并登录网站

业务需求:
 
   用户点击网站登陆,弹出二维码,用户打开微信扫描二维码登陆,如果用户没有关注,先关注微信公众号再登陆 
 
技术:
 
      微信生成带参数临时二维码 
     
      微信事件推送(用户扫码就是一个扫码事件)
         
      微信公众号获取用户信息
     推送事件里的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']);
    }
问题:
    按照文档说的, 如果用户还未关注公众号,则用户可以关注公众号,关注后微信会将带场景值关注事件推送给开发者。但是我这边如果没关注,点了关注之后登录逻辑就不会走,所以在订阅事件里面也把扫码登陆的逻辑加上了
原文地址:https://www.cnblogs.com/jint-php7/p/11936963.html