Completed
Pull Request — master (#1556)
by wannanbigpig
14:01
created

BaseClient::request()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 31
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 19
nc 8
nop 5
dl 0
loc 31
rs 9.3222
c 0
b 0
f 0
ccs 18
cts 18
cp 1
crap 5
1
<?php
2
/*
3
 * This file is part of the overtrue/wechat.
4
 *
5
 * (c) overtrue <[email protected]>
6
 *
7
 * This source file is subject to the MIT license that is bundled
8
 * with this source code in the file LICENSE.
9
 */
10
11
namespace EasyWeChat\MicroMerchant\Kernel;
12
13
use EasyWeChat\Kernel\Support;
14
use EasyWeChat\Kernel\Traits\HasHttpRequests;
15
use EasyWeChat\MicroMerchant\Application;
16
use EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException;
17
use GuzzleHttp\MessageFormatter;
18
use GuzzleHttp\Middleware;
19
20
/**
21
 * Class BaseClient.
22
 *
23
 * @author overtrue <[email protected]>
24
 */
25
class BaseClient
26
{
27
    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...
28
        request as performRequest;
29
    }
30
31
    /**
32
     * @var string
33
     */
34
    protected $microCertificates;
35
36
    /**
37
     * @var string
38
     */
39
    protected $certificates;
40
41
    /**
42
     * @var \EasyWeChat\MicroMerchant\Application
43
     */
44
    protected $app;
45
46
    /**
47
     * Constructor
48
     *
49
     * @param  \EasyWeChat\MicroMerchant\Application  $app
50
     */
51 21
    public function __construct(Application $app)
52
    {
53 21
        $this->app = $app;
54
55 21
        $this->microCertificates = $this->app['config']->mch_id.'_micro_certificates';
56
57 21
        $this->setHttpClient($this->app['http_client']);
58 21
    }
59
60
    /**
61
     * Extra request params.
62
     *
63
     * @return array
64
     */
65 4
    protected function prepends()
66
    {
67 4
        return [];
68
    }
69
70
    /**
71
     * request
72
     *
73
     * @param  string  $endpoint
74
     * @param  array   $params
75
     * @param  string  $method
76
     * @param  array   $options
77
     * @param  bool    $returnResponse
78
     *
79
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
80
     *
81
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
82
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
83
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
84
     */
85 4
    protected function request(string $endpoint, array $params = [], $method = 'post', array $options = [], $returnResponse = false)
86
    {
87
        $base = [
88 4
            'mch_id' => $this->app['config']['mch_id'],
89
        ];
90
91 4
        $params = array_filter(array_merge($base, $this->prepends(), $params));
92
93 4
        $secretKey = $this->app->getKey();
94 4
        if ('HMAC-SHA256' === ($params['sign_type'] ?? 'MD5')) {
95 1
            $encryptMethod = function ($str) use ($secretKey) {
96 1
                return hash_hmac('sha256', $str, $secretKey);
97 1
            };
98
        } else {
99 3
            $encryptMethod = 'md5';
100
        }
101 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

101
        $params['sign'] = /** @scrutinizer ignore-call */ Support\generate_sign($params, $secretKey, $encryptMethod);
Loading history...
102
103 4
        $options = array_merge([
104 4
            'body' => Support\XML::build($params),
105
        ], $options);
106
107 4
        $this->pushMiddleware($this->logMiddleware(), 'log');
108
109 4
        $response = $this->performRequest($endpoint, $method, $options);
110 4
        $response = $returnResponse ? $response : $this->castResponseToType($response, $this->app->config->get('response_type'));
111
        // auto verify signature
112 4
        if (!$returnResponse && ($this->app->config->get('response_type') ?? 'array') === 'array') {
113 1
            $this->app->verifySignature($response);
114
        }
115 4
        return $response;
116
    }
117
118
    /**
119
     * Log the request.
120
     *
121
     * @return \Closure
122
     */
123 4
    protected function logMiddleware()
124
    {
125 4
        $formatter = new MessageFormatter($this->app['config']['http.log_template'] ?? MessageFormatter::DEBUG);
126
127 4
        return Middleware::log($this->app['logger'], $formatter);
128
    }
129
130
    /**
131
     * Make a request and return raw response.
132
     *
133
     * @param          $endpoint
134
     * @param  array   $params
135
     * @param  string  $method
136
     * @param  array   $options
137
     *
138
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
139
     *
140
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
141
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
142
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
143
     */
144 4
    protected function requestRaw($endpoint, array $params = [], $method = 'post', array $options = [])
145
    {
146 4
        return $this->request($endpoint, $params, $method, $options, true);
147
    }
148
149
    /**
150
     * Request with SSL.
151
     *
152
     * @param          $endpoint
153
     * @param  array   $params
154
     * @param  string  $method
155
     * @param  array   $options
156
     *
157
     * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
158
     *
159
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
160
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
161
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
162
     */
163 1
    protected function safeRequest($endpoint, array $params, $method = 'post', array $options = [])
164
    {
165 1
        $options = array_merge([
166 1
            'cert'    => $this->app['config']->get('cert_path'),
167 1
            'ssl_key' => $this->app['config']->get('key_path'),
168
        ], $options);
169
170 1
        return $this->request($endpoint, $params, $method, $options);
171
    }
172
173
    /**
174
     * processing parameters contain fields that require sensitive information encryption.
175
     *
176
     * @param  array  $params
177
     *
178
     * @return array
179
     *
180
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
181
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
182
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
183
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidExtensionException
184
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\InvalidSignException
185
     * @throws \Psr\SimpleCache\InvalidArgumentException
186
     */
187
    protected function processingParams(array $params)
188
    {
189
        $cert               = $this->app->getCertficates();
190
        $this->certificates = $cert['certificates'];
191
        $params['cert_sn']  = $cert['serial_no'];
192
        $sensitive_fields   = $this->getSensitiveFieldsName();
193
        foreach ($params as $k => $v) {
194
            if (in_array($k, $sensitive_fields)) {
195
                $params[$k] = $this->encryptionOfSensitiveInformation($v);
196
            }
197
        }
198
        return $params;
199
    }
200
201
    /**
202
     * To id card, mobile phone number and other fields sensitive information encryption
203
     *
204
     * @param  string  $string
205
     *
206
     * @return string
207
     *
208
     * @throws \EasyWeChat\MicroMerchant\Kernel\Exceptions\EncryptException
209
     */
210
    protected function encryptionOfSensitiveInformation(string $string)
211
    {
212
        $encrypted         = '';
213
        $publicKeyResource = openssl_get_publickey($this->certificates);
214
        $f                 = openssl_public_encrypt($string, $encrypted, $publicKeyResource);
215
        openssl_free_key($publicKeyResource);
216
        if ($f) {
217
            return base64_encode($encrypted);
218
        }
219
        throw new EncryptException('Encryption of sensitive information failed');
220
    }
221
222
    /**
223
     * get sensitive fields name
224
     *
225
     * @return array
226
     */
227
    protected function getSensitiveFieldsName()
228
    {
229
        return [
230
            'id_card_name',
231
            'id_card_number',
232
            'account_name',
233
            'account_number',
234
            'contact',
235
            'contact_phone',
236
            'contact_email',
237
            'legal_person',
238
            'mobile_phone',
239
            'email',
240
        ];
241
    }
242
}
243