This commit is contained in:
yansongda 2021-06-06 21:39:26 +08:00
parent a434f127ac
commit 2db053aba4
17 changed files with 455 additions and 141 deletions

View File

@ -37,6 +37,8 @@ class Exception extends \Exception
public const ALIPAY_CONFIG_ERROR = 3002;
public const LOGGER_CONFIG_ERROR = 3003;
/*
* 关于参数.
*/

View File

@ -27,7 +27,7 @@ if (!function_exists('get_alipay_config')) {
* @throws \Yansongda\Pay\Exception\ContainerException
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
*/
function get_alipay_config(array $params): Config
function get_alipay_config(array $params = []): Config
{
$alipay = Pay::get(ConfigInterface::class)->get('alipay');

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Yansongda\Pay;
use Yansongda\Pay\Contract\LoggerInterface;
use Yansongda\Pay\Exception\InvalidConfigException;
/**
* @method static void emergency($message, array $context = [])
@ -23,6 +24,7 @@ class Logger
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
* @throws \Yansongda\Pay\Exception\ContainerException
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
* @throws \Yansongda\Pay\Exception\InvalidConfigException
*/
public static function __callStatic(string $method, array $args): void
{
@ -32,6 +34,10 @@ class Logger
$class = Pay::get(LoggerInterface::class);
forward_static_call_array([$class, $method], $args);
if ($class instanceof \Psr\Log\LoggerInterface) {
$class->{$method}(...$args);
}
throw new InvalidConfigException(InvalidConfigException::LOGGER_CONFIG_ERROR);
}
}

View File

@ -13,6 +13,7 @@ use Yansongda\Pay\Contract\ContainerInterface;
use Yansongda\Pay\Contract\ServiceProviderInterface;
use Yansongda\Pay\Exception\ContainerDependencyException;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\ContainerNotFoundException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Service\AlipayServiceProvider;
use Yansongda\Pay\Service\ConfigServiceProvider;
@ -89,7 +90,7 @@ class Pay
*/
public static function __callStatic(string $service, array $config)
{
if (!empty($config)) {
if (!empty($config) && !self::hasContainer()) {
self::config(...$config);
}
@ -105,7 +106,7 @@ class Pay
* @throws \Yansongda\Pay\Exception\ContainerException
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
*/
public static function config(array $config): Pay
public static function config(array $config = []): Pay
{
if (empty($config) && self::hasContainer()) {
return self::get(Pay::class);
@ -132,8 +133,8 @@ class Pay
* 获取服务.
*
* @throws \Yansongda\Pay\Exception\ContainerDependencyException
* @throws \Yansongda\Pay\Exception\ContainerException
* @throws \Yansongda\Pay\Exception\ServiceNotFoundException
* @throws \Yansongda\Pay\Exception\ContainerException
*
* @return mixed
*/
@ -163,15 +164,15 @@ class Pay
*
* @author yansongda <me@yansongda.cn>
*
* @throws \Yansongda\Pay\Exception\ContainerException
* @throws \Yansongda\Pay\Exception\ContainerNotFoundException
*/
public static function getContainer(): Container
{
if (self::$container) {
if (self::hasContainer()) {
return self::$container;
}
throw new ContainerException('You should init/config PAY first', ContainerException::CONTAINER_NOT_FOUND);
throw new ContainerNotFoundException('You should init/config PAY first', ContainerException::CONTAINER_NOT_FOUND);
}
/**

View File

@ -12,6 +12,9 @@ use Yansongda\Pay\Provider\Alipay;
class AlipayServiceProvider implements ServiceProviderInterface
{
/**
* @throws \Yansongda\Pay\Exception\ContainerException
*/
public function register(Pay $pay, ?array $data = null): void
{
Pay::set(ParserInterface::class, CollectionParser::class);

View File

@ -30,6 +30,9 @@ class ConfigServiceProvider implements ServiceProviderInterface
'mode' => Pay::MODE_NORMAL,
];
/**
* @throws \Yansongda\Pay\Exception\ContainerException
*/
public function register(Pay $pay, ?array $data = null): void
{
$config = new Config(array_replace_recursive($this->config, $data ?? []));

View File

@ -43,6 +43,5 @@ class LoggerServiceProvider implements ServiceProviderInterface
};
Pay::set(LoggerInterface::class, $logger);
Pay::set(\Psr\Log\LoggerInterface::class, $logger);
}
}

View File

@ -10,6 +10,9 @@ use Yansongda\Pay\Provider\Wechat;
class WechatServiceProvider implements ServiceProviderInterface
{
/**
* @throws \Yansongda\Pay\Exception\ContainerException
*/
public function register(Pay $pay, ?array $data = null): void
{
$service = function () {

84
tests/FunctionTest.php Normal file
View File

@ -0,0 +1,84 @@
<?php
namespace Yansongda\Pay\Tests;
use PHPUnit\Framework\TestCase;
use Yansongda\Pay\Exception\InvalidConfigException;
use Yansongda\Pay\Parser\CollectionParser;
use Yansongda\Pay\Parser\NoHttpRequestParser;
use Yansongda\Pay\Parser\ResponseParser;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Rocket;
use Yansongda\Supports\Collection;
use Yansongda\Supports\Str;
class FunctionTest extends TestCase
{
protected function tearDown (): void
{
Pay::clear();
}
public function testShouldDoHttpRequest()
{
$rocket = new Rocket();
self::assertTrue(should_do_http_request($rocket));
$rocket->setDirection(CollectionParser::class);
self::assertTrue(should_do_http_request($rocket));
$rocket->setDirection(ResponseParser::class);
self::assertFalse(should_do_http_request($rocket));
$rocket->setDirection(NoHttpRequestParser::class);
self::assertFalse(should_do_http_request($rocket));
}
public function testGetAlipayConfig()
{
$config1 = [];
Pay::config($config1);
self::assertEquals([], get_alipay_config([])->all());
Pay::clear();
$config2 = [
'alipay' => [
'default' => ['name' => 'yansongda'],
'c1' => ['age' => 28]
]
];
Pay::config($config2);
self::assertEquals(['name' => 'yansongda'], get_alipay_config([])->all());
self::assertEquals(['age' => 28], get_alipay_config(['_config' => 'c1'])->all());
}
public function testGetPublicCrtOrPrivateCert()
{
$alipayPublicCertPath = __DIR__.'/Stubs/cert/alipayCertPublicKey_RSA2.crt';
$appSecretCert = file_get_contents( __DIR__.'/Stubs/cert/appSecretKey_RSA2_PKCS1.txt');
$appSecretCertPath = __DIR__.'/Stubs/cert/appSecretKey_RSA2_PKCS1.pem';
self::assertEquals(file_get_contents($alipayPublicCertPath), get_public_crt_or_private_cert($alipayPublicCertPath));
self::assertTrue(Str::contains(get_public_crt_or_private_cert($appSecretCert), 'END RSA PRIVATE KEY'));
self::assertIsResource(get_public_crt_or_private_cert($appSecretCertPath));
}
public function testVerifyAlipayResponse()
{
$config1 = [
'alipay' => [
'default' => [
// 'alipay_public_cert_path' => __DIR__.'/Stubs/cert/alipayCertPublicKey_RSA2.crt'
],
]
];
Pay::config($config1);
self::expectException(InvalidConfigException::class);
self::expectExceptionCode(InvalidConfigException::ALIPAY_CONFIG_ERROR);
verify_alipay_response([], '', '');
}
}

View File

@ -2,140 +2,145 @@
namespace Yansongda\Pay\Tests;
use DI\Container;
use GuzzleHttp\Client;
use PHPUnit\Framework\TestCase;
use Psr\Container\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Yansongda\Pay\Contract\ConfigInterface;
use Yansongda\Pay\Contract\EventDispatcherInterface;
use Yansongda\Pay\Contract\HttpClientInterface;
use Yansongda\Pay\Contract\LoggerInterface;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Tests\Stubs\FooServiceProvider;
use Yansongda\Supports\Config;
use Yansongda\Supports\Logger;
class PayTest extends TestCase
{
// public function testGetContainerNullConfig()
// {
// $this->expectException(ContainerNotFoundException::class);
// $this->expectExceptionCode(ContainerNotFoundException::CONTAINER_NOT_FOUND);
// $this->expectExceptionMessage('You must init the container first with config');
//
// Pay::getContainer();
// }
//
// public function testGetContainer()
// {
// self::assertInstanceOf(Container::class, Pay::getContainer([]));
// }
//
// public function testHasContainer()
// {
// self::assertFalse(Pay::hasContainer());
//
// Pay::getContainer([]);
//
// self::assertTrue(Pay::hasContainer());
// }
//
// public function testMagicCallNotFoundService()
// {
// $this->expectException(ServiceNotFoundException::class);
//
// Pay::foo([]);
// }
//
// public function testMagicCallSetAndGet()
// {
// $data = [
// 'name' => 'yansongda',
// 'age' => 26
// ];
//
// Pay::getContainer([]);
//
// Pay::set('profile', $data);
//
// self::assertEquals($data, Pay::get('profile'));
// }
//
// public function testCoreServiceBase()
// {
// $container = Pay::getContainer([]);
//
// self::assertInstanceOf(Container::class, $container);
// self::assertInstanceOf(Pay::class, $container->get(ContainerInterface::class));
// self::assertInstanceOf(Pay::class, Pay::get(Pay::class));
// }
//
// public function testCoreServiceConfig()
// {
// $config = [
// 'name' => 'yansongda',
// ];
//
// $container = Pay::getContainer($config);
//
// self::assertInstanceOf(Config::class, $container->get(ConfigInterface::class));
// self::assertEquals($config['name'], Pay::get(ConfigInterface::class)->get('name'));
//
// // 修改 config 的情况
// $config2 = [
// 'name' => 'yansongda2',
// ];
// Pay::set(ConfigInterface::class, new Config($config2));
//
// self::assertEquals($config2['name'], Pay::get(ConfigInterface::class)->get('name'));
// }
//
// public function testCoreServiceLogger()
// {
// $container = Pay::getContainer([]);
// $otherLogger = new \Monolog\Logger('test');
//
// self::assertInstanceOf(Logger::class, $container->get(\Yansongda\Pay\Contract\LoggerInterface::class));
// self::assertInstanceOf(\Monolog\Logger::class, $container->get(\Yansongda\Pay\Contract\LoggerInterface::class)->getLogger());
// self::assertInstanceOf(LoggerInterface::class, $container->get(\Yansongda\Pay\Contract\LoggerInterface::class)->getLogger());
// self::assertNotEquals($otherLogger, $container->get(\Yansongda\Pay\Contract\LoggerInterface::class));
//
// $container->get(\Yansongda\Pay\Contract\LoggerInterface::class)->setLogger($otherLogger);
// self::assertEquals($otherLogger, $container->get(\Yansongda\Pay\Contract\LoggerInterface::class)->getLogger());
// }
//
// public function testCoreServiceEvent()
// {
// $container = Pay::getContainer([]);
//
// self::assertInstanceOf(EventDispatcher::class, $container->get(EventDispatcherInterface::class));
// }
//
// public function testCoreServiceHttpClient()
// {
// $container = Pay::getContainer([]);
//
// self::assertInstanceOf(Client::class, $container->get(HttpClientInterface::class));
// }
//
// public function testCoreServiceExternalHttpClient()
// {
// Pay::getContainer([]);
//
// $oldClient = Pay::get(HttpClientInterface::class);
//
// $client = new Client(['timeout' => 3.0]);
// Pay::set(HttpClientInterface::class, $client);
//
// self::assertEquals($client, Pay::get(HttpClientInterface::class));
// self::assertNotEquals($oldClient, Pay::get(HttpClientInterface::class));
// }
//
// public function testSingletonContainer()
// {
// $config1 = ['name' => 'yansongda'];
// $config2 = ['age' => 26];
//
// $container1 = Pay::getContainer($config1);
// $container2 = Pay::getContainer($config2);
//
// self::assertEquals($container1, $container2);
// }
//
// public function testGetNotFoundContainer()
// {
// $this->expectExceptionMessage('You must init the container first with config');
// $this->expectException(ContainerNotFoundException::class);
//
// Pay::getContainer();
// }
protected function tearDown (): void
{
Pay::clear();
}
public function testConfig()
{
$result = Pay::config(['name' => 'yansongda']);
static::assertInstanceOf(Pay::class, $result);
}
public function testSetAndGet()
{
Pay::config(['name' => 'yansongda']);
Pay::set('age', 28);
self::assertEquals(28, Pay::get('age'));
}
public function testHas()
{
Pay::config(['name' => 'yansongda']);
Pay::set('age', 28);
self::assertFalse(Pay::has('name'));
self::assertTrue(Pay::has('age'));
}
public function testGetContainerAndClear()
{
Pay::config(['name' => 'yansongda']);
self::assertInstanceOf(ContainerInterface::class, Pay::getContainer());
Pay::clear();
$this->expectException(ContainerException::class);
$this->expectExceptionCode(ContainerException::CONTAINER_NOT_FOUND);
$this->expectExceptionMessage('You should init/config PAY first');
Pay::getContainer();
}
public function testRegisterService()
{
Pay::config(['name' => 'yansongda']);
Pay::registerService(FooServiceProvider::class, []);
self::assertEquals('bar', Pay::get('foo'));
}
public function testMagicCallNotFoundService()
{
$this->expectException(ServiceNotFoundException::class);
Pay::foo([]);
}
public function testCoreService()
{
Pay::config(['name' => 'yansongda']);
self::assertInstanceOf(Container::class, Pay::get(\Yansongda\Pay\Contract\ContainerInterface::class));
self::assertInstanceOf(Container::class, Pay::get(ContainerInterface::class));
self::assertInstanceOf(Pay::class, Pay::get(Pay::class));
}
public function testCoreServiceConfig()
{
$config = ['name' => 'yansongda'];
Pay::config($config);
self::assertInstanceOf(Config::class, Pay::get(ConfigInterface::class));
self::assertInstanceOf(Config::class, Pay::get('config'));
self::assertEquals($config['name'], Pay::get(ConfigInterface::class)->get('name'));
// 修改 config 的情况
$config2 = [
'name' => 'yansongda2',
];
Pay::set(ConfigInterface::class, new Config($config2));
self::assertEquals($config2['name'], Pay::get(ConfigInterface::class)->get('name'));
}
public function testCoreServiceLogger()
{
$config = ['name' => 'yansongda','logger' => ['enable' => true]];
Pay::config($config);
self::assertInstanceOf(Logger::class, Pay::get(LoggerInterface::class));
$otherLogger = new \Monolog\Logger('test');
Pay::set(LoggerInterface::class, $otherLogger);
self::assertEquals($otherLogger, Pay::get(LoggerInterface::class));
}
public function testCoreServiceEvent()
{
$config = ['name' => 'yansongda'];
Pay::config($config);
self::assertInstanceOf(EventDispatcher::class, Pay::get(EventDispatcherInterface::class));
}
public function testCoreServiceHttpClient()
{
$config = ['name' => 'yansongda'];
Pay::config($config);
self::assertInstanceOf(Client::class, Pay::get(HttpClientInterface::class));
// 使用外部 http client
$oldClient = Pay::get(HttpClientInterface::class);
$client = new Client(['timeout' => 3.0]);
Pay::set(HttpClientInterface::class, $client);
self::assertEquals($client, Pay::get(HttpClientInterface::class));
self::assertNotEquals($oldClient, Pay::get(HttpClientInterface::class));
}
}

View File

@ -0,0 +1,10 @@
<?php
namespace Yansongda\Pay\Tests\Provider;
use PHPUnit\Framework\TestCase;
class AlipayTest extends TestCase
{
}

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Tests\Stubs;
use Yansongda\Pay\Contract\ServiceProviderInterface;
use Yansongda\Pay\Pay;
class FooServiceProvider implements ServiceProviderInterface
{
/**
* @throws \Yansongda\Pay\Exception\ContainerException
*/
public function register(Pay $pay, ?array $data = null): void
{
$pay::set('foo', 'bar');
}
}

View File

@ -0,0 +1,43 @@
-----BEGIN CERTIFICATE-----
MIIDqDCCApCgAwIBAgIQICAEBs+h6FBxohbHywNvrTANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE
BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjAwNDA2MDgzMzE4WhcNMjMwNDA1MDgzMzE4WjB6
MQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxQzBB
BgNVBAMMOuaUr+S7mOWunSjkuK3lm70p572R57uc5oqA5pyv5pyJ6ZmQ5YWs5Y+4LTIwODgxMDIx
NzIyMzcyMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5YkqtDpJa9LqeIj7i8RVm
Jh+OQJ8tB+gUjacKn1ksNLjZC2IvgJzLHyxyBzeeFXCZVG17x/ntMW8aG8kPS6lPg7k7+VHGZON5
yFcCiuKtV0A4Ok67SYV9BX3L9P2j2EedT5WY7mymhVve6aqmroP8+3ynbliTznb/DTVVMhzOtcLh
CWts4R7eyvUT1q6gLuuBiOMI7qVlQgONf+gGY1dnGFEOtjHhh/lfvLwVEEW/KAgTYWDFXhjD5Ivd
ABrabkwtxu6wmnE6aX1hVB8/yJK6vHjU++9dQyjj0kbcENV6udoJhdAKhQm/18nBud9l3snlgHIL
7kozixuUlOrttdlZAgMBAAGjEjAQMA4GA1UdDwEB/wQEAwIE8DANBgkqhkiG9w0BAQsFAAOCAQEA
ObuZ3F5prPrkRWE0fsr0IuMgUEIkOG/D+uRFk0btDGxIhp8tI7Rb/mJS7s4tiky/Srihu4WV1VKf
tB0slh13BVEf2LkzZiGb6VwZdxp+ZdB7IOSmuWvLBjq3YEW9j/ike63ufXJQeoxqpxjSE1QeLumS
JYnrZl/voiwKODoFs1VcZx+Q8i4+ipVgWcul3Hy6oqYn8Vb8iDIjZoMsCeLLo5pMGRQe5u+Ea3ya
4aInWs2PYoUBITqqmJLhm2Z8/VGcfV5v5rjqekWyoechI7gDJDbTa+mVo0vavNgVAmo+o6xLiSVr
xdZIYMDZhcinZXyXCuw1cLgJPB4IG6EZOQAzbA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE4jCCAsqgAwIBAgIIddq/0OOwJzIwDQYJKoZIhvcNAQELBQAwejELMAkGA1UEBhMCQ04xFjAU
BgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEw
LwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMy
MjE0MzAzMVoXDTM3MTEyNjE0MzAzMVowgYIxCzAJBgNVBAYTAkNOMRYwFAYDVQQKDA1BbnQgRmlu
YW5jaWFsMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTE5MDcGA1UEAwwwQW50IEZp
bmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSBDbGFzcyAxIFIxMIIBIjANBgkqhkiG9w0B
AQEFAAOCAQ8AMIIBCgKCAQEA3OruCD7d4evJiEKxzJQYmwp5ziF7lT4fMpBb+WLme42Ulrkh4cJC
DEOTUL29Yb8NyQ6cRe9UHLupI2HbByDZoSJl7nkxyi5NGJLaADC7wnFBJq39WMaVBzouFo0yQkkY
NbbkJm+MsV4obu3l2xFGQx72bz6ThDJLpfYJbnGXqC4Bcyn8ubj1ddrJ0VsGdj/3Knmuo7XWLYqq
N/qomK3LJIpfhVozi0b2FWQl+lE9urch+FVhXSg0AlRGn8FTOVNlKrY+hAKZGZhqC+J+BD4GL3hQ
ZzVeNl0tMmSGz474lnt7DExNq33WfyJkn5UIoCfg8Tno7XTnocmBzbNYPq1aSQIDAQABo2MwYTAf
BgNVHSMEGDAWgBRfdLQEwE8HWurlsdsio4dBspzhATAdBgNVHQ4EFgQUcQfiBGEW5OXyZesxD8ng
9Dya1ZEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQELBQADggIB
AGkc6bDB4YQCa5D6IbgRtLfiqTQb5DeCp38uVKKrUl8ZCE5U+wXSu/fFhOkIs+Aq9tEOdPWgi7TA
xPMMbfJRTAF20qK1qF/X6lwRYGSi7LBbEhmI7dYFKj7i7z6fupBMVaI4C4O8KJGfovp3qD/FkXyb
13Lo8vL85Ll0BFk89Qbim0qYhW2JRsf9G46vBeIZaoMm8iMv9vvlVgMs30R96W+gZBgvlIE4ah+o
OEUd+G/V74vTbaXtWI8gkmwCzs/yUGW2g2ERHqZ3ksq4xwL+mNmqRNzq3aC9iA4p0uoHp/els89v
WHCUaPjHmEnhx+M843/WVjN8LWpoeQ+wc7Wz1jfYy0e+JXidqWkPn7qorlEQTfzcFBZh+YHnV6oV
tcG5iYatRKVTAPA+RrjJnEEzn6hAIPsiYsLmdA18f6ruuUUuKRukAEbCQ9q9L1gyOkaz2LxZj5kO
FyemDa3pjqESuHuazztnOvs6u4YrH03CPyK3G/6MhCNEJTxGDYy+8bRtNsTGRUbdmhZm/u8tjYIr
eNEy55f4WYlb72R6PODBLXmf4HWWPpyX1Zy9TEhmFsuPfelhBrdmBVM1iTwVFLW7gLqoEwzYhMt5
KRPjmfCc2P2pcbpLnYNcbSYiykFsCa7jHG0137Jv8Z/QH2N9r4+xdER7SW40ndmD59ynmGvrWUMj
-----END CERTIFICATE-----

View File

@ -0,0 +1,88 @@
-----BEGIN CERTIFICATE-----
MIIBszCCAVegAwIBAgIIaeL+wBcKxnswDAYIKoEcz1UBg3UFADAuMQswCQYDVQQG
EwJDTjEOMAwGA1UECgwFTlJDQUMxDzANBgNVBAMMBlJPT1RDQTAeFw0xMjA3MTQw
MzExNTlaFw00MjA3MDcwMzExNTlaMC4xCzAJBgNVBAYTAkNOMQ4wDAYDVQQKDAVO
UkNBQzEPMA0GA1UEAwwGUk9PVENBMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE
MPCca6pmgcchsTf2UnBeL9rtp4nw+itk1Kzrmbnqo05lUwkwlWK+4OIrtFdAqnRT
V7Q9v1htkv42TsIutzd126NdMFswHwYDVR0jBBgwFoAUTDKxl9kzG8SmBcHG5Yti
W/CXdlgwDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFEwysZfZ
MxvEpgXBxuWLYlvwl3ZYMAwGCCqBHM9VAYN1BQADSAAwRQIgG1bSLeOXp3oB8H7b
53W+CKOPl2PknmWEq/lMhtn25HkCIQDaHDgWxWFtnCrBjH16/W3Ezn7/U/Vjo5xI
pDoiVhsLwg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIF0zCCA7ugAwIBAgIIH8+hjWpIDREwDQYJKoZIhvcNAQELBQAwejELMAkGA1UE
BhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNVBAsMF0NlcnRpZmlj
YXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5jaWFsIENlcnRpZmlj
YXRpb24gQXV0aG9yaXR5IFIxMB4XDTE4MDMyMTEzNDg0MFoXDTM4MDIyODEzNDg0
MFowejELMAkGA1UEBhMCQ04xFjAUBgNVBAoMDUFudCBGaW5hbmNpYWwxIDAeBgNV
BAsMF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MTEwLwYDVQQDDChBbnQgRmluYW5j
aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFIxMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAtytTRcBNuur5h8xuxnlKJetT65cHGemGi8oD+beHFPTk
rUTlFt9Xn7fAVGo6QSsPb9uGLpUFGEdGmbsQ2q9cV4P89qkH04VzIPwT7AywJdt2
xAvMs+MgHFJzOYfL1QkdOOVO7NwKxH8IvlQgFabWomWk2Ei9WfUyxFjVO1LVh0Bp
dRBeWLMkdudx0tl3+21t1apnReFNQ5nfX29xeSxIhesaMHDZFViO/DXDNW2BcTs6
vSWKyJ4YIIIzStumD8K1xMsoaZBMDxg4itjWFaKRgNuPiIn4kjDY3kC66Sl/6yTl
YUz8AybbEsICZzssdZh7jcNb1VRfk79lgAprm/Ktl+mgrU1gaMGP1OE25JCbqli1
Pbw/BpPynyP9+XulE+2mxFwTYhKAwpDIDKuYsFUXuo8t261pCovI1CXFzAQM2w7H
DtA2nOXSW6q0jGDJ5+WauH+K8ZSvA6x4sFo4u0KNCx0ROTBpLif6GTngqo3sj+98
SZiMNLFMQoQkjkdN5Q5g9N6CFZPVZ6QpO0JcIc7S1le/g9z5iBKnifrKxy0TQjtG
PsDwc8ubPnRm/F82RReCoyNyx63indpgFfhN7+KxUIQ9cOwwTvemmor0A+ZQamRe
9LMuiEfEaWUDK+6O0Gl8lO571uI5onYdN1VIgOmwFbe+D8TcuzVjIZ/zvHrAGUcC
AwEAAaNdMFswCwYDVR0PBAQDAgEGMAwGA1UdEwQFMAMBAf8wHQYDVR0OBBYEFF90
tATATwda6uWx2yKjh0GynOEBMB8GA1UdIwQYMBaAFF90tATATwda6uWx2yKjh0Gy
nOEBMA0GCSqGSIb3DQEBCwUAA4ICAQCVYaOtqOLIpsrEikE5lb+UARNSFJg6tpkf
tJ2U8QF/DejemEHx5IClQu6ajxjtu0Aie4/3UnIXop8nH/Q57l+Wyt9T7N2WPiNq
JSlYKYbJpPF8LXbuKYG3BTFTdOVFIeRe2NUyYh/xs6bXGr4WKTXb3qBmzR02FSy3
IODQw5Q6zpXj8prYqFHYsOvGCEc1CwJaSaYwRhTkFedJUxiyhyB5GQwoFfExCVHW
05ZFCAVYFldCJvUzfzrWubN6wX0DD2dwultgmldOn/W/n8at52mpPNvIdbZb2F41
T0YZeoWnCJrYXjq/32oc1cmifIHqySnyMnavi75DxPCdZsCOpSAT4j4lAQRGsfgI
kkLPGQieMfNNkMCKh7qjwdXAVtdqhf0RVtFILH3OyEodlk1HYXqX5iE5wlaKzDop
PKwf2Q3BErq1xChYGGVS+dEvyXc/2nIBlt7uLWKp4XFjqekKbaGaLJdjYP5b2s7N
1dM0MXQ/f8XoXKBkJNzEiM3hfsU6DOREgMc1DIsFKxfuMwX3EkVQM1If8ghb6x5Y
jXayv+NLbidOSzk4vl5QwngO/JYFMkoc6i9LNwEaEtR9PhnrdubxmrtM+RjfBm02
77q3dSWFESFQ4QxYWew4pHE0DpWbWy/iMIKQ6UZ5RLvB8GEcgt8ON7BBJeMc+Dyi
kT9qhqn+lw==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIICiDCCAgygAwIBAgIIQX76UsB/30owDAYIKoZIzj0EAwMFADB6MQswCQYDVQQG
EwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UECwwXQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNpYWwgQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkgRTEwHhcNMTkwNDI4MTYyMDQ0WhcNNDkwNDIwMTYyMDQ0
WjB6MQswCQYDVQQGEwJDTjEWMBQGA1UECgwNQW50IEZpbmFuY2lhbDEgMB4GA1UE
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxMTAvBgNVBAMMKEFudCBGaW5hbmNp
YWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRTEwdjAQBgcqhkjOPQIBBgUrgQQA
IgNiAASCCRa94QI0vR5Up9Yr9HEupz6hSoyjySYqo7v837KnmjveUIUNiuC9pWAU
WP3jwLX3HkzeiNdeg22a0IZPoSUCpasufiLAnfXh6NInLiWBrjLJXDSGaY7vaokt
rpZvAdmjXTBbMAsGA1UdDwQEAwIBBjAMBgNVHRMEBTADAQH/MB0GA1UdDgQWBBRZ
4ZTgDpksHL2qcpkFkxD2zVd16TAfBgNVHSMEGDAWgBRZ4ZTgDpksHL2qcpkFkxD2
zVd16TAMBggqhkjOPQQDAwUAA2gAMGUCMQD4IoqT2hTUn0jt7oXLdMJ8q4vLp6sg
wHfPiOr9gxreb+e6Oidwd2LDnC4OUqCWiF8CMAzwKs4SnDJYcMLf2vpkbuVE4dTH
Rglz+HGcTLWsFs4KxLsq7MuU+vJTBUeDJeDjdA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIUEMdk6dVgOEIS2cCP0Q43P90Ps5YwDQYJKoZIhvcNAQEF
BQAwajELMAkGA1UEBhMCQ04xEzARBgNVBAoMCmlUcnVzQ2hpbmExHDAaBgNVBAsM
E0NoaW5hIFRydXN0IE5ldHdvcmsxKDAmBgNVBAMMH2lUcnVzQ2hpbmEgQ2xhc3Mg
MiBSb290IENBIC0gRzMwHhcNMTMwNDE4MDkzNjU2WhcNMzMwNDE4MDkzNjU2WjBq
MQswCQYDVQQGEwJDTjETMBEGA1UECgwKaVRydXNDaGluYTEcMBoGA1UECwwTQ2hp
bmEgVHJ1c3QgTmV0d29yazEoMCYGA1UEAwwfaVRydXNDaGluYSBDbGFzcyAyIFJv
b3QgQ0EgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOPPShpV
nJbMqqCw6Bz1kehnoPst9pkr0V9idOwU2oyS47/HjJXk9Rd5a9xfwkPO88trUpz5
4GmmwspDXjVFu9L0eFaRuH3KMha1Ak01citbF7cQLJlS7XI+tpkTGHEY5pt3EsQg
wykfZl/A1jrnSkspMS997r2Gim54cwz+mTMgDRhZsKK/lbOeBPpWtcFizjXYCqhw
WktvQfZBYi6o4sHCshnOswi4yV1p+LuFcQ2ciYdWvULh1eZhLxHbGXyznYHi0dGN
z+I9H8aXxqAQfHVhbdHNzi77hCxFjOy+hHrGsyzjrd2swVQ2iUWP8BfEQqGLqM1g
KgWKYfcTGdbPB1MCAwEAAaNjMGEwHQYDVR0OBBYEFG/oAMxTVe7y0+408CTAK8hA
uTyRMB8GA1UdIwQYMBaAFG/oAMxTVe7y0+408CTAK8hAuTyRMA8GA1UdEwEB/wQF
MAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBLnUTfW7hp
emMbuUGCk7RBswzOT83bDM6824EkUnf+X0iKS95SUNGeeSWK2o/3ALJo5hi7GZr3
U8eLaWAcYizfO99UXMRBPw5PRR+gXGEronGUugLpxsjuynoLQu8GQAeysSXKbN1I
UugDo9u8igJORYA+5ms0s5sCUySqbQ2R5z/GoceyI9LdxIVa1RjVX8pYOj8JFwtn
DJN3ftSFvNMYwRuILKuqUYSHc2GPYiHVflDh5nDymCMOQFcFG3WsEuB+EYQPFgIU
1DHmdZcz7Llx8UOZXX2JupWCYzK1XhJb+r4hK5ncf/w8qGtYlmyJpxk3hr1TfUJX
Yf4Zr0fJsGuv
-----END CERTIFICATE-----

View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDjzCCAnegAwIBAgIQICEGAoffj/XW+j0EEDtjBTANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UE
BhMCQ04xGzAZBgNVBAoMEkFudCBGaW5hbmNpYWwgdGVzdDElMCMGA1UECwwcQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkgdGVzdDE+MDwGA1UEAww1QW50IEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eSBDbGFzcyAyIFIxIHRlc3QwHhcNMjEwNjAyMTM0MTQ4WhcNMjQwNTMxMTM0MTQ4WjBh
MQswCQYDVQQGEwJDTjEVMBMGA1UECgwM5rKZ566x546v5aKDMQ8wDQYDVQQLDAZBbGlwYXkxKjAo
BgNVBAMMITIwODgxMDIxNzIyMzcyMTAtMjAxNjA4MjAwMDI5NTY0MTCCASIwDQYJKoZIhvcNAQEB
BQADggEPADCCAQoCggEBAINGM6DkOdf7wv6sHx3YxutDfRnsk8ziGIOFrAdLBAJDtGWZA2mXpv83
ois8tw8ULW6KLXv1TkiXnFNnKd+ORTImOce6yqeYeyR+0skMqSYZtJQUwCU6/42WlRYwnYD5VSim
X70UvKpxX5eBtpaLPFTcuxO23ri/z2JnaILXofr/prdhw/6ENlSOI0ZDH1y7CL14nLKS9zCEOQU/
F4HEdt/Cmmy6X4NhTJMJyXQu1uBr+ZR5yGTkGSxbrI8/CmtgdAFfIzXolzerkds3GHfrrQXK9QEU
u5VYgGzpG1HaBkJrpvys60KQ9AqFQq/NEyWCF46jBexZ2T30aPEZAMrlbhcCAwEAAaMSMBAwDgYD
VR0PAQH/BAQDAgTwMA0GCSqGSIb3DQEBCwUAA4IBAQC46MmE3Aa9YVmsSeXZ7yfj0gty/dyxWImE
K9rWoFfhIzI5xIEX457XVyYYqRpR+48qkyxyoOoPU70vLYMy9VLshaj0KCeObPA/kyTTBP5lfk5c
TIurmpIeD9uznfJIccl8OWsgJ81YsoCYrI7y3jtqpMu5fqBrrYPe7TPUna4LZzJldaBpD1muQ5W6
EPGtXcOWWU1Zo3ZI0K/fDuT8B/sD7yJDPQXOsqeluKI385A33O6LSOjSae19KqQqpGG+vP5LjoHK
y7ilY/sY8mJijLC1KX+RFofi61nPzcR3szEHIFncvWaN12I28To7h7s63tJ+buBpF+Lafp35AxkW
spCi
-----END CERTIFICATE-----

View File

@ -0,0 +1 @@
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCDRjOg5DnX+8L+rB8d2MbrQ30Z7JPM4hiDhawHSwQCQ7RlmQNpl6b/N6IrPLcPFC1uii179U5Il5xTZynfjkUyJjnHusqnmHskftLJDKkmGbSUFMAlOv+NlpUWMJ2A+VUopl+9FLyqcV+XgbaWizxU3LsTtt64v89iZ2iC16H6/6a3YcP+hDZUjiNGQx9cuwi9eJyykvcwhDkFPxeBxHbfwppsul+DYUyTCcl0Ltbga/mUechk5BksW6yPPwprYHQBXyM16Jc3q5HbNxh3660FyvUBFLuVWIBs6RtR2gZCa6b8rOtCkPQKhUKvzRMlgheOowXsWdk99GjxGQDK5W4XAgMBAAECggEAYPKnjlr+nRPBnnNfR5ugzH67FToyrU0M7ZT6xygPfdyijaXDb2ggXLupeGUOjIRKSSijDrjLZ7EQMkguFHvtfmvcoDTDFaL2zq0a3oALK6gwRGxOuzAnK1naINkmeOmqiqrUab+21emEv098mRGbLNEXGCgltCtz7SiRdo/pgIPZ1wHj4MH0b0K2bFG3xwr51EyaLXKYH4j6w9YAXXsTdvzcJ+eRE0Yq4uGPfkziqg8d0xXSEt90HmCGHKo4O2eh1w1IlBcHfK0F6vkeUAtrtAV01MU2bNoRU147vKFxjDOVBlY1nIZY/drsbiPMuAfSsodL0hJxGSYivbKTX4CWgQKBgQDd0MkF5AIPPdFC+fhWdNclePRw4gUkBwPTIUljMP4o+MhJNrHp0sEy0sr1mzYsOT4J20hsbw/qTnMKGdgy784bySf6/CC7lv2hHp0wyS3Es0DRJuN+aTyyONOKGvQqd8gvuQtuYJy+hkIoHygjvC3TKndX1v66f9vCr/7TS0QPywKBgQCXgVHERHP+CarSAEDG6bzI878/5yqyJVlUeVMG5OXdlwCl0GAAl4mDvfqweUawSVFE7qiSqy3Eaok8KHkYcoRlQmAefHg/C8t2PNFfNrANDdDB99f7UhqhXTdBA6DPyW02eKIaBcXjZ7jEXZzA41a/zxZydKgHvz4pUq1BdbU5ZQKBgHyqGCDgaavpQVAUL1df6X8dALzkuqDp9GNXxOgjo+ShFefX/pv8oCqRQBJTflnSfiSKAqU2skosdwlJRzIxhrQlFPxBcaAcl0VTcGL33mo7mIU0Bw2H1d4QhAuNZIbttSvlIyCQ2edWi54DDMswusyAhHxwz88/huJfiad1GLaLAoGASIweMVNuD5lleMWyPw2x3rAJRnpVUZTc37xw6340LBWgs8XCEsZ9jN4t6s9H8CZLiiyWABWEBufU6z+eLPy5NRvBlxeXJOlq9iVNRMCVMMsKybb6b1fzdI2EZdds69LSPyEozjkxdyE1sqH468xwv8xUPV5rD7qd83+pgwzwSJkCgYBrRV0OZmicfVJ7RqbWyneBG03r7ziA0WTcLdRWDnOujQ9orhrkm+EY2evhLEkkF6TOYv4QFBGSHfGJ0SwD7ghbCQC/8oBvNvuQiPWI8B+00LwyxXNrkFOxy7UfIUdUmLoLc1s/VdBHku+JEd0YmEY+p4sjmcRnlu4AlzLxkWUTTg==

View File

@ -0,0 +1,28 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCDRjOg5DnX+8L+
rB8d2MbrQ30Z7JPM4hiDhawHSwQCQ7RlmQNpl6b/N6IrPLcPFC1uii179U5Il5xT
ZynfjkUyJjnHusqnmHskftLJDKkmGbSUFMAlOv+NlpUWMJ2A+VUopl+9FLyqcV+X
gbaWizxU3LsTtt64v89iZ2iC16H6/6a3YcP+hDZUjiNGQx9cuwi9eJyykvcwhDkF
PxeBxHbfwppsul+DYUyTCcl0Ltbga/mUechk5BksW6yPPwprYHQBXyM16Jc3q5Hb
Nxh3660FyvUBFLuVWIBs6RtR2gZCa6b8rOtCkPQKhUKvzRMlgheOowXsWdk99Gjx
GQDK5W4XAgMBAAECggEAYPKnjlr+nRPBnnNfR5ugzH67FToyrU0M7ZT6xygPfdyi
jaXDb2ggXLupeGUOjIRKSSijDrjLZ7EQMkguFHvtfmvcoDTDFaL2zq0a3oALK6gw
RGxOuzAnK1naINkmeOmqiqrUab+21emEv098mRGbLNEXGCgltCtz7SiRdo/pgIPZ
1wHj4MH0b0K2bFG3xwr51EyaLXKYH4j6w9YAXXsTdvzcJ+eRE0Yq4uGPfkziqg8d
0xXSEt90HmCGHKo4O2eh1w1IlBcHfK0F6vkeUAtrtAV01MU2bNoRU147vKFxjDOV
BlY1nIZY/drsbiPMuAfSsodL0hJxGSYivbKTX4CWgQKBgQDd0MkF5AIPPdFC+fhW
dNclePRw4gUkBwPTIUljMP4o+MhJNrHp0sEy0sr1mzYsOT4J20hsbw/qTnMKGdgy
784bySf6/CC7lv2hHp0wyS3Es0DRJuN+aTyyONOKGvQqd8gvuQtuYJy+hkIoHygj
vC3TKndX1v66f9vCr/7TS0QPywKBgQCXgVHERHP+CarSAEDG6bzI878/5yqyJVlU
eVMG5OXdlwCl0GAAl4mDvfqweUawSVFE7qiSqy3Eaok8KHkYcoRlQmAefHg/C8t2
PNFfNrANDdDB99f7UhqhXTdBA6DPyW02eKIaBcXjZ7jEXZzA41a/zxZydKgHvz4p
Uq1BdbU5ZQKBgHyqGCDgaavpQVAUL1df6X8dALzkuqDp9GNXxOgjo+ShFefX/pv8
oCqRQBJTflnSfiSKAqU2skosdwlJRzIxhrQlFPxBcaAcl0VTcGL33mo7mIU0Bw2H
1d4QhAuNZIbttSvlIyCQ2edWi54DDMswusyAhHxwz88/huJfiad1GLaLAoGASIwe
MVNuD5lleMWyPw2x3rAJRnpVUZTc37xw6340LBWgs8XCEsZ9jN4t6s9H8CZLiiyW
ABWEBufU6z+eLPy5NRvBlxeXJOlq9iVNRMCVMMsKybb6b1fzdI2EZdds69LSPyEo
zjkxdyE1sqH468xwv8xUPV5rD7qd83+pgwzwSJkCgYBrRV0OZmicfVJ7RqbWyneB
G03r7ziA0WTcLdRWDnOujQ9orhrkm+EY2evhLEkkF6TOYv4QFBGSHfGJ0SwD7ghb
CQC/8oBvNvuQiPWI8B+00LwyxXNrkFOxy7UfIUdUmLoLc1s/VdBHku+JEd0YmEY+
p4sjmcRnlu4AlzLxkWUTTg==
-----END RSA PRIVATE KEY-----