Passed
Push — master ( d1dcd3...a849c7 )
by Songda
01:59
created

AddPayloadSignaturePlugin::getSignature()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
dl 0
loc 24
rs 9.7998
c 1
b 0
f 0
cc 3
nc 3
nop 4
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yansongda\Pay\Plugin\Wechat;
6
7
use Closure;
8
use Throwable;
9
use Yansongda\Pay\Contract\PluginInterface;
10
use Yansongda\Pay\Exception\ContainerException;
11
use Yansongda\Pay\Exception\Exception;
12
use Yansongda\Pay\Exception\InvalidConfigException;
13
use Yansongda\Pay\Exception\InvalidParamsException;
14
use Yansongda\Pay\Exception\ServiceNotFoundException;
15
use Yansongda\Pay\Logger;
16
use Yansongda\Pay\Rocket;
17
use Yansongda\Supports\Collection;
18
use Yansongda\Supports\Str;
19
20
use function Yansongda\Pay\get_public_cert;
21
use function Yansongda\Pay\get_wechat_body;
22
use function Yansongda\Pay\get_wechat_config;
23
use function Yansongda\Pay\get_wechat_method;
24
use function Yansongda\Pay\get_wechat_sign;
25
use function Yansongda\Pay\get_wechat_url;
26
27
class AddPayloadSignaturePlugin implements PluginInterface
28
{
29
    /**
30
     * @throws ContainerException
31
     * @throws InvalidConfigException
32
     * @throws InvalidParamsException
33
     * @throws ServiceNotFoundException
34
     * @throws Throwable                随机数生成失败
35
     */
36
    public function assembly(Rocket $rocket, Closure $next): Rocket
37
    {
38
        Logger::debug('[Wechat][AddPayloadSignaturePlugin] 插件开始装载', ['rocket' => $rocket]);
39
40
        $config = get_wechat_config($rocket->getParams());
41
        $payload = $rocket->getPayload();
42
43
        $timestamp = time();
44
        $random = Str::random(32);
45
        $signContent = $this->getSignatureContent($config, $payload, $timestamp, $random);
46
        $signature = $this->getSignature($config, $timestamp, $random, $signContent);
47
48
        $rocket->mergePayload(['_authorization' => $signature]);
49
50
        Logger::info('[Wechat][AddPayloadSignaturePlugin] 插件装载完毕', ['rocket' => $rocket]);
51
52
        return $next($rocket);
53
    }
54
55
    /**
56
     * @throws InvalidParamsException
57
     */
58
    protected function getSignatureContent(array $config, ?Collection $payload, int $timestamp, string $random): string
59
    {
60
        $url = get_wechat_url($config, $payload);
61
        $urlPath = parse_url($url, PHP_URL_PATH);
62
        $urlQuery = parse_url($url, PHP_URL_QUERY);
63
64
        return get_wechat_method($payload)."\n".
65
            $urlPath.(empty($urlQuery) ? '' : '?'.$urlQuery)."\n".
66
            $timestamp."\n".
67
            $random."\n".
68
            get_wechat_body($payload)."\n";
69
    }
70
71
    /**
72
     * @throws InvalidConfigException
73
     */
74
    protected function getSignature(array $config, int $timestamp, string $random, string $contents): string
75
    {
76
        $mchPublicCertPath = $config['mch_public_cert_path'] ?? null;
77
78
        if (empty($mchPublicCertPath)) {
79
            throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 缺少微信配置 -- [mch_public_cert_path]');
80
        }
81
82
        $ssl = openssl_x509_parse(get_public_cert($mchPublicCertPath));
83
84
        if (empty($ssl['serialNumberHex'])) {
85
            throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 解析微信配置 [mch_public_cert_path] 出错');
86
        }
87
88
        $auth = sprintf(
89
            'mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
90
            $config['mch_id'] ?? '',
91
            $random,
92
            $timestamp,
93
            $ssl['serialNumberHex'],
94
            get_wechat_sign($config, $contents),
95
        );
96
97
        return 'WECHATPAY2-SHA256-RSA2048 '.$auth;
98
    }
99
}
100