Completed
Pull Request — master (#1556)
by wannanbigpig
05:05 queued 57s
created

BaseClient   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 219
Duplicated Lines 0 %

Test Coverage

Coverage 98.18%

Importance

Changes 0
Metric Value
eloc 65
dl 0
loc 219
ccs 54
cts 55
cp 0.9818
rs 10
c 0
b 0
f 0
wmc 16

9 Methods

Rating   Name   Duplication   Size   Complexity  
A prepends() 0 3 1
A __construct() 0 7 1
A processParams() 0 13 3
A requestRaw() 0 3 1
A getSensitiveFieldsName() 0 13 1
A logMiddleware() 0 5 1
A safeRequest() 0 8 1
A request() 0 33 5
A encryptSensitiveInformation() 0 11 2
1
<?php
2
3
/*
4
 * This file is part of the overtrue/wechat.
5
 *
6
 * (c) overtrue <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace EasyWeChat\MicroMerchant\Kernel;
13
14
use EasyWeChat\Kernel\Support;
15
use EasyWeChat\Kernel\Traits\HasHttpRequests;
16
use EasyWeChat\MicroMerchant\Application;
17
use EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException;
18
use GuzzleHttp\MessageFormatter;
19
use GuzzleHttp\Middleware;
20
21
/**
22
 * Class BaseClient.
23
 *
24
 * @author overtrue <[email protected]>
25
 */
26
class BaseClient
27
{
28
    use HasHttpRequests {
0 ignored issues
show
Bug introduced by
The trait EasyWeChat\Kernel\Traits\HasHttpRequests requires the property $baseUri which is not provided by EasyWeChat\MicroMerchant\Kernel\BaseClient.
Loading history...
29
        request as performRequest;
30
    }
31
32
    /**
33
     * @var string
34
     */
35
    protected $microCertificates;
36
37
    /**
38
     * @var string
39
     */
40
    protected $certificates;
41
42
    /**
43
     * @var \EasyWeChat\MicroMerchant\Application
44
     */
45
    protected $app;
46
47
    /**
48
     * BaseClient constructor.
49
     *
50
     * @param \EasyWeChat\MicroMerchant\Application $app
51
     */
52 22
    public function __construct(Application $app)
53
    {
54 22
        $this->app = $app;
55
56 22
        $this->microCertificates = $this->app['config']->mch_id.'_micro_certificates';
57
58 22
        $this->setHttpClient($this->app['http_client']);
59 22
    }
60
61
    /**
62
     * Extra request params.
63
     *
64
     * @return array
65
     */
66 4
    protected function prepends()
67
    {
68 4
        return [];
69
    }
70
71
    /**
72
     * request.
73
     *
74
     * @param string $endpoint
75
     * @param array  $params
76
     * @param string $method
77
     * @param array  $options
78
     * @param bool   $returnResponse
79
     *
80
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
81
     *
82
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
83
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
84
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
85
     */
86 4
    protected function request(string $endpoint, array $params = [], $method = 'post', array $options = [], $returnResponse = false)
87
    {
88
        $base = [
89 4
            'mch_id' => $this->app['config']['mch_id'],
90
        ];
91
92 4
        $params = array_filter(array_merge($base, $this->prepends(), $params));
93
94 4
        $secretKey = $this->app->getKey();
95 4
        if ('HMAC-SHA256' === ($params['sign_type'] ?? 'MD5')) {
96 1
            $encryptMethod = function ($str) use ($secretKey) {
97 1
                return hash_hmac('sha256', $str, $secretKey);
98 1
            };
99
        } else {
100 3
            $encryptMethod = 'md5';
101
        }
102 4
        $params['sign'] = Support\generate_sign($params, $secretKey, $encryptMethod);
0 ignored issues
show
Bug introduced by
The function generate_sign was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

102
        $params['sign'] = /** @scrutinizer ignore-call */ Support\generate_sign($params, $secretKey, $encryptMethod);
Loading history...
103
104 4
        $options = array_merge([
105 4
            'body' => Support\XML::build($params),
106
        ], $options);
107
108 4
        $this->pushMiddleware($this->logMiddleware(), 'log');
109 4
        $response = $this->performRequest($endpoint, $method, $options);
110 4
        $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
111
        // auto verify signature
112 4
        if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
113 4
            $this->app->verifySignature($this->castResponseToType($response, 'array'));
0 ignored issues
show
Bug introduced by
$this->castResponseToType($response, 'array') of type EasyWeChat\Kernel\Support\Collection is incompatible with the type array expected by parameter $data of EasyWeChat\MicroMerchant...tion::verifySignature(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

113
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $this->castResponseToType($response, 'array'));
Loading history...
114
        } else {
115 1
            $this->app->verifySignature($result);
0 ignored issues
show
Bug introduced by
$result of type EasyWeChat\Kernel\Suppor...ssage\ResponseInterface is incompatible with the type array expected by parameter $data of EasyWeChat\MicroMerchant...tion::verifySignature(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

115
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $result);
Loading history...
116
        }
117
118 4
        return $result;
119
    }
120
121
    /**
122
     * Log the request.
123
     *
124
     * @return \Closure
125
     */
126 4
    protected function logMiddleware()
127
    {
128 4
        $formatter = new MessageFormatter($this->app['config']['http.log_template'] ?? MessageFormatter::DEBUG);
129
130 4
        return Middleware::log($this->app['logger'], $formatter);
131
    }
132
133
    /**
134
     * Make a request and return raw response.
135
     *
136
     * @param string $endpoint
137
     * @param array  $params
138
     * @param string $method
139
     * @param array  $options
140
     *
141
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
142
     *
143
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
144
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
145
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
146
     */
147 4
    protected function requestRaw(string $endpoint, array $params = [], $method = 'post', array $options = [])
148
    {
149 4
        return $this->request($endpoint, $params, $method, $options, true);
150
    }
151
152
    /**
153
     * Request with SSL.
154
     *
155
     * @param string $endpoint
156
     * @param array  $params
157
     * @param string $method
158
     * @param array  $options
159
     *
160
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
161
     *
162
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
163
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
164
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
165
     */
166 1
    protected function safeRequest(string $endpoint, array $params, $method = 'post', array $options = [])
167
    {
168 1
        $options = array_merge([
169 1
            'cert' => $this->app['config']->get('cert_path'),
170 1
            'ssl_key' => $this->app['config']->get('key_path'),
171
        ], $options);
172
173 1
        return $this->request($endpoint, $params, $method, $options);
174
    }
175
176
    /**
177
     * processing parameters contain fields that require sensitive information encryption.
178
     *
179
     * @param array $params
180
     *
181
     * @return array
182
     *
183
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
184
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
185
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
186
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException
187
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
188
     * @throws \Psr\SimpleCache\InvalidArgumentException
189
     */
190 1
    protected function processParams(array $params)
191
    {
192 1
        $cert = $this->app->getCertficates();
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 15 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
193 1
        $this->certificates = $cert['certificates'];
194 1
        $params['cert_sn'] = $cert['serial_no'];
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
195 1
        $sensitive_fields = $this->getSensitiveFieldsName();
196 1
        foreach ($params as $k => $v) {
197 1
            if (in_array($k, $sensitive_fields, true)) {
198 1
                $params[$k] = $this->encryptSensitiveInformation($v);
199
            }
200
        }
201
202 1
        return $params;
203
    }
204
205
    /**
206
     * To id card, mobile phone number and other fields sensitive information encryption.
207
     *
208
     * @param string $string
209
     *
210
     * @return string
211
     *
212
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
213
     */
214 1
    protected function encryptSensitiveInformation(string $string)
215
    {
216 1
        $encrypted = '';
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 9 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
217 1
        $publicKeyResource = openssl_get_publickey($this->certificates);
218 1
        $f = openssl_public_encrypt($string, $encrypted, $publicKeyResource);
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 17 spaces but found 1 space

This check looks for multiple assignments in successive lines of code. It will report an issue if the operators are not in a straight line.

To visualize

$a = "a";
$ab = "ab";
$abc = "abc";

will produce issues in the first and second line, while this second example

$a   = "a";
$ab  = "ab";
$abc = "abc";

will produce no issues.

Loading history...
219 1
        openssl_free_key($publicKeyResource);
220 1
        if ($f) {
221 1
            return base64_encode($encrypted);
222
        }
223
224
        throw new EncryptException('Encryption of sensitive information failed');
225
    }
226
227
    /**
228
     * get sensitive fields name.
229
     *
230
     * @return array
231
     */
232 1
    protected function getSensitiveFieldsName()
233
    {
234
        return [
235 1
            'id_card_name',
236
            'id_card_number',
237
            'account_name',
238
            'account_number',
239
            'contact',
240
            'contact_phone',
241
            'contact_email',
242
            'legal_person',
243
            'mobile_phone',
244
            'email',
245
        ];
246
    }
247
}
248