Typecho社会化登录插件TeConnect

前言

大卫科技 Blog原创作品,版权属于:大卫科技 Blog(转载请著名出处)!
原文链接https://www.iyuu.cn/archives/88/
如需转载,可下载Markdown原文:点此下载md.txt

本插件已部署,欢迎体验:qq-login.png

一、功能介绍

Typecho互联登录插件,目前已支持15种第三方登录:QQ/腾讯微博/新浪微博/网易微博/人人网/360/豆瓣/Github/Google/Msn/点点/淘宝网/百度/开心网/搜狐。
特色亮点功能:同一用户,可以绑定15种不同的登录方式!
在原项目TeConnect的基础上,进行完全的二次开发、优化及修复。重点有:

  1. 重新设计数据表结构,删除原connect表,后续具有完美的扩展性及兼容性;
  2. 已开发支持15种第三方登录,后续可以支持更多……;
  3. 优化会员绑定逻辑,修复原项目登录状态下绑定错乱、重复绑定等Bug;
  4. 增加会员uuid机制,自动关联users数据表的uid字段,支持更多功能开发的可能;
  5. 优化解绑逻辑,和第三方资料更新逻辑等。

二、插件下载

样式1样式2样式3样式4样式5
bt_blue_76X24.pngbt_white_76X24.pngbt_blue_24X24.pngbt_white_24X24.pngbt_92X120.png

三、安装步骤 qq-login.png 即可查看!

此处内容需要评论回复后(审核通过)方可阅读。

四、参数配置

配置示例

名称类型配置示例网站回调域
腾讯QQqqqq:APP_KEY,APP_SECRET,腾讯QQhttps://127.0.0.1/oauth_callback?type=qq
腾讯微博tencenttencent:APP_KEY,APP_SECRET,腾讯微博https://127.0.0.1/oauth_callback?type=tencent
新浪微博sinasina:APP_KEY,APP_SECRET,新浪微博https://127.0.0.1/oauth_callback?type=sina
网易微博t163t163:APP_KEY,APP_SECRET,网易微博https://127.0.0.1/oauth_callback?type=t163
人人网renrenrenren:APP_KEY,APP_SECRET,人人网https://127.0.0.1/oauth_callback?type=renren
360x360x360:APP_KEY,APP_SECRET,360https://127.0.0.1/oauth_callback?type=x360
豆瓣doubandouban:APP_KEY,APP_SECRET,豆瓣https://127.0.0.1/oauth_callback?type=douban
Githubgithubgithub:APP_KEY,APP_SECRET,Githubhttps://127.0.0.1/oauth_callback?type=github
Googlegooglegoogle:APP_KEY,APP_SECRET,Googlehttps://127.0.0.1/oauth_callback?type=google
MSNmsnmsn:APP_KEY,APP_SECRET,MSNhttps://127.0.0.1/oauth_callback?type=msn
点点diandiandiandian:APP_KEY,APP_SECRET,点点https://127.0.0.1/oauth_callback?type=diandian
淘宝网taobaotaobao:APP_KEY,APP_SECRET,淘宝网https://127.0.0.1/oauth_callback?type=taobao
百度baidubaidu:APP_KEY,APP_SECRET,百度https://127.0.0.1/oauth_callback?type=baidu
开心网kaixinkaixin:APP_KEY,APP_SECRET,开心网https://127.0.0.1/oauth_callback?type=kaixin
搜狐微博sohusohu:APP_KEY,APP_SECRET,搜狐微博https://127.0.0.1/oauth_callback?type=sohu

1:后台互联配置

具体格式为:type:appid,appkey,title,注释:

  • type:第三方登录帐号类型
  • appid:第三方开放平台申请的应用id
  • appkey:第三方开放平台申请的应用key
  • title:登录按钮的标题
    在后台互联配置中,直接以文本形式填写,一行为一个帐号系统的参数;

为减少错误发生,您可以复制对应的配置示例,把APP_KEYAPP_SECRET改成您自己的参数就可以了!
例如:qq:APP_KEY,APP_SECRET,腾讯QQ
改成:qq:101015836,547s87f8s7df7sd877ji75s78sdfd,腾讯QQ
粘贴到后台互联配置,即完成了腾讯QQ登录的配置,其他类型同理!

2:网站回调域配置 bt_blue_76X24.png 即可查看

此处内容需要评论回复后(审核通过)方可阅读。

五、第三方账号绑定流程

1、方案选择

我参考了国内主流的几家互联网公司的第三方账号登录功能,发现主要分成两种设计方案;
一种是账号强绑,像京东、小米等,在第三方账号授权通过后,需要用户绑定自己的账号;
一种是今日头条、知乎,在第三方账号授权通过后,随机给用户生成一个账号或者调用第三方账号昵称,无需绑定账号,即可成功登录。
目前,两种方案都支持,您可以在后台开启或关闭强制绑定

2、绑定流程一(未登录状态)

绑定流程一(未登录状态).png
用户在登录界面点击第三方账号,授权通过后,我们获得用户第三方账号的OpenID,由此判断用户的第三方账号之前是否绑定过,如果绑定过则直接登录成功。
如果没有绑定过,则跳到账号绑定页面。账号绑定页面需要分成已有账号直接绑定,和没有账号,新注册账号进行绑定两种情况。
当用户已有账号时,通过输入账号密码校验身份,校验通过后即可绑定成功/登录成功。
当用户没有账号时,用户可通过注册新账号,注册成功后即可绑定成功/登录成功。

3、绑定流程二(登录状态)

在个人账号中心里提供绑定管理的功能和界面,在用户已经登录的情况下,可以直接绑定第三方账号,只要获得授权通过,即可绑定成功。


六、第三方帐号解绑流程

在个人账号中心>绑定管理中,可以对已经绑定的第三方账号进行解绑操作。在这里需要注意,由于用户长期使用第三方账号登录,实际上是由第三方账号承担了提交账号和保护账号安全的工作,因此在解绑第三方账号时,我们需要提醒用户,解绑以后只能通过本平台账号密码方式来登录。最好是提示用户记住当前账号
提示用户记住当前账号.jpg
京东的解绑账号功能

另一方面,由于之前是由第三方账号“帮平台”做了账号安全的工作,因此在解绑账号的时候,我们需要考虑如何保护账号安全。因此可以在解绑的时候,对账号做一定的安全校验或安全保护。
我们最终定的方案是 当用户在解绑时,需要校验手机短信验证码,如果没有绑定手机,则提示用户先去绑定手机。
第三方帐号解绑流程.png
解绑流程

总结
第三方账号虽然是一个小功能,但是在设计过程中,我们要结合自身产品的特点来确定产品方案和产品流程。授权之后,是直接登录成功,还是绑定自己平台的账号,这是由自己产品特点决定。同时,对新增账号来说,如何设计用户账号的安全,也需要根据产品特点和安全策略来设计适合的产品流程。


七、数据表结构(不开发,可以不看)

typecho_oauth_user数据库表结构:

字段类型注释
uidint(10) unsigned NOT NULL COMMENT用户ID
access_tokenvarchar(255) NOT NULL COMMENT用户对应access_token
datetimetimestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT最后登录
expires_inint(10) unsigned NOT NULL DEFAULT '0' COMMENTaccess_token过期时间戳
gendertinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT性别0未知,1男,2女
head_imgvarchar(255) NOT NULL COMMENT头像
namevarchar(38) NOT NULL COMMENT名字
nicknamevarchar(38) NOT NULL COMMENT第三方昵称
openidchar(50) NOT NULL COMMENT第三方平台的用户唯一标识
refresh_tokenvarchar(255) NOT NULL COMMENT刷新有效期token
typechar(32) NOT NULL COMMENT第三方平台的类型
uuidint(10) unsigned NOT NULL COMMENT对应users表uid

特色亮点功能:同一用户,可以绑定15种不同的登录方式!
【推荐:后台关闭强制绑定】

  1. 管理员已登录状态时,直接互联登录,可以绑定管理员身份!(源码第128行此时users表不变,oauth_user表创建绑定关系,uid、uuid等于管理员uid);
  2. 管理员未登录时,直接互联登录(源码第153行此时users表创建新用户、oauth_user表绑定关系:uid、uuid等于新用户uid);
  3. 在第2步完成后,退出互联登录;重新用管理员登录成功后不退出,再次互联登录(源码第256行此时users表不变,oauth_user表更新绑定关系:uuid不变、uid等于管理员uid);
  4. 同一用户,可以绑定15种不同的登录方式!但是,同类型的第三方账号仅可绑定一个!通俗点:用户不能绑定2个QQ号码来进行登录。(源码250行、267行
  5. oauth_user表完整保存用户的关键授权参数access_token、expires_in、datetime,可以在用户离线的情况下调用API;
  6. uuid完整记录着原始绑定关系,支持解绑后数据不丢失。

typecho_oauth_user表结构.png
oauth_user表数据结构.png

创建数据表SQL语句

CREATE TABLE IF NOT EXISTS `typecho_oauth_user` (
  `uid` int(10) unsigned NOT NULL COMMENT '用户ID',
  `access_token` varchar(255) NOT NULL COMMENT '用户对应access_token',
  `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '最后登录',
  `expires_in` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'access_token过期时间戳',
  `gender` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '性别0未知,1男,2女',
  `head_img` varchar(255) NOT NULL COMMENT '头像',
  `name` varchar(38) NOT NULL COMMENT '名字',
  `nickname` varchar(38) NOT NULL COMMENT '第三方昵称',
  `openid` char(50) NOT NULL COMMENT '第三方平台的用户唯一标识',
  `refresh_token` varchar(255) NOT NULL COMMENT '刷新有效期token',
  `type` char(32) NOT NULL COMMENT '第三方平台的类型',
  `uuid` int(10) unsigned NOT NULL COMMENT '对应users表uid',
  PRIMARY KEY (`uid`),
  KEY `uid` (`uid`),
  KEY `oauth_openid` (`openid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

项目仓库

码云:https://gitee.com/ledc/TeConnect

关键代码

关键PHP代码段

/**
     * 获取Oauth登录地址,重定向
     *
     * @access public
     * @param string $type 第三方登录类型
     */
    public function oauth(){
        $type = $this->request->get('type');
        if(is_null($type)){
            throw new Typecho_Widget_Exception("请选择登录方式!");
        }
        $options = TeConnect_Plugin::options();
        $type = strtolower($type);
        //判断登录方式是否支持
        if(!isset($options[$type])){
            throw new Typecho_Widget_Exception("暂不支持该登录方式! {$type}");
        }
        //组装回调地址
        $callback_url = Typecho_Common::url('/oauth_callback?type='.$type, $this->options->index);
        //加载ThinkOauth类并实例化一个对象
        require_once 'ThinkOauth.php';
        $sdk = ThinkOauth::getInstance($type);
        //302重定向
        $this->response->redirect($sdk->getRequestCodeURL($callback_url));
    }
    /**
     * 第三方登录回调
     *
     * @access public
     * @param array $do POST来的用户绑定数据
     * @param string $type 第三方登录类型
     */
    public function callback(){
        if(!isset($_SESSION)){
            session_start();
            $this->auth = isset($_SESSION['__typecho_auth']) ? $_SESSION['__typecho_auth']  : array();
            $this->oauth_user = isset($_SESSION['__typecho_oauth_user']) ? $_SESSION['__typecho_oauth_user']  : array();
        }
        //仅处理来自绑定界面POST提交的数据,第三方回调会跳过
        if($this->request->isPost()){
            $do = $this->request->get('do');
            if(!in_array($do,array('bind','reg'))){
                throw new Typecho_Widget_Exception("错误数据!");
            }

            if(!isset($this->auth['openid']) || !isset($this->auth['type'])){
                $this->response->redirect($this->options->index);
            }
            $func = 'doCallback'.ucfirst($do);
            $this->$func();
            unset($_SESSION['__typecho_auth']);
            $this->response->redirect($this->options->index);
        }

        //第三方登录回调处理
        $options = TeConnect_Plugin::options();
        if(empty($this->auth)){
            $this->auth['code'] = $this->request->get('code','');
            $this->auth['type'] = $this->request->get('type','');

            if(empty($this->auth['code']) && empty($this->auth['type']) && !isset($options[$this->auth['type']])){
                //缺少code、type、type未开启,直接跳主页
                $this->response->redirect($this->options->index);
            }
            //转小写
            $this->auth['type'] = $type = strtolower($this->auth['type']);
            //组装回调地址
            $callback_url = Typecho_Common::url('/oauth_callback?type='.$type, $this->options->index);
            //加载ThinkOauth类并实例化一个对象
            require_once 'ThinkOauth.php';
            $sdk = ThinkOauth::getInstance($type);
            //请求接口(返回值包含openid)
            $token = $sdk->getAccessToken($callback_url, $this->auth['code']);
            if(is_array($token)){
                //获取第三方账号数据
                $user_info = $this->$type($token);
                $oauth_user = array(
                    'uid'=>0,
                    'access_token'=>$token['access_token'],
                    'expires_in'=>isset($token['expires_in']) ? $this->options->gmtTime+$token['expires_in']: 0,
                    'gender'=>$user_info['gender'],
                    'head_img'=>$user_info['head_img'],
                    'name'=>$user_info['name'],
                    'nickname'=>$user_info['nickname'],
                    'openid'=>$token['openid'],
                    'type'=>$type,
                    );
                //获取openid
                $this->auth['openid'] = $token['openid'];
                $this->auth['nickname'] = $user_info['nickname'];
            }else{
                $this->response->redirect($this->options->index);
            }
        }
        //登录状态
        if ($this->user->hasLogin()) {
            //UUID会员的原始ID
            $this->auth['uuid'] = $this->user->uid;

            //直接绑定第三方账号
            $this->bindUser($this->user->uid, $oauth_user, $this->auth['type']);
            //提示,并跳转
            $this->widget('Widget_Notice')->set(array('成功绑定账号!'));
            $this->response->redirect($this->options->index);
        }

        //未登录状态,查询第三方账号的绑定关系
        $isConnect = $this->findConnectUser($oauth_user,$this->auth['type']);
        if($isConnect){
            //已经绑定,直接登录
            $this->useUidLogin($isConnect['uid']);
            //提示,并跳转
            $this->widget('Widget_Notice')->set(array('已成功登陆!'));
            $this->response->redirect($this->options->index);
        }

        //未登录状态且未绑定,控制显示绑定界面
        $custom = $this->options->plugin('TeConnect')->custom;
        if(!$custom && !empty($this->auth['nickname'])){
            $dataStruct = array(
                'screenName'=>  $this->auth['nickname'],
                'created'   =>  $this->options->gmtTime,
                'group'     =>  'subscriber'
            );
            //新注册账号
            $uid = $this->regConnectUser($dataStruct,$oauth_user);
            if($uid){
                $this->widget('Widget_Notice')->set(array('已成功注册并登陆!'));
            }else{
                $this->widget('Widget_Notice')->set(array('注册用户失败!'),'error');
            }
            $this->response->redirect($this->options->index);
        }else{
            //用户绑定界面
            if(!isset($_SESSION['__typecho_auth']))
            $_SESSION['__typecho_auth'] = $this->auth;
            $_SESSION['__typecho_oauth_user'] = $oauth_user;

            //未绑定,引导用户到绑定界面
            $this->render('callback.php');
        }
    }
    //绑定已有用户
    protected function doCallbackBind(){
        $name = $this->request->get('name');
        $password = $this->request->get('password');

        if(empty($name) || empty($password)){
            $this->widget('Widget_Notice')->set(array('帐号或密码不能为空!'),'error');
            $this->response->goBack();
        }
        $isLogin = $this->user->login($name,$password);
        if($isLogin){
            //UUID会员的原始ID
            $this->auth['uuid'] = $this->user->uid;

            $this->widget('Widget_Notice')->set(array('已成功绑定并登陆!'));
            $this->bindUser($this->user->uid,$this->oauth_user,$this->auth['type']);
        }else{
            $this->widget('Widget_Notice')->set(array('帐号或密码错误!'),'error');
            $this->response->goBack();
        }
    }
    //注册新用户
    protected function doCallbackReg(){
        $url = $this->request->get('url');

        $validator = new Typecho_Validate();
        $validator->addRule('mail', 'required', _t('必须填写电子邮箱'));
        $validator->addRule('mail', array($this, 'mailExists'), _t('电子邮箱地址已经存在'));
        $validator->addRule('mail', 'email', _t('电子邮箱格式错误'));
        $validator->addRule('mail', 'maxLength', _t('电子邮箱最多包含200个字符'), 200);

        $validator->addRule('screenName', 'required', _t('必须填写昵称'));
        $validator->addRule('screenName', 'xssCheck', _t('请不要在昵称中使用特殊字符'));
        $validator->addRule('screenName', array($this, 'screenNameExists'), _t('昵称已经存在'));

        if($url){
            $validator->addRule('url', 'url', _t('个人主页地址格式错误'));
        }

        /** 截获验证异常 */
        if ($error = $validator->run($this->request->from('mail', 'screenName', 'url'))) {
            /** 设置提示信息 */
            $this->widget('Widget_Notice')->set($error);
            $this->response->goBack();
        }

        $dataStruct = array(
            'mail'      =>  $this->request->mail,
            'screenName'=>  $this->request->screenName,
            'created'   =>  $this->options->gmtTime,
            'group'     =>  'subscriber'
        );
        $uid = $this->regConnectUser($dataStruct, $this->oauth_user);
        if($uid){
            $this->widget('Widget_Notice')->set(array('已成功注册并登陆!'));
        }
    }

    protected function regConnectUser($data,$oauth_user){
        $insertId = $this->insert($data);
        if($insertId){
            //UUID会员的原始ID
            $this->auth['uuid'] = $insertId;

            $this->bindUser($insertId,$oauth_user,$this->auth['type']);
            $this->useUidLogin($insertId);
            return $insertId;
        }else{
            return false;
        }
    }

    //处理用户与第三方账号的绑定关系(逻辑复杂)
    protected function bindUser($uid,$oauth_user,$type){
        $oauth_user['uid'] = $uid;
        if(isset($this->auth['uuid'])){
            $oauth_user['uuid'] = $this->auth['uuid'];
        }
        //查询当前登录的账号是否绑定?
        $connect = $this->db->fetchRow($this->db->select()
            ->from('table.oauth_user')
            ->where('uid = ?', $uid)
            ->where('type = ?', $type)
            ->limit(1));
        if(empty($connect)){
            //未绑定
            $oauthRow = $this->findConnectUser($oauth_user,$type);
            if($oauthRow){
                //已存在第三方账号,更新绑定关系
                $this->db->query($this->db
                ->update('table.oauth_user')
                ->rows(array('uid' => $uid))
                ->where('openid = ?', $oauth_user['openid'])
                ->where('type = ?', $type));
            }else{
                //未绑定,插入数据并绑定
                $this->db->query($this->db->insert('table.oauth_user')->rows($oauth_user));
            }
        }else{
            //已绑定,判断更新条件,避免绑定错乱(同类型的第三方账号,用户只能绑定一个)
            if($connect[$type.'OpenId'] == $openid){
                ###更新资料tudo
            }else{
                ###换绑tudo
            }
        }
    }
    //查找第三方账号
    protected function findConnectUser($oauth_user,$type){
        $user = $this->db->fetchRow($this->db->select()
            ->from('table.oauth_user')
            ->where('openid = ?', $oauth_user['openid'])
            ->where('type = ?', $type)
            ->limit(1));
        return empty($user)? 0 : $user;
    }
    //使用用户uid登录
    protected function useUidLogin($uid,$expire = 0){
        $authCode = function_exists('openssl_random_pseudo_bytes') ?
        bin2hex(openssl_random_pseudo_bytes(16)) : sha1(Typecho_Common::randString(20));
        $user = array('uid'=>$uid,'authCode'=>$authCode);

        Typecho_Cookie::set('__typecho_uid', $uid, $expire);
        Typecho_Cookie::set('__typecho_authCode', Typecho_Common::hash($authCode), $expire);

        //更新最后登录时间以及验证码
        $this->db->query($this->db
            ->update('table.users')
            ->expression('logged', 'activated')
            ->rows(array('authCode' => $authCode))
            ->where('uid = ?', $uid));
        $this->db->query($this->db
            ->update('table.oauth_user')
            ->rows(array('datetime' => date("Y-m-d H:i:s",time())))
            ->where('uid = ?', $uid));
    }

    public function render($themeFile){
        /** 文件不存在 */
        if (!file_exists($this->_themeDir . $themeFile)) {
            Typecho_Common::error(500);
        }
        /** 输出模板 */
        require_once $this->_themeDir . $themeFile;
    }
    /**
     * 获取主题文件
     *
     * @access public
     * @param string $fileName 主题文件
     * @return void
     */
    public function need($fileName){
        require $this->_themeDir . $fileName;
    }

    //登录成功,获取腾讯QQ用户信息
    public function qq($token){
        $qq = ThinkOauth::getInstance('qq', $token);
        $data = $qq->call('user/get_user_info');
        if($data['ret'] == 0){
            $userInfo['name'] = $data['nickname'];
            $userInfo['nickname'] = $data['nickname'];
            $userInfo['head_img'] = $data['figureurl_2'];

            if($data['gender'] == '男'){
                $userInfo['gender'] = 1;
            }elseif($data['gender'] == '女'){
                $userInfo['gender'] = 2;
            }else{
                $userInfo['gender'] = 0;
            }
            return $userInfo;
        } else {
            $this->widget('Widget_Notice')->set(array("获取腾讯QQ用户信息失败:{$data['msg']}"),'error');
        }
    }

    //登录成功,获取腾讯微博用户信息
    public function tencent($token){
        $tencent = ThinkOauth::getInstance('tencent', $token);
        $data    = $tencent->call('user/info');
        if($data['ret'] == 0){
            $userInfo['name'] = $data['data']['name'];
            $userInfo['nickname'] = $data['data']['nick'];
            $userInfo['head_img'] = $data['data']['head'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取腾讯微博用户信息失败:{$data['msg']}");
        }
    }

    //登录成功,获取新浪微博用户信息
    public function sina($token){
        $sina = ThinkOauth::getInstance('sina', $token);
        $data = $sina->call('users/show', "uid={$sina->openid()}");
        if($data['error_code'] == 0){
            $userInfo['name'] = $data['name'];
            $userInfo['nickname'] = $data['screen_name'];
            $userInfo['head_img'] = $data['avatar_large'];
            return $userInfo;
        } else {
            //throw_exception("获取新浪微博用户信息失败:{$data['error']}");
        }
    }

    //登录成功,获取网易微博用户信息
    public function t163($token){
        $t163 = ThinkOauth::getInstance('t163', $token);
        $data = $t163->call('users/show');
        if($data['error_code'] == 0){
            $userInfo['name'] = $data['name'];
            $userInfo['nickname'] = $data['screen_name'];
            $userInfo['head_img'] = str_replace('w=48&h=48', 'w=180&h=180', $data['profile_image_url']);
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取网易微博用户信息失败:{$data['error']}");
        }
    }

    //登录成功,获取人人网用户信息
    public function renren($token){
        $renren = ThinkOauth::getInstance('renren', $token);
        $data   = $renren->call('user/get');
        if(!isset($data['error'])){
            $userInfo['name'] = $data['response']['name'];
            $userInfo['nickname'] = $data['response']['name'];
            $userInfo['head_img'] = $data['response']['avatar'][20]['url'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取人人网用户信息失败:{$data['error_msg']}");
        }
    }

    //登录成功,获取360用户信息
    public function x360($token){
        $x360 = ThinkOauth::getInstance('x360', $token);
        $data = $x360->call('user/me');
        if($data['error_code'] == 0){
            $userInfo['name'] = $data['name'];
            $userInfo['nickname'] = $data['name'];
            $userInfo['head_img'] = $data['avatar'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取360用户信息失败:{$data['error']}");
        }
    }

    //登录成功,获取豆瓣用户信息
    public function douban($token){
        $douban = ThinkOauth::getInstance('douban', $token);
        $data   = $douban->call('user/~me');
        if(empty($data['code'])){
            $userInfo['name'] = $data['name'];
            $userInfo['nickname'] = $data['name'];
            $userInfo['head_img'] = $data['avatar'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取豆瓣用户信息失败:{$data['msg']}");
        }
    }

    //登录成功,获取Github用户信息
    public function github($token){
        $github = ThinkOauth::getInstance('github', $token);
        $data   = $github->call('user');
        if(empty($data['code'])){
            $userInfo['name'] = $data['login'];
            $userInfo['nickname'] = $data['name'];
            $userInfo['head_img'] = $data['avatar_url'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取Github用户信息失败:{$data}");
        }
    }

    //登录成功,获取Google用户信息
    public function google($token){
        $google = ThinkOauth::getInstance('google', $token);
        $data   = $google->call('userinfo');
        if(!empty($data['id'])){
            $userInfo['name'] = $data['name'];
            $userInfo['nickname'] = $data['name'];
            $userInfo['head_img'] = $data['picture'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取Google用户信息失败:{$data}");
        }
    }

    //登录成功,获取msn用户信息
    public function msn($token){
        $msn  = ThinkOauth::getInstance('msn', $token);
        $data = $msn->call('me');
        if(!empty($data['id'])){
            $userInfo['name'] = $data['name'];
            $userInfo['nickname'] = $data['name'];
            $userInfo['head_img'] = '微软暂未提供头像URL,请通过 me/picture 接口下载';
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取msn用户信息失败:{$data}");
        }
    }

    //登录成功,获取点点用户信息
    public function diandian($token){
        $diandian  = ThinkOauth::getInstance('diandian', $token);
        $data      = $diandian->call('user/info');
        if(!empty($data['meta']['status']) && $data['meta']['status'] == 200){
            $userInfo['name'] = $data['response']['name'];
            $userInfo['nickname'] = $data['response']['name'];
            $userInfo['head_img'] = "https://api.diandian.com/v1/blog/{$data['response']['blogs'][0]['blogUuid']}/avatar/144";
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取点点用户信息失败:{$data}");
        }
    }

    //登录成功,获取淘宝网用户信息
    public function taobao($token){
        $taobao = ThinkOauth::getInstance('taobao', $token);
        $fields = 'user_id,nick,sex,buyer_credit,avatar,has_shop,vip_info';
        $data   = $taobao->call('taobao.user.buyer.get', "fields={$fields}");
        if(!empty($data['user_buyer_get_response']['user'])){
            $user = $data['user_buyer_get_response']['user'];
            $userInfo['name'] = $user['user_id'];
            $userInfo['nickname'] = $user['nick'];
            $userInfo['head_img'] = $user['avatar'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取淘宝网用户信息失败:{$data['error_response']['msg']}");
        }
    }

    //登录成功,获取百度用户信息
    public function baidu($token){
        $baidu = ThinkOauth::getInstance('baidu', $token);
        $data  = $baidu->call('passport/users/getLoggedInUser');
        if(!empty($data['uid'])){
            $userInfo['name'] = $data['uid'];
            $userInfo['nickname'] = $data['uname'];
            $userInfo['head_img'] = "http://tb.himg.baidu.com/sys/portrait/item/{$data['portrait']}";
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取百度用户信息失败:{$data['error_msg']}");
        }
    }

    //登录成功,获取开心网用户信息
    public function kaixin($token){
        $kaixin = ThinkOauth::getInstance('kaixin', $token);
        $data   = $kaixin->call('users/me');
        if(!empty($data['uid'])){
            $userInfo['name'] = $data['uid'];
            $userInfo['nickname'] = $data['name'];
            $userInfo['head_img'] = $data['logo50'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取开心网用户信息失败:{$data['error']}");
        }
    }

    //登录成功,获取搜狐用户信息
    public function sohu($token){
        $sohu = ThinkOauth::getInstance('sohu', $token);
        $data = $sohu->call('user/get_info');
        if('success' == $data['message'] && !empty($data['data'])){
            $userInfo['name'] = $data['data']['open_id'];
            $userInfo['nickname'] = $data['data']['nick'];
            $userInfo['head_img'] = $data['data']['icon'];
            $userInfo['gender'] = 0;
            return $userInfo;
        } else {
            //throw_exception("获取搜狐用户信息失败:{$data['message']}");
        }
    }

本插件已部署,欢迎体验:qq-login.png

最后修改:2019 年 08 月 22 日 08 : 34 PM
如果觉得我的文章对你有用,请随意赞赏

11 条评论

  1. 小威云

    看看

  2. 暗尘弥散

    这个“适当位置”就很魔性了,整了半天愣是没整明白

    1. David
      @暗尘弥散

      每个模板登录按钮所在位置不一样。具体分析。

  3. 张益达

    牛批

    1. 模板
      @张益达

      评论一下看下,评论一下看下

  4. 一稿计划

    (๑•̀ㅁ•́ฅ)
    留个记号

  5.  

    冒个泡

  6. 渐行渐远

    学习学习!

  7. 大卫科技客服

    此贴留名记录。2019年8月11日

  8. 泽泽社长

    之前用TeConnect的怎么做数据迁移

    1. David
      @泽泽社长

      我做个升级脚本,做好了放到本页面。

发表评论