Passed
Push — master ( ffbf7e...4ee940 )
by ma
01:42
created

Qq   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 185
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 24
eloc 72
dl 0
loc 185
rs 10
c 1
b 0
f 0

8 Methods

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