Completed
Pull Request — master (#1556)
by wannanbigpig
07:00 queued 03:07
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\Exceptions\InvalidArgumentException;
15
use EasyWeChat\Kernel\Support;
16
use EasyWeChat\Kernel\Traits\HasHttpRequests;
17
use EasyWeChat\MicroMerchant\Application;
18
use EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException;
19
use EasyWeChat\Payment\Kernel\BaseClient as PaymentBaseClient;
20
21
/**
22
 * Class BaseClient.
23
 *
24
 * @author overtrue <[email protected]>
25
 */
26
class BaseClient extends PaymentBaseClient
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 $certificates;
36
37
    /**
38
     * @var \EasyWeChat\MicroMerchant\Application
39
     */
40
    protected $app;
41
42
    /**
43
     * BaseClient constructor.
44
     *
45
     * @param \EasyWeChat\MicroMerchant\Application $app
46
     */
47 24
    public function __construct(Application $app)
48
    {
49 24
        $this->app = $app;
50
51 24
        $this->setHttpClient($this->app['http_client']);
52 24
    }
53
54
    /**
55
     * Extra request params.
56
     *
57
     * @return array
58
     */
59 4
    protected function prepends()
60
    {
61 4
        return [];
62
    }
63
64
    /**
65
     * httpUpload.
66
     *
67
     * @param string $url
68
     * @param array  $files
69
     * @param array  $form
70
     * @param array  $query
71
     * @param bool   $returnResponse
72
     *
73
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
74
     *
75
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
76
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
77
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
78
     */
79
    public function httpUpload(string $url, array $files = [], array $form = [], array $query = [], $returnResponse = false)
80
    {
81
        $multipart = [];
82
83
        foreach ($files as $name => $path) {
84
            $multipart[] = [
85
                'name' => $name,
86
                'contents' => fopen($path, 'r'),
87
            ];
88
        }
89
90
        $base = [
91
            'mch_id' => $this->app['config']['mch_id'],
92
        ];
93
94
        $form = array_merge($base, $form);
95
96
        $form['sign'] = $this->getSign($form);
97
98
        foreach ($form as $name => $contents) {
99
            $multipart[] = compact('name', 'contents');
100
        }
101
102
        $options = [
103
            'query' => $query,
104
            'multipart' => $multipart,
105
            'connect_timeout' => 30,
106
            'timeout' => 30,
107
            'read_timeout' => 30,
108
            'cert' => $this->app['config']->get('cert_path'),
109
            'ssl_key' => $this->app['config']->get('key_path'),
110
        ];
111
112
        $this->pushMiddleware($this->logMiddleware(), 'log');
113
114
        $response = $this->performRequest($url, 'POST', $options);
115
116
        $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
117
        // auto verify signature
118
        if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
119
            $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

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

121
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $result);
Loading history...
122
        }
123
124
        return $result;
125
    }
126
127
    /**
128
     * request.
129
     *
130
     * @param string $endpoint
131
     * @param array  $params
132
     * @param string $method
133
     * @param array  $options
134
     * @param bool   $returnResponse
135
     *
136
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
137
     *
138
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
139
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
140
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
141
     */
142 4
    protected function request(string $endpoint, array $params = [], $method = 'post', array $options = [], $returnResponse = false)
143
    {
144
        $base = [
145 4
            'mch_id' => $this->app['config']['mch_id'],
146
        ];
147
148 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...
149 4
        $params['sign'] = $this->getSign($params);
150 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...
151 4
            'body' => Support\XML::build($params),
152
        ], $options);
153
154 4
        $this->pushMiddleware($this->logMiddleware(), 'log');
155 4
        $response = $this->performRequest($endpoint, $method, $options);
156 4
        $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
157
        // auto verify signature
158 4
        if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
159 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

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

161
            $this->app->verifySignature(/** @scrutinizer ignore-type */ $result);
Loading history...
162
        }
163
164 4
        return $result;
165
    }
166
167
    /**
168
     * processing parameters contain fields that require sensitive information encryption.
169
     *
170
     * @param array $params
171
     *
172
     * @return array
173
     *
174
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
175
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
176
     */
177
    protected function processParams(array $params)
178
    {
179
        $serial_no = $this->app['config']->get('serial_no');
180
        if (null === $serial_no) {
181
            throw new InvalidArgumentException('config serial_no connot be empty.');
182
        }
183
184
        $params['cert_sn'] = $serial_no;
185
        $sensitive_fields = $this->getSensitiveFieldsName();
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...
186
        foreach ($params as $k => $v) {
187
            if (in_array($k, $sensitive_fields, true)) {
188
                $params[$k] = $this->encryptSensitiveInformation($v);
189
            }
190
        }
191
192
        return $params;
193
    }
194
195
    /**
196
     * To id card, mobile phone number and other fields sensitive information encryption.
197
     *
198
     * @param string $string
199
     *
200
     * @return string
201
     *
202
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
203
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
204
     */
205
    protected function encryptSensitiveInformation(string $string)
206
    {
207
        $certificates = $this->app['config']->get('certificate');
208
        if (null === $certificates) {
209
            throw new InvalidArgumentException('config certificate connot be empty.');
210
        }
211
212
        $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...
213
        $publicKeyResource = openssl_get_publickey($certificates);
214
        $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...
215
        openssl_free_key($publicKeyResource);
216
        if ($f) {
217
            return base64_encode($encrypted);
218
        }
219
220
        throw new EncryptException('Encryption of sensitive information failed');
221
    }
222
223
    /**
224
     * get sensitive fields name.
225
     *
226
     * @return array
227
     */
228
    protected function getSensitiveFieldsName()
229
    {
230
        return [
231
            'id_card_name',
232
            'id_card_number',
233
            'account_name',
234
            'account_number',
235
            'contact',
236
            'contact_phone',
237
            'contact_email',
238
            'legal_person',
239
            'mobile_phone',
240
            'email',
241
        ];
242
    }
243
244
    /**
245
     * getSign.
246
     *
247
     * @param $params
248
     *
249
     * @return string
250
     *
251
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
252
     */
253 5
    protected function getSign($params)
254
    {
255 5
        $params = array_filter($params);
256
257 5
        $key = $this->app->getKey();
258 5
        if ('HMAC-SHA256' === ($params['sign_type'] ?? 'MD5')) {
259 1
            $encryptMethod = function ($str) use ($key) {
260 1
                return hash_hmac('sha256', $str, $key);
261 1
            };
262
        } else {
263 4
            $encryptMethod = 'md5';
264
        }
265
266 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

266
        return /** @scrutinizer ignore-call */ Support\generate_sign($params, $key, $encryptMethod);
Loading history...
267
    }
268
}
269