Qq::openid()   A
last analyzed

Complexity

Conditions 6
Paths 7

Size

Total Lines 17
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

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