Passed
Push — master ( 4ee940...caedb6 )
by ma
01:46
created

Qq::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 4
c 0
b 0
f 0
dl 0
loc 6
rs 10
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * QQ互联  https://connect.qq.com/index.html
4
 * api接口文档
5
 *      http://wiki.connect.qq.com/开发攻略_server-side
6
 * 注:
7
 *      1.如果要获取unionid,先去申请:http://wiki.connect.qq.com/开发者反馈
8
*/
9
namespace tinymeng\OAuth2\Gateways;
10
use tinymeng\OAuth2\Connector\Gateway;
11
use tinymeng\OAuth2\Helper\ConstCode;
12
13
/**
14
 * Class Qq
15
 * @package tinymeng\OAuth2\Gateways
16
 * @Author: TinyMeng <[email protected]>
17
 * @Created: 2018/11/9
18
 */
19
class Qq extends Gateway
20
{
21
    const API_BASE            = 'https://graph.qq.com/';
22
    protected $AuthorizeURL   = 'oauth2.0/authorize';
23
    protected $AccessTokenURL = 'oauth2.0/token';
24
    protected $UserInfoURL = 'user/get_user_info';
25
26
    /**
27
     * @param $config
28
     * @throws \Exception
29
     */
30
    public function __construct($config)
31
    {
32
        parent::__construct($config);
33
        $this->AuthorizeURL = static::API_BASE.$this->AuthorizeURL;
34
        $this->AccessTokenURL = static::API_BASE.$this->AccessTokenURL;
35
        $this->UserInfoURL = static::API_BASE.$this->UserInfoURL;
36
    }
37
38
    /**
39
     * Description:  得到跳转地址
40
     * @author: JiaMeng <[email protected]>
41
     * Updater:
42
     * @return string
43
     */
44
    public function getRedirectUrl()
45
    {
46
        //存储state
47
        $this->saveState();
48
        //登录参数
49
        $params = [
50
            'response_type' => $this->config['response_type'],
51
            'client_id'     => $this->config['app_id'],
52
            'redirect_uri'  => $this->config['callback'],
53
            'state'         => $this->config['state'],
54
            'scope'         => $this->config['scope'],
55
            'display'       => $this->display,
56
        ];
57
        return $this->AuthorizeURL . '?' . http_build_query($params);
58
    }
59
60
    /**
61
     * Description:  获取格式化后的用户信息
62
     * @return array
63
     * @throws \Exception
64
     * @author: JiaMeng <[email protected]>
65
     * Updater:
66
     */
67
    public function userInfo()
68
    {
69
        $result = $this->getUserInfo();
70
71
        $userInfo = [
72
            'open_id' => $this->openid(),
73
            'union_id'=> $this->token['unionid'] ?? '',
74
            'access_token'=> $this->token['access_token'] ?? '',
75
            'channel' => ConstCode::TYPE_QQ,
76
            'nickname'=> $result['nickname'],
77
            'gender'  => isset($result['gender']) ? $this->getGender($result['gender']) : ConstCode::GENDER,
78
            'avatar'  => $result['figureurl_qq_2'] ? $result['figureurl_qq_2'] : $result['figureurl_qq_1'],
79
            'birthday'=> date('Y-m-d',strtotime($result['year'])),
80
        ];
81
        return $userInfo;
82
    }
83
84
    /**
85
     * Description:  获取原始接口返回的用户信息
86
     * @return array
87
     * @throws \Exception
88
     * @author: JiaMeng <[email protected]>
89
     * Updater:
90
     */
91
    public function getUserInfo()
92
    {
93
        /** 获取用户信息 */
94
        $params = [
95
            'openid'=>$this->openid(),
96
            'oauth_consumer_key'=>$this->config['app_id'],
97
            'access_token'=>$this->token['access_token'],
98
            'format'=>'json',
99
        ];
100
        $data = $this->get($this->UserInfoURL, $params);
101
        return json_decode($data, true);
102
    }
103
104
    /**
105
     * Description:  获取当前授权用户的openid标识
106
     * @author: JiaMeng <[email protected]>
107
     * Updater:
108
     * @return mixed
109
     * @throws \Exception
110
     */
111
    public function openid()
112
    {
113
        if($this->type == 'app'){//App登录
114
            if(!isset($_REQUEST['access_token'])){
115
                throw new \Exception("腾讯QQ,APP登录 需要传输access_token参数! ");
116
            }
117
            $this->token['access_token'] = $_REQUEST['access_token'];
118
        }else{
119
            /** 获取token */
120
            $this->getToken();
121
        }
122
        if (!isset($this->token['openid']) || !$this->token['openid']) {
123
            $userID                 = $this->getOpenID();
124
            $this->token['openid']  = $userID['openid'];
125
            $this->token['unionid'] = isset($userID['unionid']) ? $userID['unionid'] : '';
126
        }
127
        return $this->token['openid'];
128
    }
129
130
    /**
131
     * Description:  解析access_token方法请求后的返回值
132
     * @author: JiaMeng <[email protected]>
133
     * Updater:
134
     * @param $token
135
     * @return mixed
136
     * @throws \Exception
137
     */
138
    protected function parseToken($token)
139
    {
140
        parse_str($token, $data);
141
        if (isset($data['access_token'])) {
142
            return $data;
143
        } else {
144
            throw new \Exception("获取腾讯QQ ACCESS_TOKEN 出错:" . $token);
145
        }
146
    }
147
148
    /**
149
     * Description:  通过接口获取openid
150
     * @author: JiaMeng <[email protected]>
151
     * Updater:
152
     * @return mixed|string
153
     * @throws \Exception
154
     */
155
    private function getOpenID(){
156
        $query = [
157
            'access_token' => $this->token['access_token']
158
        ];
159
        /** 如果要获取unionid,先去申请:http://wiki.connect.qq.com/开发者反馈 */
160
        if (isset($this->config['is_unioid']) && $this->config['is_unioid'] === true) {
161
            $query['unionid'] = 1;
162
        }
163
164
        $data = $this->get(self::API_BASE . 'oauth2.0/me',$query);
165
        $data     = json_decode(trim(substr($data, 9), " );\n"), true);
166
        if (isset($data['openid'])) {
167
            return $data;
168
        } else {
169
            throw new \Exception("获取用户openid出错:" . $data['error_description']);
170
        }
171
    }
172
173
    /**
174
     * 格式化性别参数
175
     * M代表男性,F代表女性
176
     * @param $gender
177
     */
178
    public function getGender($gender){
179
        return $gender == '男' ? ConstCode::GENDER_MAN : ConstCode::GENDER_WOMEN;
180
    }
181
182
183
    /**
184
     * 解密小程序 qq.getUserInfo() 敏感数据.
185
     *
186
     * @param string $encryptedData
187
     * @param string $iv
188
     * @param string $sessionKey
189
     *
190
     * @return array
191
     */
192
    public function descryptData($encryptedData, $iv, $sessionKey)
193
    {
194
        if (24 != strlen($sessionKey))
195
        {
196
            throw new \InvalidArgumentException('sessionKey 格式错误');
197
        }
198
        if (24 != strlen($iv))
199
        {
200
            throw new \InvalidArgumentException('iv 格式错误');
201
        }
202
        $aesKey = base64_decode($sessionKey);
203
        $aesIV = base64_decode($iv);
204
        $aesCipher = base64_decode($encryptedData);
205
        $result = openssl_decrypt($aesCipher, 'AES-128-CBC', $aesKey, 1, $aesIV);
206
        if (!$result)
207
        {
208
            throw new \InvalidArgumentException('解密失败');
209
        }
210
        $dataObj = json_decode($result, true);
211
        if (!$dataObj)
212
        {
213
            throw new \InvalidArgumentException('反序列化数据失败');
214
        }
215
216
        return $dataObj;
217
    }
218
219
}
220