Passed
Pull Request — master (#461)
by Songda
02:16
created

PreparePlugin::getNotifyUrl()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
c 0
b 0
f 0
dl 0
loc 7
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yansongda\Pay\Plugin\Alipay;
6
7
use Closure;
8
use Yansongda\Pay\Contract\PluginInterface;
9
use Yansongda\Pay\Exception\InvalidConfigException;
10
use Yansongda\Pay\Logger;
11
use Yansongda\Pay\Rocket;
12
13
class PreparePlugin implements PluginInterface
14
{
15
    /**
16
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
17
     * @throws \Yansongda\Pay\Exception\ContainerException
18
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
19
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
20
     */
21
    public function assembly(Rocket $rocket, Closure $next): Rocket
22
    {
23
        Logger::info('[alipay][PreparePlugin] 插件开始装载', ['rocket' => $rocket]);
24
25
        $rocket->mergePayload($this->getPayload($rocket->getParams()));
26
27
        Logger::info('[alipay][PreparePlugin] 插件装载完毕', ['rocket' => $rocket]);
28
29
        return $next($rocket);
30
    }
31
32
    /**
33
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
34
     * @throws \Yansongda\Pay\Exception\ContainerException
35
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
36
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
37
     */
38
    protected function getPayload(array $params): array
39
    {
40
        return [
41
            'app_id' => get_alipay_config($params)->get('app_id', ''),
42
            'method' => '',
43
            'format' => 'JSON',
44
            'return_url' => $this->getReturnUrl($params),
45
            'charset' => 'utf-8',
46
            'sign_type' => 'RSA2',
47
            'sign' => '',
48
            'timestamp' => date('Y-m-d H:i:s'),
49
            'version' => '1.0',
50
            'notify_url' => $this->getNotifyUrl($params),
51
            'app_auth_token' => '',
52
            'app_cert_sn' => $this->getAppCertSn($params),
53
            'alipay_root_cert_sn' => $this->getAlipayRootCertSn($params),
54
            'biz_content' => [],
55
        ];
56
    }
57
58
    /**
59
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
60
     * @throws \Yansongda\Pay\Exception\ContainerException
61
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
62
     */
63
    protected function getReturnUrl(array $params): string
64
    {
65
        if (!empty($params['_return_url'])) {
66
            return $params['_return_url'];
67
        }
68
69
        return get_alipay_config($params)->get('return_url', '');
70
    }
71
72
    /**
73
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
74
     * @throws \Yansongda\Pay\Exception\ContainerException
75
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
76
     */
77
    protected function getNotifyUrl(array $params): string
78
    {
79
        if (!empty($params['_notify_url'])) {
80
            return $params['_notify_url'];
81
        }
82
83
        return get_alipay_config($params)->get('notify_url', '');
84
    }
85
86
    /**
87
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
88
     * @throws \Yansongda\Pay\Exception\ContainerException
89
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
90
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
91
     */
92
    protected function getAppCertSn(array $params): string
93
    {
94
        $path = get_alipay_config($params)->get('app_public_cert_path');
95
96
        if (is_null($path)) {
97
            throw new InvalidConfigException(InvalidConfigException::ALIPAY_CONFIG_ERROR, 'Missing Alipay Config -- [app_public_cert_path]');
98
        }
99
100
        $cert = file_get_contents($path);
101
        $ssl = openssl_x509_parse($cert);
102
103
        return $this->getCertSn($ssl['issuer'], $ssl['serialNumber']);
104
    }
105
106
    /**
107
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
108
     * @throws \Yansongda\Pay\Exception\ContainerException
109
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
110
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
111
     */
112
    protected function getAlipayRootCertSn(array $params): string
113
    {
114
        $path = get_alipay_config($params)->get('alipay_root_cert_path');
115
116
        if (is_null($path)) {
117
            throw new InvalidConfigException(InvalidConfigException::ALIPAY_CONFIG_ERROR, 'Missing Alipay Config -- [alipay_root_cert_path]');
118
        }
119
120
        $sn = '';
121
        $exploded = explode('-----END CERTIFICATE-----', file_get_contents($path));
122
123
        foreach ($exploded as $cert) {
124
            if (empty($cert)) {
125
                continue;
126
            }
127
128
            $detail = $this->formatCert(openssl_x509_parse($cert.'-----END CERTIFICATE-----'));
129
130
            if ('sha1WithRSAEncryption' == $detail['signatureTypeLN'] || 'sha256WithRSAEncryption' == $detail['signatureTypeLN']) {
131
                $sn .= $this->getCertSn($detail['issuer'], $detail['serialNumber']).'_';
132
            }
133
        }
134
135
        return substr($sn, 0, -1);
136
    }
137
138
    protected function getCertSn(array $issuer, string $serialNumber): string
139
    {
140
        return md5(
141
            $this->array2string(array_reverse($issuer)).$serialNumber
142
        );
143
    }
144
145
    protected function array2string(array $array): string
146
    {
147
        $string = [];
148
149
        foreach ($array as $key => $value) {
150
            $string[] = $key.'='.$value;
151
        }
152
153
        return implode(',', $string);
154
    }
155
156
    protected function formatCert(array $ssl): array
157
    {
158
        if (0 === strpos($ssl['serialNumber'], '0x')) {
159
            $ssl['serialNumber'] = $this->hex2dec($ssl['serialNumberHex']);
160
        }
161
162
        return $ssl;
163
    }
164
165
    protected function hex2dec(string $hex): string
166
    {
167
        $dec = '0';
168
        $len = strlen($hex);
169
170
        for ($i = 1; $i <= $len; ++$i) {
171
            $dec = bcadd(
172
                $dec,
173
                bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i)))
174
            );
175
        }
176
177
        return $dec;
178
    }
179
}
180