init
- 框架初始化 - 安装插件 - 修复PHP8.4报错
This commit is contained in:
@@ -0,0 +1,214 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\ConfigInterface;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_alipay_config;
|
||||
use function Yansongda\Pay\get_tenant;
|
||||
|
||||
class PreparePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[alipay][PreparePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$rocket->mergePayload($this->getPayload($rocket->getParams()));
|
||||
|
||||
Logger::info('[alipay][PreparePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
protected function getPayload(array $params): array
|
||||
{
|
||||
$tenant = get_tenant($params);
|
||||
$config = get_alipay_config($params);
|
||||
|
||||
$payload = [
|
||||
'app_id' => $config['app_id'] ?? '',
|
||||
'method' => '',
|
||||
'format' => 'JSON',
|
||||
'return_url' => $this->getReturnUrl($params, $config),
|
||||
'charset' => 'utf-8',
|
||||
'sign_type' => 'RSA2',
|
||||
'sign' => '',
|
||||
'timestamp' => date('Y-m-d H:i:s'),
|
||||
'version' => '1.0',
|
||||
'notify_url' => $this->getNotifyUrl($params, $config),
|
||||
'app_auth_token' => $this->getAppAuthToken($params, $config),
|
||||
'biz_content' => [],
|
||||
];
|
||||
if (!empty($config['app_cert_public_key']) && !empty($config['alipay_root_cert'])) {
|
||||
$payload = array_merge($payload, ['app_cert_sn' => $this->getAppCertSn($tenant, $config), 'alipay_root_cert_sn' => $this->getAlipayRootCertSn($tenant, $config)]);
|
||||
}
|
||||
return $payload;
|
||||
}
|
||||
|
||||
protected function getReturnUrl(array $params, ?array $config): string
|
||||
{
|
||||
if (!empty($params['_return_url'])) {
|
||||
return $params['_return_url'];
|
||||
}
|
||||
|
||||
return $config['return_url'] ?? '';
|
||||
}
|
||||
|
||||
protected function getNotifyUrl(array $params, ?array $config): string
|
||||
{
|
||||
if (!empty($params['_notify_url'])) {
|
||||
return $params['_notify_url'];
|
||||
}
|
||||
|
||||
return $config['notify_url'] ?? '';
|
||||
}
|
||||
|
||||
protected function getAppAuthToken(array $params, ?array $config): string
|
||||
{
|
||||
if (!empty($params['_app_auth_token'])) {
|
||||
return $params['_app_auth_token'];
|
||||
}
|
||||
|
||||
return $config['app_auth_token'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getAppCertSn(string $tenant, ?array $config): string
|
||||
{
|
||||
if (!empty($config['app_public_cert_sn'])) {
|
||||
return $config['app_public_cert_sn'];
|
||||
}
|
||||
|
||||
$path = $config['app_public_cert_path'] ?? null;
|
||||
|
||||
if (is_null($path)) {
|
||||
throw new InvalidConfigException(Exception::ALIPAY_CONFIG_ERROR, 'Missing Alipay Config -- [app_public_cert_path]');
|
||||
}
|
||||
|
||||
$cert = file_get_contents($path);
|
||||
$ssl = openssl_x509_parse($cert);
|
||||
|
||||
if (false === $ssl) {
|
||||
throw new InvalidConfigException(Exception::ALIPAY_CONFIG_ERROR, 'Parse `app_public_cert_path` Error');
|
||||
}
|
||||
|
||||
$result = $this->getCertSn($ssl['issuer'] ?? [], $ssl['serialNumber'] ?? '');
|
||||
|
||||
Pay::get(ConfigInterface::class)->set('alipay.'.$tenant.'.app_public_cert_sn', $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getAlipayRootCertSn(string $tenant, ?array $config): string
|
||||
{
|
||||
if (!empty($config['alipay_root_cert_sn'])) {
|
||||
return $config['alipay_root_cert_sn'];
|
||||
}
|
||||
|
||||
$path = $config['alipay_root_cert_path'] ?? null;
|
||||
|
||||
if (is_null($path)) {
|
||||
throw new InvalidConfigException(Exception::ALIPAY_CONFIG_ERROR, 'Missing Alipay Config -- [alipay_root_cert_path]');
|
||||
}
|
||||
|
||||
$sn = '';
|
||||
$exploded = explode('-----END CERTIFICATE-----', file_get_contents($path));
|
||||
|
||||
foreach ($exploded as $cert) {
|
||||
if (empty(trim($cert))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$ssl = openssl_x509_parse($cert.'-----END CERTIFICATE-----');
|
||||
|
||||
if (false === $ssl) {
|
||||
throw new InvalidConfigException(Exception::ALIPAY_CONFIG_ERROR, 'Invalid alipay_root_cert');
|
||||
}
|
||||
|
||||
$detail = $this->formatCert($ssl);
|
||||
|
||||
if ('sha1WithRSAEncryption' == $detail['signatureTypeLN'] || 'sha256WithRSAEncryption' == $detail['signatureTypeLN']) {
|
||||
$sn .= $this->getCertSn($detail['issuer'], $detail['serialNumber']).'_';
|
||||
}
|
||||
}
|
||||
|
||||
$result = substr($sn, 0, -1);
|
||||
|
||||
Pay::get(ConfigInterface::class)->set('alipay.'.$tenant.'.alipay_root_cert_sn', $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getCertSn(array $issuer, ?string $serialNumber): string
|
||||
{
|
||||
return md5(
|
||||
$this->array2string(array_reverse($issuer)).$serialNumber
|
||||
);
|
||||
}
|
||||
|
||||
protected function array2string(array $array): string
|
||||
{
|
||||
$string = [];
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
$string[] = $key.'='.$value;
|
||||
}
|
||||
|
||||
return implode(',', $string);
|
||||
}
|
||||
|
||||
protected function formatCert(array $ssl): array
|
||||
{
|
||||
if (0 === strpos($ssl['serialNumber'] ?? '', '0x')) {
|
||||
$ssl['serialNumber'] = $this->hex2dec($ssl['serialNumberHex'] ?? '');
|
||||
}
|
||||
|
||||
return $ssl;
|
||||
}
|
||||
|
||||
protected function hex2dec(string $hex): string
|
||||
{
|
||||
$dec = '0';
|
||||
$len = strlen($hex);
|
||||
|
||||
for ($i = 1; $i <= $len; ++$i) {
|
||||
$dec = bcadd(
|
||||
$dec,
|
||||
bcmul(strval(hexdec($hex[$i - 1])), bcpow('16', strval($len - $i), 0), 0),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
return $dec;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user