审查视图

simplewind/cmf/lib/Oauth2.php 7.0 KB
董瑞恩 authored
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265
<?php

namespace cmf\lib;
// +----------------------------------------------------------------------
// | TOPThink [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2010 http://topthink.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi.cn@gmail.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------
// | ThinkOauth.class.php 2013-02-25
// +----------------------------------------------------------------------
// | 老猫 <catman@bronet.cn> 规范代码和用法
// +----------------------------------------------------------------------

abstract class Oauth2
{
    /**
     * oauth版本
     * @var string
     */
    protected $version = '2.0';

    /**
     * 申请应用时分配的app_key
     * @var string
     */
    protected $appKey = '';

    /**
     * 申请应用时分配的 app_secret
     * @var string
     */
    protected $appSecret = '';

    /**
     * 授权类型 response_type 目前只能为code
     * @var string
     */
    protected $responseType = 'code';

    /**
     * grant_type 目前只能为 authorization_code
     * @var string
     */
    protected $grantType = 'authorization_code';

    /**
     * 回调页面URL  可以通过配置文件配置
     * @var string
     */
    protected $callback = '';

    /**
     * 获取request_code的额外参数 URL查询字符串格式
     * @var string
     */
    protected $authorize = '';

    /**
     * 获取request_code请求的URL
     * @var string
     */
    protected $getRequestCodeURL = '';

    /**
     * 获取access_token请求的URL
     * @var string
     */
    protected $getAccessTokenURL = '';

    /**
     * API根路径
     * @var string
     */
    protected $apiBase = '';

    /**
     * 授权后获取到的TOKEN信息
     * @var array
     */
    protected $token = null;

    /**
     * 初始化配置
     */
    private function config()
    {
//        $config = C("THINK_SDK_{$this->Type}");
//        if (!empty($config['AUTHORIZE']))
//            $this->authorize = $config['AUTHORIZE'];
//        if (!empty($config['CALLBACK']))
//            $this->callback = $config['CALLBACK'];
//        else
//            throw new Exception('请配置回调页面地址');
    }

    /**
     * @param string $appKey
     */
    public function setAppKey(string $appKey)
    {
        $this->appKey = $appKey;
    }

    /**
     * @param string $callback
     */
    public function setCallback(string $callback)
    {
        $this->callback = $callback;
    }


    /**
     * @param string $appSecret
     */
    public function setAppSecret(string $appSecret)
    {
        $this->appSecret = $appSecret;
    }


    /**
     * 请求code
     */
    public function getRequestCodeURL()
    {
        $this->config();
        //Oauth 标准参数
        $params = [
            'client_id'     => $this->appKey,
            'redirect_uri'  => $this->callback,
            'response_type' => $this->responseType,
        ];

        //获取额外参数
        if ($this->authorize) {
            parse_str($this->authorize, $_param);
            if (is_array($_param)) {
                $params = array_merge($params, $_param);
            } else {
                throw new \Exception('AUTHORIZE配置不正确!');
            }
        }
        return $this->getRequestCodeURL . '?' . http_build_query($params);
    }

    /**
     * 获取access_token
     * @param string $code 上一步请求到的code
     * @param null $extend
     * @return array
     */
    public function getAccessToken($code, $extend = null)
    {
        $this->config();
        $params = [
            'client_id'     => $this->appKey,
            'client_secret' => $this->appSecret,
            'grant_type'    => $this->grantType,
            'code'          => $code,
            'redirect_uri'  => $this->callback,
        ];

        $data        = $this->http($this->getAccessTokenURL, $params, 'POST');
        $this->token = $this->parseToken($data, $extend);
        return $this->token;
    }

    /**
     * 合并默认参数和额外参数
     * @param array $params 默认参数
     * @param array /string $param 额外参数
     * @return array:
     */
    protected function param($params, $param)
    {
        if (is_string($param))
            parse_str($param, $param);
        return array_merge($params, $param);
    }

    /**
     * 获取指定API请求的URL
     * @param  string $api API名称
     * @param  string $fix api后缀
     * @return string      请求的完整URL
     */
    protected function url($api, $fix = '')
    {
        return $this->apiBase . $api . $fix;
    }

    /**
     * /**
     * 发送HTTP请求方法,目前只支持CURL发送请求
     * @param string $url 请求URL
     * @param array $params 请求参数
     * @param string $method 请求方法GET/POST
     * @param array $header
     * @param bool $multi
     * @return array  $data   响应数据
     * @throws \Exception
     */
    protected function http($url, $params, $method = 'GET', $header = [], $multi = false)
    {
        $opts = [
            CURLOPT_TIMEOUT        => 30,
            CURLOPT_RETURNTRANSFER => 1,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_SSL_VERIFYHOST => false,
            CURLOPT_HTTPHEADER     => $header
        ];

        /* 根据请求类型设置特定参数 */
        switch (strtoupper($method)) {
            case 'GET':
                $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
                break;
            case 'POST':
                //判断是否传输文件
                $params                   = $multi ? $params : http_build_query($params);
                $opts[CURLOPT_URL]        = $url;
                $opts[CURLOPT_POST]       = 1;
                $opts[CURLOPT_POSTFIELDS] = $params;
                break;
            default:
                throw new \Exception('不支持的请求方式!');
        }

        /* 初始化并执行curl请求 */
        $ch = curl_init();
        curl_setopt_array($ch, $opts);
        $data  = curl_exec($ch);
        $error = curl_error($ch);
        curl_close($ch);
        if ($error) throw new \Exception('请求发生错误:' . $error);
        return $data;
    }

    /**
     * 组装接口调用参数 并调用接口
     * @param $api
     * @param string $param
     * @param string $method
     * @param bool $multi
     * @return mixed
     */
    abstract protected function call($api, $param = '', $method = 'GET', $multi = false);

    /**
     * 解析access_token方法请求后的返回值
     * @param $result
     * @param $extend
     */
    abstract protected function parseToken($result, $extend);

    /**
     * 获取当前授权用户的SNS标识
     */
    abstract public function openid();
}