1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace OpenOauth; |
4
|
|
|
|
5
|
|
|
use OpenOauth\Core\Core; |
6
|
|
|
use OpenOauth\Core\Http\Http; |
7
|
|
|
|
8
|
|
|
class Authorized extends Core |
9
|
|
|
{ |
10
|
|
|
const GET_API_QUERY_AUTH = 'https://api.weixin.qq.com/cgi-bin/component/api_query_auth'; //使用授权码换取公众号的接口调用凭据和授权信息 |
11
|
|
|
const GET_API_AUTHORIZER_TOKEN_URL = 'https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token'; //获取(刷新)授权公众号的接口调用凭据(令牌) |
12
|
|
|
|
13
|
|
|
/** |
14
|
|
|
* @param $redirect_path |
15
|
|
|
*/ |
16
|
|
|
public function getAuthHTML($redirect_path) |
17
|
|
|
{ |
18
|
|
|
$component_app_id = $this->configs->component_app_id; |
19
|
|
|
$pre_auth_code = $this->getComponentPreAuthCode(); |
20
|
|
|
$redirect_uri = $this->current() . $redirect_path; |
21
|
|
|
|
22
|
|
|
$editorSrc = <<<HTML |
23
|
|
|
<script language="JavaScript" type="text/javascript"> |
24
|
|
|
window.location.href="https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=$component_app_id&pre_auth_code=$pre_auth_code&redirect_uri=$redirect_uri"; |
25
|
|
|
</script> |
26
|
|
|
HTML; |
27
|
|
|
exit($editorSrc); |
|
|
|
|
28
|
|
|
} |
29
|
|
|
|
30
|
|
View Code Duplication |
public function current() |
|
|
|
|
31
|
|
|
{ |
32
|
|
|
$protocol = (!empty($_SERVER['HTTPS']) |
33
|
|
|
&& $_SERVER['HTTPS'] !== 'off' |
34
|
|
|
|| $_SERVER['SERVER_PORT'] === 443) ? 'https://' : 'http://'; |
35
|
|
|
|
36
|
|
|
if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) { |
37
|
|
|
$host = $_SERVER['HTTP_X_FORWARDED_HOST']; |
38
|
|
|
} else { |
39
|
|
|
$host = $_SERVER['HTTP_HOST']; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
return $protocol . $host . '/'; |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* 使用授权码换取公众号的接口调用凭据和授权信息 |
47
|
|
|
* |
48
|
|
|
* @param string $authorizer_app_id |
49
|
|
|
* |
50
|
|
|
* @return array|bool|null|string|void |
51
|
|
|
*/ |
52
|
|
|
public function getApiQueryAuth($authorizer_app_id = '') |
53
|
|
|
{ |
54
|
|
|
$time = time(); |
55
|
|
|
|
56
|
|
|
$authorization_info_key = 'authorized:' . $this->configs->component_app_id . ':' . $authorizer_app_id; |
57
|
|
|
$query_auth_key = 'query_auth:' . $this->configs->component_app_id . ':' . $authorizer_app_id; |
58
|
|
|
|
59
|
|
|
$query_auth_info = parent::$databaseDriver->_get($query_auth_key); |
60
|
|
|
//如果存在数据 |
61
|
|
|
if (!empty($query_auth_info)) { |
62
|
|
|
|
63
|
|
|
//没超时 返回数据 |
64
|
|
|
if ($query_auth_info['expired_time'] >= ($time + 1000) && $query_auth_info['authorization_state'] == 'authorized') { |
65
|
|
|
return $query_auth_info; |
66
|
|
|
} else { |
67
|
|
|
//如果超时了 获取新的 access_token 和 新的 刷新令牌 refresh_token |
68
|
|
|
$api_authorizer_token = $this->getApiAuthorizerToken($query_auth_info['authorization_info']['authorizer_appid'], $query_auth_info['authorization_info']['authorizer_refresh_token']); |
69
|
|
|
if (!empty($api_authorizer_token)) { |
70
|
|
|
$query_auth_info['authorization_info']['authorizer_access_token'] = $api_authorizer_token['authorizer_access_token']; |
71
|
|
|
$query_auth_info['authorization_info']['authorizer_refresh_token'] = $api_authorizer_token['authorizer_refresh_token']; |
72
|
|
|
$query_auth_info['authorization_info']['expires_in'] = $api_authorizer_token['expires_in']; |
73
|
|
|
$query_auth_info['expired_time'] = $time + $api_authorizer_token['expires_in']; |
74
|
|
|
$query_auth_info['authorization_state'] = 'authorized'; |
75
|
|
|
|
76
|
|
|
parent::$databaseDriver->_set($query_auth_key, $query_auth_info); |
77
|
|
|
|
78
|
|
|
return $query_auth_info; |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
$authorization_info = parent::$databaseDriver->_get($authorization_info_key); |
84
|
|
|
|
85
|
|
|
$query_data = http_build_query(['component_access_token' => $this->getComponentAccessToken()]); |
86
|
|
|
|
87
|
|
|
if ($authorization_info['AuthorizationCodeExpiredTime'] <= $time) { |
88
|
|
|
$this->setError('授权Code超时'); |
89
|
|
|
|
90
|
|
|
return false; |
91
|
|
|
} |
92
|
|
|
$request_data = [ |
93
|
|
|
'component_appid' => $authorization_info['AppId'], |
94
|
|
|
'authorization_code' => $authorization_info['AuthorizationCode'], |
95
|
|
|
]; |
96
|
|
|
|
97
|
|
|
$response_data = Http::_post(self::GET_API_QUERY_AUTH . '?' . $query_data, $request_data); |
98
|
|
|
|
99
|
|
|
if (!$response_data) { |
|
|
|
|
100
|
|
|
$this->setError(Http::$error); |
101
|
|
|
|
102
|
|
|
return false; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
$response_data['authorization_state'] = 'authorized'; |
106
|
|
|
$response_data['expired_time'] = $time + $response_data['authorization_info']['expires_in']; |
107
|
|
|
parent::$databaseDriver->_set($query_auth_key, $response_data); |
108
|
|
|
|
109
|
|
|
return $response_data; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
/** |
113
|
|
|
* 获取(刷新)授权公众号的接口调用凭据(令牌) |
114
|
|
|
* |
115
|
|
|
* @param string $authorizer_app_id 公众号app_id |
116
|
|
|
* @param string $authorizer_refresh_token 刷新TOKEN的 authorizer_refresh_token |
117
|
|
|
* |
118
|
|
|
* @return array authorization_info |
119
|
|
|
*/ |
120
|
|
|
private function getApiAuthorizerToken($authorizer_app_id = '', $authorizer_refresh_token = '') |
121
|
|
|
{ |
122
|
|
|
$query_data = http_build_query(['component_access_token' => $this->getComponentAccessToken()]); |
123
|
|
|
$request_data = [ |
124
|
|
|
'component_appid' => $this->configs->component_app_id, |
125
|
|
|
'authorizer_appid' => $authorizer_app_id, |
126
|
|
|
'authorizer_refresh_token' => $authorizer_refresh_token, |
127
|
|
|
]; |
128
|
|
|
|
129
|
|
|
$response_data = Http::_post(self::GET_API_AUTHORIZER_TOKEN_URL . '?' . $query_data, $request_data); |
130
|
|
|
|
131
|
|
|
if (!$response_data) { |
|
|
|
|
132
|
|
|
$this->setError(Http::$error); |
133
|
|
|
|
134
|
|
|
return false; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
return $response_data; |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
/** |
141
|
|
|
* 获取授权服务号 AccessToken |
142
|
|
|
* |
143
|
|
|
* @param string $authorizer_app_id |
144
|
|
|
* |
145
|
|
|
* @return bool |
146
|
|
|
*/ |
147
|
|
|
public function getAuthorizerAccessToken($authorizer_app_id = '') |
148
|
|
|
{ |
149
|
|
|
$query_auth_info = $this->getApiQueryAuth($authorizer_app_id); |
150
|
|
|
|
151
|
|
|
if (!empty($query_auth_info)) { |
152
|
|
|
|
153
|
|
|
if ($query_auth_info['authorization_state'] == 'authorized') { |
154
|
|
|
return $query_auth_info['authorization_info']['authorizer_access_token']; |
155
|
|
|
} else { |
156
|
|
|
$this->setError('已经取消授权的服务号:' . $query_auth_info['authorization_info']['authorizer_appid']); |
157
|
|
|
|
158
|
|
|
return false; |
159
|
|
|
} |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
return false; |
163
|
|
|
} |
164
|
|
|
} |
An exit expression should only be used in rare cases. For example, if you write a short command line script.
In most cases however, using an
exit
expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.