Issues (9)

src/Wechat/Traits/SecurityTrait.php (1 issue)

Severity
1
<?php
2
3
namespace Nilnice\Payment\Wechat\Traits;
4
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Str;
7
use Nilnice\Payment\Constant;
8
use Nilnice\Payment\Exception\InvalidKeyException;
9
10
trait SecurityTrait
11
{
12
    /**
13
     * Generate signature.
14
     *
15
     * @param array       $array
16
     * @param string|null $key
17
     *
18
     * @return string
19
     *
20
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
21
     */
22 3
    public static function generateSign(array $array, $key = null) : string
23
    {
24 3
        if ($key === null) {
25 3
            throw new InvalidKeyException(
26 3
                'Invalid Wechat [key] configuration.',
27 3
                Constant::WX_PAY_KEY_INVALID
28
            );
29
        }
30
31
        ksort($array);
32
        $string = md5(self::getSignContent($array) . '&key=' . $key);
33
        $string = strtoupper($string);
34
35
        return $string;
36
    }
37
38
    /**
39
     * Get signature content.
40
     *
41
     * @param array $array
42
     *
43
     * @return string
44
     */
45
    public static function getSignContent(array $array) : string
46
    {
47
        $string = '';
48
        foreach ($array as $key => $val) {
49
            if ($key !== 'sign' && $val !== '' && ! \is_array($val)) {
50
                $string .= $key . '=' . $val . '&';
51
            }
52
        }
53
54
        return rtrim($string, '&');
55
    }
56
57
    /**
58
     * Verify signature.
59
     *
60
     * @param array       $array
61
     * @param string|null $key
62
     * @param bool        $isSync
63
     * @param string|null $sign
64
     *
65
     * @return bool
66
     *
67
     * @throws \Nilnice\Payment\Exception\InvalidKeyException
68
     */
69
    public static function verifySign(
70
        array $array,
71
        $key = null,
72
        $isSync = false,
73
        $sign = null
74
    ) : bool {
75
        if ($key === null) {
76
            throw new InvalidKeyException(
77
                'Invalid Alipay [public key] configuration.',
78
                Constant::ALI_PAY_PUBLIC_KEY_INVALID
79
            );
80
        }
81
82
        if (Str::endsWith($key, '.pem')) {
83
            $key = openssl_pkey_get_public($key);
84
        } else {
85
            $key = self::getKey($key);
86
        }
87
88
        $sign = $sign ?? Arr::get($array, 'sign');
89
        $data = $isSync
90
            ? mb_convert_encoding(
91
                json_encode($array, JSON_UNESCAPED_UNICODE),
92
                'GB2312',
93
                'UTF-8'
94
            )
95
            : self::getSignContent($array, true);
0 ignored issues
show
The call to Nilnice\Payment\Wechat\T...Trait::getSignContent() has too many arguments starting with true. ( Ignorable by Annotation )

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

95
            : self::/** @scrutinizer ignore-call */ getSignContent($array, true);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
96
        $sign = base64_decode($sign);
97
        $result = openssl_verify($data, $sign, $key, OPENSSL_ALGO_SHA256) === 1;
98
99
        return $result === 1;
100
    }
101
102
    /**
103
     * To encoding.
104
     *
105
     * @param array  $array
106
     * @param string $to
107
     * @param string $from
108
     *
109
     * @return array
110
     */
111
    public static function toEncoding(
112
        array $array,
113
        $to = 'GB2312',
114
        $from = 'UTF-8'
115
    ) : array {
116
        $data = [];
117
        foreach ($array as $key => $val) {
118
            if (\is_array($val)) {
119
                $data[$key] = self::toEncoding((array)$val, $to, $from);
120
            } else {
121
                $data[$key] = mb_convert_encoding($val, $to, $from);
122
            }
123
        }
124
125
        return $data;
126
    }
127
128
    /**
129
     * Get key.
130
     *
131
     * @param string $key
132
     * @param bool   $isPublicKey
133
     *
134
     * @return string
135
     */
136
    public static function getKey(
137
        string $key,
138
        bool $isPublicKey = true
139
    ) : string {
140
        $char = $isPublicKey ? 'PUBLIC' : 'RSA PRIVATE';
141
        $format = "-----BEGIN %s KEY-----\n%s\n-----END %s KEY-----";
142
        $key = wordwrap($key, 64, PHP_EOL, true);
143
        $string = sprintf($format, $char, $key, $char);
144
145
        return $string;
146
    }
147
}
148