From 342d15ba5b48a6cf5fb2afdf87071ba189d1e97d Mon Sep 17 00:00:00 2001 From: Vragov Roman Date: Wed, 24 Jul 2019 17:13:55 +0300 Subject: [PATCH] Update guzzle to guzzlehttp/guzzle": "~6.3" --- .gitignore | 3 +- .travis.yml | 10 + composer.json | 13 +- phpunit.xml.dist | 29 +- src/AtolOnlineClient/AtolOnline.php | 86 +++- src/AtolOnlineClient/AtolOnlineApi.php | 287 ++++++----- src/AtolOnlineClient/Configuration.php | 16 +- .../Configuration/Connection.php | 2 +- .../Exception/AtolException.php | 5 +- .../Exception/InvalidResponseException.php | 59 +++ .../Request/V4/VatReceiptRequest.php | 2 +- src/AtolOnlineClient/Response/Error.php | 3 + .../Response/OperationResponse.php | 3 + src/AtolOnlineClient/Response/Payload.php | 3 + tests/AtolOnlineClient/AtolOnlineApiTest.php | 479 ++++++++++++++++++ tests/AtolOnlineClient/AtolOnlineTest.php | 265 ++++++++++ .../Configuration/ConnectionTest.php | 89 ++++ tests/AtolOnlineClient/ConfigurationTest.php | 78 +++ .../Response/ResponseTest.php | 63 +++ .../AtolOnlineClient/Tests/AtolOnlineTest.php | 46 -- bootstrap.php => tests/bootstrap.php | 4 +- .../error_response_v3.json} | 0 .../error_response_v4.json} | 0 tests/fixtures/success_response_v4_1.json | 5 + tests/fixtures/success_response_v4_2.json | 6 + tests/fixtures/success_response_v4_3.json | 22 + 26 files changed, 1344 insertions(+), 234 deletions(-) create mode 100644 .travis.yml create mode 100644 src/AtolOnlineClient/Exception/InvalidResponseException.php create mode 100644 tests/AtolOnlineClient/AtolOnlineApiTest.php create mode 100644 tests/AtolOnlineClient/AtolOnlineTest.php create mode 100644 tests/AtolOnlineClient/Configuration/ConnectionTest.php create mode 100644 tests/AtolOnlineClient/ConfigurationTest.php create mode 100644 tests/AtolOnlineClient/Response/ResponseTest.php delete mode 100644 tests/AtolOnlineClient/Tests/AtolOnlineTest.php rename bootstrap.php => tests/bootstrap.php (79%) rename tests/{AtolOnlineClient/Tests/data/sell_error_response_v3.json => fixtures/error_response_v3.json} (100%) rename tests/{AtolOnlineClient/Tests/data/sell_error_response_v4.json => fixtures/error_response_v4.json} (100%) create mode 100644 tests/fixtures/success_response_v4_1.json create mode 100644 tests/fixtures/success_response_v4_2.json create mode 100644 tests/fixtures/success_response_v4_3.json diff --git a/.gitignore b/.gitignore index c37da9f..47e1659 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /.idea /vendor -composer.lock \ No newline at end of file +composer.lock +.phpunit.result.cache diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..9e19205 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: php + +php: + - 7.1 + - 7.2 + - 7.3 + +before_install: + - composer selfupdate + - composer install --dev --no-interaction --prefer-dist diff --git a/composer.json b/composer.json index f232e70..b200d9a 100644 --- a/composer.json +++ b/composer.json @@ -13,19 +13,26 @@ "php": ">=7.1", "ext-curl": "*", "ext-json": "*", - "guzzle/guzzle": "~3.7", + "guzzlehttp/guzzle": "~6.3", "jms/serializer": "~0.12 || ~1.4.2", "symfony/validator": "~2.8|~3.4|~4.0", "doctrine/cache": "~1.6", "psr/log": "~1.0" }, "require-dev": { - "phpunit/phpunit": "~7" + "phpunit/phpunit": "~8.0" }, "support": { "email": "support@retailcrm.ru" }, "autoload": { - "psr-0": { "AtolOnlineClient\\": "src/" } + "psr-0": { + "AtolOnlineClient\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "AtolOnlineClient\\": "tests/" + } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ff40e8a..dfb6b9b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,24 +1,27 @@ - - + - ./tests/*/Tests + ./tests/AtolOnlineClient + + + src + + diff --git a/src/AtolOnlineClient/AtolOnline.php b/src/AtolOnlineClient/AtolOnline.php index cc2d642..1191f29 100644 --- a/src/AtolOnlineClient/AtolOnline.php +++ b/src/AtolOnlineClient/AtolOnline.php @@ -3,18 +3,25 @@ namespace AtolOnlineClient; use AtolOnlineClient\Configuration\Connection; +use AtolOnlineClient\Exception\InvalidResponseException; use AtolOnlineClient\Response\OperationResponse; -use Guzzle\Http\Client; +use GuzzleHttp\Client; use JMS\Serializer\DeserializationContext; +use JMS\Serializer\Exception\RuntimeException; use JMS\Serializer\SerializationContext; use JMS\Serializer\SerializerBuilder; +use JMS\Serializer\SerializerInterface; class AtolOnline { - + /** + * @var SerializerInterface + */ private $serializer; - /** @var AtolOnlineApi */ + /** + * @var AtolOnlineApi + */ private $api; public function __construct() @@ -22,37 +29,48 @@ class AtolOnline $this->serializer = SerializerBuilder::create()->build(); } - public function createConfiguration() + /** + * @return Configuration + */ + public function createConfiguration(): ConfigurationInterface { return new Configuration(); } /** - * @param $response + * @param string $response * @return OperationResponse */ - public function deserializeOperationResponse($response) + public function deserializeOperationResponse(string $response): OperationResponse { - return $this->serializer->deserialize( - $response, - OperationResponse::class, - 'json', - DeserializationContext::create()->setGroups(['post']) - ); + try { + return $this->serializer->deserialize( + $response, + OperationResponse::class, + 'json', + DeserializationContext::create()->setGroups(['post']) + ); + } catch (RuntimeException $exception) { + throw $this->createInvalidResponseException($response, $exception); + } } /** * @param $response * @return OperationResponse */ - public function deserializeCheckStatusResponse($response) + public function deserializeCheckStatusResponse($response): OperationResponse { - return $this->serializer->deserialize( - $response, - OperationResponse::class, - 'json', - DeserializationContext::create()->setGroups(['get']) - ); + try { + return $this->serializer->deserialize( + $response, + OperationResponse::class, + 'json', + DeserializationContext::create()->setGroups(['get']) + ); + } catch (RuntimeException $exception) { + throw $this->createInvalidResponseException($response, $exception); + } } /** @@ -69,11 +87,11 @@ class AtolOnline } /** - * @param $client + * @param Client $client * @param Connection $connection * @return AtolOnlineApi */ - public function createApi(Client $client, Connection $connection) + public function createApi(Client $client, Connection $connection): AtolOnlineApi { if (!$this->api) { $this->api = new AtolOnlineApi($client, $connection); @@ -85,8 +103,30 @@ class AtolOnline /** * @return AtolOnlineApi */ - public function getApi() + public function getApi(): AtolOnlineApi { return $this->api; } -} \ No newline at end of file + + /** + * @param string $response + * @param RuntimeException $previous + * @return InvalidResponseException + */ + private function createInvalidResponseException(string $response, RuntimeException $previous): InvalidResponseException + { + $exception = new InvalidResponseException($previous->getMessage()); + + preg_match('/(\d+) ([\w ]+)<\/title><\/head>/m', $response, $matches); + + if (count($matches) === 3) { + [, $code, $message] = $matches; + + $exception + ->setCodeError($code) + ->setMessageError($message); + } + + return $exception; + } +} diff --git a/src/AtolOnlineClient/AtolOnlineApi.php b/src/AtolOnlineClient/AtolOnlineApi.php index 1968852..10c2325 100644 --- a/src/AtolOnlineClient/AtolOnlineApi.php +++ b/src/AtolOnlineClient/AtolOnlineApi.php @@ -4,36 +4,29 @@ namespace AtolOnlineClient; use AtolOnlineClient\Configuration\Connection; use Doctrine\Common\Cache\Cache; - -use Guzzle\Http\Client; - -use Guzzle\Http\Exception\BadResponseException; -use Guzzle\Http\Message\Response; +use GuzzleHttp\Client; +use GuzzleHttp\Exception\BadResponseException; +use Psr\Http\Message\ResponseInterface; use Psr\Log\LoggerInterface; class AtolOnlineApi { + public const API_VERSION_V4 = 'v4'; + public const API_VERSION_V3 = 'v3'; - const API_VERSION_V4 = 'v4'; - const API_VERSION_V3 = 'v3'; - - const TOKEN_CACHE_KEY = 'crm_fiscal_atol_online_token'; - const TOKEN_CACHE_TIME = 60 * 60 * 24; + public const TOKEN_CACHE_KEY = 'crm_fiscal_atol_online_token'; + public const TOKEN_CACHE_TIME = 86400; private $baseApiUrl = 'https://online.atol.ru/possystem'; - - private $login; - private $pass; - private $groupCode; - private $debug; + private $testApiUrl = 'https://testonline.atol.ru/possystem'; /** - * @var LoggerInterface + * @var LoggerInterface|null */ private $logger; /** - * @var Cache + * @var Cache|null */ private $cache; @@ -42,6 +35,11 @@ class AtolOnlineApi */ private $client; + /** + * @var Connection + */ + private $connection; + /** * @var int */ @@ -52,9 +50,6 @@ class AtolOnlineApi */ private $attemptsCheckStatus; - /** @var string */ - private $version; - /** * @param Client $client * @param Connection $connectionConfig @@ -62,18 +57,44 @@ class AtolOnlineApi public function __construct(Client $client, Connection $connectionConfig) { $this->client = $client; - $this->login = $connectionConfig->login; - $this->pass = $connectionConfig->pass; - $this->groupCode = $connectionConfig->group; - if (!$connectionConfig->version) { - $connectionConfig->version = self::API_VERSION_V3; - } - $this->version = $connectionConfig->version; - $this->debug = $connectionConfig->isDebug(); + $this->connection = $connectionConfig; + $this->attempts = 0; - if ($connectionConfig->isTestMode()) { - $this->baseApiUrl = 'https://testonline.atol.ru/possystem'; - } + } + + /** + * @param LoggerInterface $logger + */ + public function setLogger(LoggerInterface $logger): void + { + $this->logger = $logger; + } + + /** + * @param Cache $cache + */ + public function setCache(Cache $cache): void + { + $this->cache = $cache; + } + + /** + * @param string $version + * @return AtolOnlineApi + */ + public function setVersion(string $version): AtolOnlineApi + { + $this->connection->version = $version; + + return $this; + } + + /** + * @return string + */ + public function getVersion(): string + { + return $this->connection->version ?: self::API_VERSION_V3; } /** @@ -84,9 +105,7 @@ class AtolOnlineApi */ public function sell($paymentReceiptRequest) { - if ($response = $this->sendOperationRequest('sell', $paymentReceiptRequest)) { - return $response->getBody()->__toString(); - }; + return $this->sendOperationRequest('sell', $paymentReceiptRequest); } /** @@ -97,74 +116,48 @@ class AtolOnlineApi */ public function sellRefund($paymentReceiptRequest) { - if ($response = $this->sendOperationRequest('sell_refund', $paymentReceiptRequest)) { - return $response->getBody()->__toString(); - }; + return $this->sendOperationRequest('sell_refund', $paymentReceiptRequest); } /** * Запрос для проверки статуса * - * @param $uuid + * @param string $uuid * @return mixed */ public function checkStatus($uuid) { $token = $this->getToken(); + $url = $this->buildUrl('report/'.$uuid, $token); - $request = $this->client->get($url); try { $this->attemptsCheckStatus++; - $response = $request->send(); - } catch (BadResponseException $e) { - $this->cache->delete($this->getTokenCacheKey()); - $body = json_decode($e->getResponse()->getBody()); - if ($this->isTokenExpired($body) && $this->attemptsCheckStatus <= 1) { + $response = $this->client->get($url); + } catch (BadResponseException $exception) { + if ($this->cache) { + $this->cache->delete($this->getTokenCacheKey()); + } + + $response = $exception->getResponse(); + $body = json_decode($response->getBody(), false); + + if ($this->attemptsCheckStatus <= 1 && $this->isTokenExpired($body)) { return $this->checkStatus($uuid); } - $response = $e->getResponse(); } - if ($response) { - $this->logDebug($url, $uuid, $response); + $this->logDebug($url, $uuid, $response); - return $response->getBody()->__toString(); - } - - return false; - } - - /** - * @param $logger - */ - public function setLogger(LoggerInterface $logger) - { - $this->logger = $logger; - } - - /** - * @param Cache $cache - */ - public function setCache(Cache $cache) - { - $this->cache = $cache; - } - - /** - * @param mixed $version - */ - public function setVersion($version): void - { - $this->version = $version; + return $response->getBody()->__toString(); } /** * @return string */ - public function getVersion(): string + protected function getUri(): string { - return $this->version; + return $this->connection->isTestMode() ? $this->testApiUrl : $this->baseApiUrl; } /** @@ -174,134 +167,154 @@ class AtolOnlineApi protected function getToken() { $data = [ - 'login' => $this->login, - 'pass' => $this->pass, + 'login' => $this->connection->login, + 'pass' => $this->connection->pass, ]; - if ($token = $this->cache->fetch($this->getTokenCacheKey())) { + if ($this->cache && ($token = $this->cache->fetch($this->getTokenCacheKey()))) { return $token; } $dataJson = json_encode((object)$data, JSON_UNESCAPED_UNICODE); - $url = $this->baseApiUrl - .'/'.$this->version - .'/getToken'; - $request = $this->client->createRequest('POST', $url, null, $dataJson); + $url = $this->getUri().'/'.$this->connection->version.'/getToken'; + $response = false; try { - $response = $this->client->send($request); - } catch (BadResponseException $e) { - if ($this->logger) { - $this->logger->error($e->getResponse()->getBody()); + $response = $this->client->post($url, ['body' => $dataJson]); + } catch (BadResponseException $exception) { + if ($this->logger && $exception->getResponse()) { + $this->logger->error((string) $exception->getResponse()->getBody()); } } if ($response) { - $response = json_decode($response->getBody()); + $response = json_decode($response->getBody(), true); - if ($this->version === self::API_VERSION_V4) { - if (!isset ($response->error)) { - $this->cache->save($this->getTokenCacheKey(), $response->token, self::TOKEN_CACHE_TIME); - - return $response->token; - } else { - $this->logger->error($response->error->code . ' '. $response->error->text); + if ($this->connection->isVersion4()) { + if ($this->cache && !isset($response['error'])) { + $this->cache->save($this->getTokenCacheKey(), $response['token'], self::TOKEN_CACHE_TIME); } - } else { - if (isset($response->code) && ($response->code == 1 || $response->code == 0)) { - $this->cache->save($this->getTokenCacheKey(), $response->token, self::TOKEN_CACHE_TIME); - return $response->token; + if ($this->logger && isset($response['error'])) { + $this->logger->error($response['error']['code'] . ' '. $response['error']['text']); } + + if (!isset($response['error'])) { + return $response['token']; + } + + return false; } + if (isset($response['code']) && in_array($response['code'], [0, 1], true)) { + if ($this->cache) { + $this->cache->save($this->getTokenCacheKey(), $response['token'], self::TOKEN_CACHE_TIME); + } + + return $response['token']; + } } return false; } - /** - * @return string - */ - protected function getTokenCacheKey() - { - return self::TOKEN_CACHE_KEY.'_'.md5($this->login.$this->pass).'_'.$this->version; - } - /** * @param string $operation - * @param null $token + * @param string|null $token * @return string */ - protected function buildUrl($operation, $token = null) + protected function buildUrl(string $operation, string $token = null): string { - $url = $this->baseApiUrl - .'/'.$this->version - .'/'.$this->groupCode + $url = $this->getUri() + .'/'.$this->connection->version + .'/'.$this->connection->group .'/'.$operation; - if ($token) { - if ($this->version === self::API_VERSION_V4) { - $url .= '?token='.$token; - } elseif ($this->version === self::API_VERSION_V3) { - $url .= '?tokenid='.$token; - } + if (!$token) { + return $url; } - return $url; + if ($this->getVersion() === self::API_VERSION_V4) { + return $url.'?token='.$token; + } + + return $url.'?tokenid='.$token; } /** * @param string $operation - * @param string $data - * @return Response|bool + * @param mixed $data + * @return string */ - protected function sendOperationRequest($operation, $data) + protected function sendOperationRequest(string $operation, $data): string { $token = $this->getToken(); + $url = $this->buildUrl($operation, $token); - $request = $this->client->createRequest('POST', $url, null, $data); try { $this->attempts++; - $response = $this->client->send($request); + $response = $this->client->post($url, ['body' => $data]); } catch (BadResponseException $e) { - $this->cache->delete($this->getTokenCacheKey()); - $body = json_decode($e->getResponse()->getBody()); + if ($this->cache) { + $this->cache->delete($this->getTokenCacheKey()); + } + + $response = $e->getResponse(); + + $body = json_decode($response->getBody()->__toString(), false); + if ($this->isTokenExpired($body) && $this->attempts <= 1) { return $this->sendOperationRequest($operation, $data); } - $response = $e->getResponse(); } if ($response) { $this->logDebug($url, $data, $response); } - return $response; + return $response->getBody()->__toString(); } - protected function logDebug($url, $data, Response $response) + /** + * @param string $url + * @param string $data + * @param ResponseInterface $response + */ + protected function logDebug(string $url, string $data, ResponseInterface $response): void { - if ($this->debug && $this->logger) { - $v = "* URL: ".$url; + if ($this->logger && $this->connection->isDebug()) { + $headers = []; + + foreach ($response->getHeaders() as $key => $value) { + $headers[] = implode(': ', [$key, $value[0]]); + } + + $v = '* URL: '.$url; $v .= "\n * POSTFIELDS: ".$data; - $v .= "\n * RESPONSE HEADERS: ".$response->getRawHeaders(); + $v .= "\n * RESPONSE HEADERS: ".implode(', ', $headers); $v .= "\n * RESPONSE BODY: ".$response->getBody(); $v .= "\n * ATTEMPTS: ".$this->attempts; $this->logger->debug($v); } } - protected function isTokenExpiredCode($code) + /** + * @return string + */ + protected function getTokenCacheKey(): string { - return in_array($code, [4, 5, 6, 12, 13, 14]); + return self::TOKEN_CACHE_KEY.'_'.md5($this->connection->login.$this->connection->pass).'_'.$this->connection->version; } - private function isTokenExpired($body) + /** + * @param object $body + * @return bool + */ + private function isTokenExpired($body): bool { - return isset($body->error) && $this->isTokenExpiredCode($body->error->code); + return isset($body->error) && in_array($body->error->code, [4, 5, 6, 12, 13, 14], true); } } diff --git a/src/AtolOnlineClient/Configuration.php b/src/AtolOnlineClient/Configuration.php index 1227a85..d523a1f 100644 --- a/src/AtolOnlineClient/Configuration.php +++ b/src/AtolOnlineClient/Configuration.php @@ -8,14 +8,20 @@ use Symfony\Component\Validator\Mapping\ClassMetadata; class Configuration implements ConfigurationInterface { - /** @var Connection[] */ + /** + * @var Connection[] + */ public $connections; - /** @var boolean */ - public $enabled; + /** + * @var boolean + */ + public $enabled = true; - /** @var bool */ - public $debug; + /** + * @var bool + */ + public $debug = false; /** * @param ClassMetadata $metadata diff --git a/src/AtolOnlineClient/Configuration/Connection.php b/src/AtolOnlineClient/Configuration/Connection.php index 95e19a3..a150190 100644 --- a/src/AtolOnlineClient/Configuration/Connection.php +++ b/src/AtolOnlineClient/Configuration/Connection.php @@ -45,7 +45,7 @@ class Connection public $sno; /** @var string */ - public $version; + public $version = AtolOnlineApi::API_VERSION_V3; /** @var bool */ public $testMode = false; diff --git a/src/AtolOnlineClient/Exception/AtolException.php b/src/AtolOnlineClient/Exception/AtolException.php index 9ec01a5..394a7aa 100644 --- a/src/AtolOnlineClient/Exception/AtolException.php +++ b/src/AtolOnlineClient/Exception/AtolException.php @@ -2,7 +2,8 @@ namespace AtolOnlineClient\Exception; -class AtolException extends \Exception -{ +use Exception; +class AtolException extends Exception +{ } diff --git a/src/AtolOnlineClient/Exception/InvalidResponseException.php b/src/AtolOnlineClient/Exception/InvalidResponseException.php new file mode 100644 index 0000000..5365754 --- /dev/null +++ b/src/AtolOnlineClient/Exception/InvalidResponseException.php @@ -0,0 +1,59 @@ +<?php + +namespace AtolOnlineClient\Exception; + +/** + * Class InvalidResponseException + * + * @package AtolOnlineClient\Exception + */ +class InvalidResponseException extends AtolException +{ + /** + * @var int|null + */ + protected $codeError; + + /** + * @var string|null + */ + protected $messageError; + + /** + * @return int|null + */ + public function getCodeError(): ?int + { + return $this->codeError; + } + + /** + * @param int|null $codeError + * @return InvalidResponseException + */ + public function setCodeError(?int $codeError): InvalidResponseException + { + $this->codeError = $codeError; + + return $this; + } + + /** + * @return string|null + */ + public function getMessageError(): ?string + { + return $this->messageError; + } + + /** + * @param string|null $messageError + * @return InvalidResponseException + */ + public function setMessageError(?string $messageError): InvalidResponseException + { + $this->messageError = $messageError; + + return $this; + } +} diff --git a/src/AtolOnlineClient/Request/V4/VatReceiptRequest.php b/src/AtolOnlineClient/Request/V4/VatReceiptRequest.php index bd0a10f..e2b4cf8 100644 --- a/src/AtolOnlineClient/Request/V4/VatReceiptRequest.php +++ b/src/AtolOnlineClient/Request/V4/VatReceiptRequest.php @@ -60,4 +60,4 @@ class VatReceiptRequest { return $this->sum; } -} \ No newline at end of file +} diff --git a/src/AtolOnlineClient/Response/Error.php b/src/AtolOnlineClient/Response/Error.php index 173fdde..448ae24 100644 --- a/src/AtolOnlineClient/Response/Error.php +++ b/src/AtolOnlineClient/Response/Error.php @@ -4,6 +4,9 @@ namespace AtolOnlineClient\Response; use JMS\Serializer\Annotation as Serializer; +/** + * @Serializer\AccessType("public_method") + */ class Error { diff --git a/src/AtolOnlineClient/Response/OperationResponse.php b/src/AtolOnlineClient/Response/OperationResponse.php index 300ebd4..5d48f23 100644 --- a/src/AtolOnlineClient/Response/OperationResponse.php +++ b/src/AtolOnlineClient/Response/OperationResponse.php @@ -4,6 +4,9 @@ namespace AtolOnlineClient\Response; use JMS\Serializer\Annotation as Serializer; +/** + * @Serializer\AccessType("public_method") + */ class OperationResponse { diff --git a/src/AtolOnlineClient/Response/Payload.php b/src/AtolOnlineClient/Response/Payload.php index f6d73d9..f78075c 100644 --- a/src/AtolOnlineClient/Response/Payload.php +++ b/src/AtolOnlineClient/Response/Payload.php @@ -4,6 +4,9 @@ namespace AtolOnlineClient\Response; use JMS\Serializer\Annotation as Serializer; +/** + * @Serializer\AccessType("public_method") + */ class Payload { /** diff --git a/tests/AtolOnlineClient/AtolOnlineApiTest.php b/tests/AtolOnlineClient/AtolOnlineApiTest.php new file mode 100644 index 0000000..23b5af7 --- /dev/null +++ b/tests/AtolOnlineClient/AtolOnlineApiTest.php @@ -0,0 +1,479 @@ +<?php + +namespace AtolOnlineClient\AtolOnlineClient; + +use AtolOnlineClient\AtolOnline; +use AtolOnlineClient\AtolOnlineApi; +use AtolOnlineClient\Configuration\Connection; +use AtolOnlineClient\Request\V4\PaymentReceiptRequest; +use AtolOnlineClient\Request\V4\ReceiptRequest; +use AtolOnlineClient\Request\V4\ServiceRequest; +use Doctrine\Common\Cache\ArrayCache; +use GuzzleHttp\Client; +use GuzzleHttp\Exception\BadResponseException; +use GuzzleHttp\Handler\MockHandler; +use GuzzleHttp\HandlerStack; +use GuzzleHttp\Psr7\Request; +use GuzzleHttp\Psr7\Response; +use PHPUnit\Framework\TestCase; +use Psr\Log\NullLogger; +use Psr\Log\Test\TestLogger; + +/** + * Class AtolOnlineApiTest + * + * @package AtolOnlineClient\AtolOnlineClient + */ +class AtolOnlineApiTest extends TestCase +{ + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::__construct + * @covers \AtolOnlineClient\AtolOnlineApi::setLogger + * @covers \AtolOnlineClient\AtolOnlineApi::setCache + * @covers \AtolOnlineClient\AtolOnlineApi::setVersion + * @covers \AtolOnlineClient\AtolOnlineApi::getVersion + */ + public function testCreateApi(): void + { + $api = new AtolOnlineApi(new Client(), new Connection()); + + $this->assertInstanceOf(AtolOnlineApi::class, $api); + + $this->assertSame(AtolOnlineApi::API_VERSION_V3, $api->getVersion()); + + $api->setVersion(AtolOnlineApi::API_VERSION_V4); + $this->assertSame(AtolOnlineApi::API_VERSION_V4, $api->getVersion()); + + $api->setLogger(new NullLogger()); + $this->assertInstanceOf(NullLogger::class, $this->getProperty($api, 'logger')); + + $api->setCache(new ArrayCache()); + $this->assertInstanceOf(ArrayCache::class, $this->getProperty($api, 'cache')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::sell + */ + public function testSell(): void + { + $responses = [ + new Response(200, [], $this->getTokenSuccessResponseV4()), + new Response(200, [], $this->getReportSuccessReportV4()), + ]; + + $request = (new AtolOnline())->serializeOperationRequest($this->getPaymentRecepientRequest()); + + $response = $this->getApi($responses)->sell($request); + + $this->assertSame('2ea26f17–0884–4f08–b120–306fc096a58f', json_decode($response, true)['uuid']); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::sellRefund + */ + public function testSellRefund(): void + { + $responses = [ + new Response(200, [], $this->getTokenSuccessResponseV4()), + new Response(200, [], $this->getReportSuccessReportV4()), + ]; + + $request = (new AtolOnline())->serializeOperationRequest($this->getPaymentRecepientRequest()); + + $response = $this->getApi($responses)->sellRefund($request); + + $this->assertSame('2ea26f17–0884–4f08–b120–306fc096a58f', json_decode($response, true)['uuid']); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::checkStatus + */ + public function testCheckStatusSuccessResponse(): void + { + $responses = [ + new Response(200, [], $this->getTokenSuccessResponseV4()), + new Response(200, [], $this->getReportSuccessReportV4()), + ]; + + $response = $this->callMethod($this->getApi($responses), 'checkStatus', [ + 'uuid' => '2ea26f17–0884–4f08–b120–306fc096a58f', + ]); + + $this->assertSame('2ea26f17–0884–4f08–b120–306fc096a58f', json_decode($response, true)['uuid']); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::checkStatus + */ + public function testCheckStatusBadResponse(): void + { + $responses = [ + new Response(200, [], $this->getTokenSuccessResponseV4()), + new BadResponseException('', new Request('GET', 'test'), new Response(200, [], $this->getErrorResponseV4())), + new Response(200, [], $this->getTokenSuccessResponseV4()), + new Response(200, [], $this->getReportSuccessReportV4()), + ]; + + $api = $this->getApi($responses); + $api->setCache(new ArrayCache()); + + $response = $this->callMethod($api, 'checkStatus', [ + 'uuid' => '2ea26f17–0884–4f08–b120–306fc096a58f', + ]); + + $this->assertSame('2ea26f17–0884–4f08–b120–306fc096a58f', json_decode($response, true)['uuid']); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getUri + */ + public function testGetUri(): void + { + $this->assertSame('https://online.atol.ru/possystem', $this->callMethod($this->getApi(), 'getUri')); + $this->assertSame('https://testonline.atol.ru/possystem', $this->callMethod($this->getApi([], true, true), 'getUri')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getToken + */ + public function testGetTokenBadResponse(): void + { + $api = $this->getApi([new BadResponseException('', new Request('GET', 'test'))]); + + $this->assertFalse($this->callMethod($api, 'getToken')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getToken + */ + public function testGetTokenSuccessResponse(): void + { + $api = $this->getApi([new Response(200, [], $this->getTokenSuccessResponseV4())]); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', $this->callMethod($api, 'getToken')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getToken + */ + public function testGetTokenErrorResponseWithLogger(): void + { + $logger = new TestLogger(); + + $api = $this->getApi([new Response(200, [], $this->getErrorResponseV4())]); + $api->setLogger($logger); + + $this->assertFalse($this->callMethod($api, 'getToken')); + $this->assertTrue($logger->hasError('12 Неверный логин или пароль')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getToken + */ + public function testGetTokenBadResponseWithLogger(): void + { + $logger = new TestLogger(); + + $api = $this->getApi([new BadResponseException('', new Request('GET', 'test'), new Response(200, [], $this->getErrorResponseV4()))]); + $api->setLogger($logger); + + $this->assertFalse($this->callMethod($api, 'getToken')); + $this->assertTrue($logger->hasError('{"error":{"error_id":"4475d6d8d-844d-4d05-aa8b-e3dbdf3defd5","code":12,"text":"\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043b\u043e\u0433\u0438\u043d \u0438\u043b\u0438 \u043f\u0430\u0440\u043e\u043b\u044c","type":"system"},"timestamp":"30.11.2017 17:58:53"}')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getToken + */ + public function testGetTokenSuccessResponseWithCache(): void + { + $cache = new ArrayCache(); + + $api = $this->getApi([new Response(200, [], $this->getTokenSuccessResponseV4())]); + $api->setCache($cache); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', $this->callMethod($api, 'getToken')); + $this->assertTrue($cache->contains($this->callMethod($api, 'getTokenCacheKey'))); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', $this->callMethod($api, 'getToken')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getToken + */ + public function testGetTokenSuccessResponseV3(): void + { + $api = $this->getApi([new Response(200, [], $this->getTokenSuccessResponseV3())])->setVersion(AtolOnlineApi::API_VERSION_V3); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', $this->callMethod($api, 'getToken')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getToken + */ + public function testGetTokenSuccessResponseV3WithCache(): void + { + $cache = new ArrayCache(); + + $api = $this->getApi([new Response(200, [], $this->getTokenSuccessResponseV3())])->setVersion(AtolOnlineApi::API_VERSION_V3); + $api->setCache($cache); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', $this->callMethod($api, 'getToken')); + $this->assertTrue($cache->contains($this->callMethod($api, 'getTokenCacheKey'))); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', $this->callMethod($api, 'getToken')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::buildUrl + */ + public function testBuildUrlWithoutToken(): void + { + $args = ['operation' => 'test']; + + $this->assertSame('https://online.atol.ru/possystem/v4/group/test', $this->callMethod($this->getApi(), 'buildUrl', $args)); + $this->assertSame('https://online.atol.ru/possystem/v3/group/test', $this->callMethod($this->getApi()->setVersion(AtolOnlineApi::API_VERSION_V3), 'buildUrl', $args)); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::buildUrl + */ + public function testBuildUrlWithToken(): void + { + $args = ['operation' => 'test', 'token' => 'test']; + + $this->assertSame('https://online.atol.ru/possystem/v4/group/test?token=test', $this->callMethod($this->getApi(), 'buildUrl', $args)); + $this->assertSame('https://online.atol.ru/possystem/v3/group/test?tokenid=test', $this->callMethod($this->getApi()->setVersion(AtolOnlineApi::API_VERSION_V3), 'buildUrl', $args)); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::sendOperationRequest + */ + public function testSendOperationRequestSuccessResponse(): void + { + $responses = [ + new Response(200, [], $this->getTokenSuccessResponseV4()), + new Response(200, [], $this->getTokenSuccessResponseV4()) + ]; + + $request = (new AtolOnline())->serializeOperationRequest($this->getPaymentRecepientRequest()); + + $response = $this->callMethod($this->getApi($responses), 'sendOperationRequest', [ + 'operation' => 'sell', + 'data' => $request, + ]); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', json_decode($response, true)['token']); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::sendOperationRequest + */ + public function testSendOperationRequestBadResponse(): void + { + $responses = [ + new Response(200, [], $this->getTokenSuccessResponseV4()), + new BadResponseException('', new Request('GET', 'test'), new Response(200, [], $this->getErrorResponseV4())), + new Response(200, [], $this->getTokenSuccessResponseV4()), + new Response(200, [], $this->getTokenSuccessResponseV4()), + ]; + + $request = (new AtolOnline())->serializeOperationRequest($this->getPaymentRecepientRequest()); + + $api = $this->getApi($responses); + $api->setCache(new ArrayCache()); + + $response = $this->callMethod($api, 'sendOperationRequest', [ + 'operation' => 'sell', + 'data' => $request, + ]); + + $this->assertSame('fj45u923j59ju42395iu9423i59243u0', json_decode($response, true)['token']); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::logDebug + */ + public function testLogDebug(): void + { + $logger = new TestLogger(); + + $api = $this->getApi(); + $api->setLogger($logger); + + $this->callMethod($api, 'logDebug', [ + 'url' => '/test', + 'data' => 'test', + 'response' => new Response(200, ['X-Foo' => 'Bar', 'X-Foo2' => 'Bar2'], 'test'), + ]); + + $this->assertTrue($logger->hasDebug('* URL: /test + * POSTFIELDS: test + * RESPONSE HEADERS: X-Foo: Bar, X-Foo2: Bar2 + * RESPONSE BODY: test + * ATTEMPTS: 0')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::getTokenCacheKey + */ + public function testGetTokenCacheKey(): void + { + $this->assertSame('crm_fiscal_atol_online_token_68526766e6751745b52ae70b7bd3c6fe_v4', $this->callMethod($this->getApi(), 'getTokenCacheKey')); + $this->assertSame('crm_fiscal_atol_online_token_68526766e6751745b52ae70b7bd3c6fe_v3', $this->callMethod($this->getApi()->setVersion(AtolOnlineApi::API_VERSION_V3), 'getTokenCacheKey')); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnlineApi::isTokenExpired + */ + public function testIsTokenExpired(): void + { + $body = new \stdClass(); + $body->error = new \stdClass(); + $body->error->code = 4; + + $this->assertTrue($this->callMethod($this->getApi(), 'isTokenExpired', ['body' => $body])); + + $body = new \stdClass(); + $this->assertFalse($this->callMethod($this->getApi(), 'isTokenExpired', ['body' => $body])); + } + + /** + * @param array $responses + * @param bool $debug + * @param bool $test + * @return AtolOnlineApi + */ + private function getApi(array $responses = [], bool $debug = true, bool $test = false): AtolOnlineApi + { + $connection = new Connection(); + $connection->login = 'login'; + $connection->pass = 'pass'; + $connection->group = 'group'; + $connection->sno = Connection::SNO_GENERAL; + $connection->version = AtolOnlineApi::API_VERSION_V4; + $connection->setDebug($debug); + $connection->setTestMode($test); + + $mock = new MockHandler($responses); + + $handler = HandlerStack::create($mock); + + return new AtolOnlineApi(new Client(['handler' => $handler]), $connection); + } + + /** + * @param mixed $object + * @param string $name + * @param array $args + * @return mixed + */ + private function callMethod($object, string $name, array $args = []) + { + $reflection = new \ReflectionClass($object); + $method = $reflection->getMethod($name); + $method->setAccessible(true); + + return $method->invokeArgs($object, $args); + } + + /** + * @param mixed $object + * @param string $name + * @return mixed + */ + private function getProperty($object, string $name) + { + $reflection = new \ReflectionClass($object); + $property = $reflection->getProperty($name); + $property->setAccessible(true); + + return $property->getValue($object); + } + + /** + * @return false|string + */ + private function getTokenSuccessResponseV3() + { + return json_encode([ + 'token' => 'fj45u923j59ju42395iu9423i59243u0', + 'code' => 1, + ]); + } + + /** + * @return false|string + */ + private function getTokenSuccessResponseV4() + { + return json_encode([ + 'error' => null, + 'token' => 'fj45u923j59ju42395iu9423i59243u0', + 'timestamp' => '30.11.2017 17:58:53', + ]); + } + + /** + * @return false|string + */ + private function getErrorResponseV4() + { + return json_encode([ + 'error' => [ + 'error_id' => '4475d6d8d-844d-4d05-aa8b-e3dbdf3defd5', + 'code' => 12, + 'text' => 'Неверный логин или пароль', + 'type' => 'system', + ], + 'timestamp' => '30.11.2017 17:58:53', + ]); + } + + /** + * @return string + */ + private function getReportSuccessReportV4(): string + { + return file_get_contents(__DIR__.'/../fixtures/success_response_v4_3.json'); + } + + /** + * @return PaymentReceiptRequest + */ + private function getPaymentRecepientRequest(): PaymentReceiptRequest + { + $service = new ServiceRequest(); + $service->setCallbackUrl('test.local'); + + $receipt = new ReceiptRequest(); + $receipt->setTotal('100'); + + /** @var PaymentReceiptRequest $request */ + $request = new PaymentReceiptRequest(); + $request->setExternalId('test'); + $request->setService($service); + $request->setReceipt($receipt); + + return $request; + } +} diff --git a/tests/AtolOnlineClient/AtolOnlineTest.php b/tests/AtolOnlineClient/AtolOnlineTest.php new file mode 100644 index 0000000..bbdc577 --- /dev/null +++ b/tests/AtolOnlineClient/AtolOnlineTest.php @@ -0,0 +1,265 @@ +<?php + +namespace AtolOnlineClient\Tests; + +use AtolOnlineClient\AtolOnline; +use AtolOnlineClient\Configuration\Connection; +use AtolOnlineClient\ConfigurationInterface; +use AtolOnlineClient\Exception\InvalidResponseException; +use AtolOnlineClient\Request\V4\PaymentReceiptRequest; +use AtolOnlineClient\Request\V4\ReceiptRequest; +use AtolOnlineClient\Request\V4\ServiceRequest; +use GuzzleHttp\Client; +use JMS\Serializer\Exception\RuntimeException; +use JMS\Serializer\SerializerInterface; +use PHPUnit\Framework\TestCase; + +class AtolOnlineTest extends TestCase +{ + /** + * @var AtolOnline + */ + protected $atol; + + /** + * @return void + */ + public function setUp(): void + { + $this->atol = new AtolOnline(); + } + + /** + * @return void + * @covers \AtolOnlineClient\AtolOnline::__construct + */ + public function testConstructor(): void + { + $reflection = new \ReflectionClass(get_class($this->atol)); + + $property = $reflection->getProperty('serializer'); + $property->setAccessible(true); + + $this->assertInstanceOf(SerializerInterface::class, $property->getValue($this->atol)); + } + + /** + * @covers \AtolOnlineClient\AtolOnline::createConfiguration + * @return void + */ + public function testCreateConfiguration(): void + { + $this->assertInstanceOf(ConfigurationInterface::class, $this->atol->createConfiguration()); + } + + /** + * @param string $file + * @covers \AtolOnlineClient\AtolOnline::deserializeOperationResponse + * @dataProvider dataSuccessResponse + */ + public function testSuccessDeserializeOperationResponse(string $file): void + { + $response = file_get_contents(__DIR__.'/../fixtures/'. $file); + + $operationResponse = $this->atol->deserializeOperationResponse($response); + + $this->assertEquals('12.04.2017 06:15:06', $operationResponse->getTimestamp()); + } + + /** + * @param string $file + * @covers \AtolOnlineClient\AtolOnline::deserializeOperationResponse + * @dataProvider dataErrorResponse + */ + public function testErrorDeserializeOperationResponse(string $file): void + { + $response = file_get_contents(__DIR__.'/../fixtures/'. $file); + + $operationResponse = $this->atol->deserializeOperationResponse($response); + + $this->assertEquals('12.04.2017 06:15:06', $operationResponse->getTimestamp()); + $this->assertEquals('fail', $operationResponse->getStatus()); + $this->assertEquals(30, $operationResponse->getError()->getCode()); + $this->assertEquals('system', $operationResponse->getError()->getType()); + + $this->assertEquals( + ' Передан некорректный UUID : "{0}". Необходимо повторить запрос с корректными данными ', + $operationResponse->getError()->getText() + ); + } + + /** + * @covers \AtolOnlineClient\AtolOnline::deserializeOperationResponse + */ + public function testFailDeserializeOperationResponse(): void + { + $this->expectException(InvalidResponseException::class); + + $this->atol->deserializeOperationResponse('<html></html>'); + } + + /** + * @param string $file + * @covers \AtolOnlineClient\AtolOnline::deserializeCheckStatusResponse + * @dataProvider dataSuccessResponse + */ + public function testSuccessDeserializeCheckStatusResponse(string $file): void + { + $response = file_get_contents(__DIR__.'/../fixtures/'. $file); + + $operationResponse = $this->atol->deserializeCheckStatusResponse($response); + + $this->assertEquals('12.04.2017 06:15:06', $operationResponse->getTimestamp()); + } + + /** + * @covers \AtolOnlineClient\AtolOnline::deserializeCheckStatusResponse + */ + public function testFailDeserializeCheckStatusResponse(): void + { + $this->expectException(InvalidResponseException::class); + + $this->atol->deserializeCheckStatusResponse('<html></html>'); + } + + /** + * @param int|null $code + * @param string|null $message + * @param string $html + * @covers \AtolOnlineClient\AtolOnline::createInvalidResponseException + * @dataProvider dataInvalidResponse + */ + public function testCreateInvalidResponseException(?int $code, ?string $message, string $html): void + { + /** @var InvalidResponseException $exception */ + $exception = $this->callMethod($this->atol, 'createInvalidResponseException', [ + 'response' => $html, + 'previous' => new RuntimeException() + ]); + + $this->assertInstanceOf(InvalidResponseException::class, $exception); + $this->assertEquals($code, $exception->getCodeError()); + $this->assertEquals($message, $exception->getMessageError()); + } + + /** + * @covers \AtolOnlineClient\AtolOnline::serializeOperationRequest + */ + public function testSerializeOperationRequest(): void + { + $service = new ServiceRequest(); + $service->setCallbackUrl('test.local'); + + $receipt = new ReceiptRequest(); + $receipt->setTotal('100'); + + /** @var PaymentReceiptRequest $paymentReceipt */ + $paymentReceipt = new PaymentReceiptRequest(); + + $reflection = new \ReflectionClass($paymentReceipt); + $property = $reflection->getProperty('timestamp'); + $property->setAccessible(true); + $property->setValue($paymentReceipt, 1); + + $paymentReceipt->setExternalId('test'); + $paymentReceipt->setService($service); + $paymentReceipt->setReceipt($receipt); + + $request = $this->atol->serializeOperationRequest($paymentReceipt); + + $this->assertEquals('{"external_id":"test","receipt":{"total":100},"timestamp":"1","service":{"callback_url":"test.local"}}', $request); + } + + /** + * @return void + * + * @covers \AtolOnlineClient\AtolOnline::createApi + */ + public function testCreateApi(): void + { + $api1 = $this->atol->createApi(new Client(), new Connection()); + $api2 = $this->atol->createApi(new Client(), new Connection()); + + $this->assertSame($api1, $api2); + } + + /** + * @return void + * + * @covers \AtolOnlineClient\AtolOnline::getApi + */ + public function testGetApi(): void + { + $api1 = $this->atol->createApi(new Client(), new Connection()); + $api2 = $this->atol->getApi(); + + $this->assertSame($api1, $api2); + } + + /** + * @return array + */ + public function dataSuccessResponse(): array + { + return [ + ['success_response_v4_1.json'], + ['success_response_v4_2.json'], + ['success_response_v4_3.json'], + ]; + } + + /** + * @return array + */ + public function dataErrorResponse(): array + { + return [ + ['error_response_v3.json'], + ['error_response_v4.json'] + ]; + } + + /** + * @return array + */ + public function dataInvalidResponse(): array + { + return [ + [ + 'code' => 404, + 'message' => 'Not Found', + 'html' => '<html><head><title>404 Not Found

404 Not Found


openresty/1.15.8.1rc1
', + ], + [ + 'code' => 502, + 'message' => 'Bad Gateway', + 'html' => '502 Bad Gateway

502 Bad Gateway


nginx/1.15.8
', + ], + [ + 'code' => null, + 'message' => null, + 'html' => '', + ], + [ + 'code' => null, + 'message' => null, + 'html' => '', + ], + ]; + } + + /** + * @param mixed $object + * @param string $name + * @param array $args + * @return mixed + */ + private function callMethod($object, string $name, array $args = []) + { + $reflection = new \ReflectionClass($object); + $method = $reflection->getMethod($name); + $method->setAccessible(true); + + return $method->invokeArgs($object, $args); + } +} diff --git a/tests/AtolOnlineClient/Configuration/ConnectionTest.php b/tests/AtolOnlineClient/Configuration/ConnectionTest.php new file mode 100644 index 0000000..4947d09 --- /dev/null +++ b/tests/AtolOnlineClient/Configuration/ConnectionTest.php @@ -0,0 +1,89 @@ +connection = new Connection(); + } + + /** + * @return void + * @covers \AtolOnlineClient\Configuration\Connection::setDebug + * @covers \AtolOnlineClient\Configuration\Connection::isDebug + */ + public function testDebug(): void + { + $this->assertFalse($this->connection->isDebug()); + + $this->connection->setDebug(true); + $this->assertTrue($this->connection->isDebug()); + } + + /** + * @return void + * @covers \AtolOnlineClient\Configuration\Connection::isTestMode + * @covers \AtolOnlineClient\Configuration\Connection::setTestMode + */ + public function testTestMode(): void + { + $this->assertFalse($this->connection->isTestMode()); + + $this->connection->setTestMode(true); + $this->assertTrue($this->connection->isTestMode()); + } + + /** + * @return void + * @covers \AtolOnlineClient\Configuration\Connection::getVersion + * @covers \AtolOnlineClient\Configuration\Connection::isVersion4 + * @covers \AtolOnlineClient\Configuration\Connection::isVersion3 + */ + public function testVersion(): void + { + $this->assertEquals(AtolOnlineApi::API_VERSION_V3, $this->connection->getVersion()); + $this->assertTrue($this->connection->isVersion3()); + + $this->connection->version = AtolOnlineApi::API_VERSION_V4; + $this->assertTrue($this->connection->isVersion4()); + } + + /** + * @return void + * @covers \AtolOnlineClient\Configuration\Connection::loadValidatorMetadata + */ + public function testValidator(): void + { + + $validator = Validation::createValidatorBuilder() + ->addMethodMapping('loadValidatorMetadata') + ->getValidator(); + + $list = $validator->validate($this->connection); + + $this->assertEquals(3, $list->count()); + + $this->connection->login = 'login'; + $this->connection->pass = 'login'; + $this->connection->group = 'group'; + + $list = $validator->validate($this->connection); + + $this->assertEquals(0, $list->count()); + } +} diff --git a/tests/AtolOnlineClient/ConfigurationTest.php b/tests/AtolOnlineClient/ConfigurationTest.php new file mode 100644 index 0000000..ade8698 --- /dev/null +++ b/tests/AtolOnlineClient/ConfigurationTest.php @@ -0,0 +1,78 @@ +configuration = new Configuration(); + } + + /** + * @return void + * @covers \AtolOnlineClient\Configuration::isDebug + * @covers \AtolOnlineClient\Configuration::setDebug + */ + public function testDebug(): void + { + $this->assertFalse($this->configuration->isDebug()); + + $this->configuration->setDebug(true); + $this->assertTrue($this->configuration->isDebug()); + } + + /** + * @return void + * @covers \AtolOnlineClient\Configuration::isEnabled + * @covers \AtolOnlineClient\Configuration::setEnabled + */ + public function testEnabled(): void + { + $this->assertTrue($this->configuration->isEnabled()); + + $this->configuration->setEnabled(false); + $this->assertFalse($this->configuration->isEnabled()); + } + + /** + * @return void + * @covers \AtolOnlineClient\Configuration::loadValidatorMetadata + */ + public function testValidator(): void + { + + $validator = Validation::createValidatorBuilder() + ->addMethodMapping('loadValidatorMetadata') + ->getValidator(); + + $list = $validator->validate($this->configuration); + + $this->assertEquals(1, $list->count()); + + $connection = new Configuration\Connection(); + $connection->login = 'login'; + $connection->pass = 'login'; + $connection->group = 'group'; + + $this->configuration->connections[] = $connection; + + $list = $validator->validate($this->configuration); + + $this->assertEquals(0, $list->count()); + } +} diff --git a/tests/AtolOnlineClient/Response/ResponseTest.php b/tests/AtolOnlineClient/Response/ResponseTest.php new file mode 100644 index 0000000..6b71c30 --- /dev/null +++ b/tests/AtolOnlineClient/Response/ResponseTest.php @@ -0,0 +1,63 @@ +build(); + + $response = '{ + "uuid": "4355", + "timestamp": "12.04.2017 06:15:06", + "status": "fail", + "error": { + "error_id": "475d6d8d-844d-4d05-aa8b-e3dbdf4defd6", + "code": 30, + "text": " Передан некорректный UUID : \"{0}\". Необходимо повторить запрос с корректными данными ", + "type": "system" + }, + "payload": { + "total": 1598, + "fns_site": "www.nalog.ru", + "fn_number": "1110000100238211", + "shift_number": 23, + "receipt_datetime": "12.04.2017 20:16:00", + "fiscal_receipt_number": 6, + "fiscal_document_number": 133, + "ecr_registration_number": "0000111118041361", + "fiscal_document_attribute": 3449555941 + }, + "group_code": " MyCompany_MyShop", + "daemon_code": "prod–agent–1", + "device_code": "KSR13.00–1–11", + "external_id": "TRF10601_1", + "callback_url": "" +}'; + $response = $serializer->deserialize( + $response, + OperationResponse::class, + 'json' + ); + + $serializer->serialize( + $response, + 'json' + ); + + $this->assertTrue(true); + } +} diff --git a/tests/AtolOnlineClient/Tests/AtolOnlineTest.php b/tests/AtolOnlineClient/Tests/AtolOnlineTest.php deleted file mode 100644 index ad5249d..0000000 --- a/tests/AtolOnlineClient/Tests/AtolOnlineTest.php +++ /dev/null @@ -1,46 +0,0 @@ -assertInstanceOf(Configuration::class, $atol->createConfiguration()); - } - - - /** - * @dataProvider dataSellErrorResponse - */ - public function testDeserializeOperationResponse($file) - { - $response = file_get_contents(__DIR__ . '/data/'. $file); - $atol = new AtolOnline(); - $operationResponse = $atol->deserializeOperationResponse($response); - $this->assertInstanceOf(OperationResponse::class, $operationResponse); - $this->assertEquals('12.04.2017 06:15:06', $operationResponse->getTimestamp()); - $this->assertEquals('fail', $operationResponse->getStatus()); - $this->assertEquals(30, $operationResponse->getError()->getCode()); - $this->assertEquals('system', $operationResponse->getError()->getType()); - $this->assertEquals( - ' Передан некорректный UUID : "{0}". Необходимо повторить запрос с корректными данными ', - $operationResponse->getError()->getText() - ); - } - - public function dataSellErrorResponse() - { - return [ - ['sell_error_response_v3.json'], - ['sell_error_response_v3.json'] - ]; - } -} diff --git a/bootstrap.php b/tests/bootstrap.php similarity index 79% rename from bootstrap.php rename to tests/bootstrap.php index 8c24c52..6559848 100644 --- a/bootstrap.php +++ b/tests/bootstrap.php @@ -1,13 +1,13 @@