Passed
Pull Request — master (#678)
by Songda
02:10
created

RadarSignPlugin::getSign()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 4
c 1
b 0
f 0
dl 0
loc 9
rs 10
cc 1
nc 1
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\Exception;
10
use Yansongda\Pay\Exception\InvalidConfigException;
11
12
use function Yansongda\Pay\get_alipay_config;
13
use function Yansongda\Pay\get_private_cert;
14
15
use Yansongda\Pay\Logger;
16
use Yansongda\Pay\Pay;
17
use Yansongda\Pay\Provider\Alipay;
18
use Yansongda\Pay\Request;
19
use Yansongda\Pay\Rocket;
20
use Yansongda\Supports\Collection;
21
use Yansongda\Supports\Str;
22
23
class RadarSignPlugin implements PluginInterface
24
{
25
    /**
26
     * @throws \Yansongda\Pay\Exception\ContainerException
27
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
28
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
29
     */
30
    public function assembly(Rocket $rocket, Closure $next): Rocket
31
    {
32
        Logger::info('[alipay][RadarSignPlugin] 插件开始装载', ['rocket' => $rocket]);
33
34
        $this->sign($rocket);
35
36
        $this->reRadar($rocket);
37
38
        Logger::info('[alipay][RadarSignPlugin] 插件装载完毕', ['rocket' => $rocket]);
39
40
        return $next($rocket);
41
    }
42
43
    /**
44
     * @throws \Yansongda\Pay\Exception\ContainerException
45
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
46
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
47
     */
48
    protected function sign(Rocket $rocket): void
49
    {
50
        $this->formatPayload($rocket);
51
52
        $sign = $this->getSign($rocket);
53
54
        $rocket->mergePayload(['sign' => $sign]);
55
    }
56
57
    /**
58
     * @throws \Yansongda\Pay\Exception\ContainerException
59
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
60
     */
61
    protected function reRadar(Rocket $rocket): void
62
    {
63
        $params = $rocket->getParams();
64
65
        $rocket->setRadar(new Request(
66
            $this->getMethod($params),
67
            $this->getUrl($params),
68
            $this->getHeaders(),
69
            $this->getBody($rocket->getPayload()),
0 ignored issues
show
Bug introduced by
It seems like $rocket->getPayload() can also be of type null; however, parameter $payload of Yansongda\Pay\Plugin\Ali...arSignPlugin::getBody() does only seem to accept Yansongda\Supports\Collection, maybe add an additional type check? ( Ignorable by Annotation )

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

69
            $this->getBody(/** @scrutinizer ignore-type */ $rocket->getPayload()),
Loading history...
70
        ));
71
    }
72
73
    protected function formatPayload(Rocket $rocket): void
74
    {
75
        $payload = $rocket->getPayload()->filter(fn ($v, $k) => '' !== $v && !is_null($v) && 'sign' != $k);
76
77
        $contents = array_filter($payload->get('biz_content', []), fn ($v, $k) => !Str::startsWith(strval($k), '_'), ARRAY_FILTER_USE_BOTH);
78
79
        $rocket->setPayload(
80
            $payload->merge(['biz_content' => json_encode($contents)])
81
        );
82
    }
83
84
    /**
85
     * @throws \Yansongda\Pay\Exception\ContainerException
86
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
87
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
88
     */
89
    protected function getSign(Rocket $rocket): string
90
    {
91
        $privateKey = $this->getPrivateKey($rocket->getParams());
92
93
        $content = $rocket->getPayload()->sortKeys()->toString();
94
95
        openssl_sign($content, $sign, $privateKey, OPENSSL_ALGO_SHA256);
96
97
        return base64_encode($sign);
98
    }
99
100
    /**
101
     * @throws \Yansongda\Pay\Exception\ContainerException
102
     * @throws \Yansongda\Pay\Exception\InvalidConfigException
103
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
104
     */
105
    protected function getPrivateKey(array $params): string
106
    {
107
        $privateKey = get_alipay_config($params)['app_secret_cert'] ?? null;
108
109
        if (is_null($privateKey)) {
110
            throw new InvalidConfigException(Exception::ALIPAY_CONFIG_ERROR, 'Missing Alipay Config -- [app_secret_cert]');
111
        }
112
113
        return get_private_cert($privateKey);
114
    }
115
116
    protected function getMethod(array $params): string
117
    {
118
        return strtoupper($params['_method'] ?? 'POST');
119
    }
120
121
    /**
122
     * @throws \Yansongda\Pay\Exception\ContainerException
123
     * @throws \Yansongda\Pay\Exception\ServiceNotFoundException
124
     */
125
    protected function getUrl(array $params): string
126
    {
127
        $config = get_alipay_config($params);
128
129
        return Alipay::URL[$config['mode'] ?? Pay::MODE_NORMAL];
130
    }
131
132
    protected function getHeaders(): array
133
    {
134
        return [
135
            'Content-Type' => 'application/x-www-form-urlencoded',
136
        ];
137
    }
138
139
    protected function getBody(Collection $payload): string
140
    {
141
        return $payload->query();
142
    }
143
}
144