Completed
Pull Request — master (#1556)
by wannanbigpig
04:17
created

BaseClient::prepends()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
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 25
    public function __construct(Application $app)
53
    {
54 25
        $this->app = $app;
55
56 25
        $this->microCertificates = $this->app['config']->mch_id.'_micro_certificates';
57
58 25
        $this->setHttpClient($this->app['http_client']);
59 25
    }
60
61
    /**
62
     * Extra request params.
63
     *
64
     * @return array
65
     */
66 4
    protected function prepends()
67
    {
68 4
        return [];
69
    }
70
71
    /**
72
     * httpUpload.
73
     *
74
     * @param string $url
75
     * @param array  $files
76
     * @param array  $form
77
     * @param array  $query
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
    public function httpUpload(string $url, array $files = [], array $form = [], array $query = [], $returnResponse = false)
87
    {
88
        $multipart = [];
89
90
        foreach ($files as $name => $path) {
91
            $multipart[] = [
92
                'name' => $name,
93
                'contents' => fopen($path, 'r'),
94
            ];
95
        }
96
97
        $base = [
98
            'mch_id' => $this->app['config']['mch_id'],
99
        ];
100
101
        $form = array_merge($base, $form);
102
103
        $form['sign'] = $this->getSign($form);
104
105
        foreach ($form as $name => $contents) {
106
            $multipart[] = compact('name', 'contents');
107
        }
108
109
        $options = [
110
            'query' => $query,
111
            'multipart' => $multipart,
112
            'connect_timeout' => 30,
113
            'timeout' => 30,
114
            'read_timeout' => 30,
115
            'cert' => $this->app['config']->get('cert_path'),
116
            'ssl_key' => $this->app['config']->get('key_path'),
117
        ];
118
119
        $this->pushMiddleware($this->logMiddleware(), 'log');
120
121
        $response = $this->performRequest($url, 'POST', $options);
122
123
        $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
124
        // auto verify signature
125
        if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
126
            $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

126
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $this->castResponseToType($response, 'array'));
Loading history...
127
        } else {
128
            $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

128
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $result);
Loading history...
129
        }
130
131
        return $result;
132
    }
133
134
    /**
135
     * request.
136
     *
137
     * @param string $endpoint
138
     * @param array  $params
139
     * @param string $method
140
     * @param array  $options
141
     * @param bool   $returnResponse
142
     *
143
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
144
     *
145
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
146
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
147
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
148
     */
149 4
    protected function request(string $endpoint, array $params = [], $method = 'post', array $options = [], $returnResponse = false)
150
    {
151
        $base = [
152 4
            'mch_id' => $this->app['config']['mch_id'],
153
        ];
154
155 4
        $params = array_merge($base, $this->prepends(), $params);
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...
156 4
        $params['sign'] = $this->getSign($params);
157 4
        $options = array_merge([
0 ignored issues
show
Coding Style introduced by
Equals sign not aligned with surrounding assignments; expected 8 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...
158 4
            'body' => Support\XML::build($params),
159
        ], $options);
160
161 4
        $this->pushMiddleware($this->logMiddleware(), 'log');
162 4
        $response = $this->performRequest($endpoint, $method, $options);
163 4
        $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
164
        // auto verify signature
165 4
        if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
166 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

166
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $this->castResponseToType($response, 'array'));
Loading history...
167
        } else {
168 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

168
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $result);
Loading history...
169
        }
170
171 4
        return $result;
172
    }
173
174
    /**
175
     * Log the request.
176
     *
177
     * @return \Closure
178
     */
179 4
    protected function logMiddleware()
180
    {
181 4
        $formatter = new MessageFormatter($this->app['config']['http.log_template'] ?? MessageFormatter::DEBUG);
182
183 4
        return Middleware::log($this->app['logger'], $formatter);
184
    }
185
186
    /**
187
     * Make a request and return raw response.
188
     *
189
     * @param string $endpoint
190
     * @param array  $params
191
     * @param string $method
192
     * @param array  $options
193
     *
194
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
195
     *
196
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
197
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
198
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
199
     */
200 4
    protected function requestRaw(string $endpoint, array $params = [], $method = 'post', array $options = [])
201
    {
202 4
        return $this->request($endpoint, $params, $method, $options, true);
203
    }
204
205
    /**
206
     * Request with SSL.
207
     *
208
     * @param string $endpoint
209
     * @param array  $params
210
     * @param string $method
211
     * @param array  $options
212
     *
213
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
214
     *
215
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
216
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
217
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
218
     */
219 1
    protected function safeRequest(string $endpoint, array $params, $method = 'post', array $options = [])
220
    {
221 1
        $options = array_merge([
222 1
            'cert' => $this->app['config']->get('cert_path'),
223 1
            'ssl_key' => $this->app['config']->get('key_path'),
224
        ], $options);
225
226 1
        return $this->request($endpoint, $params, $method, $options);
227
    }
228
229
    /**
230
     * processing parameters contain fields that require sensitive information encryption.
231
     *
232
     * @param array $params
233
     *
234
     * @return array
235
     *
236
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
237
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
238
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
239
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException
240
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
241
     * @throws \Psr\SimpleCache\InvalidArgumentException
242
     */
243 1
    protected function processParams(array $params)
244
    {
245 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...
246 1
        $this->certificates = $cert['certificates'];
247 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...
248 1
        $sensitive_fields = $this->getSensitiveFieldsName();
249 1
        foreach ($params as $k => $v) {
250 1
            if (in_array($k, $sensitive_fields, true)) {
251 1
                $params[$k] = $this->encryptSensitiveInformation($v);
252
            }
253
        }
254
255 1
        return $params;
256
    }
257
258
    /**
259
     * To id card, mobile phone number and other fields sensitive information encryption.
260
     *
261
     * @param string $string
262
     *
263
     * @return string
264
     *
265
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
266
     */
267 1
    protected function encryptSensitiveInformation(string $string)
268
    {
269 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...
270 1
        $publicKeyResource = openssl_get_publickey($this->certificates);
271 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...
272 1
        openssl_free_key($publicKeyResource);
273 1
        if ($f) {
274 1
            return base64_encode($encrypted);
275
        }
276
277
        throw new EncryptException('Encryption of sensitive information failed');
278
    }
279
280
    /**
281
     * get sensitive fields name.
282
     *
283
     * @return array
284
     */
285 1
    protected function getSensitiveFieldsName()
286
    {
287
        return [
288 1
            'id_card_name',
289
            'id_card_number',
290
            'account_name',
291
            'account_number',
292
            'contact',
293
            'contact_phone',
294
            'contact_email',
295
            'legal_person',
296
            'mobile_phone',
297
            'email',
298
        ];
299
    }
300
301
    /**
302
     * getSign.
303
     *
304
     * @param $params
305
     *
306
     * @return string
307
     *
308
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
309
     */
310 5
    protected function getSign($params)
311
    {
312 5
        $params = array_filter($params);
313
314 5
        $key = $this->app->getKey();
315 5
        if ('HMAC-SHA256' === ($params['sign_type'] ?? 'MD5')) {
316 1
            $encryptMethod = function ($str) use ($key) {
317 1
                return hash_hmac('sha256', $str, $key);
318 1
            };
319
        } else {
320 4
            $encryptMethod = 'md5';
321
        }
322
323 5
        return Support\generate_sign($params, $key, $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

323
        return /** @scrutinizer ignore-call */ Support\generate_sign($params, $key, $encryptMethod);
Loading history...
324
    }
325
}
326