# 前言 [scode type=red]大卫科技 Blog原创作品,版权属于:[大卫科技 Blog][1](转载请著名出处)! 原文链接httpswww.iyuu.cnarchives88 如需转载,可下载Markdown原文:点此下载 [scode] # 本插件已部署,欢迎体验:[![qq-login.png][2]](httpswww.iyuu.cnoauthtype=qq) ## 一、功能介绍 [scode type=green]Typecho互联登录插件,目前已支持15种第三方登录:QQ腾讯微博新浪微博网易微博人人网360豆瓣GithubGoogleMsn点点淘宝网百度开心网搜狐。 特色亮点功能:同一用户,可以绑定15种不同的登录方式! 在原项目[TeConnect][3]的基础上,进行完全的二次开发、优化及修复。重点有: 1. 重新设计数据表结构,删除原connect表,后续具有完美的扩展性及兼容性; 2. 已开发支持15种第三方登录,后续可以支持更多……; 3. 优化会员绑定逻辑,修复原项目登录状态下绑定错乱、重复绑定等Bug; 4. 增加会员uuid机制,自动关联users数据表的uid字段,支持更多功能开发的可能; 5. 优化解绑逻辑,和第三方资料更新逻辑等。 [scode] ---------- ## 二、插件下载 [button color=info icon=fontello fontello-angle-down url=httpswww.iyuu.cnusruploads2019081217520852.zip type=]从本站下载[button] [button color=danger icon=fontello fontello-angle-down url=httpsgitee.comledcTeConnectrepositoryarchivemaster.zip type=]从Gitee仓库下载[button] 样式1 样式2 样式3 样式4 样式5 ------ [![bt_blue_76X24.png][5]](httpswww.iyuu.cnoauthtype=qq) [![bt_white_76X24.png][6]](httpswww.iyuu.cnoauthtype=qq) [![bt_blue_24X24.png][7]](httpswww.iyuu.cnoauthtype=qq) [![bt_white_24X24.png][8]](httpswww.iyuu.cnoauthtype=qq) [![bt_92X120.png][9]](httpswww.iyuu.cnoauthtype=qq) ---------- ## 三、安装步骤 [![qq-login.png][19]](httpswww.iyuu.cnoauthtype=qq) 即可查看! [hide] 1. 解压插件到`Plugins`目录下,把本插件目录下的`callback.php`文件拷贝到当前使用主题的根目录中; 2. 在后台启用插件,并配置插件参数(方法见:参数配置 - 配置示例); 3. 在当前使用主题的适当位置添加`TeConnect_Pluginshow()`方法,代码: ```php php TeConnect_Pluginshow(); ``` `handsome Theme`示例图:![handsome Theme示例图][10] ![getAvator函数.png][11] 下载你喜欢的png登录图标,放到`usrpluginsTeConnectlogin_ico{type}.png`,然后修改登录按钮样式在`Plugin.php 第125行`,代码: `a href={url}img src=usrpluginsTeConnectlogin_ico{type}.png alt={type}-{title} style=margin-top 0.8em;a` 4. 在第三方平台设置网站回调域,`注意区分http、https`及`地址重写隐藏index.php`(方法见:参数配置 - 配置示例)。 [hide] ---------- ## 四、参数配置 ### 配置示例 名称 类型 配置示例 网站回调域 ---- 腾讯QQ qq qqAPP_KEY,APP_SECRET,腾讯QQ https127.0.0.1oauth_callbacktype=qq 腾讯微博 tencent tencentAPP_KEY,APP_SECRET,腾讯微博 https127.0.0.1oauth_callbacktype=tencent 新浪微博 sina sinaAPP_KEY,APP_SECRET,新浪微博 https127.0.0.1oauth_callbacktype=sina 网易微博 t163 t163APP_KEY,APP_SECRET,网易微博 https127.0.0.1oauth_callbacktype=t163 人人网 renren renrenAPP_KEY,APP_SECRET,人人网 https127.0.0.1oauth_callbacktype=renren 360 x360 x360APP_KEY,APP_SECRET,360 https127.0.0.1oauth_callbacktype=x360 豆瓣 douban doubanAPP_KEY,APP_SECRET,豆瓣 https127.0.0.1oauth_callbacktype=douban Github github githubAPP_KEY,APP_SECRET,Github https127.0.0.1oauth_callbacktype=github Google google googleAPP_KEY,APP_SECRET,Google https127.0.0.1oauth_callbacktype=google MSN msn msnAPP_KEY,APP_SECRET,MSN https127.0.0.1oauth_callbacktype=msn 点点 diandian diandianAPP_KEY,APP_SECRET,点点 https127.0.0.1oauth_callbacktype=diandian 淘宝网 taobao taobaoAPP_KEY,APP_SECRET,淘宝网 https127.0.0.1oauth_callbacktype=taobao 百度 baidu baiduAPP_KEY,APP_SECRET,百度 https127.0.0.1oauth_callbacktype=baidu 开心网 kaixin kaixinAPP_KEY,APP_SECRET,开心网 https127.0.0.1oauth_callbacktype=kaixin 搜狐微博 sohu sohuAPP_KEY,APP_SECRET,搜狐微博 https127.0.0.1oauth_callbacktype=sohu ### 1:后台互联配置 具体格式为:`typeappid,appkey,title`,注释: - type:第三方登录帐号类型 - appid:第三方开放平台申请的应用id - appkey:第三方开放平台申请的应用key - title:登录按钮的标题 在后台互联配置中,直接以文本形式填写,一行为一个帐号系统的参数; 为减少错误发生,您可以复制对应的`配置示例`,把`APP_KEY`和`APP_SECRET`改成您自己的参数就可以了! 例如:`qqAPP_KEY,APP_SECRET,腾讯QQ` 改成:`qq101015836,547s87f8s7df7sd877ji75s78sdfd,腾讯QQ` 粘贴到后台`互联配置`,即完成了腾讯QQ登录的配置,其他类型同理! ### 2:网站回调域配置 [![bt_blue_76X24.png][5]](httpswww.iyuu.cnoauthtype=qq) 即可查看 [hide] 您可以复制对应的`配置示例`,把`127.0.0.1`改成您的域名,填写到第三方开发平台的网站回调域设置中,即可完成配置! 以本博客`www.iyuu.cn`,设置腾讯QQ登录,为例: 复制:`https127.0.0.1oauth_callbacktype=qq` 把`127.0.0.1`改成`www.iyuu.cn`,改好后: `httpswww.iyuu.cnoauth_callbacktype=qq` 推荐同时设置2个提高兼容性: `https127.0.0.1oauth_callbacktype=qq;https127.0.0.1index.phpoauth_callbacktype=qq` ![QQ互联网站回调域设置.png][12] [hide] ---------- ## 五、第三方账号绑定流程 ### 1、方案选择 我参考了国内主流的几家互联网公司的第三方账号登录功能,发现主要分成两种设计方案; 一种是账号强绑,像京东、小米等,在第三方账号授权通过后,需要用户绑定自己的账号; 一种是今日头条、知乎,在第三方账号授权通过后,随机给用户生成一个账号或者调用第三方账号昵称,无需绑定账号,即可成功登录。 目前,`两种方案都支持`,您可以在`后台开启或关闭强制绑定`! ### 2、绑定流程一(未登录状态) ![绑定流程一(未登录状态).png][13] 用户在登录界面点击第三方账号,授权通过后,我们获得用户第三方账号的OpenID,由此判断用户的第三方账号之前是否绑定过,如果绑定过则直接登录成功。 如果没有绑定过,则跳到账号绑定页面。账号绑定页面需要分成已有账号直接绑定,和没有账号,新注册账号进行绑定两种情况。 当用户已有账号时,通过输入账号密码校验身份,校验通过后即可绑定成功登录成功。 当用户没有账号时,用户可通过注册新账号,注册成功后即可绑定成功登录成功。 ### 3、绑定流程二(登录状态) 在个人账号中心里提供绑定管理的功能和界面,在用户已经登录的情况下,可以直接绑定第三方账号,只要获得授权通过,即可绑定成功。 ---------- ## 六、第三方帐号解绑流程 在个人账号中心绑定管理中,可以对已经绑定的第三方账号进行解绑操作。在这里需要注意,由于用户长期使用第三方账号登录,实际上是由第三方账号承担了提交账号和保护账号安全的工作,因此在解绑第三方账号时,我们需要提醒用户,解绑以后只能通过本平台账号密码方式来登录。最好是提示用户记住当前账号 ![提示用户记住当前账号.jpg][14] 京东的解绑账号功能 另一方面,由于之前是由第三方账号“帮平台”做了账号安全的工作,因此在解绑账号的时候,我们需要考虑如何保护账号安全。因此可以在解绑的时候,对账号做一定的安全校验或安全保护。 我们最终定的方案是 当用户在解绑时,需要校验手机短信验证码,如果没有绑定手机,则提示用户先去绑定手机。 ![第三方帐号解绑流程.png][15] 解绑流程 [scode type=blue]总结 第三方账号虽然是一个小功能,但是在设计过程中,我们要结合自身产品的特点来确定产品方案和产品流程。授权之后,是直接登录成功,还是绑定自己平台的账号,这是由自己产品特点决定。同时,对新增账号来说,如何设计用户账号的安全,也需要根据产品特点和安全策略来设计适合的产品流程。 [scode] ---------- ## 七、数据表结构(不开发,可以不看) ### 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 [scode type=blue]特色亮点功能:同一用户,可以绑定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完整记录着原始绑定关系,支持解绑后数据不丢失。 [scode] ![typecho_oauth_user表结构.png][16] ![oauth_user表数据结构.png][17] ### 创建数据表SQL语句 ```mysql 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; ``` ---------- ## 项目仓库 码云:httpsgitee.comledcTeConnect ## 关键代码 [collapse status=true title=关键PHP代码段] ```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_Pluginoptions(); $type = strtolower($type); 判断登录方式是否支持 if(!isset($options[$type])){ throw new Typecho_Widget_Exception(暂不支持该登录方式! {$type}); } 组装回调地址 $callback_url = Typecho_Commonurl('oauth_callbacktype='.$type, $this-options-index); 加载ThinkOauth类并实例化一个对象 require_once 'ThinkOauth.php'; $sdk = ThinkOauthgetInstance($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_Pluginoptions(); 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_Commonurl('oauth_callbacktype='.$type, $this-options-index); 加载ThinkOauth类并实例化一个对象 require_once 'ThinkOauth.php'; $sdk = ThinkOauthgetInstance($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_CommonrandString(20)); $user = array('uid'=$uid,'authCode'=$authCode); Typecho_Cookieset('__typecho_uid', $uid, $expire); Typecho_Cookieset('__typecho_authCode', Typecho_Commonhash($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 His,time()))) -where('uid = ', $uid)); } public function render($themeFile){ 文件不存在 if (!file_exists($this-_themeDir . $themeFile)) { Typecho_Commonerror(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 = ThinkOauthgetInstance('qq', $token); $data = $qq-call('userget_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 = ThinkOauthgetInstance('tencent', $token); $data = $tencent-call('userinfo'); 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 = ThinkOauthgetInstance('sina', $token); $data = $sina-call('usersshow', 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 = ThinkOauthgetInstance('t163', $token); $data = $t163-call('usersshow'); 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 = ThinkOauthgetInstance('renren', $token); $data = $renren-call('userget'); if(!isset($data['error'])){ $userInfo['name'] = $data['response']['name']; $userInfo['nickname'] = $data['response']['name']; $userInfo['head_img'] = $data['response']['avatar'][18]['url']; $userInfo['gender'] = 0; return $userInfo; } else { throw_exception(获取人人网用户信息失败:{$data['error_msg']}); } } 登录成功,获取360用户信息 public function x360($token){ $x360 = ThinkOauthgetInstance('x360', $token); $data = $x360-call('userme'); 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 = ThinkOauthgetInstance('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 = ThinkOauthgetInstance('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 = ThinkOauthgetInstance('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 = ThinkOauthgetInstance('msn', $token); $data = $msn-call('me'); if(!empty($data['id'])){ $userInfo['name'] = $data['name']; $userInfo['nickname'] = $data['name']; $userInfo['head_img'] = '微软暂未提供头像URL,请通过 mepicture 接口下载'; $userInfo['gender'] = 0; return $userInfo; } else { throw_exception(获取msn用户信息失败:{$data}); } } 登录成功,获取点点用户信息 public function diandian($token){ $diandian = ThinkOauthgetInstance('diandian', $token); $data = $diandian-call('userinfo'); if(!empty($data['meta']['status']) && $data['meta']['status'] == 200){ $userInfo['name'] = $data['response']['name']; $userInfo['nickname'] = $data['response']['name']; $userInfo['head_img'] = httpsapi.diandian.comv1blog{$data['response']['blogs'][0]['blogUuid']}avatar144; $userInfo['gender'] = 0; return $userInfo; } else { throw_exception(获取点点用户信息失败:{$data}); } } 登录成功,获取淘宝网用户信息 public function taobao($token){ $taobao = ThinkOauthgetInstance('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 = ThinkOauthgetInstance('baidu', $token); $data = $baidu-call('passportusersgetLoggedInUser'); if(!empty($data['uid'])){ $userInfo['name'] = $data['uid']; $userInfo['nickname'] = $data['uname']; $userInfo['head_img'] = httptb.himg.baidu.comsysportraititem{$data['portrait']}; $userInfo['gender'] = 0; return $userInfo; } else { throw_exception(获取百度用户信息失败:{$data['error_msg']}); } } 登录成功,获取开心网用户信息 public function kaixin($token){ $kaixin = ThinkOauthgetInstance('kaixin', $token); $data = $kaixin-call('usersme'); 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 = ThinkOauthgetInstance('sohu', $token); $data = $sohu-call('userget_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']}); } } ``` [collapse] # 本插件已部署,欢迎体验:[![qq-login.png][19]](httpswww.iyuu.cnoauthtype=qq) [post cid=101 ] [1] httpswww.iyuu.cn [2] httpswww.iyuu.cnusruploads2019083262692976.png [3] httpsgithub.comjiangmuziTeConnect [4] httpswww.iyuu.cnusruploads2019083262692976.png [5] httpswww.iyuu.cnusruploads201908379738753.png [6] httpswww.iyuu.cnusruploads2019081686542734.png [7] httpswww.iyuu.cnusruploads2019082003267968.png [8] httpswww.iyuu.cnusruploads2019082078951516.png [9] httpswww.iyuu.cnusruploads2019081192845902.png [10] httpswww.iyuu.cnusruploads2019081213036462.png [11] httpswww.iyuu.cnusruploads2019081809525413.png [12] httpswww.iyuu.cnusruploads2019081395775936.png [13] httpswww.iyuu.cnusruploads2019081331919342.png [14] httpswww.iyuu.cnusruploads2019083278948233.jpg [15] httpswww.iyuu.cnusruploads2019082385470498.png [16] httpswww.iyuu.cnusruploads2019083510776867.png [17] httpswww.iyuu.cnusruploads2019082906414904.png [18] httpswww.iyuu.cnusruploads2019083262692976.png [19] httpswww.iyuu.cnusruploads2019083262692976.png