Client.class.php 8.41 KB
<?php
defined('SITE_API') || define('SITE_API', 'http://api.yoho.cn');
/**
 * YOHO OAuth2认证使用类
 * 
 * @name Lib_Oauth_Yoho_Client
 * @package lib/oauth/yoho
 * @version 1.0 (2013-04-24 17:29:16)
 * @author fei.hong <fei.hong@yoho.cn>
 */
class Lib_Oauth_Yoho_Client
{
    public static $clientId = null; // 唯一的应用APPID
    public static $clientSecret = null; // 应用APPID对应的密钥

    /**
     * 获取服务端授权地址
     * 
     * @return string
     */
    private static function genAuthorizeUrl()
    {
        return SITE_API . '/api/oauth2/authorize';
    }
    
    /**
     * 获取服务端授权后可访问token的地址
     * 
     * @return string
     */
    private static function genAccessTokenUrl()
    {
        return SITE_API . '/api/oauth2/token';
    }
    
    /**
     * 获取用户身份信息的接口地址
     * 
     * @return string
     */
    private static function genOpenidUrl()
    {
        return SITE_API . '/api/user/info.json';
    }
    
    /**
     * 初始化
     * 
     * @param integer $clientId (申请应用时分配的AppID)
     * @param string $clientSecret (应用分配的AppID对应的密钥, [亲,请保密哦])
     * @return void
     */
    public static function init($clientId, $clientSecret)
    {
        if ($clientId !== null && $clientSecret !== null)
        {
            self::$clientId = $clientId;
            self::$clientSecret = $clientSecret;
        }
    }

    /**
     * 获取授权的URL
     * 
     * @param string $redirectUri (授权成功后的回调页面地址,即第三方应用的url地址)
     * @param string $responseType (授权类型,默认为code. [非必须])
     * @param string $display (授权页面的终端类型[default, pc, mobile], 默认为default [非必须])
     * @return string
     */
    public static function getAuthorizeURL($redirectUri, $responseType = 'code', $display = 'pc')
    {
        // 随机生成唯一串防CSRF攻击
        $state = md5(uniqid(rand(), true));
        $params = array(
            'client_id' => self::$clientId,
            'redirect_uri' => $redirectUri,
            'response_type' => $responseType,
            'state' => $state,
            'display' => $display,
        );
        return self::genAuthorizeUrl() . '?' . http_build_query($params);
    }

    /**
     * 授权并获取访问token
     * 
     * @param string $code (请求授权时返回的code)
     * @param string $refreshToken (刷新token)
     * @param string $redirectUri (授权的回调地址,必须和请求code时的redirect_uri一致)
     * @param string $grantType (支持authorization_code 或 refresh_token)
     * @return array
     */
    public static function getAccessToken($redirectUri = '', $grantType = 'authorization_code', $code = null, $refreshToken = null)
    {
        $params = array(
    		'client_id' => self::$clientId, 'client_secret' => self::$clientSecret,
            'redirect_uri' => $redirectUri, 'grant_type' => $grantType,
        );
        switch ($grantType)
        {
            case 'refresh_token':
                $params['refresh_token'] = $refreshToken;
                break;
            case 'authorization_code':
            default:
                $params['code'] = $code;
                break;
        }
        $response = Http::request(self::genAccessTokenUrl(), $params, 'POST', false, array());
        return ($response !== false) ? json_decode($response, true) : false;
    }
    
    /**
     * 根据access_token获得对应用户身份的openid
     * 
     * @param string $accessToken (授权成功后返回的access_token)
     * @throws Exception
     * @return integer | null
     */
    public static function getOpenid($accessToken)
    {
        $params = array('oauth_token' => $accessToken,);
        $response = Http::request(self::genOpenidUrl(), $params, 'GET', false, array());
        if ($response !== false)
        {
            $response = json_decode($response, true);
            if (isset($response['data']) && isset($response['data']['uid']))
            {
                return $response['data']['uid'];
            }
        }
        return null;
    }
    
}


/**
 * HTTP请求类
 */
class Http
{
    private static $_debug = false;
    private static $_boundary = '';
    
    /**
     * 发起一个HTTP/HTTPS的请求
     * 
     * @param $url (接口的URL) 
     * @param $params (接口参数)
     * @param $method (请求类型 GET|POST)
     * @param $multi (图片信息)
     * @param $headers (扩展的包头信息)
     * @return string
     */
    public static function request($url, $params = array(), $method = 'GET' , $multi = false, $headers = array())
    {
        if (! function_exists('curl_init'))
        { 
            exit('PHP Need to open the curl extension!');
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_USERAGENT, 'YOHO PHP-SDK OAuth2.0');
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($ch, CURLOPT_TIMEOUT, 3);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $headers[] = "API-RemoteIP: " . $_SERVER['REMOTE_ADDR'];
        switch (strtoupper($method))
        {
            case 'POST':
                curl_setopt($ch, CURLOPT_POST, 1);
                if (! empty($params))
                {
                    if (! $multi)
                    {
                        $headers[]= 'Content-Type: application/x-www-form-urlencoded';
                        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params, null, '&'));
                    }
                    else
                    {
                        foreach ($multi as $key => $file)
                        {
                        	$params[$key] = '@' . $file;
                        }
                        $headers[] = 'Expect: ';
                        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
                    }
                }
                break;
            case 'DELETE':
                curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
                if (! empty($params))
                {
                	$url = $url . (strpos($url, '?') ? '&' : '?')
                	. (is_array($params) ? http_build_query($params) : $params);
                }
                break;
            case 'GET':
                if (! empty($params))
                {
                	$url = $url . (strpos($url, '?') ? '&' : '?')
                	. (is_array($params) ? http_build_query($params, null, '&') : $params);
                }
                if (ini_get("allow_url_fopen") == "1") 
                {
                	$response = file_get_contents($url);
                	return $response;
                }
                break;
        }
        curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_URL, $url);
        $response = curl_exec($ch);
        if (self::$_debug)
        {
            var_dump($response);
        }
        curl_close($ch);
        return $response;
    }
    
    /**
     * 构建表单提交的数据
     * 
     * @ignore
     */
    private static function buildQuery($params) 
    {
    	if (! $params || ! is_array($params)) 
    	{
    	    return '';
    	}
    
    	uksort($params, 'strcmp');
    
    	self::$_boundary = $boundary = uniqid('------------------');
    	$MPboundary = '--'.$boundary;
    	$endMPboundary = $MPboundary. '--';
    	$multipartbody = '';
    
    	foreach ($params as $parameter => $value) 
    	{
    		if (in_array($parameter, array('pic', 'image')) && $value{0} == '@') 
    		{
    			$url = ltrim($value, '@');
    			$content = file_get_contents($url);
    			$array = explode('?', basename($url));
    			$filename = $array[0];
    
    			$multipartbody .= $MPboundary . "\r\n";
    			$multipartbody .= 'Content-Disposition: form-data; name="' . $parameter . '"; filename="' . $filename . '"'. "\r\n";
    			$multipartbody .= "Content-Type: image/unknown\r\n\r\n";
    			$multipartbody .= $content . "\r\n";
    		} 
    		else 
    		{
    			$multipartbody .= $MPboundary . "\r\n";
    			$multipartbody .= 'Content-Disposition: form-data; name="' . $parameter . "\"\r\n\r\n";
    			$multipartbody .= $value . "\r\n";
    		}
    	}
    
    	$multipartbody .= $endMPboundary;
    	return $multipartbody;
    }
    
}