微信扫码关注公众号并登录网站
业务需求:
用户点击网站登陆,弹出二维码,用户打开微信扫描二维码登陆,如果用户没有关注,先关注微信公众号再登陆
技术:
微信生成带参数临时二维码
文档: [https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html](https://developers.weixin.qq.com/doc/offiaccount/Account_Management/Generating_a_Parametric_QR_Code.html)
微信事件推送(用户扫码就是一个扫码事件)
文档:[https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html](https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html)
微信公众号获取用户信息
文档:[https://developers.weixin.qq.com/doc/offiaccount/Message_Management/Receiving_event_pushes.html](https://developers.weixin.qq.com/doc/offiaccount/User_Management/Get_users_basic_information_UnionID.html#UinonId)
推送事件里的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']);
}
网友评论