1
0
Fork 0
mirror of synced 2025-04-19 17:01:00 +00:00

Compare commits

..

No commits in common. "master" and "1.0.1" have entirely different histories.

48 changed files with 3455 additions and 1772 deletions

5
.gitignore vendored
View file

@ -1,5 +1,2 @@
/.idea
./idea
/vendor
composer.lock
.phpunit.result.cache
.env

View file

@ -1,16 +0,0 @@
language: php
php:
- 7.2
- 7.3
- 7.4
env:
- JMS=0.12
- JMS=1.0
- JMS=2.0
- JMS=3.0
before_install:
- composer selfupdate
- composer require jms/serializer=^$JMS --no-interaction --prefer-dist

View file

@ -1,6 +0,0 @@
ARG PHP_IMAGE_TAG
FROM php:${PHP_IMAGE_TAG}-cli-alpine
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
WORKDIR /opt/test

21
LICENSE
View file

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2018 retailCRM
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -1,16 +0,0 @@
ifneq (,$(shell (type docker-compose 2>&1 >/dev/null && echo 1) || true))
PHP=docker-compose run --rm --no-deps php
else
PHP=php
endif
PHP_CONSOLE_DEPS=vendor
vendor: composer.json
@$(PHP) composer install -o -n --no-ansi
@touch vendor || true
phpunit: $(PHP_CONSOLE_DEPS)
@$(PHP) vendor/bin/phpunit --color=always
check: phpunit

View file

@ -1,38 +1,28 @@
[![Build Status](https://app.travis-ci.com/retailcrm/atol-online-client.svg?branch=master)](https://app.travis-ci.com/retailcrm/atol-online-client)
[![Latest stable](https://img.shields.io/packagist/v/retailcrm/atol-online-client.svg?style=flat-square)](https://packagist.org/packages/retailcrm/atol-online-client)
# API клиент для сервиса фискализации платежей АТОЛ Онлайн
# API-клиент для АТОЛ.Онлайн
API-клиент на PHP для сервиса онлайн-фискализации платежей АТОЛ.Онлайн
## Требования
* PHP 7.2 и выше
* PHP extension cURL
## Пример использования
Пример использования:
```php
$atol = new \AtolOnlineClient\AtolOnline();
$client = new \Guzzle\Http\Client();
$connection = new \AtolOnlineClient\Configuration\Connection();
$connection->version = \AtolOnlineClient\AtolOnlineApi::API_VERSION_V4;
$connection->login = 'login';
$connection->pass = 'pass';
$connection->enabled = true;
$connection->group = 'group';
$config = new \AtolOnlineClient\Configuration();
$config->connections = [$connection];
$client = new \Guzzle\Http\Client();
$api = $atol->createApi($client, $connection);
// $api->setLogger(...);
// $api->setCache(...);
// собираем объект запроса
$api = $this->atol->createApi($client, $connection);
//$api->setLogger();
//$api->setCache();
$request = new \AtolOnlineClient\Request\V4\PaymentReceiptRequest();
/// ...
/// собираем объект запроса
///
$paymentReceiptRequest = $atol->serializeOperationRequest($request);
$response = $atol->getApi()->sell($paymentReceiptRequest);

13
bootstrap.php Normal file
View file

@ -0,0 +1,13 @@
<?php
use Composer\Autoload\ClassLoader;
use Doctrine\Common\Annotations\AnnotationRegistry;
/**
* @var ClassLoader $loader
*/
$loader = require __DIR__.'/vendor/autoload.php';
AnnotationRegistry::registerLoader('class_exists');
return $loader;

View file

@ -2,7 +2,7 @@
"name": "retailcrm/atol-online-client",
"type": "library",
"license": "proprietary",
"description": "PHP API client for ATOL Online",
"description": "Api client for Atol Online",
"authors": [
{
"name": "retailCRM",
@ -10,29 +10,21 @@
}
],
"require": {
"php": ">=7.2",
"php": ">=7.1",
"ext-curl": "*",
"ext-json": "*",
"guzzlehttp/guzzle": "~6.3|^7.0",
"jms/serializer": "^0.12|^1.0|^2.0|^3.0",
"symfony/validator": "~2.8|~3.0|~4.0|^5.0|^6.0",
"guzzle/guzzle": "~3.7",
"jms/serializer": "~0.12 || ~1.4.2",
"symfony/validator": "2.8.*",
"doctrine/cache": "~1.6",
"psr/log": "~1.0|^2.0|^3.0"
"psr/log": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "~8.0"
"phpunit/phpunit": "7.1."
},
"support": {
"email": "support@retailcrm.ru"
},
"autoload": {
"psr-0": {
"AtolOnlineClient\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"AtolOnlineClient\\": "tests/"
}
"psr-0": { "AtolOnlineClient\\": "src/" }
}
}

2389
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,11 +0,0 @@
version: '3.4'
services:
php:
build:
context: .
args:
PHP_IMAGE_TAG: ${PHP_IMAGE_TAG:-7.4}
volumes:
- "./:/opt/test"

View file

@ -1,28 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="tests/bootstrap.php"
backupGlobals="false"
backupStaticAttributes="false"
colors="true"
verbose="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
convertDeprecationsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<!-- http://www.phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit
backupGlobals = "false"
backupStaticAttributes = "false"
colors = "true"
convertErrorsToExceptions = "true"
convertNoticesToExceptions = "true"
convertWarningsToExceptions = "true"
processIsolation = "true"
stopOnFailure = "false"
syntaxCheck = "false"
bootstrap = "bootstrap.php" >
<testsuites>
<testsuite name="php">
<directory>./tests/AtolOnlineClient</directory>
<directory>./tests/*/Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>src</directory>
</whitelist>
</filter>
</phpunit>

View file

@ -3,25 +3,18 @@
namespace AtolOnlineClient;
use AtolOnlineClient\Configuration\Connection;
use AtolOnlineClient\Exception\InvalidResponseException;
use AtolOnlineClient\Response\OperationResponse;
use GuzzleHttp\Client;
use Guzzle\Http\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()
@ -29,48 +22,37 @@ class AtolOnline
$this->serializer = SerializerBuilder::create()->build();
}
/**
* @return Configuration
*/
public function createConfiguration(): ConfigurationInterface
public function createConfiguration()
{
return new Configuration();
}
/**
* @param string $response
* @return OperationResponse
*/
public function deserializeOperationResponse(string $response): OperationResponse
{
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): OperationResponse
public function deserializeOperationResponse($response)
{
try {
return $this->serializer->deserialize(
$response,
OperationResponse::class,
'json',
DeserializationContext::create()->setGroups(['get'])
);
} catch (RuntimeException $exception) {
throw $this->createInvalidResponseException($response, $exception);
}
return $this->serializer->deserialize(
$response,
OperationResponse::class,
'json',
DeserializationContext::create()->setGroups(['post'])
);
}
/**
* @param $response
* @return OperationResponse
*/
public function deserializeCheckStatusResponse($response)
{
return $this->serializer->deserialize(
$response,
OperationResponse::class,
'json',
DeserializationContext::create()->setGroups(['get'])
);
}
/**
@ -87,11 +69,11 @@ class AtolOnline
}
/**
* @param Client $client
* @param $client
* @param Connection $connection
* @return AtolOnlineApi
*/
public function createApi(Client $client, Connection $connection): AtolOnlineApi
public function createApi(Client $client, Connection $connection)
{
if (!$this->api) {
$this->api = new AtolOnlineApi($client, $connection);
@ -103,30 +85,8 @@ class AtolOnline
/**
* @return AtolOnlineApi
*/
public function getApi(): AtolOnlineApi
public function getApi()
{
return $this->api;
}
/**
* @param string $response
* @param RuntimeException $previous
* @return InvalidResponseException
*/
private function createInvalidResponseException(string $response, RuntimeException $previous): InvalidResponseException
{
$exception = new InvalidResponseException($previous->getMessage());
preg_match('/<head><title>(\d+) ([\w ]+)<\/title><\/head>/m', $response, $matches);
if (count($matches) === 3) {
[, $code, $message] = $matches;
$exception
->setCodeError($code)
->setMessageError($message);
}
return $exception;
}
}
}

View file

@ -4,28 +4,36 @@ namespace AtolOnlineClient;
use AtolOnlineClient\Configuration\Connection;
use Doctrine\Common\Cache\Cache;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\BadResponseException;
use Psr\Http\Message\ResponseInterface;
use Guzzle\Http\Client;
use Guzzle\Http\Exception\BadResponseException;
use Guzzle\Http\Message\Response;
use Psr\Log\LoggerInterface;
class AtolOnlineApi
{
public const API_VERSION_V4 = 'v4';
public const TOKEN_CACHE_KEY = 'crm_fiscal_atol_online_token';
public const TOKEN_CACHE_TIME = 86400;
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;
private $baseApiUrl = 'https://online.atol.ru/possystem';
private $testApiUrl = 'https://testonline.atol.ru/possystem';
private $login;
private $pass;
private $groupCode;
private $debug;
/**
* @var LoggerInterface|null
* @var LoggerInterface
*/
private $logger;
/**
* @var Cache|null
* @var Cache
*/
private $cache;
@ -34,11 +42,6 @@ class AtolOnlineApi
*/
private $client;
/**
* @var Connection
*/
private $connection;
/**
* @var int
*/
@ -49,6 +52,9 @@ class AtolOnlineApi
*/
private $attemptsCheckStatus;
/** @var string */
private $version;
/**
* @param Client $client
* @param Connection $connectionConfig
@ -56,44 +62,18 @@ class AtolOnlineApi
public function __construct(Client $client, Connection $connectionConfig)
{
$this->client = $client;
$this->connection = $connectionConfig;
$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->attempts = 0;
}
/**
* @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_V4;
if ($connectionConfig->isTestMode()) {
$this->baseApiUrl = 'https://testonline.atol.ru/possystem';
}
}
/**
@ -104,7 +84,9 @@ class AtolOnlineApi
*/
public function sell($paymentReceiptRequest)
{
return $this->sendOperationRequest('sell', $paymentReceiptRequest);
if ($response = $this->sendOperationRequest('sell', $paymentReceiptRequest)) {
return $response->getBody()->__toString();
};
}
/**
@ -115,48 +97,73 @@ class AtolOnlineApi
*/
public function sellRefund($paymentReceiptRequest)
{
return $this->sendOperationRequest('sell_refund', $paymentReceiptRequest);
if ($response = $this->sendOperationRequest('sell_refund', $paymentReceiptRequest)) {
return $response->getBody()->__toString();
};
}
/**
* Запрос для проверки статуса
*
* @param string $uuid
* @param $uuid
* @return mixed
*/
public function checkStatus($uuid)
{
$token = $this->getToken();
$url = $this->buildUrl('report/'.$uuid, $token);
$request = $this->client->get($url);
$response = false;
try {
$this->attemptsCheckStatus++;
$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)) {
$response = $request->send();
} catch (BadResponseException $e) {
$this->cache->delete($this->getTokenCacheKey());
$body = json_decode($e->getResponse()->getBody());
if ($this->isTokenExpired($body) && $this->attemptsCheckStatus <= 1) {
return $this->checkStatus($uuid);
}
$this->logDebug($url, $uuid, $e->getResponse());
}
$this->logDebug($url, $uuid, $response);
if ($response) {
return $response->getBody()->__toString();
}
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 string
*/
protected function getUri(): string
public function getVersion(): string
{
return $this->connection->isTestMode() ? $this->testApiUrl : $this->baseApiUrl;
return $this->version;
}
/**
@ -166,137 +173,134 @@ class AtolOnlineApi
protected function getToken()
{
$data = [
'login' => $this->connection->login,
'pass' => $this->connection->pass,
'login' => $this->login,
'pass' => $this->pass,
];
if ($this->cache && ($token = $this->cache->fetch($this->getTokenCacheKey()))) {
if ($token = $this->cache->fetch($this->getTokenCacheKey())) {
return $token;
}
$dataJson = json_encode((object)$data, JSON_UNESCAPED_UNICODE);
$url = $this->baseApiUrl
.'/'.$this->version
.'/getToken';
$url = $this->getUri().'/'.$this->connection->version.'/getToken';
$request = $this->client->createRequest('POST', $url, null, $dataJson);
$response = false;
try {
$response = $this->client->post($url, ['body' => $dataJson]);
} catch (BadResponseException $exception) {
if ($this->logger && $exception->getResponse()) {
$this->logger->error((string) $exception->getResponse()->getBody());
$response = $this->client->send($request);
} catch (BadResponseException $e) {
if ($this->logger) {
$this->logger->error($e->getResponse()->getBody());
}
}
if ($response) {
$response = json_decode($response->getBody(), true);
$response = json_decode($response->getBody());
if ($this->cache && !isset($response['error'])) {
$this->cache->save($this->getTokenCacheKey(), $response['token'], self::TOKEN_CACHE_TIME);
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);
}
} 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;
}
/**
* @param string $operation
* @param string|null $token
* @return string
*/
protected function buildUrl(string $operation, string $token = null): string
protected function getTokenCacheKey()
{
$url = $this->getUri()
.'/'.$this->connection->version
.'/'.$this->connection->group
.'/'.$operation;
if (!$token) {
return $url;
}
return $url.'?token='.$token;
return self::TOKEN_CACHE_KEY.'_'.md5($this->login.$this->pass).'_'.$this->version;
}
/**
* @param string $operation
* @param mixed $data
* @param null $token
* @return string
*/
protected function sendOperationRequest(string $operation, $data): string
protected function buildUrl($operation, $token = null)
{
$token = $this->getToken();
$url = $this->baseApiUrl
.'/'.$this->version
.'/'.$this->groupCode
.'/'.$operation;
$url = $this->buildUrl($operation, $token);
try {
$this->attempts++;
$response = $this->client->post($url, ['body' => $data]);
} catch (BadResponseException $e) {
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);
if ($token) {
if ($this->version === self::API_VERSION_V4) {
$url .= '?token='.$token;
} elseif ($this->version === self::API_VERSION_V3) {
$url .= '?tokenid='.$token;
}
}
return $url;
}
/**
* @param string $operation
* @param string $data
* @return Response|bool
*/
protected function sendOperationRequest($operation, $data)
{
$token = $this->getToken();
$url = $this->buildUrl($operation, $token);
$request = $this->client->createRequest('POST', $url, null, $data);
$response = false;
try {
$this->attempts++;
$response = $this->client->send($request);
} catch (BadResponseException $e) {
$this->cache->delete($this->getTokenCacheKey());
$body = json_decode($e->getResponse()->getBody());
if ($this->isTokenExpired($body) && $this->attempts <= 1) {
return $this->sendOperationRequest($operation, $data);
}
$this->logDebug($url, $data, $e->getResponse());
}
if ($response) {
$this->logDebug($url, $data, $response);
}
return $response->getBody()->__toString();
return $response;
}
/**
* @param string $url
* @param string $data
* @param ResponseInterface $response
*/
protected function logDebug(string $url, string $data, ResponseInterface $response): void
protected function logDebug($url, $data, Response $response)
{
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: ".implode(', ', $headers);
if ($this->debug && $this->logger) {
$v = "* URL: ".$url;
$v .= "\n * POSTFILEDS: ".$data;
$v .= "\n * RESPONSE HEADERS: ".$response->getRawHeaders();
$v .= "\n * RESPONSE BODY: ".$response->getBody();
$v .= "\n * ATTEMPTS: ".$this->attempts;
$this->logger->debug($v);
}
}
/**
* @return string
*/
protected function getTokenCacheKey(): string
protected function isTokenExpiredCode($code)
{
return self::TOKEN_CACHE_KEY.'_'.md5($this->connection->login.$this->connection->pass).'_'.$this->connection->version;
return in_array($code, [4, 5, 6, 12, 13, 14]);
}
/**
* @param object $body
* @return bool
*/
private function isTokenExpired($body): bool
private function isTokenExpired($body)
{
return isset($body->error) && in_array($body->error->code, [4, 5, 6, 12, 13, 14], true);
return isset($body->error) && $this->isTokenExpiredCode($body->error->code);
}
}

View file

@ -8,20 +8,14 @@ use Symfony\Component\Validator\Mapping\ClassMetadata;
class Configuration implements ConfigurationInterface
{
/**
* @var Connection[]
*/
/** @var Connection[] */
public $connections;
/**
* @var boolean
*/
public $enabled = true;
/** @var boolean */
public $enabled;
/**
* @var bool
*/
public $debug = false;
/** @var bool */
public $debug;
/**
* @param ClassMetadata $metadata

View file

@ -2,7 +2,6 @@
namespace AtolOnlineClient\Configuration;
use AtolOnlineClient\AtolOnlineApi;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Mapping\ClassMetadata;
@ -15,6 +14,13 @@ class Connection
const SNO_ESN = 'esn';
const SNO_PATENT = 'patent';
const PLATFORMA_OFD = 'platforma_ofd';
const PERVIY_OFD = 'perviy_ofd';
const TAXCOM_OFD = 'taxcom_ofd';
const V3 = 'v3';
const V4 = 'v4';
const snoTypes = [
self::SNO_GENERAL,
self::SNO_USN_INCOME,
@ -24,10 +30,20 @@ class Connection
self::SNO_PATENT,
];
const versions = [
AtolOnlineApi::API_VERSION_V4,
const ofdList = [
self::PLATFORMA_OFD,
self::PERVIY_OFD,
self::TAXCOM_OFD,
];
const versions = [
self::V3,
self::V4,
];
/** @var string */
protected $url;
/** @var bool */
protected $debug = false;
@ -40,11 +56,17 @@ class Connection
/** @var string */
public $group;
/** @var boolean */
public $enabled;
/** @var string */
public $sno;
/** @var string */
public $version = AtolOnlineApi::API_VERSION_V4;
public $ofd;
/** @var string */
public $version;
/** @var bool */
public $testMode = false;
@ -52,7 +74,7 @@ class Connection
/**
* @return bool
*/
public function isTestMode(): bool
public function isTestMode()
{
return $this->testMode;
}
@ -60,7 +82,7 @@ class Connection
/**
* @param bool $testMode
*/
public function setTestMode(bool $testMode): void
public function setTestMode(bool $testMode)
{
$this->testMode = $testMode;
}
@ -84,7 +106,7 @@ class Connection
/**
* @param ClassMetadata $metadata
*/
public static function loadValidatorMetadata(ClassMetadata $metadata): void
public static function loadValidatorMetadata(ClassMetadata $metadata)
{
$metadata->addPropertyConstraint('login', new Assert\NotBlank());
$metadata->addPropertyConstraint('pass', new Assert\NotBlank());
@ -94,7 +116,11 @@ class Connection
'choices' => self::snoTypes,
])
]);
$metadata->addPropertyConstraints('ofd', [
new Assert\Choice([
'choices' => self::ofdList,
])
]);
$metadata->addPropertyConstraints('version', [
new Assert\Choice([
'choices' => self::versions,
@ -102,6 +128,23 @@ class Connection
]);
}
/**
* @return string
*/
public function getOfdAddress()
{
switch ($this->ofd) {
case self::PLATFORMA_OFD:
return 'platformaofd.ru';
case self::PERVIY_OFD:
return 'www.1-ofd.ru';
case self::TAXCOM_OFD:
return 'taxcom.ru/ofd/';
}
return null;
}
/**
* @return string
*/
@ -109,12 +152,4 @@ class Connection
{
return $this->version;
}
/**
* @return bool
*/
public function isVersion4()
{
return $this->getVersion() === AtolOnlineApi::API_VERSION_V4;
}
}

View file

@ -2,8 +2,7 @@
namespace AtolOnlineClient\Exception;
use Exception;
class AtolException extends Exception
class AtolException extends \Exception
{
}

View file

@ -1,59 +0,0 @@
<?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;
}
}

View file

@ -0,0 +1,129 @@
<?php
namespace AtolOnlineClient\Request\V3;
use JMS\Serializer\Annotation as Serializer;
class PaymentReceiptRequest
{
/**
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("timestamp")
* @Serializer\Type("string")
*/
private $timestamp;
/**
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("external_id")
* @Serializer\Type("string")
*/
private $externalId;
/**
* @var ServiceRequest
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("service")
* @Serializer\Type("AtolOnlineClient\Request\V3\ServiceRequest")
*/
private $service;
/**
* @var ReceiptRequest
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("receipt")
* @Serializer\Type("AtolOnlineClient\Request\V3\ReceiptRequest")
*/
private $receipt;
public function __construct()
{
$this->timestamp = (new \DateTime())->format('d.m.Y H:i:s');
}
/**
* @return string
*/
public function getTimestamp()
{
return $this->timestamp;
}
/**
* @param string $timestamp
*
* @return $this
*/
public function setTimestamp($timestamp)
{
$this->timestamp = $timestamp;
return $this;
}
/**
* @return string
*/
public function getExternalId()
{
return $this->externalId;
}
/**
* @param string $externalId
*
* @return $this
*/
public function setExternalId($externalId)
{
$this->externalId = $externalId;
return $this;
}
/**
* @return \AtolOnlineClient\Request\V3\ServiceRequest
*/
public function getService()
{
return $this->service;
}
/**
* @param \AtolOnlineClient\Request\V3\ServiceRequest $service
*
* @return $this
*/
public function setService($service)
{
$this->service = $service;
return $this;
}
/**
* @return ReceiptRequest
*/
public function getReceipt()
{
return $this->receipt;
}
/**
* @param ReceiptRequest $receipt
*
* @return $this
*/
public function setReceipt($receipt)
{
$this->receipt = $receipt;
return $this;
}
}

View file

@ -0,0 +1,98 @@
<?php
namespace AtolOnlineClient\Request\V3;
use JMS\Serializer\Annotation as Serializer;
class ReceiptAttributesRequest
{
/**
* @var string
*
* "enum": [
* "osn",
* "usn_income",
* "usn_income_outcome",
* "envd",
* "esn",
* "patent"
* ]
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("sno")
* @Serializer\Type("string")
*/
private $sno;
/**
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("email")
* @Serializer\Type("string")
*/
private $email;
/**
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("phone")
* @Serializer\Type("string")
*/
private $phone;
/**
* ReceiptAttributesRequest constructor.
* @param string $email
* @param string $phone
*/
public function __construct($email, $phone)
{
$this->email = $email;
if ($email == null) {
$this->email = '';
}
$this->phone = $phone;
if ($phone == null) {
$this->phone = '';
}
}
/**
* @return string
*/
public function getSno()
{
return $this->sno;
}
/**
* @param string $sno
*
* @return $this
*/
public function setSno($sno)
{
$this->sno = $sno;
return $this;
}
/**
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* @return string
*/
public function getPhone()
{
return $this->phone;
}
}

View file

@ -0,0 +1,163 @@
<?php
namespace AtolOnlineClient\Request\V3;
use JMS\Serializer\Annotation as Serializer;
class ReceiptItemRequest
{
/**
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
private $name;
/**
* @var float
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("price")
* @Serializer\Type("float")
*/
private $price;
/**
* @var integer
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("quantity")
* @Serializer\Type("integer")
*/
private $quantity;
/**
* @var float
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("sum")
* @Serializer\Type("float")
*/
private $sum;
/**
* @var string
*
* "enum": [
* "none",
* "vat0",
* "vat10",
* "vat18",
* "vat110",
* "vat118"
* ]
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("tax")
* @Serializer\Type("string")
*/
private $tax;
/**
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* @param string $name
*
* @return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* @return float
*/
public function getPrice()
{
return $this->price;
}
/**
* @param float $price
*
* @return $this
*/
public function setPrice($price)
{
$this->price = $price;
return $this;
}
/**
* @return integer
*/
public function getQuantity()
{
return $this->quantity;
}
/**
* @param int $quantity
*
* @return $this
*/
public function setQuantity($quantity)
{
$this->quantity = $quantity;
return $this;
}
/**
* @return float
*/
public function getSum()
{
return $this->sum;
}
/**
* @param float $sum
*
* @return $this
*/
public function setSum($sum)
{
$this->sum = $sum;
return $this;
}
/**
* @return string
*/
public function getTax()
{
return $this->tax;
}
/**
* @param string $tax
*
* @return $this
*/
public function setTax($tax)
{
$this->tax = $tax;
return $this;
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace AtolOnlineClient\Request\V3;
use JMS\Serializer\Annotation as Serializer;
class ReceiptPaymentRequest
{
const TYPE_ELECTRON = 1;
const TYPE_PREPAY = 2;
const TYPE_CREDIT = 3;
const TYPE_OTHER = 4;
/**
* @var int
* "enum": 0..9
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("type")
* @Serializer\Type("integer")
*/
private $type;
/**
* @var float
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("sum")
* @Serializer\Type("float")
*/
private $sum;
/**
* @param int $type
* @param float $sum
*/
public function __construct($type, $sum)
{
$this->type = $type;
$this->sum = $sum;
}
/**
* @return int
*/
public function getType()
{
return $this->type;
}
/**
* @return float
*/
public function getSum()
{
return $this->sum;
}
}

View file

@ -0,0 +1,127 @@
<?php
namespace AtolOnlineClient\Request\V3;
use JMS\Serializer\Annotation as Serializer;
class ReceiptRequest
{
/**
* @var ReceiptAttributesRequest
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("attributes")
* @Serializer\Type("AtolOnlineClient\Request\V3\ReceiptAttributesRequest")
*/
private $attributes;
/**
* @var ReceiptItemRequest[]
* "minItems": 1, "maxItems": 100,
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("items")
* @Serializer\Type("array<AtolOnlineClient\Request\V3\ReceiptItemRequest>")
*/
private $items;
/**
* @var float
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("total")
* @Serializer\Type("float")
*/
private $total;
/**
* @var \AtolOnlineClient\Request\V3\ReceiptPaymentRequest[]
* "minItems": 1, "maxItems": 10,
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("payments")
* @Serializer\Type("array<AtolOnlineClient\Request\V3\ReceiptPaymentRequest>")
*/
private $payments;
/**
* @return ReceiptAttributesRequest
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* @param ReceiptAttributesRequest $attributes
*
* @return $this
*/
public function setAttributes($attributes)
{
$this->attributes = $attributes;
return $this;
}
/**
* @return ReceiptItemRequest[]
*/
public function getItems()
{
return $this->items;
}
/**
* @param ReceiptItemRequest[] $items
*
* @return $this
*/
public function setItems($items)
{
$this->items = $items;
return $this;
}
/**
* @return float
*/
public function getTotal()
{
return $this->total;
}
/**
* @param float $total
*
* @return $this
*/
public function setTotal($total)
{
$this->total = $total;
return $this;
}
/**
* @return \AtolOnlineClient\Request\V3\ReceiptPaymentRequest[]
*/
public function getPayments()
{
return $this->payments;
}
/**
* @param \AtolOnlineClient\Request\V3\ReceiptPaymentRequest[] $payments
*
* @return $this
*/
public function setPayments($payments)
{
$this->payments = $payments;
return $this;
}
}

View file

@ -0,0 +1,106 @@
<?php
namespace AtolOnlineClient\Request\V3;
use JMS\Serializer\Annotation as Serializer;
class ServiceRequest
{
/**
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("inn")
* @Serializer\Type("string")
*/
private $inn;
/**
* @var string
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("callback_url")
* @Serializer\Type("string")
*/
private $callbackUrl;
/**
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("payment_address")
* @Serializer\Type("string")
*/
private $paymentAddress;
/**
* Service constructor.
* @param string $inn
* @param string $paymentAddress
*/
public function __construct($inn, $paymentAddress)
{
$this->inn = $inn;
$this->paymentAddress = $paymentAddress;
}
/**
* @return string
*/
public function getCallbackUrl()
{
return $this->callbackUrl;
}
/**
* @param string $callbackUrl
*
* @return $this
*/
public function setCallbackUrl($callbackUrl)
{
$this->callbackUrl = $callbackUrl;
return $this;
}
/**
* @return string
*/
public function getInn()
{
return $this->inn;
}
/**
* @param string $inn
*
* @return $this
*/
public function setInn($inn)
{
$this->inn = $inn;
return $this;
}
/**
* @return string
*/
public function getPaymentAddress()
{
return $this->paymentAddress;
}
/**
* @param string $paymentAddress
*
* @return $this
*/
public function setPaymentAddress($paymentAddress)
{
$this->paymentAddress = $paymentAddress;
return $this;
}
}

View file

@ -7,12 +7,12 @@ use JMS\Serializer\Annotation as Serializer;
/**
* В запросе обязательно должно быть заполнено хотя бы одно из полей: email или phone.
* Если заполнены оба поля, ОФД отправит электронный чек только на email.
* @Serializer\AccessType("public_method")
*/
class ClientReceiptRequest
{
/**
* @var string|null
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("email")
* @Serializer\Type("string")
@ -20,7 +20,8 @@ class ClientReceiptRequest
private $email;
/**
* @var string|null
* @var string
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("phone")
* @Serializer\Type("string")
@ -28,91 +29,25 @@ class ClientReceiptRequest
private $phone;
/**
* @var string|null
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("name")
* @Serializer\Type("string")
*/
private $name;
/**
* @var string|null
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("inn")
* @Serializer\Type("string")
*/
private $inn;
public function __construct(string $email = null, string $phone = null)
public function __construct($email, $phone)
{
$this->email = $email;
$this->phone = $phone;
}
/**
* @return string|null
* @return string
*/
public function getEmail(): ?string
public function getEmail(): string
{
return $this->email;
}
/**
* @param string|null $email
* @return string
*/
public function setEmail(?string $email): void
{
$this->email = $email;
}
/**
* @return string|null
*/
public function getPhone(): ?string
public function getPhone(): string
{
return $this->phone;
}
/**
* @param string|null $phone
*/
public function setPhone(?string $phone): void
{
$this->phone = $phone;
}
/**
* @return string|null
*/
public function getName(): ?string
{
return $this->name;
}
/**
* @param string|null $name
*/
public function setName(?string $name): void
{
$this->name = $name;
}
/**
* @return string|null
*/
public function getInn(): ?string
{
return $this->inn;
}
/**
* @param string|null $inn
*/
public function setInn(?string $inn): void
{
$this->inn = $inn;
}
}

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Request\V4;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class CompanyReceiptRequest
{
/**
@ -19,10 +16,10 @@ class CompanyReceiptRequest
private $email;
/**
* @var string|null
* @var string
* Поле необязательно, если у организации один тип налогообложения
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("sno")
* @Serializer\SerializedName("phone")
* @Serializer\Type("string")
*/
private $sno;
@ -62,17 +59,17 @@ class CompanyReceiptRequest
}
/**
* @return string|null
* @return string
*/
public function getSno(): ?string
public function getSno(): string
{
return $this->sno;
}
/**
* @param string|null $sno
* @param string $sno
*/
public function setSno(?string $sno): void
public function setSno(string $sno): void
{
$this->sno = $sno;
}

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Request\V4;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class PaymentReceiptRequest
{
/**
@ -47,6 +44,7 @@ class PaymentReceiptRequest
private $service;
public function __construct()
{
$this->timestamp = (new \DateTime())->format('d.m.Y H:i:s');
@ -92,14 +90,6 @@ class PaymentReceiptRequest
return $this->timestamp;
}
/**
* @param string $timestamp
*/
public function setTimestamp(string $timestamp): void
{
$this->timestamp = $timestamp;
}
/**
* @return ServiceRequest
*/

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Request\V4;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class ReceiptItemRequest
{
@ -53,11 +50,11 @@ class ReceiptItemRequest
private $price;
/**
* @var float
* @var integer
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("quantity")
* @Serializer\Type("float")
* @Serializer\Type("integer")
*/
private $quantity;
@ -71,7 +68,7 @@ class ReceiptItemRequest
private $sum;
/**
* @var string|null
* @var string
*
* required
* @Serializer\Groups({"set", "get"})
@ -91,7 +88,7 @@ class ReceiptItemRequest
* «partial_payment» частичный расчет и кредит. Частичная оплата предмета расчета в момент его передачи с последующей оплатой в кредит.
* «credit» передача в кредит. Передача предмета расчета без его оплаты в момент его передачи с последующей оплатой в кредит.
* «credit_payment» оплата кредита. Оплата предмета расчета после его передачи с оплатой в кредит (оплата кредита).
* @var string|null
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("payment_method")
@ -116,7 +113,7 @@ class ReceiptItemRequest
* «composite» составной предмет расчета. О предмете расчета, состоящем из предметов, каждому из которых может быть присвоено значение выше перечисленных признаков.
* «another» иной предмет расчета. О предмете расчета, не относящемуся к выше перечисленным предметам расчета
*
* @var string|null
* @var string
*
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("payment_object")
@ -134,14 +131,6 @@ class ReceiptItemRequest
*/
private $vat;
/**
* @var string|null
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("nomenclature_code")
* @Serializer\Type("string")
*/
private $nomenclatureCode;
/**
* @return string
*/
@ -175,17 +164,17 @@ class ReceiptItemRequest
}
/**
* @return float
* @return int
*/
public function getQuantity(): float
public function getQuantity(): int
{
return $this->quantity;
}
/**
* @param float $quantity
* @param int $quantity
*/
public function setQuantity(float $quantity): void
public function setQuantity(int $quantity): void
{
$this->quantity = $quantity;
}
@ -207,49 +196,49 @@ class ReceiptItemRequest
}
/**
* @return string|null
* @return string
*/
public function getMeasurementUnit(): ?string
public function getMeasurementUnit(): string
{
return $this->measurementUnit;
}
/**
* @param string|null $measurementUnit
* @param string $measurementUnit
*/
public function setMeasurementUnit(?string $measurementUnit): void
public function setMeasurementUnit(string $measurementUnit): void
{
$this->measurementUnit = $measurementUnit;
}
/**
* @return string|null
* @return string
*/
public function getPaymentMethod(): ?string
public function getPaymentMethod(): string
{
return $this->paymentMethod;
}
/**
* @param string|null $paymentMethod
* @param string $paymentMethod
*/
public function setPaymentMethod(?string $paymentMethod): void
public function setPaymentMethod(string $paymentMethod): void
{
$this->paymentMethod = $paymentMethod;
}
/**
* @return string|null
* @return string
*/
public function getPaymentObject(): ?string
public function getPaymentObject(): string
{
return $this->paymentObject;
}
/**
* @param string|null $paymentObject
* @param string $paymentObject
*/
public function setPaymentObject(?string $paymentObject): void
public function setPaymentObject(string $paymentObject): void
{
$this->paymentObject = $paymentObject;
}
@ -269,20 +258,4 @@ class ReceiptItemRequest
{
$this->vat = $vat;
}
/**
* @return string|null
*/
public function getNomenclatureCode(): ?string
{
return $this->nomenclatureCode;
}
/**
* @param string|null $nomenclatureCode
*/
public function setNomenclatureCode(?string $nomenclatureCode): void
{
$this->nomenclatureCode = $nomenclatureCode;
}
}

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Request\V4;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class ReceiptPaymentRequest
{
const TYPE_ELECTRON = 1;
@ -52,14 +49,6 @@ class ReceiptPaymentRequest
return $this->type;
}
/**
* @param int $type
*/
public function setType(int $type): void
{
$this->type = $type;
}
/**
* @return float
*/
@ -67,12 +56,4 @@ class ReceiptPaymentRequest
{
return $this->sum;
}
/**
* @param float $sum
*/
public function setSum(float $sum): void
{
$this->sum = $sum;
}
}

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Request\V4;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class ReceiptRequest
{
@ -50,9 +47,9 @@ class ReceiptRequest
private $payments;
/**
* @var \AtolOnlineClient\Request\V4\VatReceiptRequest[]|null
* @var \AtolOnlineClient\Request\V4\VatReceiptRequest[]
* "minItems": 1, "maxItems": 6,
*
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("vats")
* @Serializer\Type("array<AtolOnlineClient\Request\V4\VatReceiptRequest>")
@ -133,17 +130,17 @@ class ReceiptRequest
}
/**
* @return VatReceiptRequest[]|null
* @return VatReceiptRequest[]
*/
public function getVats(): ?array
public function getVats(): array
{
return $this->vats;
}
/**
* @param VatReceiptRequest[]|null $vats
* @param VatReceiptRequest[] $vats
*/
public function setVats(?array $vats): void
public function setVats(array $vats): void
{
$this->vats = $vats;
}

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Request\V4;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class ServiceRequest
{

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Request\V4;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class VatReceiptRequest
{
/**
@ -15,9 +12,9 @@ class VatReceiptRequest
* "none",
* "vat0",
* "vat10",
* "vat20",
* "vat18",
* "vat110",
* "vat120"
* "vat118"
* ]
*
* @var string
@ -29,8 +26,8 @@ class VatReceiptRequest
private $type;
/**
* @var float|null
*
* @var float
* required
* @Serializer\Groups({"set", "get"})
* @Serializer\SerializedName("sum")
* @Serializer\Type("float")
@ -42,10 +39,10 @@ class VatReceiptRequest
* @param string $type
* @param float $sum
*/
public function __construct(string $type, $sum)
public function __construct(string $type, string $sum)
{
$this->type = $type;
$this->sum = (float) $sum;
$this->sum = $sum;
}
/**
@ -56,27 +53,11 @@ class VatReceiptRequest
return $this->type;
}
/**
* @param string $type
*/
public function setType(string $type): void
{
$this->type = $type;
}
/**
* @return float
*/
public function getSum()
public function getSum(): string
{
return $this->sum;
}
/**
* @param float $sum
*/
public function setSum(float $sum): void
{
$this->sum = $sum;
}
}
}

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Response;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class Error
{

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Response;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class OperationResponse
{
@ -226,7 +223,7 @@ class OperationResponse
/**
* @param string $groupCode
*/
public function setGroupCode(?string $groupCode)
public function setGroupCode(string $groupCode)
{
$this->groupCode = $groupCode;
}
@ -242,7 +239,7 @@ class OperationResponse
/**
* @param string $daemonCode
*/
public function setDaemonCode(?string $daemonCode)
public function setDaemonCode(string $daemonCode)
{
$this->daemonCode = $daemonCode;
}
@ -258,7 +255,7 @@ class OperationResponse
/**
* @param string $deviceCode
*/
public function setDeviceCode(?string $deviceCode)
public function setDeviceCode(string $deviceCode)
{
$this->deviceCode = $deviceCode;
}

View file

@ -4,9 +4,6 @@ namespace AtolOnlineClient\Response;
use JMS\Serializer\Annotation as Serializer;
/**
* @Serializer\AccessType("public_method")
*/
class Payload
{
/**
@ -89,16 +86,6 @@ class Payload
*/
private $fiscalDocumentAttribute;
/**
* Адрес сайта ФНС
*
* @var string
* @Serializer\Groups({"get"})
* @Serializer\SerializedName("fns_site")
* @Serializer\Type("string")
*/
private $fnsSite;
/**
* @return mixed
*/
@ -258,24 +245,4 @@ class Payload
return $this;
}
/**
* @return string
*/
public function getFnsSite()
{
return $this->fnsSite;
}
/**
* @param $string $fnsSite
*
* @return $this
*/
public function setFnsSite($fnsSite)
{
$this->fnsSite = $fnsSite;
return $this;
}
}

View file

@ -1,415 +0,0 @@
<?php
namespace AtolOnlineClient\AtolOnlineClient;
use AtolOnlineClient\AtolOnline;
use AtolOnlineClient\AtolOnlineApi;
use AtolOnlineClient\AtolOnlineClient\Traits\PaymentReceiptRequestTrait;
use AtolOnlineClient\Configuration\Connection;
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
{
use PaymentReceiptRequestTrait;
/**
* @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);
$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->getPaymentReceiptRequest());
$response = $this->getApi($responses)->sell($request);
$this->assertSame('2ea26f1708844f08b120306fc096a58f', 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->getPaymentReceiptRequest());
$response = $this->getApi($responses)->sellRefund($request);
$this->assertSame('2ea26f1708844f08b120306fc096a58f', 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' => '2ea26f1708844f08b120306fc096a58f',
]);
$this->assertSame('2ea26f1708844f08b120306fc096a58f', 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' => '2ea26f1708844f08b120306fc096a58f',
]);
$this->assertSame('2ea26f1708844f08b120306fc096a58f', 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'), new Response())]);
$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::buildUrl
*/
public function testBuildUrlWithoutToken(): void
{
$args = ['operation' => 'test'];
$this->assertSame('https://online.atol.ru/possystem/v4/group/test', $this->callMethod($this->getApi(), '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));
}
/**
* @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->getPaymentReceiptRequest());
$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->getPaymentReceiptRequest());
$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'));
}
/**
* @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 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');
}
}

View file

@ -1,259 +0,0 @@
<?php
namespace AtolOnlineClient\Tests;
use AtolOnlineClient\AtolOnline;
use AtolOnlineClient\AtolOnlineClient\Traits\PaymentReceiptRequestTrait;
use AtolOnlineClient\Configuration\Connection;
use AtolOnlineClient\ConfigurationInterface;
use AtolOnlineClient\Exception\InvalidResponseException;
use GuzzleHttp\Client;
use JMS\Serializer\Exception\RuntimeException;
use JMS\Serializer\SerializerInterface;
use PHPUnit\Framework\TestCase;
class AtolOnlineTest extends TestCase
{
use PaymentReceiptRequestTrait;
/**
* @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
* @covers \AtolOnlineClient\Exception\InvalidResponseException
* @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
* @covers \AtolOnlineClient\Request\V4\ClientReceiptRequest
* @covers \AtolOnlineClient\Request\V4\CompanyReceiptRequest
* @covers \AtolOnlineClient\Request\V4\PaymentReceiptRequest
* @covers \AtolOnlineClient\Request\V4\ReceiptItemRequest
* @covers \AtolOnlineClient\Request\V4\ReceiptPaymentRequest
* @covers \AtolOnlineClient\Request\V4\ReceiptRequest
* @covers \AtolOnlineClient\Request\V4\ServiceRequest
* @covers \AtolOnlineClient\Request\V4\VatReceiptRequest
*/
public function testSerializeOperationRequest(): void
{
$request = $this->getPaymentReceiptRequest();
$request->setTimestamp('17.07.2019 10:14:22');
$this->assertEquals(
'{"external_id":"test","receipt":{"client":{"email":"test@test.local"},"company":{"email":"test@test.local","inn":"11111111","payment_address":"address"},"items":[{"name":"test item","price":100.1,"quantity":1.1,"sum":100.1,"measurement_unit":"kg","payment_method":"advance","payment_object":"agent_commission","vat":{"type":"vat20","sum":20.2},"nomenclature_code":"00"}],"payments":[{"type":0,"sum":100.1}],"vats":[{"type":"vat20","sum":20.2}],"total":100.1},"timestamp":"17.07.2019 10:14:22","service":{"callback_url":"test.local"}}',
$this->atol->serializeOperationRequest($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_v4.json']
];
}
/**
* @return array
*/
public function dataInvalidResponse(): array
{
return [
[
'code' => 404,
'message' => 'Not Found',
'html' => '<html><head><title>404 Not Found</title></head><body><center><h1>404 Not Found</h1></center><hr><center>openresty/1.15.8.1rc1</center></body></html>',
],
[
'code' => 502,
'message' => 'Bad Gateway',
'html' => '<html><head><title>502 Bad Gateway</title></head><body><center><h1>502 Bad Gateway</h1></center><hr><center>nginx/1.15.8</center></body></html>',
],
[
'code' => null,
'message' => null,
'html' => '<html></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);
}
}

View file

@ -1,85 +0,0 @@
<?php
namespace AtolOnlineClient\AtolOnlineClient\Connection;
use AtolOnlineClient\AtolOnlineApi;
use AtolOnlineClient\Configuration\Connection;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Validation;
class ConnectionTest extends TestCase
{
/**
* @var Connection
*/
private $connection;
/**
* @return void
*/
public function setUp(): void
{
$this->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
*/
public function testVersion(): void
{
$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());
}
}

View file

@ -1,78 +0,0 @@
<?php
namespace AtolOnlineClient\AtolOnlineClient;
use AtolOnlineClient\Configuration;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Validator\Validation;
/**
* Class ConfigurationTest
*
* @package AtolOnlineClient\AtolOnlineClient
*/
class ConfigurationTest extends TestCase
{
/**
* @var Configuration
*/
private $configuration;
public function setUp(): void
{
$this->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());
}
}

View file

@ -1,102 +0,0 @@
<?php
namespace AtolOnlineClient\AtolOnlineClient\Response;
use AtolOnlineClient\Request\V4\PaymentReceiptRequest;
use JMS\Serializer\SerializerBuilder;
use PHPUnit\Framework\TestCase;
/**
*/
class RequestTest extends TestCase
{
/**
* @return void
* @covers \AtolOnlineClient\Request\V4\ClientReceiptRequest
* @covers \AtolOnlineClient\Request\V4\CompanyReceiptRequest
* @covers \AtolOnlineClient\Request\V4\PaymentReceiptRequest
* @covers \AtolOnlineClient\Request\V4\ReceiptItemRequest
* @covers \AtolOnlineClient\Request\V4\ReceiptPaymentRequest
* @covers \AtolOnlineClient\Request\V4\ReceiptRequest
* @covers \AtolOnlineClient\Request\V4\ServiceRequest
* @covers \AtolOnlineClient\Request\V4\VatReceiptRequest
*/
public function testRequest(): void
{
$serializer = SerializerBuilder::create()->build();
$request = '{
"external_id": "17052917561851307",
"receipt": {
"client": {
"name": "name",
"email": "kkt@kkt.ru",
"phone": "88002000600",
"inn": "111111111"
},
"company": {
"email": "chek@romashka.ru",
"sno": "osn",
"inn": "1234567891",
"payment_address": "http://magazin.ru/"
},
"items": [
{
"name": "колбаса Клинский Брауншвейгская с/к в/с ",
"price": 1000,
"quantity": 0.3,
"sum": 300,
"measurement_unit": "кг",
"payment_method": "full_payment",
"payment_object": "commodity",
"vat": {
"type": "vat18"
}
},
{
"name": "яйцоОкскоекуриноеС0 белое",
"price": 100,
"quantity": 1,
"sum": 100,
"measurement_unit": "Упаковка10 шт.",
"payment_method": "full_payment",
"payment_object": "commodity",
"vat": {
"type": "vat10"
}
}
],
"payments": [
{
"type": 1,
"sum": 400
}
],
"vats": [
{
"type": "vat18",
"sum": 45.76
},
{
"type": "vat10",
"sum": 9.09
}
],
"total": 400
},
"service": {
"callback_url": "http://testtest"
},
"timestamp": "01.02.1713:45:00"
}';
/** @var PaymentReceiptRequest $request */
$request = $serializer->deserialize(
$request,
PaymentReceiptRequest::class,
'json'
);
$this->assertSame('17052917561851307', $request->getExternalId());
}
}

View file

@ -1,64 +0,0 @@
<?php
namespace AtolOnlineClient\AtolOnlineClient\Response;
use AtolOnlineClient\Response\OperationResponse;
use JMS\Serializer\SerializerBuilder;
use PHPUnit\Framework\TestCase;
/**
*/
class ResponseTest extends TestCase
{
/**
* @return void
* @covers \AtolOnlineClient\Response\OperationResponse
* @covers \AtolOnlineClient\Response\Error
* @covers \AtolOnlineClient\Response\Payload
*/
public function testResponse(): void
{
$serializer = SerializerBuilder::create()->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": "prodagent1",
"device_code": "KSR13.00111",
"external_id": "TRF10601_1",
"callback_url": ""
}';
/** @var OperationResponse $response */
$response = $serializer->deserialize(
$response,
OperationResponse::class,
'json'
);
$serializer->serialize(
$response,
'json'
);
$this->assertSame('4355', $response->getUuid());
}
}

View file

@ -0,0 +1,46 @@
<?php
namespace AtolOnlineClient\Tests;
use AtolOnlineClient\AtolOnline;
use AtolOnlineClient\Configuration;
use AtolOnlineClient\Response\OperationResponse;
use PHPUnit\Framework\TestCase;
class AtolOnlineTest extends TestCase
{
public function testCreateConfiguration()
{
$atol = new AtolOnline();
$this->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']
];
}
}

View file

@ -1,58 +0,0 @@
<?php
namespace AtolOnlineClient\AtolOnlineClient\Traits;
use AtolOnlineClient\Request\V4\ClientReceiptRequest;
use AtolOnlineClient\Request\V4\CompanyReceiptRequest;
use AtolOnlineClient\Request\V4\PaymentReceiptRequest;
use AtolOnlineClient\Request\V4\ReceiptItemRequest;
use AtolOnlineClient\Request\V4\ReceiptPaymentRequest;
use AtolOnlineClient\Request\V4\ReceiptRequest;
use AtolOnlineClient\Request\V4\ServiceRequest;
use AtolOnlineClient\Request\V4\VatReceiptRequest;
trait PaymentReceiptRequestTrait
{
/**
* @return PaymentReceiptRequest
*/
protected function getPaymentReceiptRequest(): PaymentReceiptRequest
{
$service = new ServiceRequest();
$service->setCallbackUrl('test.local');
$client = new ClientReceiptRequest('test@test.local');
$company = new CompanyReceiptRequest();
$company->setEmail('test@test.local');
$company->setInn('11111111');
$company->setPaymentAddress('address');
$item = new ReceiptItemRequest();
$item->setName('test item');
$item->setPrice(100.1);
$item->setQuantity(1.1);
$item->setSum(100.1);
$item->setMeasurementUnit('kg');
$item->setPaymentMethod(ReceiptItemRequest::PAYMENT_METHOD_ADVANCE);
$item->setPaymentObject(ReceiptItemRequest::PAYMENT_OBJECT_AGENT_COMMISSION);
$item->setVat(new VatReceiptRequest('vat20', 20.2));
$item->setNomenclatureCode('00');
$receipt = new ReceiptRequest();
$receipt->setTotal(100.1);
$receipt->setClient($client);
$receipt->setCompany($company);
$receipt->setItems([$item]);
$receipt->setPayments([new ReceiptPaymentRequest(0, 100.1)]);
$receipt->setVats([new VatReceiptRequest('vat20', 20.2)]);
/** @var PaymentReceiptRequest $request */
$request = new PaymentReceiptRequest();
$request->setExternalId('test');
$request->setService($service);
$request->setReceipt($receipt);
return $request;
}
}

View file

@ -1,3 +0,0 @@
<?php
return require __DIR__.'/../vendor/autoload.php';

View file

@ -1,5 +0,0 @@
{
"error": null,
"token": "fj45u923j59ju42395iu9423i59243u0",
"timestamp": "12.04.2017 06:15:06"
}

View file

@ -1,6 +0,0 @@
{
"uuid": "2ea26f1708844f08b120306fc096a58f",
"timestamp": "12.04.2017 06:15:06",
"error": null,
"status": "wait"
}

View file

@ -1,22 +0,0 @@
{
"uuid": "2ea26f1708844f08b120306fc096a58f",
"error": null,
"status": "done",
"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
},
"timestamp": "12.04.2017 06:15:06",
"group_code": "MyCompany_MyShop",
"daemon_code": "prodagent1",
"device_code": "KSR13.00111",
"external_id": "TRF10601_1",
"callback_url": ""
}