BaseClient::encryptSensitiveInformation()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 3
nop 1
dl 0
loc 16
ccs 0
cts 11
cp 0
crap 12
rs 9.9332
c 0
b 0
f 0
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\MicroMerchant\Application;
17
use EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException;
18
use EasyWeChat\Payment\Kernel\BaseClient as PaymentBaseClient;
19
20
/**
21
 * Class BaseClient.
22
 *
23
 * @author   liuml  <[email protected]>
24
 * @DateTime 2019-07-10  12:06
25
 */
26
class BaseClient extends PaymentBaseClient
27
{
28
    /**
29
     * @var string
30
     */
31
    protected $certificates;
32
33
    /**
34
     * BaseClient constructor.
35
     *
36
     * @param \EasyWeChat\MicroMerchant\Application $app
37
     */
38 24
    public function __construct(Application $app)
39
    {
40 24
        $this->app = $app;
0 ignored issues
show
Documentation Bug introduced by
It seems like $app of type EasyWeChat\MicroMerchant\Application is incompatible with the declared type EasyWeChat\Payment\Application of property $app.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
41
42 24
        $this->setHttpClient($this->app['http_client']);
43 24
    }
44
45
    /**
46
     * Extra request params.
47
     *
48
     * @return array
49
     */
50 4
    protected function prepends()
51
    {
52 4
        return [];
53
    }
54
55
    /**
56
     * httpUpload.
57
     *
58
     * @param string $url
59
     * @param array  $files
60
     * @param array  $form
61
     * @param array  $query
62
     * @param bool   $returnResponse
63
     *
64
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
65
     *
66
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
67
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
68
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
69
     * @throws \GuzzleHttp\Exception\GuzzleException
70
     */
71
    public function httpUpload(string $url, array $files = [], array $form = [], array $query = [], $returnResponse = false)
72
    {
73
        $multipart = [];
74
75
        foreach ($files as $name => $path) {
76
            $multipart[] = [
77
                'name' => $name,
78
                'contents' => fopen($path, 'r'),
79
            ];
80
        }
81
82
        $base = [
83
            'mch_id' => $this->app['config']['mch_id'],
84
        ];
85
86
        $form = array_merge($base, $form);
87
88
        $form['sign'] = $this->getSign($form);
89
90
        foreach ($form as $name => $contents) {
91
            $multipart[] = compact('name', 'contents');
92
        }
93
94
        $options = [
95
            'query' => $query,
96
            'multipart' => $multipart,
97
            'connect_timeout' => 30,
98
            'timeout' => 30,
99
            'read_timeout' => 30,
100
            'cert' => $this->app['config']->get('cert_path'),
101
            'ssl_key' => $this->app['config']->get('key_path'),
102
        ];
103
104
        $this->pushMiddleware($this->logMiddleware(), 'log');
105
106
        $response = $this->performRequest($url, 'POST', $options);
107
108
        $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
109
        // auto verify signature
110
        if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
111
            $this->app->verifySignature($this->castResponseToType($response, 'array'));
0 ignored issues
show
Bug introduced by
The method verifySignature() does not exist on EasyWeChat\Payment\Application. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

111
            $this->app->/** @scrutinizer ignore-call */ 
112
                        verifySignature($this->castResponseToType($response, 'array'));
Loading history...
112
        } else {
113
            $this->app->verifySignature($result);
114
        }
115
116
        return $result;
117
    }
118
119
    /**
120
     * request.
121
     *
122
     * @param string $endpoint
123
     * @param array  $params
124
     * @param string $method
125
     * @param array  $options
126
     * @param bool   $returnResponse
127
     *
128
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
129
     *
130
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
131
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
132
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
133
     * @throws \GuzzleHttp\Exception\GuzzleException
134
     */
135 4
    protected function request(string $endpoint, array $params = [], $method = 'post', array $options = [], $returnResponse = false)
136
    {
137
        $base = [
138 4
            'mch_id' => $this->app['config']['mch_id'],
139
        ];
140
141 4
        $params = array_merge($base, $this->prepends(), $params);
142 4
        $params['sign'] = $this->getSign($params);
143 4
        $options = array_merge([
144 4
            'body' => Support\XML::build($params),
145
        ], $options);
146
147 4
        $this->pushMiddleware($this->logMiddleware(), 'log');
148 4
        $response = $this->performRequest($endpoint, $method, $options);
149 4
        $result = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
150
        // auto verify signature
151 4
        if ($returnResponse || 'array' !== ($this->app->config->get('response_type') ?? 'array')) {
152 4
            $this->app->verifySignature($this->castResponseToType($response, 'array'));
153
        } else {
154 1
            $this->app->verifySignature($result);
155
        }
156
157 4
        return $result;
158
    }
159
160
    /**
161
     * processing parameters contain fields that require sensitive information encryption.
162
     *
163
     * @param array $params
164
     *
165
     * @return array
166
     *
167
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
168
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
169
     */
170
    protected function processParams(array $params)
171
    {
172
        $serial_no = $this->app['config']->get('serial_no');
173
        if (null === $serial_no) {
174
            throw new InvalidArgumentException('config serial_no connot be empty.');
175
        }
176
177
        $params['cert_sn'] = $serial_no;
178
        $sensitive_fields = $this->getSensitiveFieldsName();
179
        foreach ($params as $k => $v) {
180
            if (in_array($k, $sensitive_fields, true)) {
181
                $params[$k] = $this->encryptSensitiveInformation($v);
182
            }
183
        }
184
185
        return $params;
186
    }
187
188
    /**
189
     * To id card, mobile phone number and other fields sensitive information encryption.
190
     *
191
     * @param string $string
192
     *
193
     * @return string
194
     *
195
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
196
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
197
     */
198
    protected function encryptSensitiveInformation(string $string)
199
    {
200
        $certificates = $this->app['config']->get('certificate');
201
        if (null === $certificates) {
202
            throw new InvalidArgumentException('config certificate connot be empty.');
203
        }
204
205
        $encrypted = '';
206
        $publicKeyResource = openssl_get_publickey($certificates);
207
        $f = openssl_public_encrypt($string, $encrypted, $publicKeyResource);
208
        openssl_free_key($publicKeyResource);
209
        if ($f) {
210
            return base64_encode($encrypted);
211
        }
212
213
        throw new EncryptException('Encryption of sensitive information failed');
214
    }
215
216
    /**
217
     * get sensitive fields name.
218
     *
219
     * @return array
220
     */
221
    protected function getSensitiveFieldsName()
222
    {
223
        return [
224
            'id_card_name',
225
            'id_card_number',
226
            'account_name',
227
            'account_number',
228
            'contact',
229
            'contact_phone',
230
            'contact_email',
231
            'legal_person',
232
            'mobile_phone',
233
            'email',
234
        ];
235
    }
236
237
    /**
238
     * getSign.
239
     *
240
     * @param array $params
241
     *
242
     * @return string
243
     *
244
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
245
     */
246 5
    protected function getSign(array $params)
247
    {
248 5
        $params = array_filter($params);
249
250 5
        $key = $this->app->getKey();
251
252 5
        $encryptMethod = Support\get_encrypt_method(Support\Arr::get($params, 'sign_type', 'MD5'), $key);
0 ignored issues
show
Bug introduced by
The function get_encrypt_method 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

252
        $encryptMethod = /** @scrutinizer ignore-call */ Support\get_encrypt_method(Support\Arr::get($params, 'sign_type', 'MD5'), $key);
Loading history...
253
254 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

254
        return /** @scrutinizer ignore-call */ Support\generate_sign($params, $key, $encryptMethod);
Loading history...
255
    }
256
}
257