Completed
Push — master ( d40843...56c44b )
by Songda
02:04 queued 11s
created

PreparePlugin::getCertSn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 6
rs 10
c 0
b 0
f 0
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\Rocket;
11
12
class PreparePlugin implements PluginInterface
13
{
14
    /**
15
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
16
     * @throws \Yansongda\Pay\Exception\ContainerException
17
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
18
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
19
     */
20
    public function assembly(Rocket $rocket, Closure $next): Rocket
21
    {
22
        $rocket->mergePayload($this->getPayload($rocket->getParams()));
23
24
        return $next($rocket);
25
    }
26
27
    /**
28
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
29
     * @throws \Yansongda\Pay\Exception\ContainerException
30
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
31
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
32
     */
33
    protected function getPayload(array $params): array
34
    {
35
        return [
36
            'app_id' => get_alipay_config($params)->get('app_id', ''),
37
            'method' => '',
38
            'format' => 'JSON',
39
            'return_url' => get_alipay_config($params)->get('return_url', ''),
40
            'charset' => 'utf-8',
41
            'sign_type' => 'RSA2',
42
            'sign' => '',
43
            'timestamp' => date('Y-m-d H:i:s'),
44
            'version' => '1.0',
45
            'notify_url' => get_alipay_config($params)->get('notify_url', ''),
46
            'app_auth_token' => '',
47
            'app_cert_sn' => $this->getAppCertSn($params),
48
            'alipay_root_cert_sn' => $this->getAlipayRootCertSn($params),
49
            'biz_content' => [],
50
        ];
51
    }
52
53
    /**
54
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
55
     * @throws \Yansongda\Pay\Exception\ContainerException
56
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
57
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
58
     */
59
    protected function getAppCertSn(array $params): string
60
    {
61
        $path = get_alipay_config($params)->get('app_public_cert_path');
62
63
        if (is_null($path)) {
64
            throw new InvalidConfigException(InvalidConfigException::ALIPAY_CONFIG_ERROR, 'Missing Alipay Config -- [app_public_cert_path]');
65
        }
66
67
        $cert = file_get_contents($path);
68
        $ssl = openssl_x509_parse($cert);
69
70
        return $this->getCertSn($ssl['issuer'], $ssl['serialNumber']);
71
    }
72
73
    /**
74
     * @throws \Yansongda\Pay\Exception\ContainerDependencyException
75
     * @throws \Yansongda\Pay\Exception\ContainerException
76
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
77
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
78
     */
79
    protected function getAlipayRootCertSn(array $params): string
80
    {
81
        $path = get_alipay_config($params)->get('alipay_root_cert_path');
82
83
        if (is_null($path)) {
84
            throw new InvalidConfigException(InvalidConfigException::ALIPAY_CONFIG_ERROR, 'Missing Alipay Config -- [alipay_root_cert_path]');
85
        }
86
87
        $sn = '';
88
        foreach (explode("\r\n\r\n", file_get_contents($path)) as $cert) {
89
            $detail = $this->formatCert(openssl_x509_parse($cert));
90
91
            if ('sha1WithRSAEncryption' == $detail['signatureTypeLN'] || 'sha256WithRSAEncryption' == $detail['signatureTypeLN']) {
92
                $sn .= $this->getCertSn($detail['issuer'], $detail['serialNumber']).'_';
93
            }
94
        }
95
96
        return substr($sn, 0, -1);
97
    }
98
99
    protected function getCertSn(array $issuer, string $serialNumber): string
100
    {
101
        return md5(
102
            $this->array2string(array_reverse($issuer)).$serialNumber
103
        );
104
    }
105
106
    protected function array2string(array $array): string
107
    {
108
        $string = [];
109
110
        foreach ($array as $key => $value) {
111
            $string[] = $key.'='.$value;
112
        }
113
114
        return implode(',', $string);
115
    }
116
117
    protected function formatCert(array $ssl): array
118
    {
119
        if (0 === strpos($ssl['serialNumber'], '0x')) {
120
            $ssl['serialNumber'] = $this->hex2dec($ssl['serialNumber']);
121
        }
122
123
        return $ssl;
124
    }
125
126
    protected function hex2dec(string $hex): string
127
    {
128
        $dec = 0;
129
        $len = strlen($hex);
130
131
        for ($i = 1; $i <= $len; ++$i) {
132
            $dec = bcadd(
133
                $dec,
134
                bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i)))
135
            );
136
        }
137
138
        return $dec;
139
    }
140
}
141