Passed
Push — master ( 7a3599...ffbf7e )
by ma
02:12
created

Gateway   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 278
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 31
eloc 68
dl 0
loc 278
rs 9.92
c 2
b 0
f 1

14 Methods

Rating   Name   Duplication   Size   Complexity  
A setDisplay() 0 4 1
A setToken() 0 3 1
A mustCheckState() 0 3 1
A get() 0 3 1
A checkState() 0 7 6
A getConfig() 0 2 1
A setType() 0 4 1
B __construct() 0 25 7
A getCode() 0 2 2
A getToken() 0 12 2
A accessTokenParams() 0 9 1
A saveState() 0 11 4
A getGender() 0 2 2
A post() 0 4 1
1
<?php
2
namespace tinymeng\OAuth2\Connector;
3
4
use tinymeng\OAuth2\Helper\ConstCode;
5
use tinymeng\OAuth2\Helper\Str;
6
7
/**
8
 * 所有第三方登录必须继承的抽象类
9
 */
10
abstract class Gateway implements GatewayInterface
11
{
12
    /**
13
     * 配置参数
14
     * @var array
15
     */
16
    protected $config;
17
18
    /**
19
     * AppId
20
     * @var array
21
     */
22
    protected $app_id;
23
24
    /**
25
     * AppSecret
26
     * @var string
27
     */
28
    protected $app_secret;
29
30
    /**
31
     * 接口权限值
32
     * @var
33
     */
34
    protected $scope;
35
36
    /**
37
     * 回调地址
38
     * @var string
39
     */
40
    protected $callback;
41
42
    /**
43
     * 当前时间戳
44
     * @var int
45
     */
46
    protected $timestamp;
47
48
    /**
49
     * 默认第三方授权页面样式
50
     * @var string
51
     */
52
    protected $display = 'default';
53
54
    /**
55
     * 登录类型:app applets
56
     * @var bool
57
     */
58
    protected $type;
59
60
    /**
61
     * 第三方Token信息
62
     * @var array
63
     */
64
    protected $token = null;
65
66
    /**
67
     * 是否验证回跳地址中的state参数
68
     * @var boolean
69
     */
70
    protected $checkState = false;
71
72
    /**
73
     * 第三方返回的userInfo
74
     * @var array
75
     */
76
    protected $userInfo = [];
77
78
    /**
79
     * 格式化的userInfo
80
     * @var array
81
     */
82
    protected $formatUserInfo = [];
83
84
    /**
85
     * Gateway constructor.
86
     * @param $config
87
     * @throws \Exception
88
     */
89
    public function __construct($config)
90
    {
91
        if (!$config) {
92
            throw new \Exception('传入的配置不能为空');
93
        }
94
        if(isset($_GET['referer']) && $config['callback']){
95
            $config['callback'] .= ((strpos($config['callback'], '?') !== false) ? '&' : '?').'referer='.$_GET['referer'];
96
        }
97
        //默认参数
98
        $_config = [
99
            'app_id'        => '',
100
            'app_secret'    => '',
101
            'callback'      => '',
102
            'response_type' => 'code',
103
            'grant_type'    => 'authorization_code',
104
            'proxy'         => '',
105
            'state'         => '',
106
            'type'          => '',
107
            'is_sandbox'    => false,//是否是沙箱环境
108
        ];
109
        $this->config    = array_merge($_config, $config);
110
        foreach($this->config as $key=>$val){
111
            if(property_exists($this,$key)) $this->$key=$val;
112
        }
113
        $this->timestamp = time();
114
    }
115
116
    /**
117
     * Description:  设置授权页面样式
118
     * @author: JiaMeng <[email protected]>
119
     * Updater:
120
     * @param $display
121
     * @return $this
122
     */
123
    public function setDisplay($display)
124
    {
125
        $this->display = $display;
126
        return $this;
127
    }
128
129
    /**
130
     * Description:  设置是否是App
131
     * @author: JiaMeng <[email protected]>
132
     * Updater:
133
     * @return $this
134
     */
135
    public function setType($type)
136
    {
137
        $this->type = $type;
138
        return $this;
139
    }
140
141
    /**
142
     * Description:  强制验证回跳地址中的state参数
143
     * @author: JiaMeng <[email protected]>
144
     * Updater:
145
     * @return $this
146
     */
147
    public function mustCheckState(){
148
        $this->checkState = true;
149
        return $this;
150
    }
151
152
    /**
153
     * 获取配置信息
154
     * @Author: TinyMeng <[email protected]>
155
     * @return array
156
     */
157
    public function getConfig(){
158
        return $this->config;
159
    }
160
161
    /**
162
     * 设置token(App登录时)
163
     * @param $token
164
     * @return $this
165
     */
166
    public function setToken($token){
167
        $this->token = $token;
168
        return $this;
169
    }
170
171
    /**
172
     * 存储state
173
     * @Author: TinyMeng <[email protected]>
174
     */
175
    public function saveState(){
176
        if ($this->checkState === true) {
177
            //是否开启session
178
            if (session_status() !== PHP_SESSION_ACTIVE) {
179
                session_start();
180
            }
181
            if(empty($this->config['state'])){
182
                $this->config['state'] = Str::random();//生成随机state
183
            }
184
            //存储到session
185
            $_SESSION['tinymeng_oauth_state'] = $this->config['state'];
186
        }
187
    }
188
189
    /**
190
     * 验证state
191
     * @Author: TinyMeng <[email protected]>
192
     * @throws \Exception
193
     */
194
    public function checkState(){
195
        if ($this->checkState === true) {
196
            if (session_status() !== PHP_SESSION_ACTIVE) {
197
                session_start();
198
            }
199
            if (!isset($_REQUEST['state']) || !isset($_SESSION['tinymeng_oauth_state']) || $_REQUEST['state'] != $_SESSION['tinymeng_oauth_state']) {
200
                throw new \Exception('传递的STATE参数不匹配!');
201
            }
202
        }
203
    }
204
205
206
    /**
207
     * 获取授权后的Code
208
     * @author: JiaMeng <[email protected]>
209
     * @return string
210
     */
211
    public function getCode(){
212
        return isset($_REQUEST['code']) ? $_REQUEST['code'] : '';
213
    }
214
215
    /**
216
     * Description:  默认获取AccessToken请求参数
217
     * @author: JiaMeng <[email protected]>
218
     * Updater:
219
     * @return array
220
     */
221
    protected function accessTokenParams(){
222
        $params = [
223
            'client_id'     => $this->config['app_id'],
224
            'client_secret' => $this->config['app_secret'],
225
            'grant_type'    => $this->config['grant_type'],
226
            'code'          => $this->getCode(),
227
            'redirect_uri'  => $this->config['callback'],
228
        ];
229
        return $params;
230
    }
231
232
    /**
233
     * Description:  获取AccessToken
234
     * @author: JiaMeng <[email protected]>
235
     * Updater:
236
     */
237
    protected function getToken(){
238
        if (empty($this->token)) {
239
            /** 验证state参数 */
240
            $this->checkState();
241
242
            /** 获取参数 */
243
            $params = $this->accessTokenParams();
244
245
            /** 获取access_token */
246
            $token =  $this->POST($this->AccessTokenURL, $params);
247
            /** 解析token值(子类实现此方法) */
248
            $this->token = $this->parseToken($token);
0 ignored issues
show
Bug introduced by
The method parseToken() does not exist on tinymeng\OAuth2\Connector\Gateway. Since it exists in all sub-types, consider adding an abstract or default implementation to tinymeng\OAuth2\Connector\Gateway. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

248
            /** @scrutinizer ignore-call */ 
249
            $this->token = $this->parseToken($token);
Loading history...
249
        }
250
    }
251
252
    /**
253
     * Description:  执行GET请求操作
254
     * @author: JiaMeng <[email protected]>
255
     * Updater:
256
     * @param $url
257
     * @param array $params
258
     * @param array $headers
259
     * @return string
260
     */
261
    protected function get($url, $params = [], $headers = [])
262
    {
263
        return \tinymeng\tools\HttpRequest::httpGet($url, $params,$headers);
264
    }
265
266
    /**
267
     * Description:  执行POST请求操作
268
     * @author: JiaMeng <[email protected]>
269
     * Updater:
270
     * @param $url
271
     * @param array $params
272
     * @param array $headers
273
     * @return mixed
274
     */
275
    protected function post($url, $params = [], $headers = [])
276
    {
277
        $headers[] = 'Accept: application/json';//GitHub需要的header
278
        return \tinymeng\tools\HttpRequest::httpPost($url, $params,$headers);
279
    }
280
281
    /**
282
     * 格式化性别参数
283
     * M代表男性,F代表女性
284
     * @param $gender
285
     */
286
    public function getGender($gender){
287
        return strtolower(substr($gender , 0 , 1)) == 'm' ? ConstCode::GENDER_MAN : ConstCode::GENDER_WOMEN;
288
    }
289
}
290