1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace EntWeChat\Core; |
4
|
|
|
|
5
|
|
|
use Doctrine\Common\Cache\Cache; |
6
|
|
|
use Doctrine\Common\Cache\FilesystemCache; |
7
|
|
|
use EntWeChat\Core\Exceptions\HttpException; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* Class AccessToken. |
11
|
|
|
*/ |
12
|
|
|
class AccessToken |
13
|
|
|
{ |
14
|
|
|
/** |
15
|
|
|
* ID. |
16
|
|
|
* |
17
|
|
|
* @var string |
18
|
|
|
*/ |
19
|
|
|
protected $id; |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Secret. |
23
|
|
|
* |
24
|
|
|
* @var string |
25
|
|
|
*/ |
26
|
|
|
protected $secret; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* Cache. |
30
|
|
|
* |
31
|
|
|
* @var Cache |
32
|
|
|
*/ |
33
|
|
|
protected $cache; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Cache Key. |
37
|
|
|
* |
38
|
|
|
* @var string |
39
|
|
|
*/ |
40
|
|
|
protected $cacheKey; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Http instance. |
44
|
|
|
* |
45
|
|
|
* @var Http |
46
|
|
|
*/ |
47
|
|
|
protected $http; |
48
|
|
|
|
49
|
|
|
/** |
50
|
|
|
* Query name. |
51
|
|
|
* |
52
|
|
|
* @var string |
53
|
|
|
*/ |
54
|
|
|
protected $queryName = 'access_token'; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Response Json key name. |
58
|
|
|
* |
59
|
|
|
* @var string |
60
|
|
|
*/ |
61
|
|
|
protected $tokenJsonKey = 'access_token'; |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Cache key prefix. |
65
|
|
|
* |
66
|
|
|
* @var string |
67
|
|
|
*/ |
68
|
|
|
protected $prefix = 'entwechat.common.access_token.'; |
69
|
|
|
|
70
|
|
|
// API |
71
|
|
|
const API_TOKEN_GET = 'https://qyapi.weixin.qq.com/cgi-bin/gettoken'; |
72
|
|
|
|
73
|
|
|
/** |
74
|
|
|
* Constructor. |
75
|
|
|
* |
76
|
|
|
* @param string $id |
77
|
|
|
* @param string $secret |
78
|
|
|
* @param \Doctrine\Common\Cache\Cache $cache |
79
|
|
|
*/ |
80
|
|
|
public function __construct($id, $secret, Cache $cache = null) |
81
|
|
|
{ |
82
|
|
|
$this->id = $id; |
83
|
|
|
$this->secret = $secret; |
84
|
|
|
$this->cache = $cache; |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Get token from WeChat API. |
89
|
|
|
* |
90
|
|
|
* @param bool $forceRefresh |
91
|
|
|
* |
92
|
|
|
* @return string |
93
|
|
|
*/ |
94
|
|
|
public function getToken($forceRefresh = false) |
95
|
|
|
{ |
96
|
|
|
$cacheKey = $this->getCacheKey(); |
97
|
|
|
$cached = $this->getCache()->fetch($cacheKey); |
98
|
|
|
|
99
|
|
|
if ($forceRefresh || empty($cached)) { |
100
|
|
|
$token = $this->getTokenFromServer(); |
101
|
|
|
|
102
|
|
|
// XXX: T_T... 7200 - 1500 |
103
|
|
|
$this->getCache()->save($cacheKey, $token[$this->tokenJsonKey], $token['expires_in'] - 1500); |
104
|
|
|
|
105
|
|
|
return $token[$this->tokenJsonKey]; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
return $cached; |
109
|
|
|
} |
110
|
|
|
|
111
|
|
|
/** |
112
|
|
|
* Set custom token. |
113
|
|
|
* |
114
|
|
|
* @param string $token |
115
|
|
|
* @param int $expires |
116
|
|
|
* |
117
|
|
|
* @return $this |
118
|
|
|
*/ |
119
|
|
|
public function setToken($token, $expires = 7200) |
120
|
|
|
{ |
121
|
|
|
$this->getCache()->save($this->getCacheKey(), $token, $expires - 1500); |
122
|
|
|
|
123
|
|
|
return $this; |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
/** |
127
|
|
|
* Return the id. |
128
|
|
|
* |
129
|
|
|
* @return string |
130
|
|
|
*/ |
131
|
|
|
public function getId() |
132
|
|
|
{ |
133
|
|
|
return $this->id; |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* Return the app id. |
138
|
|
|
* |
139
|
|
|
* @return string |
140
|
|
|
*/ |
141
|
|
|
public function getAppId() |
142
|
|
|
{ |
143
|
|
|
return $this->getId(); |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Return the corp id. |
148
|
|
|
* |
149
|
|
|
* @return string |
150
|
|
|
*/ |
151
|
|
|
public function getCorpId() |
152
|
|
|
{ |
153
|
|
|
return $this->getId(); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
/** |
157
|
|
|
* Return the secret. |
158
|
|
|
* |
159
|
|
|
* @return string |
160
|
|
|
*/ |
161
|
|
|
public function getSecret() |
162
|
|
|
{ |
163
|
|
|
return $this->secret; |
164
|
|
|
} |
165
|
|
|
|
166
|
|
|
/** |
167
|
|
|
* Return the fingerprint. |
168
|
|
|
* |
169
|
|
|
* @return string |
170
|
|
|
*/ |
171
|
|
|
public function getFingerprint() |
172
|
|
|
{ |
173
|
|
|
return sha1($this->id.'|'.$this->secret); |
174
|
|
|
} |
175
|
|
|
|
176
|
|
|
/** |
177
|
|
|
* Set cache instance. |
178
|
|
|
* |
179
|
|
|
* @param \Doctrine\Common\Cache\Cache $cache |
180
|
|
|
* |
181
|
|
|
* @return AccessToken |
182
|
|
|
*/ |
183
|
|
|
public function setCache(Cache $cache) |
184
|
|
|
{ |
185
|
|
|
$this->cache = $cache; |
186
|
|
|
|
187
|
|
|
return $this; |
188
|
|
|
} |
189
|
|
|
|
190
|
|
|
/** |
191
|
|
|
* Return the cache manager. |
192
|
|
|
* |
193
|
|
|
* @return \Doctrine\Common\Cache\Cache |
194
|
|
|
*/ |
195
|
|
|
public function getCache() |
196
|
|
|
{ |
197
|
|
|
return $this->cache ?: $this->cache = new FilesystemCache(sys_get_temp_dir()); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* Set the query name. |
202
|
|
|
* |
203
|
|
|
* @param string $queryName |
204
|
|
|
* |
205
|
|
|
* @return $this |
206
|
|
|
*/ |
207
|
|
|
public function setQueryName($queryName) |
208
|
|
|
{ |
209
|
|
|
$this->queryName = $queryName; |
210
|
|
|
|
211
|
|
|
return $this; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
/** |
215
|
|
|
* Return the query name. |
216
|
|
|
* |
217
|
|
|
* @return string |
218
|
|
|
*/ |
219
|
|
|
public function getQueryName() |
220
|
|
|
{ |
221
|
|
|
return $this->queryName; |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
/** |
225
|
|
|
* Return the API request queries. |
226
|
|
|
* |
227
|
|
|
* @return array |
228
|
|
|
*/ |
229
|
|
|
public function getQueryFields() |
230
|
|
|
{ |
231
|
|
|
return [$this->queryName => $this->getToken()]; |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
/** |
235
|
|
|
* Get the access token from WeChat server. |
236
|
|
|
* |
237
|
|
|
* @throws \EntWeChat\Core\Exceptions\HttpException |
238
|
|
|
* |
239
|
|
|
* @return string |
240
|
|
|
*/ |
241
|
|
View Code Duplication |
public function getTokenFromServer() |
|
|
|
|
242
|
|
|
{ |
243
|
|
|
$params = [ |
244
|
|
|
'corpid' => $this->id, |
245
|
|
|
'corpsecret' => $this->secret, |
246
|
|
|
]; |
247
|
|
|
|
248
|
|
|
$http = $this->getHttp(); |
249
|
|
|
|
250
|
|
|
$token = $http->parseJSON($http->get(self::API_TOKEN_GET, $params)); |
251
|
|
|
|
252
|
|
|
if (empty($token[$this->tokenJsonKey])) { |
253
|
|
|
throw new HttpException('Request AccessToken fail. response: '.json_encode($token, JSON_UNESCAPED_UNICODE)); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
return $token; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* Return the http instance. |
261
|
|
|
* |
262
|
|
|
* @return \EntWeChat\Core\Http |
263
|
|
|
*/ |
264
|
|
|
public function getHttp() |
265
|
|
|
{ |
266
|
|
|
return $this->http ?: $this->http = new Http(); |
267
|
|
|
} |
268
|
|
|
|
269
|
|
|
/** |
270
|
|
|
* Set the http instance. |
271
|
|
|
* |
272
|
|
|
* @param \EntWeChat\Core\Http $http |
273
|
|
|
* |
274
|
|
|
* @return $this |
275
|
|
|
*/ |
276
|
|
|
public function setHttp(Http $http) |
277
|
|
|
{ |
278
|
|
|
$this->http = $http; |
279
|
|
|
|
280
|
|
|
return $this; |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
/** |
284
|
|
|
* Set the access token prefix. |
285
|
|
|
* |
286
|
|
|
* @param string $prefix |
287
|
|
|
* |
288
|
|
|
* @return $this |
289
|
|
|
*/ |
290
|
|
|
public function setPrefix($prefix) |
291
|
|
|
{ |
292
|
|
|
$this->prefix = $prefix; |
293
|
|
|
|
294
|
|
|
return $this; |
295
|
|
|
} |
296
|
|
|
|
297
|
|
|
/** |
298
|
|
|
* Set access token cache key. |
299
|
|
|
* |
300
|
|
|
* @param string $cacheKey |
301
|
|
|
* |
302
|
|
|
* @return $this |
303
|
|
|
*/ |
304
|
|
|
public function setCacheKey($cacheKey) |
305
|
|
|
{ |
306
|
|
|
$this->cacheKey = $cacheKey; |
307
|
|
|
|
308
|
|
|
return $this; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* Get access token cache key. |
313
|
|
|
* |
314
|
|
|
* @return string $this->cacheKey |
315
|
|
|
*/ |
316
|
|
|
public function getCacheKey() |
317
|
|
|
{ |
318
|
|
|
if (is_null($this->cacheKey)) { |
319
|
|
|
return $this->prefix.$this->id; |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
return $this->cacheKey; |
323
|
|
|
} |
324
|
|
|
} |
325
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.