Helpers::getSignContentUrlencode()   A
last analyzed

Complexity

Conditions 5
Paths 4

Size

Total Lines 20
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 12
c 0
b 0
f 0
nc 4
nop 1
dl 0
loc 20
ccs 12
cts 12
cp 1
crap 5
rs 9.5555
1
<?php
2
/*
3
 * This file is part of the wannanbigpig/alipay-sdk-php.
4
 *
5
 * (c) wannanbigpig <[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 EasyAlipay\Kernel\Traits;
12
13
use EasyAlipay\Kernel\Exceptions\InvalidSignException;
14
use WannanBigPig\Supports\Exceptions\InvalidArgumentException;
15
16
/**
17
 * Class Helpers
18
 *
19
 * @author   liuml  <[email protected]>
20
 * @DateTime 2019-07-18  17:00
21
 */
22
trait Helpers
23
{
24
    /**
25
     * generateSign.
26
     *
27
     * @param        $data
28
     * @param string $signType
29
     *
30
     * @return string
31
     *
32
     * @throws \WannanBigPig\Supports\Exceptions\InvalidArgumentException
33
     */
34 16
    public function generateSign($data, $signType = 'RSA2')
35
    {
36 16
        return $this->sign($this->getSignContent($data), $signType);
37
    }
38
39
    /**
40
     * getSignContent.
41
     *
42
     * @param $params
43
     *
44
     * @return string
45
     */
46 18
    public function getSignContent($params)
47
    {
48 18
        ksort($params);
49
50 18
        $stringToBeSigned = "";
51 18
        $i = 0;
52 18
        foreach ($params as $k => $v) {
53 18
            if (false === $this->checkEmpty($v) && "@" !== substr($v, 0, 1)) {
54 18
                if ($i === 0) {
55 18
                    $stringToBeSigned .= "$k"."="."$v";
56
                } else {
57 16
                    $stringToBeSigned .= "&"."$k"."="."$v";
58
                }
59 18
                $i++;
60
            }
61
        }
62
63 18
        unset($k, $v);
64
65 18
        return $stringToBeSigned;
66
    }
67
68
    /**
69
     * This method does URLEncode for values.
70
     *
71
     * @param $params
72
     *
73
     * @return string
74
     */
75 36
    public function getSignContentUrlencode($params)
76
    {
77 36
        ksort($params);
78
79 36
        $stringToBeSigned = "";
80 36
        $i = 0;
81 36
        foreach ($params as $k => $v) {
82 8
            if (false === $this->checkEmpty($v) && "@" !== substr($v, 0, 1)) {
83 8
                if ($i === 0) {
84 8
                    $stringToBeSigned .= "$k"."=".urlencode($v);
85
                } else {
86 4
                    $stringToBeSigned .= "&"."$k"."=".urlencode($v);
87
                }
88 8
                $i++;
89
            }
90
        }
91
92 36
        unset($k, $v);
93
94 36
        return $stringToBeSigned;
95
    }
96
97
    /**
98
     * sign.
99
     *
100
     * @param        $data
101
     * @param string $signType
102
     *
103
     * @return string
104
     *
105
     * @throws \WannanBigPig\Supports\Exceptions\InvalidArgumentException
106
     */
107 20
    protected function sign($data, $signType = "RSA2")
108
    {
109 20
        $rsaPrivateKeyFilePath = $this->app['config']->get('private_key_path');
110 20
        if ($this->checkEmpty($rsaPrivateKeyFilePath)) {
111 4
            $priKey = $this->app['config']['private_key'];
112
            $priKey = "-----BEGIN RSA PRIVATE KEY-----\n".
113 4
                wordwrap($priKey, 64, "\n", true).
114 4
                "\n-----END RSA PRIVATE KEY-----";
115
        } else {
116 16
            $priKey = file_get_contents($rsaPrivateKeyFilePath);
117
        }
118
119 20
        $res = openssl_get_privatekey($priKey);
120
121 20
        if ($res === false) {
122 2
            throw new InvalidArgumentException('Invalid private_key configuration');
123
        }
124
125 18
        if ("RSA2" === $signType) {
126 18
            openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
127
        } else {
128 2
            openssl_sign($data, $sign, $res);
129
        }
130
131
        // Release resources
132 18
        openssl_free_key($res);
133
134 18
        return base64_encode($sign);
135
    }
136
137
    /**
138
     * checkEmpty.
139
     *
140
     * @param $value
141
     *
142
     * @return bool
143
     */
144 60
    protected function checkEmpty($value)
145
    {
146 60
        if ($value === null) {
147 38
            return true;
148
        }
149
150 56
        if (is_string($value)) {
151 54
            if (trim($value) === "") {
152 54
                return true;
153
            }
154 10
        } elseif (is_array($value)) {
155 6
            if (count($value) < 1) {
156 2
                return true;
157
            }
158
        }
159
160
161 54
        return false;
162
    }
163
164
    /**
165
     * parserSignSource.
166
     *
167
     * @param array       $response
168
     * @param string|null $apiMethod
169
     *
170
     * @return array|mixed
171
     */
172 4
    public function parserSignSource(array $response, string $apiMethod = null)
173
    {
174 4
        $response_suffix = '_response';
175 4
        $error_respones = 'error_response';
176 4
        $apiMethod = $this->app['config']['api_method'] ?? $apiMethod;
177 4
        $rootNodeName = str_replace(".", "_", $apiMethod).$response_suffix;
178
179 4
        if (isset($response[$rootNodeName])) {
180 2
            return $response[$rootNodeName];
181 4
        } elseif (isset($response[$error_respones])) {
182 2
            return $response[$error_respones];
183
        } else {
184 2
            return $response;
185
        }
186
    }
187
188
    /**
189
     * verify sign.
190
     *
191
     * @param string $data
192
     * @param        $sign
193
     * @param string $signType
194
     *
195
     * @return bool
196
     *
197
     * @throws \WannanBigPig\Supports\Exceptions\InvalidArgumentException
198
     */
199 8
    public function verify(string $data, $sign, $signType = 'RSA2')
200
    {
201 8
        $alipayPublicKeyPath = $this->app['config']->get('alipay_public_Key_path');
202 8
        if ($this->checkEmpty($alipayPublicKeyPath)) {
203 2
            $pubKey = $this->app['config']->get('alipay_public_Key');
204
            $pubKey = "-----BEGIN PUBLIC KEY-----\n".
205 2
                wordwrap($pubKey, 64, "\n", true).
206 2
                "\n-----END PUBLIC KEY-----";
207
        } else {
208
            // Read public key file
209 8
            $pubKey = file_get_contents($alipayPublicKeyPath);
210
        }
211
212
        // Convert to openssl format key
213 8
        $res = openssl_get_publickey($pubKey);
214
215 8
        if ($res === false) {
216 2
            throw new InvalidArgumentException('Invalid alipay_public_Key configuration');
217
        }
218
219
        // Call openssl built-in method checksum, return bool value
220 8
        if ("RSA2" === $signType) {
221 8
            $result = (openssl_verify($data, base64_decode($sign, true), $res, OPENSSL_ALGO_SHA256) === 1);
222
        } else {
223 2
            $result = (openssl_verify($data, base64_decode($sign, true), $res) === 1);
224
        }
225
226
        // Release resources
227 8
        openssl_free_key($res);
228
229 8
        return $result;
230
    }
231
232
    /**
233
     * checkResponseSign.
234
     *
235
     * @param             $content
236
     * @param string|null $sign
237
     *
238
     * @return bool
239
     *
240
     * @throws \EasyAlipay\Kernel\Exceptions\InvalidSignException
241
     * @throws \WannanBigPig\Supports\Exceptions\InvalidArgumentException
242
     */
243 4
    public function checkResponseSign($content, string $sign = null)
244
    {
245 4
        if (!is_null($sign)) {
246 4
            $result = $this->verify(
247 4
                $content,
248 4
                $sign,
249 4
                $this->app['config']->get('sign_type', 'RSA2')
250
            );
251
        } else {
252 2
            throw new InvalidSignException('check sign Fail! The reason : sign data is Empty', 0, $content);
253
        }
254
255 4
        if (!$result) {
256 2
            throw new InvalidSignException(sprintf(
257 2
                '"%s" method responds to parameter validation signature error',
258 2
                $this->app['config']['api_method']
259
            ));
260
        }
261
262 2
        return $result;
263
    }
264
}
265