要使用qq互联授权登录,需要先去qq互联网站 https://connect.qq.com申请成为开发者,创建一个网站应用(注意网站的名称信息必须和备案信息一致,我之前几次就因为这个被拒绝了),同时需要填上网站的域名和回调地址

之后会得到一个APP ID和APP Key
。
流程
qq登录和微信登录流程基本类似,都是以下步骤
- 跳转到授权页面,用户同意授权后获取code,code有效期10分钟
- 使用code获取access_token
- 使用access_token获取用户openid
- 使用access_token和openid获取用户信息
代码部分
封装成公共类如下,(使用方法)
<?php/*** qq授权登录获取用户信息* @param $appid qq互联应用appid* @param $appkey qq互联应用appkey* @param $callback qq互联应用配置的回调地址* @author codehui <admin@codehui.net> 2017-12-23*/class QqOauth {const GET_AUTH_CODE_URL = "https://graph.qq.com/oauth2.0/authorize";const GET_ACCESS_TOKEN_URL = "https://graph.qq.com/oauth2.0/token";const GET_OPENID_URL = "https://graph.qq.com/oauth2.0/me";const GET_USER_INFO_URL = "https://graph.qq.com/user/get_user_info";private $appid;private $appkey;private $callback;public function __construct() {if (func_num_args() == 3) {$this->appid = func_get_arg(0);$this->appkey = func_get_arg(1);$this->callback = func_get_arg(2);} else {$this->error('20001', '缺少必要参数');}}/*** qq授权页面*/public function qqLogin(){// 生成唯一随机串防CSRF攻击$state = md5(uniqid(rand(), TRUE));session('state', $state);$uri = $this->combineURL(self::GET_AUTH_CODE_URL, ["response_type" => "code","client_id" => $this->appid,"redirect_uri" => $this->callback,"state" => $state,"scope" => 'get_user_info' // 请求用户授权时向用户显示的可进行授权的列表]);header("Location:$uri");}/*** 使用Authorization_Code获取Access_Token* 如果用户成功登录并授权,则会跳转到指定的回调地址,并在redirect_uri地址后带上Authorization Code(10分钟有效期)和原始的state值* @return array ['access_token'=>'授权令牌', 'expires_in'=>'有效期,单位秒','refresh_token'=>'续期令牌']*/public function getToken() {// 验证state防止CSRF攻击if (!$_REQUEST['state'] || $_REQUEST['state'] != session('state')){$this->error = 20001;}$token_url = $this->combineURL(self::GET_ACCESS_TOKEN_URL, ["grant_type" => "authorization_code","client_id" => $this->appid,"redirect_uri" => urlencode($this->callback),"client_secret" => $this->appkey,"code" => $_REQUEST['code']]);$response = $this->httpsRequest($token_url);if(strpos($response, "callback") !== false){$lpos = strpos($response, "(");$rpos = strrpos($response, ")");$response = substr($response, $lpos + 1, $rpos - $lpos -1);$msg = json_decode($response);if(isset($msg->error)){return $this->error($msg->error, $msg->error_description);}}$params = [];parse_str($response, $params);return $params;}/*** 获取openid* @param $access_token 上一步获取到的access_token* @return string*/public function getOpenid($access_token){$graph_url = $this->combineURL(self::GET_OPENID_URL, ['access_token' => $access_token]);$response = $this->httpsRequest($graph_url);// 检测错误是否发生if(strpos($response, "callback") !== false){$lpos = strpos($response, "(");$rpos = strrpos($response, ")");$response = substr($response, $lpos + 1, $rpos - $lpos -1);}$user = json_decode($response);if(isset($user->error)){return $this->error($user->error, $user->error_description);}return $user->openid;}/*** 获取用户信息* @param $access_token 授权令牌* @param $openid 用户openid* @return array*/public function getUserinfo($access_token, $openid){$get_userinfo_url = $this->combineURL(self::GET_USER_INFO_URL, ['openid' => $openid,'access_token' => $access_token,'oauth_consumer_key' => $this->appid]);$response = $this->httpsRequest($get_userinfo_url);$info = json_decode($response);if(!isset($info->ret)) {return $this->error('110500', '获取用户授权信息失败');}return $info;}/*** 错误信息* @param int $code 错误代码* @param string $info 描述信息* @return array*/public function error($code = 0, $msg = ''){return ['errcode' => $code,'errmsg' => $msg];}/*** 拼接url* @param string $baseURL 请求的url* @param array $keysArr 参数列表数组* @return string 返回拼接的url*/public function combineURL($baseURL, $keysArr) {$combined = $baseURL . "?";$valueArr = [];foreach($keysArr as $key => $val){$valueArr[] = "$key=$val";}$keyStr = implode("&", $valueArr);$combined .= ($keyStr);return $combined;}/*** 获取服务器数据* @param string $url 请求的url* @return unknown 请求返回的内容*/public function httpsRequest($url) {$curl = curl_init();curl_setopt($curl, CURLOPT_URL, $url);curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);$output = curl_exec($curl);curl_close($curl);return $output;}}
使用方法
// 用户点击qq登录之后的操作,该方法会自动跳转到授权页面function qq_login() {$qq = new QqOauth('appid', 'appkey', 'http://***/oauth/qqCallBack');$qq->qqLogin();}// 回调方法public function qqCallBack(){$qq = new QqOauth('appid', 'appkey', 'http://***/oauth/qqCallBack');$token = $qq->getToken();if(isset($token['errcode'])){return json_encode($token);}$openid = $qq->getOpenid($token['access_token']);if(isset($token['openid'])){return json_encode($token);}$info = $qq->getUserinfo($token['access_token'], $openid);return json_encode($info);}
返回参数说明
| 参数说明 | 描述 |
|---|---|
| ret | 返回码 |
| msg | 如果ret<0,会有相应的错误信息提示,返回数据全部用UTF-8编码。 |
| nickname | 用户在QQ空间的昵称。 |
| figureurl | 大小为30×30像素的QQ空间头像URL。 |
| figureurl_1 | 大小为50×50像素的QQ空间头像URL。 |
| figureurl_2 | 大小为100×100像素的QQ空间头像URL。 |
| figureurl_qq_1 | 大小为40×40像素的QQ头像URL。 |
| figureurl_qq_2 | 大小为100×100像素的QQ头像URL。需要注意,不是所有的用户都拥有QQ的100x100的头像,但40x40像素则是一定会有。 |
| gender | 性别。 如果获取不到则默认返回”男” |
