Skip to content

Instantly share code, notes, and snippets.

@daoiqi
Last active October 14, 2015 05:40
Show Gist options
  • Save daoiqi/10871911 to your computer and use it in GitHub Desktop.
Save daoiqi/10871911 to your computer and use it in GitHub Desktop.
QQ Oauth2 登录PHP SDK
<?php
/**
* get_contents
* 服务器通过get请求获得内容
* @param string $url 请求的url,拼接后的
* @return string 请求返回的内容
*/
function http_get_contents($url) {
$proxyconf = array(
'proxyswitch' => 'on',
'proxytimeout' => 10,
'proxy' => 'http://localhost:3128',
);
$needproxy = $proxyconf['proxyswitch'] ;
if (ini_get ( "allow_url_fopen" ) == "1") {
if ($needproxy) {
$ctx = stream_context_create ( array (
'http' => array (
'timeout' => (int)$proxyconf['proxytimeout'],
'proxy' => $proxyconf['proxy'],
'request_fulluri' => True
)
) );
$response = file_get_contents ( $url, False, $ctx);
}else {
$response = file_get_contents ( $url );
}
} else {
if (! function_exists ( 'curl_init' )) {
throw new Exception ( 'server not install curl' );
}
$ch = curl_init ();
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt ( $ch, CURLOPT_HEADER, true );
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_TIMEOUT, $timeout );
if ($needproxy) {
curl_setopt ( $ch, CURLOPT_PROXY, $proxy );
}
if (! empty ( $header )) {
curl_setopt ( $ch, CURLOPT_HTTPHEADER, $header );
}
$response = curl_exec ( $ch );
list ( $header, $response ) = explode ( "\r\n\r\n", $response );
$http_code = curl_getinfo ( $ch, CURLINFO_HTTP_CODE );
if ($http_code == 301 || $http_code == 302) { // redirect url
$matches = array ();
preg_match ( '/Location:(.*?)\n/', $header, $matches );
$url = trim ( array_pop ( $matches ) );
curl_setopt ( $ch, CURLOPT_URL, $url );
curl_setopt ( $ch, CURLOPT_HEADER, false );
$response = curl_exec ( $ch );
}
if ($response == false) {
curl_close ( $ch );
}
@curl_close ( $ch );
}
// -------请求为空
if (empty ( $response )) {
// TODO error
return "";
}
return $response;
}
<?php
/* PHP SDK
* @version 2.0.0
* @author connect@qq.com
* @copyright © 2013, Tencent Corporation. All rights reserved.
* @modify_author daoiqi
* @modify_date 20140416
*/
class QQ_Oauth{
const VERSION = "2.0";
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 QQ_LOGIN_STATE = 'QQ_LOGIN_STATE';
private $QQ_CONNECT_CONFIG;
function __construct( $config ){
$this->QQ_CONNECT_CONFIG = $config;
}
public function qq_login(){
$appid = $this->QQ_CONNECT_CONFIG["appid"];
$callback = $this->QQ_CONNECT_CONFIG["callback"];
$scope = $this->QQ_CONNECT_CONFIG["scope"];
//-------生成唯一随机串防CSRF攻击
$state = md5(uniqid(rand(), TRUE));
$_SESSION[self::QQ_LOGIN_STATE] = $state; //保存qq登录前的状态,将来登录成功回调验证
//-------构造请求参数列表
$keysArr = array(
"response_type" => "code",
"client_id" => $appid,
"redirect_uri" => $callback,
"state" => $state,
"scope" => $scope
);
$login_url = $this->combineURL(self::GET_AUTH_CODE_URL, $keysArr);
header("Location:$login_url");
}
public function qq_callback(){
$state = $_SESSION[self::QQ_LOGIN_STATE];//登录前的保存,现在验证和之前的用户是不是同一个
//--------验证state防止CSRF攻击
if($_GET['state'] != $state){
//TODO error
echo "state not equal , you are CSRF attacted";
}
//-------请求参数列表
$keysArr = array(
"grant_type" => "authorization_code",
"client_id" => $this->QQ_CONNECT_CONFIG["appid"],
"redirect_uri" => urlencode($this->QQ_CONNECT_CONFIG["callback"]),
"client_secret" => $this->QQ_CONNECT_CONFIG["appkey"],
"code" => $_GET['code']
);
//------构造请求access_token的url
$token_url = $this->combineURL(self::GET_ACCESS_TOKEN_URL, $keysArr);
$response = http_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)){
//
echo "get access token error\r\n";
print_r($msg->error);
}
}
//TODO 断言 超时访问的情况,没有access token
$params = array();
parse_str($response, $params);
return $params["access_token"];
}
public function get_openid($accesstoken){
//-------请求参数列表
$keysArr = array(
"access_token" => $accesstoken
);
$graph_url = $this->combineURL(self::GET_OPENID_URL, $keysArr);
$response = http_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)){
//TODO error;
echo "get openid error";
}
return $user->openid;
}
/**
* combineURL
* 拼接url
* @param string $baseURL 基于的url
* @param array $keysArr 参数列表数组
* @return string 返回拼接的url
*/
private function combineURL($baseURL,$keysArr){
$combined = $baseURL."?";
$valueArr = array();
foreach($keysArr as $key => $val){
$valueArr[] = "$key=$val";
}
$keyStr = implode("&",$valueArr);
$combined .= ($keyStr);
return $combined;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment