Api::cache()   C
last analyzed

Complexity

Conditions 8
Paths 9

Size

Total Lines 29
Code Lines 15

Duplication

Lines 29
Ratio 100 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 29
loc 29
rs 5.3846
cc 8
eloc 15
nc 9
nop 3
1
<?php
2
namespace Wechat;
3
4
use Wechat\API\BaseApi;
5
use Wechat\CacheDriver\BaseDriver;
6
7
/**
8
 * 微信接口 客户端基类.
9
 *
10
 * @author Tian.
11
 */
12
class Api
13
{
14
    private static $error           = ''; // 错误信息;
15
    private static $selfInstanceMap = []; // 实例列表;
16
    private static $postQueryStr    = []; // post数据时 需要携带的查询字符串
17
18
    private static $CACHE_DRIVER = ''; // 接口缓存驱动类名
19
20
    private static $apiData; //返回的数据
21
22
    private static $API_URL; // 微信接口地址
23
24
    private static $APP_ID; // 应用ID;
25
    private static $APP_SECRET; // 应用密钥;
26
27
    private static $ORIGINAL_ID; // 原始ID;
28
29
    private static $TOKEN; //TOKEN
30
    private static $ENCODING_AES_KEY; //ENCODING_AES_KEY
31
32
    /**
33
     * 接口初始化, 必须执行此方法才可以使用接口.
34
     *
35
     * @param string $appid
36
     * @param string $appsecret        服务号APP_SECRET
37
     * @param string $originalid       服务号ORIGINAL_ID
38
     * @param string $token            服务号TOKEN
39
     * @param string $encoding_aes_key 服务号ENCODING_AES_KEY
40
     * @param string $apiurl           微信接口地址 APIURL
41
     * @param string $cacheDriver      缓存驱动 Redis File ThinkPHP ......
42
     */
43 View Code Duplication
    public static function init($appid, $appsecret, $originalid = '', $token, $encoding_aes_key, $apiurl = 'https://api.weixin.qq.com/', $cacheDriver = 'File')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
44
    {
45
        self::$API_URL          = $apiurl ? $apiurl : 'https://api.weixin.qq.com/';
46
        self::$APP_ID           = $appid;
47
        self::$APP_SECRET       = $appsecret;
48
        self::$ORIGINAL_ID      = $originalid;
49
        self::$TOKEN            = $token;
50
        self::$ENCODING_AES_KEY = $encoding_aes_key;
51
        self::$CACHE_DRIVER     = $cacheDriver;
52
    }
53
54
    /**
55
     * 工厂+多例模式 获取接口实例.
56
     *
57
     * @author Tian
58
     *
59
     * @date   2015-12-08
60
     *
61
     * @param string $className 接口类名.
62
     *
63
     * @return object
64
     */
65
    public static function factory($className)
66
    {
67
        if (!$className || !is_string($className)) {
68
            exit('类名参数不正确');
0 ignored issues
show
Coding Style Compatibility introduced by
The method factory() contains an exit expression.

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.

Loading history...
69
        }
70
71
        $className = __NAMESPACE__ . '\\API\\' . $className . 'Api';
72
73 View Code Duplication
        if (!array_key_exists($className, self::$selfInstanceMap)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
74
            $api = new $className();
75
            if (!$api instanceof BaseApi) {
76
                exit($className . ' 必须继承 BaseApi');
0 ignored issues
show
Coding Style Compatibility introduced by
The method factory() contains an exit expression.

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.

Loading history...
77
            }
78
            self::$selfInstanceMap[$className] = $api;
79
        }
80
81
        return self::$selfInstanceMap[$className];
82
    }
83
84
    /**
85
     * 设置错误信息.
86
     *
87
     * @author Tian
88
     *
89
     * @date   2015-12-08
90
     *
91
     * @param string $errorText 错误信息
92
     */
93
    public static function setError($errorText)
94
    {
95
        self::$error = $errorText;
96
    }
97
98
    /**
99
     * 获取错误信息.
100
     *
101
     * @author Tian
102
     *
103
     * @date   2015-12-08
104
     *
105
     * @return string
106
     */
107
    public static function getError()
108
    {
109
        return self::$error;
110
    }
111
112
    /**
113
     * 设置api原始返回值
114
     *
115
     * @param $apiData
116
     */
117
    public static function setApiData($apiData)
118
    {
119
        self::$apiData = $apiData;
120
    }
121
122
    /**
123
     * 获取api原始返回值
124
     *
125
     * @return array
126
     */
127
    public static function getApiData()
128
    {
129
        return self::$apiData;
130
    }
131
132
    /**
133
     * 设置post操作的get参数.
134
     *
135
     * @author Tian
136
     *
137
     * @date   2015-08-03
138
     *
139
     * @param string $name  参数名
140
     * @param string $value 值
141
     */
142
    public static function setPostQueryStr($name, $value)
143
    {
144
        self::$postQueryStr[$name] = $value;
145
    }
146
147
    /**
148
     * 设置API_URL参数.
149
     *
150
     * @author Tian
151
     *
152
     * @date   2015-08-03
153
     *
154
     * @param string $url 参数名
155
     */
156
    public static function setApiUrl($url)
157
    {
158
        self::$API_URL = $url;
159
    }
160
161
    /**
162
     * 获取允许访问的token.
163
     *
164
     * @author Tian
165
     *
166
     * @param bool $jus 强制刷新
167
     *
168
     * @date   2015-12-08
169
     *
170
     * @return string
171
     */
172
    public static function getAccessToken($jus = false)
173
    {
174
        $key   = self::$APP_ID . 'access_token';
175
        $token = self::cache($key);
176
        if (false == $token || $jus) {
177
            $appid     = self::$APP_ID;
178
            $appsecert = self::$APP_SECRET;
179
            $module    = 'token';
180
            $queryStr  = [
181
                'grant_type' => 'client_credential',
182
                'appid'      => $appid,
183
                'secret'     => $appsecert,
184
            ];
185
186
            $res = self::_get($module, '', $queryStr, false);
187
            if (false === $res) {
188
                exit('获取AccessToken失败!');
0 ignored issues
show
Coding Style Compatibility introduced by
The method getAccessToken() contains an exit expression.

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.

Loading history...
189
            }
190
191
            $token = $res['access_token'];
192
193
            self::cache($key, $token, 3000);
194
        }
195
196
        return $token;
197
    }
198
199
    /**
200
     * 获取微信服务器ip.
201
     *
202
     * @author Tian
203
     *
204
     * @date   2015-12-08
205
     *
206
     * @return array
207
     */
208
209 View Code Duplication
    public static function getWxIpList()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
210
    {
211
        $module   = 'getcallbackip';
212
        $queryStr = [];
213
        $res      = self::_get($module, '', $queryStr);
214
        if (!$res) {
215
            exit(self::getError());
0 ignored issues
show
Coding Style Compatibility introduced by
The method getWxIpList() contains an exit expression.

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.

Loading history...
216
        }
217
218
        return $res;
219
    }
220
221
    /**
222
     * 获取AppId
223
     *
224
     * @return string AppId
225
     */
226
    public static function getAppId()
227
    {
228
        return self::$APP_ID;
229
    }
230
231
    /**
232
     * 获取ENCODING_AES_KEY
233
     *
234
     * @return string ENCODING_AES_KEY
235
     */
236
    public static function getEncoding_Aes_Key()
237
    {
238
        return self::$ENCODING_AES_KEY;
239
    }
240
241
    /**
242
     * 获取TOKEN
243
     *
244
     * @return string TOKEN
245
     */
246
    public static function getToken()
247
    {
248
        return self::$TOKEN;
249
    }
250
251
    /**
252
     * 获取AppSecret
253
     *
254
     * @return string AppSecret
255
     */
256
    public static function getAppSecret()
257
    {
258
        return self::$APP_SECRET;
259
    }
260
261
    /**
262
     * 用get的方式访问接口.
263
     *
264
     * @author Tian
265
     *
266
     * @date   2015-12-08
267
     *
268
     * @param string $module   指定接口模块
269
     * @param string $node     指定接口模块的节点
270
     * @param array  $queryStr 查询字符串
271
     * @param bool   $arsort   是否排序
272
     * @param string $apitype  Api类型
273
     *
274
     * @return array|bool 错误时返回false
275
     */
276 View Code Duplication
    public static function _get($module, $node, $queryStr = [], $arsort = true, $apitype = 'cgi-bin')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
277
    {
278
        //不需要 token 参数
279
        $no_module = ['token', 'showqrcode'];
280
281
        $no_apitye = ['sns'];
282
283
        if (in_array($apitype, $no_apitye) || in_array($module, $no_module)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
284
            //$queryStr = $queryStr;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
285
        } elseif ($module != 'token') {
286
            $info = self::getAccessToken();
287
288
            if (false == $info) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $info of type string to the boolean false. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
289
                return false;
290
            }
291
            $queryStr['access_token'] = $info;
292
        }
293
294
        if ($arsort) {
295
            arsort($queryStr);
296
        }
297
298
        $queryStr = http_build_query($queryStr);
299
300
        if (!empty($node)) {
301
            $node = '/' . $node;
302
        }
303
304
        $apiUrl = rtrim(self::$API_URL . $apitype . '/' . $module . $node, '/');
305
        $apiUrl .= '?' . $queryStr;
306
307
        $apiUrl = urldecode($apiUrl);
308
        $ch     = curl_init($apiUrl);
309
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
310
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
311
        curl_setopt($ch, CURLOPT_HEADER, true);
312
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
313
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
314
315
        $res      = curl_exec($ch);
316
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
317
        curl_close($ch);
318
319
        $header = '';
320
        $body   = $res;
321
        if ($httpcode == 200) {
322
            list($header, $body) = explode("\r\n\r\n", $res, 2);
323
            $header = self::http_parse_headers($header);
324
        }
325
326
        $result           = [];
327
        $result['info']   = $body;
328
        $result['header'] = $header;
329
        $result['status'] = $httpcode;
330
331
        $rest = self::packData($result);
332
        if ($rest == 'retry') {
333
            return self::get_retry($apiUrl);
334
        } else {
335
            return $rest;
336
        }
337
    }
338
339
    /**
340
     * 用post的方式访问接口.
341
     *
342
     * @author Tian
343
     *
344
     * @date   2015-12-08
345
     *
346
     * @param string $module     指定接口模块
347
     * @param string $node       指定接口模块的节点
348
     * @param array  $data       要发送的数据
349
     * @param bool   $jsonEncode 是否转换为jsons数据
350
     * @param string $apitype    Api类型
351
     *
352
     * @return array|bool 错误时返回false;
353
     */
354
    public static function _post($module, $node, $data, $jsonEncode = true, $apitype = 'cgi-bin')
355
    {
356
        $postQueryStr = self::$postQueryStr;
357
358
        $postQueryStr['access_token'] = self::getAccessToken();
359
360
        if (false == $postQueryStr) {
361
            return false;
362
        }
363
364
        if (!empty($node)) {
365
            $node = '/' . $node;
366
        }
367
368
        $apiUrl = rtrim(self::$API_URL . $apitype . '/' . $module . $node, '/');
369
370
        asort($postQueryStr);
371
372
        $postQueryStr = http_build_query($postQueryStr);
373
374
        $apiUrl .= '?' . $postQueryStr;
375
376 View Code Duplication
        if ($jsonEncode) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
377
            if (is_array($data)) {
378
                if (!defined('JSON_UNESCAPED_UNICODE')) {
379
                    // 解决php 5.3版本 json转码时 中文编码问题.
380
                    $data = json_encode($data);
381
                    $data = preg_replace("#\\\u([0-9a-f]{4})#ie", "iconv('UCS-2BE', 'UTF-8', pack('H4', '\\1'))", $data);
382
                } else {
383
                    $data = json_encode($data, JSON_UNESCAPED_UNICODE);
384
                }
385
            }
386
        }
387
388
        $apiUrl = urldecode($apiUrl);
389
        $ch     = curl_init();
390
391
        $php_version = explode('-', phpversion());
392
        $php_version = $php_version[0];
393
        if (strnatcasecmp($php_version, '5.6.0') >= 0) {
394
            curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
395
        }
396
397
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
398
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
399
        curl_setopt($ch, CURLOPT_HEADER, true);
400
        curl_setopt($ch, CURLOPT_NOBODY, false);
401
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
402
        curl_setopt($ch, CURLOPT_POST, 1);
403
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
404
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
405
406
        $res      = trim(curl_exec($ch));
407
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
408
        curl_close($ch);
409
410
        $header = '';
411
        $body   = $res;
412
        if ($httpcode == 200) {
413
            list($header, $body) = explode("\r\n\r\n", $res, 2);
414
            //list($header, $body) = explode("keep-alive", $res, 2);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
415
            $header = self::http_parse_headers($header);
416
        }
417
418
        $result           = [];
419
        $result['info']   = $body;
420
        $result['header'] = $header;
421
        $result['status'] = $httpcode;
422
423
        $rest = self::packData($result);
424
425
        if ($rest === 'retry') {
426
            return self::post_retry($apiUrl, $data);
427
        } else {
428
            return $rest;
429
        }
430
    }
431
432
    //token 刷新后重试 post
433 View Code Duplication
    public static function post_retry($apiUrl, $data)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
434
    {
435
        $urlarr = parse_url($apiUrl);
436
        parse_str($urlarr['query'], $parr);
437
438
        usleep(500000);
439
440
        $parr['access_token'] = self::getAccessToken();
441
442
        $apiUrl = $urlarr['scheme'] . '://' . $urlarr['host'] . $urlarr['path'];
443
        $apiUrl .= '?' . http_build_query($parr);
444
445
        $ch = curl_init();
446
        curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);
447
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
448
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
449
        curl_setopt($ch, CURLOPT_HEADER, true);
450
        curl_setopt($ch, CURLOPT_NOBODY, false);
451
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
452
        curl_setopt($ch, CURLOPT_POST, 1);
453
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
454
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
455
456
        $res      = trim(curl_exec($ch));
457
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
458
        curl_close($ch);
459
460
        $header = '';
461
        $body   = $res;
462
        if ($httpcode == 200) {
463
            list($header, $body) = explode("\r\n\r\n", $res, 2);
464
            //list($header, $body) = explode("keep-alive", $res, 2);
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
465
            $header = self::http_parse_headers($header);
466
        }
467
468
        $result           = [];
469
        $result['info']   = $body;
470
        $result['header'] = $header;
471
        $result['status'] = $httpcode;
472
473
        $rest_retry = self::packData($result);
474
        if ($rest_retry === 'retry') {
475
            return false;
476
        }
477
478
        return $rest_retry;
479
    }
480
481
    //token 刷新后重试 get
482 View Code Duplication
    public static function get_retry($apiUrl)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
483
    {
484
        $urlarr = parse_url($apiUrl);
485
        parse_str($urlarr['query'], $parr);
486
487
        usleep(500000);
488
489
        $parr['access_token'] = self::getAccessToken();
490
491
        $apiUrl = $urlarr['scheme'] . '://' . $urlarr['host'] . $urlarr['path'];
492
        $apiUrl .= '?' . http_build_query($parr);
493
494
        $apiUrl = urldecode($apiUrl);
495
        $ch     = curl_init($apiUrl);
496
        curl_setopt($ch, CURLOPT_URL, $apiUrl);
497
        curl_setopt($ch, CURLOPT_TIMEOUT, 60);
498
        curl_setopt($ch, CURLOPT_HEADER, true);
499
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
500
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
501
502
        $res      = curl_exec($ch);
503
        $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
504
        curl_close($ch);
505
506
        $header = '';
507
        $body   = $res;
508
        if ($httpcode == 200) {
509
            list($header, $body) = explode("\r\n\r\n", $res, 2);
510
            $header = self::http_parse_headers($header);
511
        }
512
513
        $result           = [];
514
        $result['info']   = $body;
515
        $result['header'] = $header;
516
        $result['status'] = $httpcode;
517
518
        $rest_retry = self::packData($result);
519
520
        if ($rest_retry === 'retry') {
521
            return false;
522
        }
523
524
        return $rest_retry;
525
    }
526
527
    /**
528
     * 对接口返回的数据进行验证和组装.
529
     *
530
     * @author Tian
531
     *
532
     * @date   2015-12-08
533
     *
534
     * @param array $apiReturnData 由_post|| _get方法返回的数据.
535
     *
536
     * @return array|bool
537
     */
538 View Code Duplication
    public static function packData($apiReturnData)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
539
    {
540
        $status     = $apiReturnData['status'];
541
        $header     = $apiReturnData['header'];
542
        $returnData = $apiReturnData['info'];
543
544
        if ($status != 200 && empty($returnData)) {
545
            self::setError('接口服务器连接失败.');
546
547
            return false;
548
        }
549
        $apiReturnData = json_decode($returnData, true);
550
551
        $apiData           = [];
552
        $apiData['status'] = $status;
553
        $apiData['header'] = $header;
554
        $apiData['info']   = $apiReturnData;
555
556
        self::setApiData($apiData);
557
558
        if (!$apiReturnData && substr($header['Content-Type'], 0, 16) != 'application/json') {
559
            $apiReturnData            = [];
560
            $apiReturnData['content'] = $returnData;
561
            $apiReturnData['type']    = $header['Content-Type'];
562
            $apiReturnData['size']    = $header['Content-Length'];
563
564
            return $apiReturnData;
565
        }
566
567
        if ($status != 200 && !$apiReturnData) {
568
            self::setError($returnData);
569
570
            return false;
571
        }
572
573
        if (isset($apiReturnData['errcode']) && ($apiReturnData['errcode'] == 42001 || $apiReturnData['errcode'] == 40001)) {
574
            $error = '错误码:' . $apiReturnData['errcode'] . ', 错误信息:' . $apiReturnData['errmsg'] . '-已重新刷新access_token';
575
576
            //强制刷新 AccessToken
577
            self::getAccessToken(true);
578
579
            self::setError($error);
580
581
            $rest = 'retry';
582
583
            return $rest;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $rest; (string) is incompatible with the return type documented by Wechat\Api::packData of type array|boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
584
        }
585
586
        if (isset($apiReturnData['errcode']) && $apiReturnData['errcode'] != 0) {
587
            $error = '错误码:' . $apiReturnData['errcode'] . ', 错误信息:' . $apiReturnData['errmsg'];
588
589
            self::setError($error);
590
591
            return false;
592
        }
593
594
        if (isset($apiReturnData['errcode'])) {
595
            unset($apiReturnData['errcode']);
596
        }
597
598
        if (count($apiReturnData) > 1 && isset($apiReturnData['errmsg'])) {
599
            unset($apiReturnData['errmsg']);
600
        }
601
602
        if (count($apiReturnData) == 1) {
603
            $apiReturnData = reset($apiReturnData);
604
        }
605
606
        return $apiReturnData;
607
    }
608
609
    /**
610
     * 接口加密方法.
611
     *
612
     * @param string $data   要加密的字符串
613
     * @param string $key    加密密钥
614
     * @param int    $expire 过期时间 单位 秒
615
     *
616
     * @return string
617
     */
618 View Code Duplication
    public static function encrypt($data, $key, $expire = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
619
    {
620
        $data = base64_encode($data);
621
        $x    = 0;
622
        $len  = strlen($data);
623
        $l    = strlen($key);
624
        $char = '';
625
626
        for ($i = 0; $i < $len; $i++) {
627
            if ($x == $l) {
628
                $x = 0;
629
            }
630
            $char .= substr($key, $x, 1);
631
            $x++;
632
        }
633
634
        $str = sprintf('%010d', $expire ? $expire + time() : 0);
635
636
        for ($i = 0; $i < $len; $i++) {
637
            $str .= chr(ord(substr($data, $i, 1)) + (ord(substr($char, $i, 1))) % 256);
638
        }
639
640
        return rawurlencode(str_replace('=', '', base64_encode($str)));
641
    }
642
643
    /**
644
     * 解析头信息
645
     *
646
     * @param $raw_headers
647
     *
648
     * @return array
649
     */
650 View Code Duplication
    public static function http_parse_headers($raw_headers)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
651
    {
652
        $headers = [];
653
        $key     = ''; // [+]
654
655
        foreach (explode("\n", $raw_headers) as $i => $h) {
656
            $h = explode(':', $h, 2);
657
658
            if (isset($h[1])) {
659
                if (!isset($headers[$h[0]])) {
660
                    $headers[$h[0]] = trim($h[1]);
661
                } elseif (is_array($headers[$h[0]])) {
662
                    // $tmp = array_merge($headers[$h[0]], array(trim($h[1]))); // [-]
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
663
                    // $headers[$h[0]] = $tmp; // [-]
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
664
                    $headers[$h[0]] = array_merge($headers[$h[0]], [trim($h[1])]); // [+]
665
                } else {
666
                    // $tmp = array_merge(array($headers[$h[0]]), array(trim($h[1]))); // [-]
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
667
                    // $headers[$h[0]] = $tmp; // [-]
0 ignored issues
show
Unused Code Comprehensibility introduced by
65% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
668
                    $headers[$h[0]] = array_merge([$headers[$h[0]]], [trim($h[1])]); // [+]
669
                }
670
671
                $key = $h[0]; // [+]
672
            } else {
673
                // [+]
674
                // [+]
675
                if (substr($h[0], 0, 1) == "\t") {
676
                    // [+]
677
                    $headers[$key] .= "\r\n\t" . trim($h[0]);
678
                } // [+]
679
                elseif (!$key) {
680
                    // [+]
681
                    $headers[0] = trim($h[0]);
682
                }
683
                trim($h[0]); // [+]
684
            } // [+]
685
        }
686
687
        return $headers;
688
    }
689
690
    /**
691
     * 缓存方法
692
     *
693
     * @param string $name    缓存名
694
     * @param string $value   缓存值 如果不输入值 则根据缓存名返回缓存值.
695
     * @param int    $expires 缓存过期时间 默认0 即永不超时. 单位秒
696
     *
697
     * @return bool|null|string
698
     */
699 View Code Duplication
    public static function cache($name, $value = '', $expires = 0)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
700
    {
701
        if (!$name || !is_string($name)) {
702
            self::setError('参数错误!');
703
704
            return false;
705
        }
706
707
        /** @var BaseDriver $cacheDriver */
708
        static $cacheDriver;
709
710
        if (!isset($cacheDriver)) {
711
            $cacheDriver = __NAMESPACE__ . '\\CacheDriver\\' . self::$CACHE_DRIVER . 'Driver';
712
            $cacheDriver = new $cacheDriver(__DIR__ . '/Cache/');
713
        }
714
715
        if (!$value && $value !== 0) {
0 ignored issues
show
Unused Code Bug introduced by
The strict comparison !== seems to always evaluate to true as the types of $value (string) and 0 (integer) can never be identical. Maybe you want to use a loose comparison != instead?
Loading history...
716
            $value = $cacheDriver->_get($name);
717
            if (false == $value) {
718
                $value = null;
719
            }
720
721
            return $value;
722
        }
723
724
        $res = $cacheDriver->_set($name, $value, $expires);
725
726
        return $res ? true : false;
727
    }
728
}
729