From 2db053aba41b4279cd6b0283eb53c40fe4a0c92a Mon Sep 17 00:00:00 2001 From: yansongda Date: Sun, 6 Jun 2021 21:39:26 +0800 Subject: [PATCH] update --- src/Exception/Exception.php | 2 + src/Functions.php | 2 +- src/Logger.php | 8 +- src/Pay.php | 13 +- src/Service/AlipayServiceProvider.php | 3 + src/Service/ConfigServiceProvider.php | 3 + src/Service/LoggerServiceProvider.php | 1 - src/Service/WechatServiceProvider.php | 3 + tests/FunctionTest.php | 84 ++++++ tests/PayTest.php | 269 +++++++++--------- tests/Provider/AlipayTest.php | 10 + tests/Stubs/FooServiceProvider.php | 19 ++ tests/Stubs/cert/alipayCertPublicKey_RSA2.crt | 43 +++ tests/Stubs/cert/alipayRootCert.crt | 88 ++++++ .../appCertPublicKey_2016082000295641.crt | 19 ++ tests/Stubs/cert/appSecretKey_RSA2_PKCS1.txt | 1 + tests/Stubs/cert/appSecretkey_RSA2_PKCS1.pem | 28 ++ 17 files changed, 455 insertions(+), 141 deletions(-) create mode 100644 tests/FunctionTest.php create mode 100644 tests/Provider/AlipayTest.php create mode 100644 tests/Stubs/FooServiceProvider.php create mode 100644 tests/Stubs/cert/alipayCertPublicKey_RSA2.crt create mode 100644 tests/Stubs/cert/alipayRootCert.crt create mode 100644 tests/Stubs/cert/appCertPublicKey_2016082000295641.crt create mode 100644 tests/Stubs/cert/appSecretKey_RSA2_PKCS1.txt create mode 100644 tests/Stubs/cert/appSecretkey_RSA2_PKCS1.pem diff --git a/src/Exception/Exception.php b/src/Exception/Exception.php index 27a2c61..f1792e5 100644 --- a/src/Exception/Exception.php +++ b/src/Exception/Exception.php @@ -37,6 +37,8 @@ class Exception extends \Exception public const ALIPAY_CONFIG_ERROR = 3002; + public const LOGGER_CONFIG_ERROR = 3003; + /* * 关于参数. */ diff --git a/src/Functions.php b/src/Functions.php index 26c42ab..0327d4f 100644 --- a/src/Functions.php +++ b/src/Functions.php @@ -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'); diff --git a/src/Logger.php b/src/Logger.php index ac7c7a7..fe4469b 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -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); } } diff --git a/src/Pay.php b/src/Pay.php index f447778..a698782 100644 --- a/src/Pay.php +++ b/src/Pay.php @@ -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 * - * @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); } /** diff --git a/src/Service/AlipayServiceProvider.php b/src/Service/AlipayServiceProvider.php index f8fc02c..e8c8989 100644 --- a/src/Service/AlipayServiceProvider.php +++ b/src/Service/AlipayServiceProvider.php @@ -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); diff --git a/src/Service/ConfigServiceProvider.php b/src/Service/ConfigServiceProvider.php index 6598d82..bc0006e 100644 --- a/src/Service/ConfigServiceProvider.php +++ b/src/Service/ConfigServiceProvider.php @@ -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 ?? [])); diff --git a/src/Service/LoggerServiceProvider.php b/src/Service/LoggerServiceProvider.php index 0224383..25ff008 100644 --- a/src/Service/LoggerServiceProvider.php +++ b/src/Service/LoggerServiceProvider.php @@ -43,6 +43,5 @@ class LoggerServiceProvider implements ServiceProviderInterface }; Pay::set(LoggerInterface::class, $logger); - Pay::set(\Psr\Log\LoggerInterface::class, $logger); } } diff --git a/src/Service/WechatServiceProvider.php b/src/Service/WechatServiceProvider.php index 13f1932..3231b03 100644 --- a/src/Service/WechatServiceProvider.php +++ b/src/Service/WechatServiceProvider.php @@ -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 () { diff --git a/tests/FunctionTest.php b/tests/FunctionTest.php new file mode 100644 index 0000000..ccd42a9 --- /dev/null +++ b/tests/FunctionTest.php @@ -0,0 +1,84 @@ +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([], '', ''); + } +} diff --git a/tests/PayTest.php b/tests/PayTest.php index cdb5673..f4e3f5e 100644 --- a/tests/PayTest.php +++ b/tests/PayTest.php @@ -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)); + } } diff --git a/tests/Provider/AlipayTest.php b/tests/Provider/AlipayTest.php new file mode 100644 index 0000000..ef345e8 --- /dev/null +++ b/tests/Provider/AlipayTest.php @@ -0,0 +1,10 @@ +