在昨天的文章《追查Ectouch QQ登录每次用户名都不同的原因和解决办法》中详细追踪了ectouch第三方qq登陆的问题及解决方案。修正了ectouch user_id输入错误的问题之后,在之后的使用中是没问题的,可以在touch_user_info表和users表中联合查询。但是在这里我们可以更进一步来改进他,及实现网站qq登陆和手机qq登陆的统一,也就是我在《追查》一文中提到的第二套方案,让从网站和手机登录的qq用户使用同一个账户,并个性化qq登陆用户资料。同时也是对QQ登录每次用户名都不同的一个彻底解决方案,即取消get_one_user的联合查询。
继续来看mobile\include\apps\default\controller\UserController.class.php
中登陆成功后的这段public function third_login代码
if ($_SESSION['access_token']) { $res = new $type($info, $_SESSION['access_token']); $openid = $res->get_openid(); // 获取用户信息 $userinfo = $res->get_user_info($openid); // 处理数据 $userinfo['aite_id'] = $type . '_' . $openid; // 添加登录标示 $_SESSION['aite_id'] = $userinfo['aite_id'];//获取qq的aite_id值 if ($userinfo['user_name'] = model('Users')->get_one_user($userinfo['aite_id'])) {// // 已有记录 self::$user->set_session($userinfo['user_name']); self::$user->set_cookie($userinfo['user_name']); model('Users')->update_user_info(); model('Users')->recalculate_price(); $jump_url = empty($this->back_act) ? url('index') : $this->back_act; $this->redirect($jump_url); } if (empty($userinfo['user_name'])) $userinfo['user_name'] =substr($openid, -6); if(self::$user->check_user($userinfo['user_name'])) { $userinfo['user_name'] = $userinfo['user_name'].rand(1000, 9999); // 重名处理 } $userinfo['email'] = empty($userinfo['email']) ? substr($openid, -6) . '@' . get_top_domain() : $userinfo['email']; // 插入数据库 model('Users')->third_reg($userinfo); self::$user->set_session($userinfo['user_name']); self::$user->set_cookie($userinfo['user_name']); model('Users')->update_user_info(); model('Users')->recalculate_price(); $jump_url = empty($this->back_act) ? url('index') : $this->back_act; $this->redirect($jump_url); }
从 $userinfo['aite_id'] = $type . '_' . $openid; // 添加登录标示
这里可以看到,以aite_id作为用户是否已经存在的依据是ok的,因为$openid是qq号与网站对应的唯一值,那么是否是同一个qq用户就以ecshop的users表中的aite_id为准来作为用户的唯一标识,这样可以使得从网站及手机登录的qq用户拥有中一个aite_id值,而不用相互隔开,实现两端登陆同步。
另外作为$userinfo[‘user_name’]来说,我觉得这样的设计不合理,为什么我每次的用户只能是数据库中已经存在的从前的用户名,网站显示我当前的昵称不是更好吗?我本来就是qq登陆嘛。
我们一步一步来改进它,首先获取qq的昵称,并赋值给$userinfo[‘user_name’],将$userinfo['user_name']=$userinfo['nickname'];//获取qq昵称
放在放在if判断前面。在这里get_one_user函数就必须修改了,即从ecshop的users查询,这也是迫不得已的选择,因为users表中已经存在很多从网站登录的qq用户了。写到这里我突然想到一个修改上一个错误的方案,就是当用qq用户登录的时候,在users中查询到aite_id值,这时候在touch_user_info中以aite_id为关联字段,来修改他的user_id,这样只要以前的客户再次登陆就可以修复这个user_id的错误。不管怎样,get_one_user函数必须要修改为从users查询。
function get_one_user($aite_id) { $sql = 'SELECT user_name FROM ' . $this->pre . 'users WHERE aite_id = "' . $aite_id . '" '; $res = $this->row($sql); return $res['user_name']; }
去掉了touch_user_info的联合查询,这样只要从网站qq登陆过就可以读取了,但是之前在手机端登陆过的就没有什么办法了。这样就将电脑QQ第三方登录与手机QQ第三方登录统一了起来。
好了,思路来了,下面要实现另外一个问题,如果将从手机登录的QQ用户的aite_id写入users表呢?aite_id都要写入了,那么把其他的参数也一起写入users,比如性别啊,头像地址啊,让我们的QQ登陆用户更加个性化!!
首先将QQ的json数组的值传给session,在$userinfo['aite_id'] = $type . '_' . $openid; // 添加登录标示
下面添加。
$userinfo['aite_id'] = $type . '_' . $openid; // 添加登录标示 $_SESSION['aite_id'] = $userinfo['aite_id'];//获取qq的aite_id值 $userinfo['user_name']=$userinfo['nickname'];//获取qq昵称 $_SESSION['figureurl_qq_2']=(string)$userinfo['figureurl_qq_2']; //获取qq头像 $_SESSION['gender']=(string)$userinfo['gender']; //获取性别
再下面的$userinfo[‘user_name’] =substr($openid, -6);要做一个判断,即if (empty($userinfo['user_name'])) $userinfo['user_name'] =substr($openid, -6);
。
邮箱名称也要变变,由于qq的第三方登录没有开放邮箱和qq号码数据,所以这里必须自己生成。昵称一般都是中文,其实这里是个鸡肋,没有邮箱不行,他是ecshop登陆的一种方式,如果有呢,实际意义不大,但是邮箱名不能是中文,所以这里要修改。
$userinfo['email'] = empty($userinfo['email']) ? $userinfo['user_name'] . '@' . get_top_domain() : $userinfo['email'];
修改为
$userinfo['email'] = empty($userinfo['email']) ? substr($openid, -6) . '@' . get_top_domain() : $userinfo['email'];
邮箱名以openid的末尾6位标识,这是是无奈之举,没有一个更好的办法,如果QQ API开放QQ邮箱就好了。
再往下看,
model('Users')->third_reg($userinfo); self::$user->set_session($userinfo['user_name']); self::$user->set_cookie($userinfo['user_name']); model('Users')->update_user_info(); model('Users')->recalculate_price();
third_reg第三方登录之后有一个update_user_info(),我们就在这里更新我们获取的数据,这个函数位于mobile\include\apps\default\model\UsersModel.class.php
,修改这个函数之前还需要做一件事情,因为users默认表中没有存放缩微图的字段,需要自己添加一个,这个进入phpmyadmin自己操作就好了,非常简单。或者进ecshop后台添加,类似这样的语句alter table users ADD thumb var(200) not null;
,有了thumb字段之后就可以存放数据了。
下面来修改update_user_info函数。
首先修改查询会员信息的sql语句
$sql = 'SELECT u.user_money,u.email, u.aite_id,u.sex,u.thumb, u.pay_points, u.user_rank, u.rank_points, ' . ' IFNULL(b.type_money, 0) AS user_bonus, u.last_login, u.last_ip' . ' FROM ' . $this->pre . 'users AS u ' . ' LEFT JOIN ' . $this->pre . 'user_bonus AS ub' . ' ON ub.user_id = u.user_id AND ub.used_time = 0 ' . ' LEFT JOIN ' . $this->pre . 'bonus_type AS b' . " ON b.type_id = ub.bonus_type_id AND b.use_start_date <= '$time' AND b.use_end_date >= '$time' " . " WHERE u.user_id = '$_SESSION[user_id]'";
添加了u.aite_id,u.sex,u.thumb,在这个sql语句前面初始化几个变量
$aite_id=''; $sex=''; $thumb='';
将读出来的数据付给这几个变量,便于比较以前的数据是否和现在的数据是否有变动。
if ($row = $this->row($sql)) { /* 更新SESSION */ $_SESSION['last_time'] = $row['last_login']; $_SESSION['last_ip'] = $row['last_ip']; $_SESSION['login_fail'] = 0; $_SESSION['email'] = $row['email']; $aite_id=$row['aite_id']; $sex=$row['sex']; $thumb=$row['thumb'];
现在来改造最后的执行更新的sql语句了。我们要根据不同的情况来构造不同的语句。
/* 更新登录时间,登录次数及登录ip */ $sql = "UPDATE " . $this->pre . "users SET" . " visit_count = visit_count + 1, " . " last_ip = '" . real_ip() . "'," ; if (!empty($_SESSION['gender']) && $sex != $_SESSION['gender']){ $gender_var=1; if ($_SESSION['gender']!='男') $gender_var=0; $sql =$sql." sex = '" . $gender_var . "',"; } if (!empty($_SESSION['figureurl_qq_2']) && $thumb != $_SESSION['figureurl_qq_2']){ $sql =$sql." thumb = '" . $_SESSION['figureurl_qq_2'] . "'"; } if (!empty($_SESSION['aite_id']) && $aite_id != $_SESSION['aite_id']){ $sql =$sql." aite_id = '" . $_SESSION['aite_id'] . "'" ; } $sql =$sql." last_login = '" . gmtime() . "'" . " WHERE user_id = '" . $_SESSION['user_id'] . "'"; $this->query($sql);
这个语句就是比较当前的aite_id,gender和thumb是否和之前一样,如果不同就更新。这样就将QQ登陆用户的最新数据同步到users了。好了,有了数据之后,在哪里显示出来呢。
查询用户资料的函数是 get_user_default,他位于mobile\include\base\model\ClipsBaseModel.class.php
文件中,在sql语句中增加thumb的字段就好了。之后在mobile\themes\default\user.dwt
显示头像的位置调用。最终效果如下。
调用qq头像,显示qq用户昵称,比原来的随机数字用户名和默认灰色头像好看多了吧。