当前位置: 移动技术网 > IT编程>开发语言>PHP > PHP实现QQ快速登录的方法

PHP实现QQ快速登录的方法

2017年12月12日  | 移动技术网IT编程  | 我要评论

东营人才招聘网,romantz,穿越曙光

前言:

php实现qq快速登录,罗列了三种方法

方法一:面向过程,回调地址和首次触发登录写到了一个方法页面【因为有了if做判断】,

方法二,三:面向对象

1.先调用登录方法,向腾讯发送请求,
2.腾讯携带本网站唯一对应参数openid,accesstoken,返回到对应回调页面,
3.回调页面接受到腾讯的参数后,通过这个两个参数,再发出对应的请求,如查询用户的数据。
4.腾讯做出对应的操作,如返回这个用户的数据给你

即使你没看懂,也没关系,按照我下面的流程来,保证你可以实现。

前期准备:

使用人家腾讯的功能,总得和人家打招呼吧!

qq互联首页:http://connect.qq.com/

进入网址后,按如下操作来:

一.进入官网


二.申请创建【网站】应用


三.按要求填写资料

注意网站地址:填写你要设置快速登录的网址,eg:http://www.test.com;  

回调地址:填写你发送qq快速登陆后,腾讯得给你信息,这个信息往此页面接受。eg:http://www.test.com/accept_info.php

【详细的申请填写,请见官方提示,这里不做赘述】


四.申请成功后,完善信息

最终要求,获得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 style="font-family: arial, helvetica, sans-serif;">openid,</span><span style="font-family: arial, helvetica, sans-serif;">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
然后操作就可以了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网