Passed
Push — master ( a4cd82...350c7c )
by ma
01:57
created

Xiaomi   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 156
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 75
c 1
b 0
f 0
dl 0
loc 156
rs 10
wmc 18

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getGender() 0 7 1
A openid() 0 4 1
A refreshToken() 0 17 2
A userInfo() 0 15 1
A getRedirectUrl() 0 12 2
A getToken() 0 13 3
A parseToken() 0 7 2
A validateAccessToken() 0 13 3
A getUserInfo() 0 16 3
1
<?php
2
/**
3
 * 小米开放平台 https://dev.mi.com/console/doc/detail?pId=711
4
 * api接口文档: https://dev.mi.com/console/doc/detail?pId=707
5
 */
6
namespace tinymeng\OAuth2\Gateways;
7
8
use tinymeng\OAuth2\Connector\Gateway;
9
use tinymeng\OAuth2\Exception\OAuthException;
10
use tinymeng\OAuth2\Helper\ConstCode;
11
12
class Xiaomi extends Gateway
13
{
14
    const API_BASE = 'https://open.account.xiaomi.com/';
15
    protected $AuthorizeURL = 'https://account.xiaomi.com/oauth2/authorize';
16
    protected $AccessTokenURL = 'https://account.xiaomi.com/oauth2/token';
17
    protected $UserInfoURL = 'https://open.account.xiaomi.com/user/profile';
18
19
    /**
20
     * 得到跳转地址
21
     */
22
    public function getRedirectUrl()
23
    {
24
        $this->saveState();
25
        $params = [
26
            'client_id'     => $this->config['app_id'],
27
            'redirect_uri'  => $this->config['callback'],
28
            'response_type' => $this->config['response_type'],
29
            'scope'         => $this->config['scope'] ?: 'profile',
30
            'state'         => $this->config['state'],
31
            'skip_confirm'  => 1,
32
        ];
33
        return $this->AuthorizeURL . '?' . http_build_query($params);
34
    }
35
36
    /**
37
     * 获取当前授权用户的openid标识
38
     */
39
    public function openid()
40
    {
41
        $this->getToken();
42
        return $this->token['user_id'] ?? '';
43
    }
44
45
    /**
46
     * 获取格式化后的用户信息
47
     */
48
    public function userInfo()
49
    {
50
        $result = $this->getUserInfo();
51
        
52
        $userInfo = [
53
            'open_id'      => $this->openid(),
54
            'union_id'     => $this->token['user_id'] ?? '',
55
            'channel'      => ConstCode::TYPE_XIAOMI,
56
            'nickname'     => $result['miliaoNick'] ?? '',
57
            'gender'       => $this->getGender($result['sex'] ?? ''),
58
            'avatar'       => $result['miliaoIcon'] ?? '',
59
            'access_token' => $this->token['access_token'] ?? '',
60
            'native'       => $result
61
        ];
62
        return $userInfo;
63
    }
64
65
    /**
66
     * 获取原始接口返回的用户信息
67
     */
68
    public function getUserInfo()
69
    {
70
        $this->getToken();
71
        
72
        $params = [
73
            'clientId'     => $this->config['app_id'],
74
            'token'        => $this->token['access_token'],
75
        ];
76
        
77
        $data = $this->get($this->UserInfoURL, $params);
78
        $data = json_decode($data, true);
79
        
80
        if (!isset($data['result']) || $data['result'] !== 'ok') {
81
            throw new OAuthException('获取小米用户信息失败:' . json_encode($data));
82
        }
83
        return $data['data'];
84
    }
85
86
    /**
87
     * 获取access_token
88
     */
89
    protected function getToken()
90
    {
91
        if (empty($this->token)) {
92
            $this->checkState();
93
            $params = [
94
                'client_id'     => $this->config['app_id'],
95
                'client_secret' => $this->config['app_secret'],
96
                'grant_type'    => $this->config['grant_type'],
97
                'code'          => isset($_REQUEST['code']) ? $_REQUEST['code'] : '',
98
                'redirect_uri'  => $this->config['callback'],
99
            ];
100
            $response = $this->post($this->AccessTokenURL, $params);
101
            $this->token = $this->parseToken($response);
102
        }
103
    }
104
105
    /**
106
     * 解析token
107
     */
108
    protected function parseToken($token)
109
    {
110
        $data = json_decode($token, true);
111
        if (isset($data['access_token'])) {
112
            return $data;
113
        }
114
        throw new OAuthException('获取小米 access_token 出错:' . json_encode($data));
115
    }
116
117
    /**
118
     * 获取性别
119
     */
120
    private function getGender($gender)
121
    {
122
        $map = [
123
            '1' => ConstCode::GENDER_MAN,
124
            '0' => ConstCode::GENDER_WOMEN,
125
        ];
126
        return $map[$gender] ?? ConstCode::GENDER;
127
    }
128
129
    /**
130
     * 检验授权凭证AccessToken是否有效
131
     */
132
    public function validateAccessToken($accessToken = null)
133
    {
134
        try {
135
            $accessToken = $accessToken ?? $this->token['access_token'];
136
            $params = [
137
                'clientId' => $this->config['app_id'],
138
                'token'    => $accessToken,
139
            ];
140
            $data = $this->get($this->UserInfoURL, $params);
141
            $data = json_decode($data, true);
142
            return isset($data['result']) && $data['result'] === 'ok';
143
        } catch (\Exception $e) {
144
            return false;
145
        }
146
    }
147
148
    /**
149
     * 刷新AccessToken续期
150
     */
151
    public function refreshToken($refreshToken)
152
    {
153
        $params = [
154
            'client_id'     => $this->config['app_id'],
155
            'client_secret' => $this->config['app_secret'],
156
            'grant_type'    => 'refresh_token',
157
            'refresh_token' => $refreshToken,
158
        ];
159
        
160
        $token = $this->post($this->AccessTokenURL, $params);
161
        $token = $this->parseToken($token);
162
        
163
        if (isset($token['access_token'])) {
164
            $this->token = $token;
165
            return true;
166
        }
167
        return false;
168
    }
169
}