Passed
Push — master ( 273c7d...4c8747 )
by ma
02:37
created

Twitter   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 65
dl 0
loc 189
rs 10
c 2
b 0
f 1
wmc 17

12 Methods

Rating   Name   Duplication   Size   Complexity  
A signature() 0 8 1
A getRedirectUrl() 0 7 1
A getAuthorizationHeader() 0 7 2
A refreshToken() 0 4 1
A getAccessToken() 0 3 1
A getOAuthParams() 0 11 1
A validateAccessToken() 0 9 2
A getUserInfo() 0 12 3
A userInfo() 0 15 1
A parseToken() 0 2 1
A call() 0 18 2
A openid() 0 4 1
1
<?php
2
3
namespace tinymeng\OAuth2\Gateways;
4
5
use tinymeng\OAuth2\Connector\Gateway;
6
use tinymeng\OAuth2\Exception\OAuthException;
7
use tinymeng\OAuth2\Helper\ConstCode;
8
use tinymeng\OAuth2\Helper\Str;
9
10
/**
11
 * Class Twitter
12
 * @package tinymeng\OAuth2\Gateways
13
 * @Author: TinyMeng <[email protected]>
14
 * @Created: 2018/11/9
15
 */
16
class Twitter extends Gateway
17
{
18
    const API_BASE = 'https://api.twitter.com/';
19
20
    private $tokenSecret = '';
21
22
    /**
23
     * 得到跳转地址
24
     */
25
    public function getRedirectUrl()
26
    {
27
        //存储state
28
        $this->saveState();
29
        //登录参数
30
        $oauthToken = $this->call('oauth/request_token', ['oauth_callback' => $this->config['callback']], 'POST');
31
        return self::API_BASE . 'oauth/authenticate?oauth_token=' . $oauthToken['oauth_token'];
32
    }
33
34
    /**
35
     * 获取当前授权用户的openid标识
36
     */
37
    public function openid()
38
    {
39
        $data = $this->getUserInfo();
40
        return $data['id_str'];
41
    }
42
43
    /**
44
     * 获取格式化后的用户信息
45
     */
46
    public function userInfo()
47
    {
48
        $result = $this->getUserInfo();
49
50
        $userInfo = [
51
            'open_id'  => $result['id_str'],
52
            'access_token'=> $this->token['oauth_token_secret'] ?? '',
53
            'union_id'=> $result['id_str'],
54
            'channel' => ConstCode::TYPE_TWITTER,
55
            'nickname'    => $result['name'],
56
            'gender'  => ConstCode::GENDER, //twitter不返回用户性别
57
            'avatar'  => $result['profile_image_url_https'],
58
            'native'  => $result,
59
        ];
60
        return $userInfo;
61
    }
62
63
    /**
64
     * 获取原始接口返回的用户信息
65
     */
66
    public function getUserInfo()
67
    {
68
        if (empty($this->token)) {
69
            $this->token = $this->getAccessToken();
70
            if (isset($this->token['oauth_token_secret'])) {
71
                $this->tokenSecret = $this->token['oauth_token_secret'];
72
            } else {
73
                throw new OAuthException("获取Twitter ACCESS_TOKEN 出错:" . json_encode($this->token));
74
            }
75
        }
76
77
        return $this->call('1.1/account/verify_credentials.json', $this->token, 'GET', true);
78
    }
79
80
    /**
81
     * 发起请求
82
     *
83
     * @param string $api
84
     * @param array $params
85
     * @param string $method
86
     * @return array
87
     */
88
    private function call($api, $params = [], $method = 'GET', $isJson = false)
89
    {
90
        $method  = strtoupper($method);
91
        $request = [
92
            'method' => $method,
93
            'uri'    => self::API_BASE . $api,
94
        ];
95
        $oauthParams                    = $this->getOAuthParams($params);
96
        $oauthParams['oauth_signature'] = $this->signature($request, $oauthParams);
97
98
        $headers = ['Authorization' => $this->getAuthorizationHeader($oauthParams)];
99
100
        $data = $this->$method($request['uri'], $params, $headers);
101
        if ($isJson) {
102
            return json_decode($data, true);
103
        }
104
        parse_str($data, $data);
105
        return $data;
106
    }
107
108
    /**
109
     * 获取oauth参数
110
     *
111
     * @param array $params
112
     * @return array
113
     */
114
    private function getOAuthParams($params = [])
115
    {
116
        $_default = [
117
            'oauth_consumer_key'     => $this->config['app_id'],
118
            'oauth_nonce'            => Str::random(),
119
            'oauth_signature_method' => 'HMAC-SHA1',
120
            'oauth_timestamp'        => $this->timestamp,
121
            'oauth_token'            => '',
122
            'oauth_version'          => '1.0',
123
        ];
124
        return array_merge($_default, $params);
125
    }
126
127
    /**
128
     * 签名操作
129
     *
130
     * @param array $request
131
     * @param array $params
132
     * @return string
133
     */
134
    private function signature($request, $params = [])
135
    {
136
        ksort($params);
137
        $sign_str = Str::buildParams($params, true);
138
        $sign_str = $request['method'] . '&' . rawurlencode($request['uri']) . '&' . rawurlencode($sign_str);
139
        $sign_key = $this->config['app_secret'] . '&' . $this->tokenSecret;
140
141
        return rawurlencode(base64_encode(hash_hmac('sha1', $sign_str, $sign_key, true)));
142
    }
143
144
    /**
145
     * 获取请求附带的Header头信息
146
     *
147
     * @param array $params
148
     * @return string
149
     */
150
    private function getAuthorizationHeader($params)
151
    {
152
        $return = 'OAuth ';
153
        foreach ($params as $k => $param) {
154
            $return .= $k . '="' . $param . '", ';
155
        }
156
        return rtrim($return, ', ');
157
    }
158
159
160
    /**
161
     * Description:  getAccessToken
162
     * @author: JiaMeng <[email protected]>
163
     * Updater:
164
     * @return array
165
     */
166
    protected function getAccessToken()
167
    {
168
        return $this->call('oauth/access_token', $_GET, 'POST');
169
    }
170
171
    /**
172
     * 解析access_token方法请求后的返回值
173
     * @param string $token 获取access_token的方法的返回值
174
     */
175
    protected function parseToken($token){
176
        return $token;
177
    }
178
179
    /**
180
     * 检验授权凭证AccessToken是否有效
181
     * @param string $accessToken
182
     * @return bool
183
     */
184
    public function validateAccessToken($accessToken = null)
185
    {
186
        try {
187
            $accessToken = $accessToken ?? $this->token['oauth_token_secret'];
188
            $this->tokenSecret = $accessToken;
189
            $result = $this->call('1.1/account/verify_credentials.json', [], 'GET', true);
190
            return isset($result['id_str']);
191
        } catch (\Exception $e) {
192
            return false;
193
        }
194
    }
195
196
    /**
197
     * 刷新AccessToken续期
198
     * @param string $refreshToken
199
     * @return bool
200
     */
201
    public function refreshToken($refreshToken)
202
    {
203
        // Twitter OAuth 1.0a 不支持刷新令牌
204
        return false;
205
    }
206
}
207