设为首页 收藏本站
查看: 1238|回复: 0

[经验分享] PHP实现QQ第三方登录的方法

[复制链接]

尚未签到

发表于 2017-12-30 12:36:46 | 显示全部楼层 |阅读模式
  前言:
  PHP实现QQ快速登录,罗列了三种方法
  方法一:面向过程,回调地址和首次触发登录写到了一个方法页面【因为有了if做判断】,
  方法二,三:面向对象
  1.先调用登录方法,向腾讯发送请求,
  2.腾讯携带本网站唯一对应参数OPENID,ACCESSTOKEN,返回到对应回调页面,
  3.回调页面接受到腾讯的参数后,通过这个两个参数,再发出对应的请求,如查询用户的数据。
  4.腾讯做出对应的操作,如返回这个用户的数据给你
  即使你没看懂,也没关系,按照我下面的流程来,保证你可以实现。
  前期准备:
  使用人家腾讯的功能,总得和人家打招呼吧!
  QQ互联首页:http://connect.qq.com/
  进入网址后,按如下操作来:
  一.进入官网
   DSC0000.png
  二.申请创建【网站】应用
   DSC0001.png
  三.按要求填写资料
  注意网站地址:填写你要设置快速登录的网址,eg:http://www.test.com;
  回调地址:填写你发送QQ快速登陆后,腾讯得给你信息,这个信息往此页面接受。eg:http://www.test.com/accept_info.php
  【详细的申请填写,请见官方提示,这里不做赘述】
   DSC0002.png
  四.申请成功后,完善信息
   DSC0003.png
  最终要求,获得APP_ID ,APP_KEY
  五.代码部分:
  在你对应的PHP文件内写入,如下
  方法一,面向过程法
  使用方法:配置$app_id,$app_secret,$my_url后,其他原封复制即可,$user_data为返回的登录信息
  代码:
  ----------------------------------------------------------------------------------------------------------------------------------------------------------
  //应用的APPID
   $app_id = "你的APPID";    //应用的APPKEY    $app_secret = "你的APPKEY";    //【成功授权】后的回调地址,即此地址在腾讯的信息中有储存    $my_url = "你的回调网址";      //Step1:获取Authorization Code    session_start();    $code = $_REQUEST["code"];//存放Authorization Code    if(empty($code))    {     //state参数用于防止CSRF攻击,成功授权后回调时会原样带回     $_SESSION['state'] = md5(uniqid(rand(), TRUE));     //拼接URL     $dialog_url = "https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id="     . $app_id . "&redirect_uri=" . urlencode($my_url) . "&state="     . $_SESSION['state'];     echo("<script> top.location.href='" . $dialog_url . "'</script>");    }      //Step2:通过Authorization Code获取Access Token    if($_REQUEST['state'] == $_SESSION['state'] || 1)    {     //拼接URL     $token_url = "https://graph.qq.com/oauth2.0/token?grant_type=authorization_code&"     . "client_id=" . $app_id . "&redirect_uri=" . urlencode($my_url)      . "&client_secret=" . $app_secret . "&code=" . $code;     $response = file_get_contents($token_url);     if (strpos($response, "callback") !== false)//如果登录用户临时改变主意取消了,返回true!==false,否则执行step3     {      $lpos = strpos($response, "(");      $rpos = strrpos($response, ")");      $response = substr($response, $lpos + 1, $rpos - $lpos -1);      $msg = json_decode($response);      if (isset($msg->error))      {       echo "<h3>error:</h3>" . $msg->error;       echo "<h3>msg :</h3>" . $msg->error_description;       exit;      }     }       //Step3:使用Access Token来获取用户的OpenID     $params = array();     parse_str($response, $params);//把传回来的数据参数变量化     $graph_url = "https://graph.qq.com/oauth2.0/me?access_token=".$params['access_token'];     $str = file_get_contents($graph_url);     if (strpos($str, "callback") !== false)     {      $lpos = strpos($str, "(");      $rpos = strrpos($str, ")");      $str = substr($str, $lpos + 1, $rpos - $lpos -1);     }     $user = json_decode($str);//存放返回的数据 client_id ,openid     if (isset($user->error))     {      echo "<h3>error:</h3>" . $user->error;      echo "<h3>msg :</h3>" . $user->error_description;      exit;     }     //echo("Hello " . $user->openid);     //echo("Hello " . $params['access_token']);       //Step4:使用<span >openid,</span><span >access_token来获取所接受的用户信息。</span>     $user_data_url = "https://graph.qq.com/user/get_user_info?access_token={$params['access_token']}&oauth_consumer_key={$app_id}&openid={$user->openid}&format=json";           $user_data = file_get_contents($user_data_url);//此为获取到的user信息     }     else    {      echo("The state does not match. You may be a victim of CSRF.");     }  ----------------------------------------------------------------------------------------------------------------------------------------------------------
  方法二,面向对象 使用类QQ_LoginAction.class
  使用方法:
  1.在QQ_LoginAction.class中正确配置 APPID,APPKEY CALLBACK(回调网址)
  2.在调用方法中,代码:
  $qq_login = new \Component\QQ_LoginAction();    //引入此类文件即可
$qq_login->qq_login();       3.在回调页面中,代码:
  $qc = new \Component\QQ_LoginAction();
$acs = $qc->qq_callback();<span style="white-space:pre">    //access_token $oid=$qc->get_openid();<span style="white-space:pre">     //openid $user_data = $qc->get_user_info();<span style="white-space:pre">  //get_user_info()为获得该用户的信息,其他操作方法见API文档   4.$user_data即为返回的用户数据。
  5.QQ_LoginAction.class.php 文件代码:【用的ThinkPHP3.2】
  ----------------------------------------------------------------------------------------------------------------------
<?php namespace Component;   session_start(); define('APPID','XXXX');   //appid define('APPKEY','XXXX');  //appkey define('CALLBACK','XXXX');  //回调地址 define('SCOPE','get_user_info,list_album,add_album,upload_pic,add_topic,add_weibo');  //授权接口列表 class QQ_LoginAction {  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";  private $APIMap = array(   "get_user_info" => array(   //获取用户资料    "https://graph.qq.com/user/get_user_info",    array("format" => "json"),   ),   "add_t" => array(    //发布一条普通微博    "https://graph.qq.com/t/add_t",    array("format" => "json", "content","#clientip","#longitude","#latitude","#compatibleflag"),    "POST"  ),   "add_pic_t" => array(    //发布一条图片微博    "https://graph.qq.com/t/add_pic_t",    array("content", "pic", "format" => "json", "#clientip", "#longitude", "#latitude", "#syncflag", "#compatiblefalg"),    "POST"  ),   "del_t" => array(      //删除一条微博    "https://graph.qq.com/t/del_t",    array("id", "format" => "json"),    "POST"  ),   "get_repost_list" => array(    //获取单条微博的转发或点评列表    "https://graph.qq.com/t/get_repost_list",    array("flag", "rootid", "pageflag", "pagetime", "reqnum", "twitterid", "format" => "json")   ),   "get_info" => array(     //获取当前用户资料    "https://graph.qq.com/user/get_info",    array("format" => "json")   ),   "get_other_info" => array(    //获取其他用户资料    "https://graph.qq.com/user/get_other_info",    array("format" => "json", "#name-1", "#fopenid-1")   ),   "get_fanslist" => array(    "https://graph.qq.com/relation/get_fanslist", //我的微博粉丝列表    array("format" => "json", "reqnum", "startindex", "#mode", "#install", "#sex")   ),   "get_idollist" => array(    "https://graph.qq.com/relation/get_idollist", //我的微博收听列表    array("format" => "json", "reqnum", "startindex", "#mode", "#install")   ),   "add_idol" => array(    "https://graph.qq.com/relation/add_idol",  //微博收听某用户    array("format" => "json", "#name-1", "#fopenids-1"),    "POST"  ),   "del_idol" => array(   //微博取消收听某用户    "https://graph.qq.com/relation/del_idol",    array("format" => "json", "#name-1", "#fopenid-1"),    "POST"  )  );  private $keysArr;  function __construct(){   if($_SESSION["openid"]){    $this->keysArr = array(     "oauth_consumer_key" => APPID,     "access_token" => $_SESSION['access_token'],     "openid" => $_SESSION["openid"]    );   }else{    $this->keysArr = array(     "oauth_consumer_key" => APPID    );   }  }  public function qq_login(){   //-------生成唯一随机串防CSRF攻击   $_SESSION['state'] = md5(uniqid(rand(), TRUE));   $keysArr = array(    "response_type" => "code",    "client_id" => APPID,    "redirect_uri" => CALLBACK,    "state" => $_SESSION['state'],    "scope" => SCOPE   );   $login_url = self::GET_AUTH_CODE_URL.'?'.http_build_query($keysArr);   header("Location:$login_url");  }  public function qq_callback(){   //--------验证state防止CSRF攻击   if($_GET['state'] != $_SESSION['state']){    return false;   }   //-------请求参数列表   $keysArr = array(    "grant_type" => "authorization_code",    "client_id" => APPID,    "redirect_uri" => CALLBACK,    "client_secret" => APPKEY,    "code" => $_GET['code']   );   //------构造请求access_token的url   $token_url = self::GET_ACCESS_TOKEN_URL.'?'.http_build_query($keysArr);   $response = $this->get_contents($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)){     $this->showError($msg->error, $msg->error_description);    }   }   $params = array();   parse_str($response, $params);   $_SESSION["access_token"]=$params["access_token"];   $this->keysArr['access_token']=$params['access_token'];   return $params["access_token"];  }    public function get_contents($url){   if (ini_get("allow_url_fopen") == "1") {    $response = file_get_contents($url);   }else{    $ch = curl_init();    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);    curl_setopt($ch, CURLOPT_URL, $url);    $response = curl_exec($ch);    curl_close($ch);   }   if(empty($response)){    return false;   }   return $response;  }  public function get_openid(){   //-------请求参数列表   $keysArr = array(    "access_token" => $_SESSION["access_token"]   );   $graph_url = self::GET_OPENID_URL.'?'.http_build_query($keysArr);   $response = $this->get_contents($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)){    $this->showError($user->error, $user->error_description);   }   //------记录openid   $_SESSION['openid']=$user->openid;   $this->keysArr['openid']=$user->openid;   return $user->openid;  }    /**   * showError   * 显示错误信息   * @param int $code 错误代码   * @param string $description 描述信息(可选)   */ public function showError($code, $description = '$'){    echo "<meta charset=\"UTF-8\">";    echo "<h3>error:</h3>$code";    echo "<h3>msg :</h3>$description";    exit();  }    /**   * _call   * 魔术方法,做api调用转发   * @param string $name 调用的方法名称   * @param array $arg  参数列表数组   * @since 5.0   * @return array   返加调用结果数组   */ public function __call($name,$arg){   //如果APIMap不存在相应的api   if(empty($this->APIMap[$name])){    $this->showError("api调用名称错误","不存在的API: <span style='color:red;'>$name</span>");   }   //从APIMap获取api相应参数   $baseUrl = $this->APIMap[$name][0];   $argsList = $this->APIMap[$name][1];   $method = isset($this->APIMap[$name][2]) ? $this->APIMap[$name][2] : "GET";   if(empty($arg)){    $arg[0] = null;   }   $responseArr = json_decode($this->_applyAPI($arg[0], $argsList, $baseUrl, $method),true);   //检查返回ret判断api是否成功调用   if($responseArr['ret'] == 0){    return $responseArr;   }else{    $this->showError($responseArr['ret'], $responseArr['msg']);   }  }    //调用相应api  private function _applyAPI($arr, $argsList, $baseUrl, $method){   $pre = "#";   $keysArr = $this->keysArr;   $optionArgList = array();//一些多项选填参数必选一的情形   foreach($argsList as $key => $val){    $tmpKey = $key;    $tmpVal = $val;    if(!is_string($key)){     $tmpKey = $val;     if(strpos($val,$pre) === 0){      $tmpVal = $pre;      $tmpKey = substr($tmpKey,1);      if(preg_match("/-(\d$)/", $tmpKey, $res)){       $tmpKey = str_replace($res[0], "", $tmpKey);       $optionArgList[]= $tmpKey;      }     }else{      $tmpVal = null;     }    }    //-----如果没有设置相应的参数    if(!isset($arr[$tmpKey]) || $arr[$tmpKey] === ""){     if($tmpVal == $pre){      continue;     }else if($tmpVal){//则使用默认的值      $arr[$tmpKey] = $tmpVal;     }else{      $this->showError("api调用参数错误","未传入参数$tmpKey");     }    }    $keysArr[$tmpKey] = $arr[$tmpKey];   }   //检查选填参数必填一的情形   if(count($optionArgList)!=0){    $n = 0;    foreach($optionArgList as $val){     if(in_array($val, array_keys($keysArr))){      $n++;     }    }    if(!$n){     $str = implode(",",$optionArgList);     $this->showError("api调用参数错误",$str."必填一个");    }   }   if($method == "POST"){    $response = $this->post($baseUrl, $keysArr, 0);   }else if($method == "GET"){    $baseUrl=$baseUrl.'?'.http_build_query($keysArr);    $response = $this->get_contents($baseUrl);   }   return $response;  }    public function post($url, $keysArr, $flag = 0){   $ch = curl_init();   if(! $flag) curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);   curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);   curl_setopt($ch, CURLOPT_POST, TRUE);   curl_setopt($ch, CURLOPT_POSTFIELDS, $keysArr);   curl_setopt($ch, CURLOPT_URL, $url);   $ret = curl_exec($ch);   curl_close($ch);   return $ret;  } } -------------------------------------------------------------------------------------------------------------------------------
  方法三,面向对象 使用腾讯给的SDK
  使用方法:腾讯SDK,API写的很详细,不做赘述
  地址:http://wiki.connect.qq.com/%E7%BD%91%E7%AB%99%E6%8E%A5%E5%85%A5%E6%A6%82%E8%BF%B0
  这样就实现了QQ快捷登录,其实很简单的,大家可以试一试。
  还有什么不清楚的,可以看看官方介绍,更详细,
  Tips:如何在本地测试QQ快速登录
  方法:修改HOST配置文件
  1. 打开C:\Windows\System32\drivers\etc\host
  2. 添加127.0.0.1    www.test.com
  然后操作就可以了。
  出处至:脚本之家  http://www.iyunv.net/article/93749.htm

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-429662-1-1.html 上篇帖子: PHP PSR 代码规范基本介绍 下篇帖子: PHP uniqid 高并发生成不重复唯一ID
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表