Passed
Pull Request — master (#662)
by Songda
03:38
created

PreparePlugin::getCertId()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 11
c 1
b 0
f 0
dl 0
loc 22
rs 9.9
cc 3
nc 3
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yansongda\Pay\Plugin\Unipay;
6
7
use Closure;
8
use Yansongda\Pay\Contract\ConfigInterface;
9
use Yansongda\Pay\Contract\PluginInterface;
10
use Yansongda\Pay\Exception\Exception;
11
use Yansongda\Pay\Exception\InvalidConfigException;
12
use Yansongda\Pay\Logger;
13
use Yansongda\Pay\Pay;
14
use Yansongda\Pay\Rocket;
15
use Yansongda\Supports\Str;
16
17
class PreparePlugin implements PluginInterface
18
{
19
    /**
20
     * @throws \Yansongda\Pay\Exception\ContainerException
21
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
22
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
23
     */
24
    public function assembly(Rocket $rocket, Closure $next): Rocket
25
    {
26
        Logger::info('[unipay][PreparePlugin] 插件开始装载', ['rocket' => $rocket]);
27
28
        $rocket->mergePayload($this->getPayload($rocket->getParams()));
29
30
        Logger::info('[unipay][PreparePlugin] 插件装载完毕', ['rocket' => $rocket]);
31
32
        return $next($rocket);
33
    }
34
35
    /**
36
     * @throws \Yansongda\Pay\Exception\ContainerException
37
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
38
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
39
     */
40
    protected function getPayload(array $params): array
41
    {
42
        $config = get_unipay_config($params);
43
44
        $init = [
45
            'version' => '5.1.0',
46
            'encoding' => 'utf-8',
47
            'bizType' => '000201',
48
            'backUrl' => $config['notify_url'] ?? '',
49
            'currencyCode' => '156',
50
            'txnType' => '01',
51
            'txnSubType' => '01',
52
            'accessType' => '0',
53
            'signature' => '',
54
            'signMethod' => '01',
55
            'channelType' => '07',
56
            'merId' => $config['mch_id'] ?? '',
57
            'frontUrl' => $config['return_url'] ?? '',
58
            'certId' => $this->getCertId($params['_config'] ?? 'default', $config),
59
        ];
60
61
        return array_merge(
62
            $init,
63
            array_filter($params, fn ($v, $k) => !Str::startsWith(strval($k), '_'), ARRAY_FILTER_USE_BOTH),
64
        );
65
    }
66
67
    /**
68
     * @throws \Yansongda\Pay\Exception\ContainerException
69
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
70
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
71
     */
72
    protected function getCertId(string $tenant, array $config): string
73
    {
74
        if (!empty($config['cert_id'])) {
75
            return $config['cert_id'];
76
        }
77
78
        $certs = $this->getCerts($config);
79
        $ssl = openssl_x509_parse($certs['cert'] ?? '');
80
81
        if (false === $ssl) {
82
            throw new InvalidConfigException(Exception::UNIPAY_CONFIG_ERROR, 'Parse `mch_cert_path` Error');
83
        }
84
85
        $certs['cert_id'] = $ssl['serialNumber'] ?? '';
86
87
        $unipay = array_merge($config, ['certs' => $certs]);
88
89
        Pay::set(ConfigInterface::class, Pay::get(ConfigInterface::class)->merge([
90
            'unipay' => [$tenant => $unipay],
91
        ]));
92
93
        return $certs['cert_id'];
94
    }
95
96
    /**
97
     * @return array ['cert' => 公钥, 'pkey' => 私钥, 'extracerts' => array]
98
     *
99
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
100
     */
101
    protected function getCerts(array $config): array
102
    {
103
        $path = $config['mch_cert_path'] ?? null;
104
        $password = $config['mch_cert_password'] ?? null;
105
106
        if (is_null($path) || is_null($password)) {
107
            throw new InvalidConfigException(Exception::UNIPAY_CONFIG_ERROR, 'Missing Unipay Config -- [mch_cert_path] or [mch_cert_password]');
108
        }
109
110
        if(false === openssl_pkcs12_read(file_get_contents($path), $certs, $password)){
111
            throw new InvalidConfigException(Exception::UNIPAY_CONFIG_ERROR, 'Read `mch_cert_path` Error');
112
        }
113
114
        return $certs;
115
    }
116
}
117