Compare commits
40 Commits
v0.3.0-b
...
95499174b0
| Author | SHA1 | Date | |
|---|---|---|---|
| 95499174b0 | |||
| 6d0cac2cbc | |||
| 6620acf1bf | |||
| e89369348a | |||
| b35b9bfa87 | |||
| e1120051c1 | |||
| 6551366d84 | |||
| 2c5144caac | |||
| 92a2c6cc48 | |||
| 949b31a85a | |||
| 03591600dd | |||
| 77481884ad | |||
| cc944a1dbb | |||
| bb05f0c752 | |||
| 1c76608468 | |||
| bd6e208216 | |||
| 7b4411ec01 | |||
| 23fa1f7eb9 | |||
| 929bf84c97 | |||
|
|
5c1c4dba12 | ||
|
|
4c40bebe14 | ||
| d321205ac9 | |||
| 387e6e445f | |||
| 3bd043bde7 | |||
| 7c8ee85b89 | |||
| aab68646e6 | |||
| e1fb74ac01 | |||
| 8d9f218280 | |||
| 9ed999f9fc | |||
| 989c06a383 | |||
| 9bd99c81a9 | |||
| 2943d93962 | |||
| 8eb309bc58 | |||
| b74f652127 | |||
| 1061914a5f | |||
| 5424726a97 | |||
| 2b3713db69 | |||
| a6b57115b6 | |||
| 12e0e49c9b | |||
| 3ffab562f8 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,3 +1,3 @@
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: # Replace with a single Patreon username
|
||||
custom: ['https://money.yandex.ru/to/41001685237530']
|
||||
custom: ['https://yoomoney.ru/to/41001685237530']
|
||||
|
||||
25
.github/workflows/dev.yml
vendored
Normal file
25
.github/workflows/dev.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Dev build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ dev ]
|
||||
pull_request:
|
||||
branches: [ dev ]
|
||||
|
||||
jobs:
|
||||
Tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
uses: php-actions/composer@40-env
|
||||
with:
|
||||
version: 2
|
||||
php_version: 8.0
|
||||
only_args: --prefer-dist --no-progress
|
||||
|
||||
- name: Run phpunit tests
|
||||
uses: php-actions/phpunit@v9
|
||||
with:
|
||||
configuration: ./phpunit.xml
|
||||
25
.github/workflows/master.yml
vendored
Normal file
25
.github/workflows/master.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: Master build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
Tests:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
uses: php-actions/composer@40-env
|
||||
with:
|
||||
version: 2
|
||||
php_version: 7.4
|
||||
only_args: --prefer-dist --no-progress
|
||||
|
||||
- name: Run phpunit tests
|
||||
uses: php-actions/phpunit@v8
|
||||
with:
|
||||
configuration: ./phpunit.xml
|
||||
26
.github/workflows/tests.yml
vendored
26
.github/workflows/tests.yml
vendored
@@ -1,26 +0,0 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: Validate composer.json and composer.lock
|
||||
run: composer validate
|
||||
|
||||
- name: Install composer dependencies
|
||||
run: composer install --prefer-dist --no-progress --no-suggest
|
||||
|
||||
- name: Run phpunit tests
|
||||
uses: php-actions/phpunit@v1.0.0
|
||||
with:
|
||||
# Configuration file location
|
||||
config: ./phpunit.xml
|
||||
17
README.md
17
README.md
@@ -1,6 +1,17 @@
|
||||
# АТОЛ Онлайн
|
||||
|
||||

|
||||
---
|
||||
|
||||
**В этой ветке проводится глубокий рефакторинг и активная подготовка к `v1.0.0`.**
|
||||
|
||||
**Актуальность документации -- околонулевая.**
|
||||
|
||||
**Общая работоспособность -- нулевая.**
|
||||
|
||||
---
|
||||
|
||||
[](https://github.com/anthonyaxenov/atol-online/actions/workflows/master.yml)
|
||||
[](https://github.com/anthonyaxenov/atol-online/actions/workflows/dev.yml)
|
||||
|
||||
Библиотека для фискализации чеков по 54-ФЗ через [облачную ККТ АТОЛ](https://online.atol.ru/).
|
||||
|
||||
@@ -10,7 +21,7 @@
|
||||
|
||||
## Системные требования
|
||||
|
||||
* PHP 7.2+
|
||||
* PHP 7.4+
|
||||
* composer
|
||||
* php-json
|
||||
|
||||
@@ -103,8 +114,6 @@
|
||||
|
||||
## Дополнительные ресурсы
|
||||
|
||||
**Discord-сервер для обсуждения этой библиотеки: [discord.gg/mFYTQmp](https://discord.gg/mFYTQmp)**
|
||||
|
||||
Функционал, находящийся в разработке: [ROADMAP.md](ROADMAP.md)
|
||||
|
||||
Официальные ресурсы АТОЛ Онлайн:
|
||||
|
||||
@@ -25,9 +25,8 @@
|
||||
- [ ] Тесты для регистрации документа расхода
|
||||
- [ ] Тесты для регистрации документа возврата расхода
|
||||
- [ ] Тесты для регистрации документа коррекции расхода
|
||||
- [ ] Вообще все расчёты вообще везде должны быть строго в копейках. Рубли (дроби) должны быть только в JSON-представлениях
|
||||
- [ ] Валидатор схемы для документов прихода, возврата прихода, расхода, возврата расхода
|
||||
- [ ] Валидатор схемы для документов коррекции прихода, коррекции расхода
|
||||
- [ ] Вообще все расчёты вообще везде должны быть строго в копейках.
|
||||
Рубли (дроби) должны быть только в JSON-представлениях
|
||||
|
||||
## Поддержка методов API (регистрация документов)
|
||||
|
||||
|
||||
@@ -5,16 +5,21 @@
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"54-fz",
|
||||
"54-фз",
|
||||
"kkt",
|
||||
"ккт",
|
||||
"e-commerce",
|
||||
"cash",
|
||||
"cash register",
|
||||
"payment",
|
||||
"payment system",
|
||||
"atol",
|
||||
"atol-online"
|
||||
"атол",
|
||||
"atol-online",
|
||||
"атол онлайн"
|
||||
],
|
||||
"homepage": "https://github.com/anthonyaxenov/atol-online",
|
||||
"readme": "https://github.com/anthonyaxenov/atol-online/blob/master/README.md",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Anthony Axenov",
|
||||
@@ -25,27 +30,39 @@
|
||||
"support": {
|
||||
"source": "https://github.com/anthonyaxenov/atol-online",
|
||||
"issues": "https://github.com/anthonyaxenov/atol-online/issues",
|
||||
"chat": "https://discord.gg/mFYTQmp"
|
||||
"docs": "https://github.com/anthonyaxenov/atol-online/blob/master/docs/readme.md"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"type": "Yoomoney",
|
||||
"url": "https://yoomoney.ru/to/41001685237530"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.2",
|
||||
"php": ">=8.0",
|
||||
"ext-json": "*",
|
||||
"guzzlehttp/guzzle": "^6.5",
|
||||
"psr/log": "^1.1",
|
||||
"ramsey/uuid": "^3.9"
|
||||
"ext-mbstring": "*",
|
||||
"guzzlehttp/guzzle": "^7.4",
|
||||
"psr/log": "^3",
|
||||
"ramsey/uuid": "^4.2",
|
||||
"myclabs/php-enum": "^1.8",
|
||||
"illuminate/collections": "^8.70"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.5"
|
||||
"phpunit/phpunit": "^9.5"
|
||||
},
|
||||
"autoload": {
|
||||
"classmap": [
|
||||
"src/AtolOnline/Api/",
|
||||
"src/AtolOnline/Api/Schemas/",
|
||||
"src/AtolOnline/Exceptions/",
|
||||
"src/AtolOnline/Entities/",
|
||||
"src/AtolOnline/Traits/",
|
||||
"src/AtolOnline/Constants/",
|
||||
"tests/"
|
||||
]
|
||||
"psr-4": {
|
||||
"AtolOnline\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"AtolOnlineTests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": "vendor/bin/phpunit --colors=always",
|
||||
"test-cov": "vendor/bin/phpunit --coverage-html coverage"
|
||||
}
|
||||
}
|
||||
|
||||
2366
composer.lock
generated
2366
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -46,10 +46,10 @@ $customer = (new AtolOnline\Entities\Client())
|
||||
* `AtolEmailValidateException` (если email невалиден).
|
||||
|
||||
Метод `setInn()` чистит входную строку от всех символов, кроме цифр, и проверяет длину (либо 10, либо 12 цифр).
|
||||
Выбрасывает исключение `AtolInnWrongLengthException` (если длина строка ИНН некорректна).
|
||||
Выбрасывает исключение `AtolInnWrongLengthException` (если длина ИНН некорректна).
|
||||
|
||||
Метод `setName()` проверяет входную строку на длину (до 256 символов).
|
||||
Выбрасывает исключение `AtolNameTooLongException` (если слишком длинное наименование).
|
||||
Выбрасывает исключение `AtolNameTooLongException` (если слишком длинное имя).
|
||||
|
||||
Метод `setPhone()` чистит входную строку от всех символов, кроме цифр и знака `+`, и проверяет длину (до 64 символов).
|
||||
Выбрасывает исключение `AtolPhoneTooLongException` (если слишком длинный номер телефона).
|
||||
|
||||
@@ -46,7 +46,7 @@ $company = (new AtolOnline\Entities\Company())
|
||||
* `AtolEmailValidateException` (если email невалиден).
|
||||
|
||||
Метод `setInn()` чистит входную строку от всех символов, кроме цифр, и проверяет длину (либо 10, либо 12 цифр).
|
||||
Выбрасывает исключение `AtolInnWrongLengthException` (если длина строка ИНН некорректна).
|
||||
Выбрасывает исключение `AtolInnWrongLengthException` (если длина ИНН некорректна).
|
||||
|
||||
Метод `setPaymentAddress()` проверяет длину (до 256 символов).
|
||||
Выбрасывает исключение `AtolPaymentAddressTooLongException` (если слишком длинный адрес места расчётов).
|
||||
|
||||
@@ -164,4 +164,4 @@ $json_array = $doc->jsonSerialize();
|
||||
|
||||
---
|
||||
|
||||
[Вернуться к содержанию](readme.md)
|
||||
[Вернуться к содержанию](readme.md)
|
||||
|
||||
25
docs/kkt.md
25
docs/kkt.md
@@ -49,6 +49,7 @@ $kkt->getGroup();
|
||||
|
||||
Эти параметры нужно задать [объекту компании](/docs/company.md), который будет передаваться в документах через эту ККТ.
|
||||
|
||||
<a name='testmode'></a>
|
||||
## Тестовый режим
|
||||
|
||||
На самом деле, в АТОЛ Онлайн нет понятия *тестовая операция* или чего-то в этом духе.
|
||||
@@ -85,10 +86,10 @@ $kkt->setTestMode(false); // выключить
|
||||
3. пп. 1 и 2 в любом случае скажутся на ваших финансовых отчётах;
|
||||
4. вся ответственность за пп. 1-3 и последствия ложится только на вас.
|
||||
|
||||
## Авторизация ККТ
|
||||
## Авторизация на ККТ
|
||||
|
||||
Перед первым запросом на ККТ происходит авторизация на сервере по логину и паролю.
|
||||
В ответ приходит авторизационный токен, срок жизни коего равен 24 часам.
|
||||
Перед первым запросом на ККТ происходит аутентификация на сервере по логину и паролю.
|
||||
В ответ приходит авторизационный токен, срок жизни коего равен **24 часам**.
|
||||
После первой успешной операции возможно получить этот токен следующим образом:
|
||||
|
||||
```php
|
||||
@@ -98,7 +99,7 @@ $kkt->getAuthToken(); // вернёт строку длиной 128 символ
|
||||
Этот токен можно сохранить и переиспользовать в течение всего срока его жизни.
|
||||
Спустя это время следует получить новый токен.
|
||||
|
||||
Однажды полученный токен, то для дальнейшего использования следует указывать его следующим образом:
|
||||
Для дальнейшего использования однажды полученный токен следует указывать следующим образом:
|
||||
|
||||
```php
|
||||
$kkt->setAuthToken($token_string);
|
||||
@@ -153,6 +154,9 @@ $result = $kkt->sellCorrection($document);
|
||||
$result = $kkt->buyCorrection($document);
|
||||
```
|
||||
|
||||
Любой из перечисленных выше шести методов может выбросить исключение `AtolAuthFailedException` при ошибке
|
||||
аутентификации или авторизации.
|
||||
|
||||
### Собственный идентификатор документа
|
||||
|
||||
Каждый документ, переданный на ККТ для регистрации, всегда имеет свой идентификатор, абсолютно уникальный среди всех
|
||||
@@ -185,6 +189,17 @@ $kkt->setCallbackUrl('http://example.com/process-kkt-result');
|
||||
$kkt->getCallbackUrl();
|
||||
```
|
||||
|
||||
Метод `setCallbackUrl()` проверяет входную строку на длину (до 256 символов) и валидность формата url по
|
||||
регулярному выражению:
|
||||
|
||||
```
|
||||
^http(s?)\:\/\/[0-9a-zA-Zа-яА-Я]([-.\w]*[0-9a-zA-Zа-яА-Я])*(:(0-9)*)*(\/?)([a-zAZ0-9а-яА-Я\-\.\?\,\'\/\\\+&=%$#_]*)?$
|
||||
```
|
||||
|
||||
Выбрасывает исключения:
|
||||
* `AtolCallbackUrlTooLongException` (если слишком длинный url);
|
||||
* `AtolInvalidCallbackUrlException` (если url невалиден).
|
||||
|
||||
## Обработка результата регистрации
|
||||
|
||||
Методы `sell()`, `sellRefund()`, `sellCorrection()`, `buy()`, `buyRefund()` и `buyCorrection()` возвращают объект `AtolOnline\Api\KktResponse`.
|
||||
@@ -194,7 +209,7 @@ $kkt->getCallbackUrl();
|
||||
Этот объект содержит в себе HTTP-код ответа, массив заголовков и JSON-декодированные данные тела ответа.
|
||||
|
||||
```php
|
||||
$result = $kkt->getLastResponse();
|
||||
$result = $kkt->getLastResponse(); // вернёт последний ответ от API
|
||||
$headers = $result->getHeaders(); // вернёт заголовки
|
||||
$code = $result->getCode(); // вернёт код ответа
|
||||
$body = $result->getContent(); // вернёт JSON-декодированное тело ответа
|
||||
|
||||
25
phpunit.xml
25
phpunit.xml
@@ -1,4 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
~
|
||||
~ This code is licensed under MIT.
|
||||
~ Этот код распространяется по лицензии MIT.
|
||||
~ https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
-->
|
||||
|
||||
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
|
||||
backupGlobals="false"
|
||||
@@ -11,15 +19,14 @@
|
||||
processIsolation="false"
|
||||
stopOnFailure="false">
|
||||
<testsuites>
|
||||
<testsuite name="Unit">
|
||||
<file>ClientTest.php</file>
|
||||
<file>CompanyTest.php</file>
|
||||
<file>VatTest.php</file>
|
||||
<directory suffix="Test.php">./tests/Unit</directory>
|
||||
</testsuite>
|
||||
<testsuite name="Feature">
|
||||
<file>ItemTest.php</file>
|
||||
<directory suffix="Test.php">./tests/Feature</directory>
|
||||
<testsuite name="All">
|
||||
<directory suffix="Test.php">./tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<coverage>
|
||||
<include>
|
||||
<directory suffix=".php">src</directory>
|
||||
</include>
|
||||
</coverage>
|
||||
</phpunit>
|
||||
311
src/Api/AtolClient.php
Normal file
311
src/Api/AtolClient.php
Normal file
@@ -0,0 +1,311 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
use AtolOnline\{
|
||||
Constants\Constraints,
|
||||
Exceptions\AuthFailedException,
|
||||
Exceptions\EmptyLoginException,
|
||||
Exceptions\EmptyPasswordException,
|
||||
Exceptions\TooLongLoginException,
|
||||
Exceptions\TooLongPasswordException};
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
/**
|
||||
* Класс для подключения АТОЛ Онлайн API
|
||||
*/
|
||||
abstract class AtolClient
|
||||
{
|
||||
/**
|
||||
* @var bool Флаг тестового режима
|
||||
*/
|
||||
protected bool $test_mode;
|
||||
|
||||
/**
|
||||
* @var Client HTTP-клиент для работы с API
|
||||
*/
|
||||
protected Client $http;
|
||||
|
||||
/**
|
||||
* @var string|null Логин доступа к API
|
||||
*/
|
||||
private ?string $login = null;
|
||||
|
||||
/**
|
||||
* @var string|null Пароль доступа к API (readonly)
|
||||
*/
|
||||
private ?string $password = null;
|
||||
|
||||
/**
|
||||
* @var string|null Токен авторизации
|
||||
*/
|
||||
private ?string $token = null;
|
||||
|
||||
/**
|
||||
* @var KktResponse|null Последний ответ сервера АТОЛ
|
||||
*/
|
||||
private ?KktResponse $response;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param bool $test_mode
|
||||
* @param string|null $login
|
||||
* @param string|null $password
|
||||
* @param array $config
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
* @see https://guzzle.readthedocs.io/en/latest/request-options.html Допустимые параметры для $config
|
||||
*/
|
||||
public function __construct(
|
||||
bool $test_mode = true,
|
||||
?string $login = null,
|
||||
?string $password = null,
|
||||
array $config = []
|
||||
) {
|
||||
$this->http = new Client(array_merge($config, [
|
||||
'http_errors' => $config['http_errors'] ?? false,
|
||||
]));
|
||||
$this->setTestMode($test_mode);
|
||||
!is_null($login) && $this->setLogin($login);
|
||||
!is_null($password) && $this->setPassword($password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный флаг тестового режима
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isTestMode(): bool
|
||||
{
|
||||
return $this->test_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает флаг тестового режима
|
||||
*
|
||||
* @param bool $test_mode
|
||||
* @return $this
|
||||
*/
|
||||
public function setTestMode(bool $test_mode = true): self
|
||||
{
|
||||
$this->test_mode = $test_mode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текущий токен авторизации
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getToken(): ?string
|
||||
{
|
||||
return $this->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает токен авторизации
|
||||
*
|
||||
* @param string|null $token
|
||||
* @return $this
|
||||
*/
|
||||
public function setToken(?string $token): self
|
||||
{
|
||||
$this->token = $token;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает последний ответ сервера
|
||||
*
|
||||
* @return KktResponse|null
|
||||
*/
|
||||
public function getResponse(): ?KktResponse
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает логин доступа к API
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getLogin(): ?string
|
||||
{
|
||||
return $this->login;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает логин доступа к API
|
||||
*
|
||||
* @param string $login
|
||||
* @return $this
|
||||
* @throws EmptyLoginException
|
||||
* @throws TooLongLoginException
|
||||
*/
|
||||
public function setLogin(string $login): self
|
||||
{
|
||||
$login = trim($login);
|
||||
if (empty($login)) {
|
||||
throw new EmptyLoginException();
|
||||
} elseif (mb_strlen($login) > Constraints::MAX_LENGTH_LOGIN) {
|
||||
throw new TooLongLoginException($login, Constraints::MAX_LENGTH_LOGIN);
|
||||
}
|
||||
$this->login = $login;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает пароль доступа к API
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPassword(): ?string
|
||||
{
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает пароль доступа к API
|
||||
*
|
||||
* @param string $password
|
||||
* @return $this
|
||||
* @throws EmptyPasswordException Пароль ККТ не может быть пустым
|
||||
* @throws TooLongPasswordException Слишком длинный пароль ККТ
|
||||
*/
|
||||
public function setPassword(string $password): self
|
||||
{
|
||||
if (empty($password)) {
|
||||
throw new EmptyPasswordException();
|
||||
} elseif (mb_strlen($password) > Constraints::MAX_LENGTH_PASSWORD) {
|
||||
throw new TooLongPasswordException($password, Constraints::MAX_LENGTH_PASSWORD);
|
||||
}
|
||||
$this->password = $password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает набор заголовков для HTTP-запроса
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getHeaders(): array
|
||||
{
|
||||
$headers['Content-type'] = 'application/json; charset=utf-8';
|
||||
if ($this->getToken()) {
|
||||
$headers['Token'] = $this->getToken();
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полный URL для запроса
|
||||
*
|
||||
* @param string $method
|
||||
* @return string
|
||||
*/
|
||||
protected function getUrlToMethod(string $method): string
|
||||
{
|
||||
return $this->getMainEndpoint() . '/' . trim($method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправляет авторизационный запрос на сервер АТОЛ и возвращает авторизационный токен
|
||||
*
|
||||
* @return string|null
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws EmptyLoginException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
protected function doAuth(): ?string
|
||||
{
|
||||
$result = $this->sendRequest('POST', $this->getAuthEndpoint(), [
|
||||
'login' => $this->getLogin() ?? throw new EmptyLoginException(),
|
||||
'pass' => $this->getPassword() ?? throw new EmptyPasswordException(),
|
||||
]);
|
||||
if (!$result->isValid() || !$result->getContent()->token) {
|
||||
throw new AuthFailedException($result);
|
||||
}
|
||||
return $result->getContent()?->token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправляет запрос и возвращает декодированный ответ
|
||||
*
|
||||
* @param string $http_method Метод HTTP
|
||||
* @param string $url URL
|
||||
* @param array|null $data Данные для передачи
|
||||
* @param array|null $options Параметры Guzzle
|
||||
* @return KktResponse
|
||||
* @throws GuzzleException
|
||||
* @see https://guzzle.readthedocs.io/en/latest/request-options.html
|
||||
*/
|
||||
protected function sendRequest(
|
||||
string $http_method,
|
||||
string $url,
|
||||
?array $data = null,
|
||||
?array $options = null
|
||||
): KktResponse {
|
||||
$http_method = strtoupper(trim($http_method));
|
||||
$options['headers'] = array_merge($this->getHeaders(), $options['headers'] ?? []);
|
||||
if ($http_method != 'GET') {
|
||||
$options['json'] = $data;
|
||||
}
|
||||
$response = $this->http->request($http_method, $url, $options);
|
||||
return $this->response = new KktResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Выполняет авторизацию на сервере АТОЛ
|
||||
*
|
||||
* Авторизация выолнится только если неизвестен токен
|
||||
*
|
||||
* @param string|null $login
|
||||
* @param string|null $password
|
||||
* @return bool
|
||||
* @throws AuthFailedException
|
||||
* @throws TooLongLoginException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongPasswordException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function auth(?string $login = null, ?string $password = null): bool
|
||||
{
|
||||
if (empty($this->getToken())) {
|
||||
$login && $this->setLogin($login);
|
||||
$password && $this->setPassword($password);
|
||||
if ($token = $this->doAuth()) {
|
||||
$this->setToken($token);
|
||||
}
|
||||
}
|
||||
return !empty($this->getToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL для запроса авторизации
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getAuthEndpoint(): string;
|
||||
|
||||
/**
|
||||
* Возвращает URL для запросов
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected function getMainEndpoint(): string;
|
||||
}
|
||||
378
src/Api/KktFiscalizer.php
Normal file
378
src/Api/KktFiscalizer.php
Normal file
@@ -0,0 +1,378 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
use AtolOnline\{
|
||||
Constants\Constraints,
|
||||
Entities\Company,
|
||||
Entities\Document,
|
||||
Exceptions\AuthFailedException,
|
||||
Exceptions\EmptyCorrectionInfoException,
|
||||
Exceptions\EmptyLoginException,
|
||||
Exceptions\EmptyPasswordException,
|
||||
Exceptions\InvalidCallbackUrlException,
|
||||
Exceptions\InvalidDocumentTypeException,
|
||||
Exceptions\InvalidInnLengthException,
|
||||
Exceptions\InvalidUuidException,
|
||||
Exceptions\TooLongCallbackUrlException,
|
||||
Exceptions\TooLongLoginException,
|
||||
Exceptions\TooLongPasswordException,
|
||||
Exceptions\TooLongPaymentAddressException,
|
||||
Exceptions\TooManyItemsException,
|
||||
Exceptions\TooManyVatsException,
|
||||
TestEnvParams
|
||||
};
|
||||
use Exception;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
/**
|
||||
* Класс для регистрации документов на ККТ
|
||||
*/
|
||||
class KktFiscalizer extends AtolClient
|
||||
{
|
||||
/**
|
||||
* @var string|null Группа ККТ
|
||||
*/
|
||||
private ?string $group = null;
|
||||
|
||||
/**
|
||||
* @var string|null URL для приёма POST-запроса от API АТОЛ с результатом регистрации документа
|
||||
*/
|
||||
private ?string $callback_url = null;
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param bool $test_mode
|
||||
* @param string|null $login
|
||||
* @param string|null $password
|
||||
* @param string|null $group
|
||||
* @param array $config
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
* @see https://guzzle.readthedocs.io/en/latest/request-options.html
|
||||
*/
|
||||
public function __construct(
|
||||
bool $test_mode = true,
|
||||
?string $login = null,
|
||||
?string $password = null,
|
||||
?string $group = null,
|
||||
array $config = []
|
||||
) {
|
||||
parent::__construct($test_mode, $login, $password, $config);
|
||||
!is_null($group) && $this->setGroup($group);
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает группу доступа к ККТ
|
||||
*
|
||||
* @param string $group
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroup(string $group): self
|
||||
{
|
||||
// критерии к длине строки не описаны ни в схеме, ни в документации
|
||||
$this->group = $group;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает группу доступа к ККТ в соответствии с флагом тестового режима
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getGroup(): ?string
|
||||
{
|
||||
return $this->group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает URL для приёма колбеков
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
* @throws TooLongCallbackUrlException
|
||||
* @throws InvalidCallbackUrlException
|
||||
*/
|
||||
public function setCallbackUrl(string $url): self
|
||||
{
|
||||
if (mb_strlen($url) > Constraints::MAX_LENGTH_CALLBACK_URL) {
|
||||
throw new TooLongCallbackUrlException($url, Constraints::MAX_LENGTH_CALLBACK_URL);
|
||||
} elseif (!preg_match(Constraints::PATTERN_CALLBACK_URL, $url)) {
|
||||
throw new InvalidCallbackUrlException('Callback URL not matches with pattern');
|
||||
}
|
||||
$this->callback_url = $url;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL для приёма колбеков
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCallbackUrl(): string
|
||||
{
|
||||
return $this->callback_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ прихода
|
||||
*
|
||||
* @param Document $document Объект документа
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyCorrectionInfoException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws TooLongPaymentAddressException
|
||||
* @throws InvalidDocumentTypeException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function sell(Document $document, ?string $external_id = null): KktResponse
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new EmptyCorrectionInfoException('Некорректная операция над документом коррекции');
|
||||
}
|
||||
return $this->registerDocument('sell', 'receipt', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ возврата прихода
|
||||
*
|
||||
* @param Document $document Объект документа
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyCorrectionInfoException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws TooLongPaymentAddressException
|
||||
* @throws TooManyVatsException
|
||||
* @throws InvalidDocumentTypeException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function sellRefund(Document $document, ?string $external_id = null): KktResponse
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new EmptyCorrectionInfoException('Invalid operation on correction document');
|
||||
}
|
||||
return $this->registerDocument('sell_refund', 'receipt', $document->clearVats(), $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ коррекции прихода
|
||||
*
|
||||
* @param Document $document Объект документа
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyCorrectionInfoException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws TooLongPaymentAddressException
|
||||
* @throws TooManyItemsException
|
||||
* @throws InvalidDocumentTypeException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function sellCorrection(Document $document, ?string $external_id = null): KktResponse
|
||||
{
|
||||
if (!$document->getCorrectionInfo()) {
|
||||
throw new EmptyCorrectionInfoException();
|
||||
}
|
||||
$document->setClient(null)->setItems([]);
|
||||
return $this->registerDocument('sell_correction', 'correction', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ расхода
|
||||
*
|
||||
* @param Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyCorrectionInfoException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws TooLongPaymentAddressException
|
||||
* @throws InvalidDocumentTypeException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function buy(Document $document, ?string $external_id = null): KktResponse
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new EmptyCorrectionInfoException('Invalid operation on correction document');
|
||||
}
|
||||
return $this->registerDocument('buy', 'receipt', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ возврата расхода
|
||||
*
|
||||
* @param Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyCorrectionInfoException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws TooLongPaymentAddressException
|
||||
* @throws TooManyVatsException
|
||||
* @throws InvalidDocumentTypeException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function buyRefund(Document $document, ?string $external_id = null): KktResponse
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new EmptyCorrectionInfoException('Invalid operation on correction document');
|
||||
}
|
||||
return $this->registerDocument('buy_refund', 'receipt', $document->clearVats(), $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ коррекции расхода
|
||||
*
|
||||
* @param Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException Ошибка авторизации
|
||||
* @throws EmptyCorrectionInfoException В документе отсутствуют данные коррекции
|
||||
* @throws InvalidInnLengthException Некорректная длтина ИНН
|
||||
* @throws TooLongPaymentAddressException Слишком длинный адрес места расчётов
|
||||
* @throws TooManyItemsException Слишком много предметов расчёта
|
||||
* @throws InvalidDocumentTypeException Некорректный тип документа
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function buyCorrection(Document $document, ?string $external_id = null): KktResponse
|
||||
{
|
||||
if (!$document->getCorrectionInfo()) {
|
||||
throw new EmptyCorrectionInfoException();
|
||||
}
|
||||
$document->setClient(null)->setItems([]);
|
||||
return $this->registerDocument('buy_correction', 'correction', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет статус чека на ККТ один раз
|
||||
*
|
||||
* @param string $uuid UUID регистрации
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws GuzzleException
|
||||
* @throws InvalidUuidException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function getDocumentStatus(string $uuid): KktResponse
|
||||
{
|
||||
$uuid = trim($uuid);
|
||||
if (!Uuid::isValid($uuid)) {
|
||||
throw new InvalidUuidException($uuid);
|
||||
}
|
||||
$this->auth();
|
||||
return $this->sendRequest('GET', 'report/' . $uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет статус чека на ККТ нужное количество раз с указанным интервалом.
|
||||
* Вернёт результат как только при очередной проверке сменится статус регистрации документа.
|
||||
*
|
||||
* @param string $uuid UUID регистрации
|
||||
* @param int $retry_count Количество попыток
|
||||
* @param int $timeout Таймаут в секундах между попытками
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws GuzzleException
|
||||
* @throws InvalidUuidException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function pollDocumentStatus(string $uuid, int $retry_count = 5, int $timeout = 1): KktResponse
|
||||
{
|
||||
$try = 0;
|
||||
do {
|
||||
$response = $this->getDocumentStatus($uuid);
|
||||
if ($response->isValid() && $response->getContent()->status == 'done') {
|
||||
break;
|
||||
} else {
|
||||
sleep($timeout);
|
||||
}
|
||||
++$try;
|
||||
} while ($try < $retry_count);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправляет документ на регистрацию
|
||||
*
|
||||
* @param string $api_method Метод API
|
||||
* @param string $type Тип документа: receipt, correction
|
||||
* @param Document $document Объект документа
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return KktResponse
|
||||
* @throws AuthFailedException Ошибка авторизации
|
||||
* @throws InvalidDocumentTypeException Некорректный тип документа
|
||||
* @throws InvalidInnLengthException Некорректная длина ИНН
|
||||
* @throws TooLongPaymentAddressException Слишком длинный адрес места расчётов
|
||||
* @throws GuzzleException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function registerDocument(
|
||||
string $api_method,
|
||||
string $type,
|
||||
Document $document,
|
||||
?string $external_id = null
|
||||
): KktResponse {
|
||||
$type = trim($type);
|
||||
if (!in_array($type, ['receipt', 'correction'])) {
|
||||
throw new InvalidDocumentTypeException($type);
|
||||
}
|
||||
$this->auth();
|
||||
if ($this->isTestMode()) {
|
||||
$document->setCompany(new Company(
|
||||
'test@example.com',
|
||||
TestEnvParams::FFD105()['sno'],
|
||||
TestEnvParams::FFD105()['inn'],
|
||||
TestEnvParams::FFD105()['payment_address'],
|
||||
));
|
||||
}
|
||||
$data['timestamp'] = date('d.m.y H:i:s');
|
||||
$data['external_id'] = $external_id ?: Uuid::uuid4()->toString();
|
||||
$data[$type] = $document;
|
||||
if ($this->getCallbackUrl()) {
|
||||
$data['service'] = ['callback_url' => $this->getCallbackUrl()];
|
||||
}
|
||||
return $this->sendRequest('POST', trim($api_method), $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getAuthEndpoint(): string
|
||||
{
|
||||
return $this->isTestMode()
|
||||
? 'https://testonline.atol.ru/possystem/v1/getToken'
|
||||
: 'https://online.atol.ru/possystem/v1/getToken';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getMainEndpoint(): string
|
||||
{
|
||||
return $this->isTestMode()
|
||||
? 'https://testonline.atol.ru/possystem/v4/'
|
||||
: 'https://online.atol.ru/possystem/v4/';
|
||||
}
|
||||
}
|
||||
115
src/Api/KktMonitor.php
Normal file
115
src/Api/KktMonitor.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
use AtolOnline\Entities\Kkt;
|
||||
use AtolOnline\Exceptions\EmptyMonitorDataException;
|
||||
use AtolOnline\Exceptions\NotEnoughMonitorDataException;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
/**
|
||||
* Класс для мониторинга ККТ
|
||||
*
|
||||
* @see https://online.atol.ru/files/API_service_information.pdf Документация
|
||||
*/
|
||||
class KktMonitor extends AtolClient
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getAuthEndpoint(): string
|
||||
{
|
||||
return $this->isTestMode()
|
||||
? 'https://testonline.atol.ru/api/auth/v1/gettoken'
|
||||
: 'https://online.atol.ru/api/auth/v1/gettoken';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getMainEndpoint(): string
|
||||
{
|
||||
return $this->isTestMode()
|
||||
? 'https://testonline.atol.ru/api/kkt/v1'
|
||||
: 'https://online.atol.ru/api/kkt/v1';
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает от API информацию обо всех ККТ и ФН в рамках группы
|
||||
*
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return KktResponse
|
||||
* @throws GuzzleException
|
||||
* @see https://online.atol.ru/files/API_service_information.pdf Документация, стр 9
|
||||
*/
|
||||
protected function fetchAll(?int $limit = null, ?int $offset = null): KktResponse
|
||||
{
|
||||
$params = [];
|
||||
$limit && $params['limit'] = $limit;
|
||||
$offset && $params['offset'] = $offset;
|
||||
return $this->sendRequest('GET', self::getUrlToMethod('cash-registers'), $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает информацию обо всех ККТ и ФН в рамках группы
|
||||
*
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return Collection
|
||||
* @throws GuzzleException
|
||||
* @see https://online.atol.ru/files/API_service_information.pdf Документация, стр 9
|
||||
*/
|
||||
public function getAll(?int $limit = null, ?int $offset = null): Collection
|
||||
{
|
||||
$collection = collect($this->fetchAll($limit, $offset)->getContent());
|
||||
return $collection->map(fn($data) => new Kkt($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает от API информацию о конкретной ККТ по её серийному номеру
|
||||
*
|
||||
* @param string $serial_number
|
||||
* @return KktResponse
|
||||
* @throws GuzzleException
|
||||
* @see https://online.atol.ru/files/API_service_information.pdf Документация, стр 11
|
||||
*/
|
||||
protected function fetchOne(string $serial_number): KktResponse
|
||||
{
|
||||
return $this->sendRequest(
|
||||
'GET',
|
||||
self::getUrlToMethod('cash-registers') . '/' . trim($serial_number),
|
||||
options: [
|
||||
'headers' => [
|
||||
'Accept' => 'application/hal+json',
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает информацию о конкретной ККТ по её серийному номеру
|
||||
*
|
||||
* @todo кастовать к отдельному классу со своими геттерами
|
||||
* @param string $serial_number
|
||||
* @return Kkt
|
||||
* @throws GuzzleException
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
* @see https://online.atol.ru/files/API_service_information.pdf Документация, стр 11
|
||||
*/
|
||||
public function getOne(string $serial_number): Kkt
|
||||
{
|
||||
return new Kkt($this->fetchOne($serial_number)->getContent()->data);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
use JsonSerializable;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use stdClass;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Класс AtolResponse, описывающий ответ от ККТ
|
||||
*
|
||||
* @property mixed $error
|
||||
* @package AtolOnline\Api
|
||||
*/
|
||||
class KktResponse implements JsonSerializable
|
||||
class KktResponse implements JsonSerializable, Stringable
|
||||
{
|
||||
/**
|
||||
* @var int Код ответа сервера
|
||||
*/
|
||||
protected $code;
|
||||
|
||||
protected int $code;
|
||||
|
||||
/**
|
||||
* @var \stdClass Содержимое ответа сервера
|
||||
* @var stdClass|array|null Содержимое ответа сервера
|
||||
*/
|
||||
protected $content;
|
||||
protected stdClass|array|null $content;
|
||||
|
||||
/**
|
||||
* @var array Заголовки ответа
|
||||
*/
|
||||
protected $headers;
|
||||
|
||||
protected array $headers;
|
||||
|
||||
/**
|
||||
* AtolResponse constructor.
|
||||
*
|
||||
* @param \Psr\Http\Message\ResponseInterface $response
|
||||
* @param ResponseInterface $response
|
||||
*/
|
||||
public function __construct(ResponseInterface $response)
|
||||
{
|
||||
$this->code = $response->getStatusCode();
|
||||
$this->headers = $response->getHeaders();
|
||||
$this->content = json_decode($response->getBody());
|
||||
$this->content = json_decode((string)$response->getBody());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,9 +67,9 @@ class KktResponse implements JsonSerializable
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
public function __get($name): mixed
|
||||
{
|
||||
return $this->getContent()->$name;
|
||||
return $this->getContent()?->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,9 +85,9 @@ class KktResponse implements JsonSerializable
|
||||
/**
|
||||
* Возвращает объект результата запроса
|
||||
*
|
||||
* @return stdClass|null
|
||||
* @return mixed
|
||||
*/
|
||||
public function getContent(): ?stdClass
|
||||
public function getContent(): mixed
|
||||
{
|
||||
return $this->content;
|
||||
}
|
||||
@@ -93,18 +97,18 @@ class KktResponse implements JsonSerializable
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid()
|
||||
public function isValid(): bool
|
||||
{
|
||||
return !empty($this->getCode())
|
||||
&& !empty($this->getContent())
|
||||
&& empty($this->getContent()->error)
|
||||
&& (int)$this->getCode() < 400;
|
||||
&& $this->getCode() < 400;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текстовое представление
|
||||
*/
|
||||
public function __toString()
|
||||
public function __toString(): string
|
||||
{
|
||||
return json_encode($this->jsonSerialize(), JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
@@ -112,7 +116,7 @@ class KktResponse implements JsonSerializable
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
return [
|
||||
'code' => $this->code,
|
||||
@@ -1,537 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
use AtolOnline\{Constants\TestEnvParams,
|
||||
Entities\Company,
|
||||
Entities\Document,
|
||||
Exceptions\AtolCorrectionInfoException,
|
||||
Exceptions\AtolInvalidUuidException,
|
||||
Exceptions\AtolKktLoginEmptyException,
|
||||
Exceptions\AtolKktLoginTooLongException,
|
||||
Exceptions\AtolKktPasswordEmptyException,
|
||||
Exceptions\AtolWrongDocumentTypeException
|
||||
};
|
||||
use GuzzleHttp\Client;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
/**
|
||||
* Класс для отправки запросов на ККТ
|
||||
*
|
||||
* @package AtolOnline\Api
|
||||
*/
|
||||
class Kkt extends Client
|
||||
{
|
||||
/**
|
||||
* @var bool Флаг тестового режима работы
|
||||
*/
|
||||
protected $is_test_mode = false;
|
||||
|
||||
/**
|
||||
* @var array Настройки доступа к ККТ
|
||||
*/
|
||||
protected $kkt_config = [];
|
||||
|
||||
/**
|
||||
* @var \AtolOnline\Api\KktResponse|null Последний ответ сервера АТОЛ
|
||||
*/
|
||||
protected $last_response;
|
||||
|
||||
/**
|
||||
* @var string|null Токен авторизации
|
||||
*/
|
||||
private $auth_token;
|
||||
|
||||
/**
|
||||
* Kkt constructor.
|
||||
*
|
||||
* @param string|null $group
|
||||
* @param string|null $login
|
||||
* @param string|null $pass
|
||||
* @param bool $test_mode Флаг тестового режима
|
||||
* @param array $guzzle_config Конфигурация GuzzleHttp
|
||||
* @throws \AtolOnline\Exceptions\AtolKktLoginEmptyException Логин ККТ не может быть пустым
|
||||
* @throws \AtolOnline\Exceptions\AtolKktLoginTooLongException Слишком длинный логин ККТ
|
||||
* @throws \AtolOnline\Exceptions\AtolKktPasswordEmptyException Пароль ККТ не может быть пустым
|
||||
* @see https://guzzle.readthedocs.io/en/latest/request-options.html
|
||||
*/
|
||||
public function __construct(
|
||||
?string $group = null,
|
||||
?string $login = null,
|
||||
?string $pass = null,
|
||||
bool $test_mode = false,
|
||||
array $guzzle_config = []
|
||||
) {
|
||||
$this->resetKktConfig();
|
||||
if ($group) {
|
||||
$this->setGroup($group);
|
||||
}
|
||||
if ($login) {
|
||||
$this->setLogin($login);
|
||||
}
|
||||
if ($login) {
|
||||
$this->setPassword($pass);
|
||||
}
|
||||
$this->setTestMode($test_mode);
|
||||
$guzzle_config['base_uri'] = $this->getEndpoint();
|
||||
$guzzle_config['http_errors'] = $guzzle_config['http_errors'] ?? false;
|
||||
parent::__construct($guzzle_config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает группу доступа к ККТ
|
||||
*
|
||||
* @param string $group
|
||||
* @return $this
|
||||
*/
|
||||
public function setGroup(string $group)
|
||||
{
|
||||
$this->kkt_config['prod']['group'] = $group;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает группу доступа к ККТ в соответствии с флагом тестового режима
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getGroup(): string
|
||||
{
|
||||
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['group'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает логин доступа к ККТ
|
||||
*
|
||||
* @param string $login
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolKktLoginEmptyException Логин ККТ не может быть пустым
|
||||
* @throws \AtolOnline\Exceptions\AtolKktLoginTooLongException Слишком длинный логин ККТ
|
||||
*/
|
||||
public function setLogin(string $login)
|
||||
{
|
||||
if (!$this->isTestMode()) {
|
||||
if (empty($login)) {
|
||||
throw new AtolKktLoginEmptyException();
|
||||
} elseif ((function_exists('mb_strlen') ? mb_strlen($login) : strlen($login)) > 100) {
|
||||
throw new AtolKktLoginTooLongException($login, 100);
|
||||
}
|
||||
}
|
||||
$this->kkt_config['prod']['login'] = $login;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает логин доступа к ККТ в соответствии с флагом тестового режима
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLogin(): string
|
||||
{
|
||||
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['login'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает пароль доступа к ККТ
|
||||
*
|
||||
* @param string $password
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolKktPasswordEmptyException Пароль ККТ не может быть пустым
|
||||
*/
|
||||
public function setPassword(string $password)
|
||||
{
|
||||
if (!$this->isTestMode()) {
|
||||
if (empty($password)) {
|
||||
throw new AtolKktPasswordEmptyException();
|
||||
}
|
||||
}
|
||||
$this->kkt_config['prod']['pass'] = $password;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает логин ККТ в соответствии с флагом тестового режима
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPassword(): string
|
||||
{
|
||||
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['pass'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает URL для приёма колбеков
|
||||
*
|
||||
* @param string $url
|
||||
* @return $this
|
||||
*/
|
||||
public function setCallbackUrl(string $url)
|
||||
{
|
||||
$this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['callback_url'] = $url;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает URL для приёма колбеков
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCallbackUrl(): string
|
||||
{
|
||||
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['callback_url'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает последний ответ сервера
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getLastResponse()
|
||||
{
|
||||
return $this->last_response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает флаг тестового режима
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isTestMode(): bool
|
||||
{
|
||||
return $this->is_test_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает флаг тестового режима
|
||||
*
|
||||
* @param bool $test_mode
|
||||
* @return $this
|
||||
*/
|
||||
public function setTestMode(bool $test_mode = true)
|
||||
{
|
||||
$this->is_test_mode = $test_mode;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ прихода
|
||||
*
|
||||
* @param \AtolOnline\Entities\Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function sell(Document $document, ?string $external_id = null)
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
|
||||
}
|
||||
return $this->registerDocument('sell', 'receipt', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ возврата прихода
|
||||
*
|
||||
* @param \AtolOnline\Entities\Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException Слишком большая сумма
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||
*/
|
||||
public function sellRefund(Document $document, ?string $external_id = null)
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
|
||||
}
|
||||
return $this->registerDocument('sell_refund', 'receipt', $document->clearVats(), $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ коррекции прихода
|
||||
*
|
||||
* @param \AtolOnline\Entities\Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе отсутствуют данные коррекции
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function sellCorrection(Document $document, ?string $external_id = null)
|
||||
{
|
||||
if (!$document->getCorrectionInfo()) {
|
||||
throw new AtolCorrectionInfoException();
|
||||
}
|
||||
$document->setClient(null)->setItems([]);
|
||||
return $this->registerDocument('sell_correction', 'correction', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ расхода
|
||||
*
|
||||
* @param \AtolOnline\Entities\Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function buy(Document $document, ?string $external_id = null)
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
|
||||
}
|
||||
return $this->registerDocument('buy', 'receipt', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ возврата расхода
|
||||
*
|
||||
* @param \AtolOnline\Entities\Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException Слишком большая сумма
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function buyRefund(Document $document, ?string $external_id = null)
|
||||
{
|
||||
if ($document->getCorrectionInfo()) {
|
||||
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
|
||||
}
|
||||
return $this->registerDocument('buy_refund', 'receipt', $document->clearVats(), $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Регистрирует документ коррекции расхода
|
||||
*
|
||||
* @param Document $document
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
|
||||
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе отсутствуют данные коррекции
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
public function buyCorrection(Document $document, ?string $external_id = null)
|
||||
{
|
||||
if (!$document->getCorrectionInfo()) {
|
||||
throw new AtolCorrectionInfoException();
|
||||
}
|
||||
$document->setClient(null)->setItems([]);
|
||||
return $this->registerDocument('buy_correction', 'correction', $document, $external_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет статус чека на ККТ один раз
|
||||
*
|
||||
* @param string $uuid UUID регистрации
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolInvalidUuidException Некорректный UUID документа
|
||||
*/
|
||||
public function getDocumentStatus(string $uuid)
|
||||
{
|
||||
$uuid = trim($uuid);
|
||||
if (!Uuid::isValid($uuid)) {
|
||||
throw new AtolInvalidUuidException($uuid);
|
||||
}
|
||||
$this->auth();
|
||||
return $this->sendAtolRequest('GET', 'report/'.$uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет статус чека на ККТ нужное количество раз с указанным интервалом.
|
||||
* Вернёт результат как только при очередной проверке сменится статус регистрации документа.
|
||||
*
|
||||
* @param string $uuid UUID регистрации
|
||||
* @param int $retry_count Количество попыток
|
||||
* @param int $timeout Таймаут в секундах между попытками
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolException Некорректный UUID документа
|
||||
*/
|
||||
public function pollDocumentStatus(string $uuid, int $retry_count = 5, int $timeout = 1)
|
||||
{
|
||||
$try = 0;
|
||||
do {
|
||||
$response = $this->getDocumentStatus($uuid);
|
||||
if ($response->isValid() && $response->getContent()->status == 'done') {
|
||||
break;
|
||||
} else {
|
||||
sleep($timeout);
|
||||
}
|
||||
++$try;
|
||||
} while ($try < $retry_count);
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает текущий токен авторизации
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthToken(): ?string
|
||||
{
|
||||
return $this->auth_token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает заранее известный токен авторизации
|
||||
*
|
||||
* @param string|null $auth_token
|
||||
* @return $this
|
||||
*/
|
||||
public function setAuthToken(?string $auth_token)
|
||||
{
|
||||
$this->auth_token = $auth_token;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сбрасывает настройки ККТ по умолчанию
|
||||
*/
|
||||
protected function resetKktConfig(): void
|
||||
{
|
||||
$this->kkt_config['prod']['group'] = '';
|
||||
$this->kkt_config['prod']['login'] = '';
|
||||
$this->kkt_config['prod']['pass'] = '';
|
||||
$this->kkt_config['prod']['url'] = 'https://online.atol.ru/possystem/v4';
|
||||
$this->kkt_config['prod']['callback_url'] = '';
|
||||
$this->kkt_config['test']['group'] = TestEnvParams::GROUP;
|
||||
$this->kkt_config['test']['login'] = TestEnvParams::LOGIN;
|
||||
$this->kkt_config['test']['pass'] = TestEnvParams::PASSWORD;
|
||||
$this->kkt_config['test']['url'] = 'https://testonline.atol.ru/possystem/v4';
|
||||
$this->kkt_config['test']['callback_url'] = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает набор заголовков для HTTP-запроса
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getHeaders()
|
||||
{
|
||||
$headers['Content-type'] = 'application/json; charset=utf-8';
|
||||
if ($this->getAuthToken()) {
|
||||
$headers['Token'] = $this->getAuthToken();
|
||||
}
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает адрес сервера в соответствии с флагом тестового режима
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getEndpoint(): string
|
||||
{
|
||||
return $this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['url'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает полный URL до метода API
|
||||
*
|
||||
* @param string $to_method
|
||||
* @param array|null $get_parameters
|
||||
* @return string
|
||||
*/
|
||||
protected function makeUrl(string $to_method, array $get_parameters = null)
|
||||
{
|
||||
$url = $this->getEndpoint().($this->getAuthToken() ? '/'.$this->getGroup() : '').'/'.$to_method;
|
||||
if ($get_parameters && is_array($get_parameters)) {
|
||||
$url .= '?'.http_build_query($get_parameters);
|
||||
}
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Делает запрос, возвращает декодированный ответ
|
||||
*
|
||||
* @param string $http_method Метод HTTP (GET, POST и пр)
|
||||
* @param string $api_method Метод API
|
||||
* @param mixed $data Данные для передачи
|
||||
* @param array|null $options Параметры Guzzle
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
* @see https://guzzle.readthedocs.io/en/latest/request-options.html
|
||||
*/
|
||||
protected function sendAtolRequest(string $http_method, string $api_method, $data = null, array $options = null)
|
||||
{
|
||||
$http_method = strtoupper($http_method);
|
||||
$options['headers'] = $this->getHeaders();
|
||||
$url = $http_method == 'GET'
|
||||
? $this->makeUrl($api_method, $data)
|
||||
: $this->makeUrl($api_method, ['token' => $this->getAuthToken()]);
|
||||
if ($http_method != 'GET') {
|
||||
$options['json'] = $data;
|
||||
}
|
||||
$response = $this->request($http_method, $url, $options);
|
||||
return $this->last_response = new KktResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Производит авторизацию на ККТ и получает токен доступа для дальнейших HTTP-запросов
|
||||
*
|
||||
* @return bool
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
protected function auth()
|
||||
{
|
||||
if (!$this->getAuthToken()) {
|
||||
$result = $this->sendAtolRequest('GET', 'getToken', [
|
||||
'login' => $this->getLogin(),
|
||||
'pass' => $this->getPassword(),
|
||||
]);
|
||||
if (!$result->isValid() || !$result->getContent()->token) {
|
||||
return false;
|
||||
}
|
||||
$this->auth_token = $result->getContent()->token;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Отправляет документ на регистрацию
|
||||
*
|
||||
* @param string $api_method Метод API
|
||||
* @param string $type Тип документа: receipt, correction
|
||||
* @param \AtolOnline\Entities\Document $document Объект документа
|
||||
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
|
||||
* @return \AtolOnline\Api\KktResponse
|
||||
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException
|
||||
* @throws \GuzzleHttp\Exception\GuzzleException
|
||||
*/
|
||||
protected function registerDocument(string $api_method, string $type, Document $document, ?string $external_id = null)
|
||||
{
|
||||
$type = trim($type);
|
||||
if (!in_array($type, ['receipt', 'correction'])) {
|
||||
throw new AtolWrongDocumentTypeException($type);
|
||||
}
|
||||
$this->auth();
|
||||
if ($this->isTestMode()) {
|
||||
$document->setCompany(($document->getCompany() ?: new Company())
|
||||
->setInn(TestEnvParams::INN)
|
||||
->setSno(TestEnvParams::SNO)
|
||||
->setPaymentAddress(TestEnvParams::PAYMENT_ADDRESS));
|
||||
}
|
||||
$data['timestamp'] = date('d.m.y H:i:s');
|
||||
$data['external_id'] = $external_id ?: Uuid::uuid4()->toString();
|
||||
$data[$type] = $document;
|
||||
if ($this->getCallbackUrl()) {
|
||||
$data['service'] = ['callback_url' => $this->getCallbackUrl()];
|
||||
}
|
||||
return $this->sendAtolRequest('POST', trim($api_method), $data);
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
abstract class AtolSchema
|
||||
{
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public static function get()
|
||||
{
|
||||
return static::$json
|
||||
?? static::$json = json_decode(file_get_contents(static::$URL));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false|string
|
||||
*/
|
||||
public static function json()
|
||||
{
|
||||
return json_encode(static::get());
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
class CorrectionSchema extends AtolSchema
|
||||
{
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected static $json;
|
||||
|
||||
/**
|
||||
* Адрес схемы
|
||||
*/
|
||||
protected static $URL = 'https://online.atol.ru/possystem/v4/schema/correction';
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace AtolOnline\Api;
|
||||
|
||||
class SellSchema extends AtolSchema
|
||||
{
|
||||
/**
|
||||
* @var
|
||||
*/
|
||||
protected static $json;
|
||||
|
||||
/**
|
||||
* Адрес схемы
|
||||
*/
|
||||
protected static $URL = 'https://online.atol.ru/possystem/v4/schema/sell';
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
|
||||
/**
|
||||
* Константы, определяющие виды оплат. Тег ФФД - 1031, 1081, 1215, 1216, 1217.
|
||||
*
|
||||
* @package AtolOnline\Constants
|
||||
*/
|
||||
class PaymentTypes
|
||||
{
|
||||
/**
|
||||
* Расчёт наличными. Тег ФФД - 1031.
|
||||
*/
|
||||
const CASH = 0;
|
||||
|
||||
/**
|
||||
* Расчёт безналичными. Тег ФФД - 1081.
|
||||
*/
|
||||
const ELECTRON = 1;
|
||||
|
||||
/**
|
||||
* Предварительная оплата (зачет аванса). Тег ФФД - 1215.
|
||||
*/
|
||||
const PRE_PAID = 2;
|
||||
|
||||
/**
|
||||
* Предварительная оплата (кредит). Тег ФФД - 1216.
|
||||
*/
|
||||
const CREDIT = 3;
|
||||
|
||||
/**
|
||||
* Иная форма оплаты (встречное предоставление). Тег ФФД - 1217.
|
||||
*/
|
||||
const OTHER = 4;
|
||||
|
||||
/**
|
||||
* Расширенный типы оплаты
|
||||
* Для каждого фискального типа оплаты можно указать расширенный тип оплаты
|
||||
*/
|
||||
const ADD_5 = 5;
|
||||
const ADD_6 = 6;
|
||||
const ADD_7 = 7;
|
||||
const ADD_8 = 8;
|
||||
const ADD_9 = 9;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
|
||||
/**
|
||||
* Константы, определяющие параметры тестовой среды
|
||||
*
|
||||
* @see https://online.atol.ru/files/ffd/test_sreda.txt
|
||||
* @package AtolOnline\Constants
|
||||
*/
|
||||
class TestEnvParams
|
||||
{
|
||||
/**
|
||||
* Логин
|
||||
*/
|
||||
const LOGIN = 'v4-online-atol-ru';
|
||||
|
||||
/**
|
||||
* Пароль
|
||||
*/
|
||||
const PASSWORD = 'iGFFuihss';
|
||||
|
||||
/**
|
||||
* Группа
|
||||
*/
|
||||
const GROUP = 'v4-online-atol-ru_4179';
|
||||
|
||||
/**
|
||||
* Система налогообложения
|
||||
*/
|
||||
const SNO = SnoTypes::OSN;
|
||||
|
||||
/**
|
||||
* ИНН
|
||||
*/
|
||||
const INN = '5544332219';
|
||||
|
||||
/**
|
||||
* Адрес места расчётов
|
||||
*/
|
||||
const PAYMENT_ADDRESS = 'https://v4.online.atol.ru';
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\{Exceptions\AtolNameTooLongException, Exceptions\AtolPhoneTooLongException, Traits\HasEmail, Traits\HasInn};
|
||||
|
||||
/**
|
||||
* Класс Client, описывающий сущность покупателя
|
||||
*
|
||||
* @package AtolOnline\Entities
|
||||
*/
|
||||
class Client extends Entity
|
||||
{
|
||||
use
|
||||
/**
|
||||
* Покупатель может иметь почту. Тег ФФД - 1008.
|
||||
*/
|
||||
HasEmail,
|
||||
|
||||
/**
|
||||
* Покупатель может иметь ИНН. Тег ФФД - 1228.
|
||||
*/
|
||||
HasInn;
|
||||
|
||||
/**
|
||||
* @var string Телефон покупателя. Тег ФФД - 1008.
|
||||
*/
|
||||
protected $phone;
|
||||
|
||||
/**
|
||||
* @var string Имя покупателя. Тег ФФД - 1227.
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Client constructor.
|
||||
*
|
||||
* @param string|null $name Наименование
|
||||
* @param string|null $phone Телефон
|
||||
* @param string|null $email Email
|
||||
* @param string|null $inn ИНН
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||
*/
|
||||
public function __construct(?string $name = null, ?string $phone = null, ?string $email = null, ?string $inn = null)
|
||||
{
|
||||
if ($name) {
|
||||
$this->setName($name);
|
||||
}
|
||||
if ($email) {
|
||||
$this->setEmail($email);
|
||||
}
|
||||
if ($phone) {
|
||||
$this->setPhone($phone);
|
||||
}
|
||||
if ($inn) {
|
||||
$this->setInn($inn);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает имя покупателя. Тег ФФД - 1227.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает имя покупателя
|
||||
* Тег ФФД - 1227.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
* @throws AtolNameTooLongException
|
||||
*/
|
||||
public function setName(string $name)
|
||||
{
|
||||
$name = trim($name);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($name) : strlen($name)) > 256) {
|
||||
throw new AtolNameTooLongException($name, 256);
|
||||
}
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает телефон покупателя.
|
||||
* Тег ФФД - 1008.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPhone()
|
||||
{
|
||||
return $this->phone ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает телефон покупателя.
|
||||
* Тег ФФД - 1008.
|
||||
* Входная строка лишается всех знаков, кроме цифр и знака '+'.
|
||||
*
|
||||
* @param string $phone
|
||||
* @return $this
|
||||
* @throws AtolPhoneTooLongException
|
||||
*/
|
||||
public function setPhone(string $phone)
|
||||
{
|
||||
$phone = preg_replace("/[^0-9+]/", '', $phone);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($phone) : strlen($phone)) > 64) {
|
||||
throw new AtolPhoneTooLongException($phone, 64);
|
||||
}
|
||||
$this->phone = $phone;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
$json = [];
|
||||
if ($this->getName()) {
|
||||
$json['name'] = $this->getName() ?? '';
|
||||
}
|
||||
if ($this->getEmail()) {
|
||||
$json['email'] = $this->getEmail() ?? '';
|
||||
}
|
||||
if ($this->getPhone()) {
|
||||
$json['phone'] = $this->getPhone() ?? '';
|
||||
}
|
||||
if ($this->getInn()) {
|
||||
$json['inn'] = $this->getInn() ?? '';
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\{Exceptions\AtolEmailTooLongException,
|
||||
Exceptions\AtolEmailValidateException,
|
||||
Exceptions\AtolInnWrongLengthException,
|
||||
Exceptions\AtolPaymentAddressTooLongException,
|
||||
Traits\HasEmail,
|
||||
Traits\HasInn
|
||||
};
|
||||
|
||||
/**
|
||||
* Класс, описывающий сущность компании-продавца
|
||||
*
|
||||
* @package AtolOnline\Entities
|
||||
*/
|
||||
class Company extends Entity
|
||||
{
|
||||
use
|
||||
/**
|
||||
* Продавец должен иметь почту. Тег ФФД - 1117.
|
||||
*/
|
||||
HasEmail,
|
||||
|
||||
/**
|
||||
* Продавец должен иметь ИНН. Тег ФФД - 1018.
|
||||
*/
|
||||
HasInn;
|
||||
|
||||
/**
|
||||
* @var string Система налогообложения продавца. Тег ФФД - 1055.
|
||||
*/
|
||||
protected $sno;
|
||||
|
||||
/**
|
||||
* @var string Место расчётов (адрес интернет-магазина). Тег ФФД - 1187.
|
||||
*/
|
||||
protected $payment_address;
|
||||
|
||||
/**
|
||||
* Company constructor.
|
||||
*
|
||||
* @param string|null $sno
|
||||
* @param string|null $inn
|
||||
* @param string|null $paymentAddress
|
||||
* @param string|null $email
|
||||
* @throws AtolEmailTooLongException
|
||||
* @throws AtolEmailValidateException
|
||||
* @throws AtolInnWrongLengthException
|
||||
* @throws AtolPaymentAddressTooLongException
|
||||
*/
|
||||
public function __construct(string $sno = null, string $inn = null, string $paymentAddress = null, string $email = null)
|
||||
{
|
||||
if ($sno) {
|
||||
$this->setSno($sno);
|
||||
}
|
||||
if ($inn) {
|
||||
$this->setInn($inn);
|
||||
}
|
||||
if ($paymentAddress) {
|
||||
$this->setPaymentAddress($paymentAddress);
|
||||
}
|
||||
if ($email) {
|
||||
$this->setEmail($email);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный тип налогообложения. Тег ФФД - 1055.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSno()
|
||||
{
|
||||
return $this->sno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает тип налогообложения. Тег ФФД - 1055.
|
||||
*
|
||||
* @param string $sno
|
||||
* @return $this
|
||||
*/
|
||||
public function setSno(string $sno)
|
||||
{
|
||||
$this->sno = trim($sno);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный адрес места расчётов. Тег ФФД - 1187.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPaymentAddress()
|
||||
{
|
||||
return $this->payment_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает адрес места расчётов. Тег ФФД - 1187.
|
||||
*
|
||||
* @param string $payment_address
|
||||
* @return $this
|
||||
* @throws AtolPaymentAddressTooLongException
|
||||
*/
|
||||
public function setPaymentAddress(string $payment_address)
|
||||
{
|
||||
$payment_address = trim($payment_address);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($payment_address) : strlen($payment_address)) > 256) {
|
||||
throw new AtolPaymentAddressTooLongException($payment_address, 256);
|
||||
}
|
||||
$this->payment_address = $payment_address;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'email' => $this->getEmail(),
|
||||
'sno' => $this->getSno(),
|
||||
'inn' => $this->getInn(),
|
||||
'payment_address' => $this->getPaymentAddress(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при ошибке валидации email
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolEmailValidateException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
1008,
|
||||
1117,
|
||||
];
|
||||
|
||||
/**
|
||||
* AtolEmailValidateException constructor.
|
||||
*
|
||||
* @param $email
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param \Throwable|null $previous
|
||||
*/
|
||||
public function __construct($email, $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message ?: 'Invalid email: '.$email, $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать ИНН некорректной длины
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolInnWrongLengthException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
1016,
|
||||
1018,
|
||||
1226,
|
||||
1228,
|
||||
];
|
||||
|
||||
/**
|
||||
* AtolInnWrongLengthException constructor.
|
||||
*
|
||||
* @param $inn
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($inn, $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message ?: 'INN length must be 10 or 12 digits only, but actual is '.
|
||||
(function_exists('mb_strlen') ? mb_strlen($inn) : strlen($inn)).')', $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать некорректный тип документа
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolWrongDocumentTypeException extends AtolException
|
||||
{
|
||||
/**
|
||||
* AtolWrongDocumentTypeException constructor.
|
||||
*
|
||||
* @param $type
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($type, $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message ?: "Wrong document type: 'receipt' or 'correction' expected, but '$type' provided", $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Traits;
|
||||
|
||||
use AtolOnline\{Exceptions\AtolEmailTooLongException, Exceptions\AtolEmailValidateException};
|
||||
|
||||
/**
|
||||
* Добавляет объекту функционал для работы с email
|
||||
*
|
||||
* @package AtolOnline\Traits
|
||||
*/
|
||||
trait HasEmail
|
||||
{
|
||||
/**
|
||||
* @var string Почта
|
||||
*/
|
||||
protected $email;
|
||||
|
||||
/**
|
||||
* Возвращает установленную почту. Тег ФФД: 1008, 1117.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmail()
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает почту. Тег ФФД: 1008, 1117.
|
||||
*
|
||||
* @param string $email
|
||||
* @return $this
|
||||
* @throws AtolEmailTooLongException
|
||||
* @throws AtolEmailValidateException
|
||||
*/
|
||||
public function setEmail(string $email)
|
||||
{
|
||||
$email = trim($email);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($email) : strlen($email)) > 64) {
|
||||
throw new AtolEmailTooLongException($email, 64);
|
||||
}
|
||||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||
throw new AtolEmailValidateException($email);
|
||||
}
|
||||
$this->email = $email;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Traits;
|
||||
|
||||
use AtolOnline\Exceptions\AtolInnWrongLengthException;
|
||||
|
||||
/**
|
||||
* Добавляет объекту функционал для работы с ИНН
|
||||
*
|
||||
* @package AtolOnline\Traits
|
||||
*/
|
||||
trait HasInn
|
||||
{
|
||||
/**
|
||||
* @var string ИНН
|
||||
*/
|
||||
protected $inn;
|
||||
|
||||
/**
|
||||
* Возвращает установленный ИНН. Тег ФФД: 1228, 1018.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInn()
|
||||
{
|
||||
return $this->inn ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ИНН. Тег ФФД: 1228, 1018.
|
||||
* Входная строка лишается всех знаков, кроме цифр.
|
||||
*
|
||||
* @param string $inn
|
||||
* @return $this
|
||||
* @throws AtolInnWrongLengthException
|
||||
*/
|
||||
public function setInn(string $inn)
|
||||
{
|
||||
$inn = preg_replace("/[^0-9]/", '', $inn);
|
||||
if (preg_match_all("/(^[0-9]{10}$)|(^[0-9]{12}$)/", $inn) == 0) {
|
||||
throw new AtolInnWrongLengthException($inn);
|
||||
}
|
||||
$this->inn = $inn;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Traits;
|
||||
|
||||
/**
|
||||
* Свойство класса, позволяющее конвертировать рубли <-> копейки
|
||||
*
|
||||
* @package AtolOnline\Traits
|
||||
*/
|
||||
trait RublesKopeksConverter
|
||||
{
|
||||
/**
|
||||
* Конвертирует рубли в копейки, учитывая только 2 знака после запятой
|
||||
*
|
||||
* @param float|null $rubles Рубли
|
||||
* @return int Копейки
|
||||
*/
|
||||
protected static function toKop(?float $rubles = null)
|
||||
{
|
||||
return $rubles === null ? null : (int)round($rubles * 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Конвертирует копейки в рубли, оставляя только 2 знака после запятой
|
||||
*
|
||||
* @param int|null $kopeks Копейки
|
||||
* @return float Рубли
|
||||
*/
|
||||
protected static function toRub(?int $kopeks = null)
|
||||
{
|
||||
return $kopeks === null ? null : round($kopeks / 100, 2);
|
||||
}
|
||||
}
|
||||
83
src/Constants/Constraints.php
Normal file
83
src/Constants/Constraints.php
Normal file
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
|
||||
/**
|
||||
* Класс с константами ограничений
|
||||
*/
|
||||
final class Constraints
|
||||
{
|
||||
/**
|
||||
* Максимальная длина Callback URL
|
||||
*/
|
||||
const MAX_LENGTH_CALLBACK_URL = 256;
|
||||
|
||||
/**
|
||||
* Максимальная длина email
|
||||
*/
|
||||
const MAX_LENGTH_EMAIL = 64;
|
||||
|
||||
/**
|
||||
* Максимальная длина логина ККТ
|
||||
*/
|
||||
const MAX_LENGTH_LOGIN = 100;
|
||||
|
||||
/**
|
||||
* Максимальная длина пароля ККТ
|
||||
*/
|
||||
const MAX_LENGTH_PASSWORD = 100;
|
||||
|
||||
/**
|
||||
* Максимальная длина имени покупателя
|
||||
*/
|
||||
const MAX_LENGTH_CLIENT_NAME = 256;
|
||||
|
||||
/**
|
||||
* Максимальная длина телефона покупателя
|
||||
*/
|
||||
const MAX_LENGTH_CLIENT_PHONE = 64;
|
||||
|
||||
/**
|
||||
* Максимальная длина адреса места расчётов
|
||||
*/
|
||||
const MAX_LENGTH_PAYMENT_ADDRESS = 256;
|
||||
|
||||
/**
|
||||
* Максимальная длина имени кассира
|
||||
*/
|
||||
const MAX_LENGTH_CASHIER_NAME = 64;
|
||||
|
||||
/**
|
||||
* Максимальная длина наименования предмета расчётов
|
||||
*/
|
||||
const MAX_LENGTH_ITEM_NAME = 128;
|
||||
|
||||
/**
|
||||
* Максимальная длина единицы измерения предмета расчётов
|
||||
*/
|
||||
const MAX_LENGTH_MEASUREMENT_UNIT = 16;
|
||||
|
||||
/**
|
||||
* Максимальная длина пользовательских данных для предмета расчётов
|
||||
*/
|
||||
const MAX_LENGTH_USER_DATA = 64;
|
||||
|
||||
/**
|
||||
* Регулярное выражание для валидации строки ИНН
|
||||
*/
|
||||
const PATTERN_INN = "/(^[0-9]{10}$)|(^[0-9]{12}$)/";
|
||||
|
||||
/**
|
||||
* Регулярное выражание для валидации строки Callback URL
|
||||
*/
|
||||
const PATTERN_CALLBACK_URL = "/^http(s?)\:\/\/[0-9a-zA-Zа-яА-Я]([-.\w]*[0-9a-zA-Zа-яА-Я])*(:(0-9)*)*(\/?)([a-zAZ0-9а-яА-Я\-\.\?\,\'\/\\\+&=%\$#_]*)?$/";
|
||||
}
|
||||
213
src/Entities/Client.php
Normal file
213
src/Entities/Client.php
Normal file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\{
|
||||
Constants\Constraints,
|
||||
Exceptions\InvalidEmailException,
|
||||
Exceptions\InvalidInnLengthException,
|
||||
Exceptions\TooLongEmailException,
|
||||
Exceptions\TooLongNameException,
|
||||
Exceptions\TooLongPhoneException};
|
||||
|
||||
/**
|
||||
* Класс Client, описывающий сущность покупателя
|
||||
*
|
||||
* @package AtolOnline\Entities
|
||||
*/
|
||||
class Client extends Entity
|
||||
{
|
||||
/**
|
||||
* @var string|null Наименование. Тег ФФД - 1227.
|
||||
*/
|
||||
protected ?string $name = null;
|
||||
|
||||
/**
|
||||
* @var string|null Email. Тег ФФД - 1008.
|
||||
*/
|
||||
protected ?string $email = null;
|
||||
|
||||
/**
|
||||
* @var string|null Телефон покупателя. Тег ФФД - 1008.
|
||||
*/
|
||||
protected ?string $phone = null;
|
||||
|
||||
/**
|
||||
* @var string|null ИНН. Тег ФФД - 1228.
|
||||
*/
|
||||
protected ?string $inn = null;
|
||||
|
||||
/**
|
||||
* Конструктор объекта покупателя
|
||||
*
|
||||
* @param string|null $name Наименование. Тег ФФД - 1227.
|
||||
* @param string|null $phone Email. Тег ФФД - 1008.
|
||||
* @param string|null $email Телефон покупателя. Тег ФФД - 1008.
|
||||
* @param string|null $inn ИНН. Тег ФФД - 1228.
|
||||
* @throws TooLongNameException Слишком длинное имя
|
||||
* @throws TooLongPhoneException Слишком длинный телефон
|
||||
* @throws TooLongEmailException Слишком длинный email
|
||||
* @throws InvalidEmailException Невалидный email
|
||||
* @throws InvalidInnLengthException Некорректная длина ИНН
|
||||
*/
|
||||
public function __construct(
|
||||
?string $name = null,
|
||||
?string $email = null,
|
||||
?string $phone = null,
|
||||
?string $inn = null
|
||||
) {
|
||||
$name && $this->setName($name);
|
||||
$email && $this->setEmail($email);
|
||||
$phone && $this->setPhone($phone);
|
||||
$inn && $this->setInn($inn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает наименование покупателя
|
||||
*
|
||||
* Тег ФФД - 1227
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает наименование покупателя
|
||||
*
|
||||
* Тег ФФД - 1227
|
||||
*
|
||||
* @param string|null $name
|
||||
* @return $this
|
||||
* @throws TooLongNameException
|
||||
*/
|
||||
public function setName(?string $name): Client
|
||||
{
|
||||
if (is_string($name)) {
|
||||
$name = preg_replace('/[\n\r\t]/', '', trim($name));
|
||||
if (mb_strlen($name) > Constraints::MAX_LENGTH_CLIENT_NAME) {
|
||||
throw new TooLongNameException($name, Constraints::MAX_LENGTH_CLIENT_NAME);
|
||||
}
|
||||
}
|
||||
$this->name = empty($name) ? null : $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный email
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getEmail(): ?string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает email
|
||||
*
|
||||
* @param string|null $email
|
||||
* @return $this
|
||||
* @throws TooLongEmailException Слишком длинный email
|
||||
* @throws InvalidEmailException Невалидный email
|
||||
*/
|
||||
public function setEmail(?string $email): self
|
||||
{
|
||||
if (is_string($email)) {
|
||||
$email = preg_replace('/[\n\r\t]/', '', trim($email));
|
||||
if (mb_strlen($email) > Constraints::MAX_LENGTH_EMAIL) {
|
||||
throw new TooLongEmailException($email, Constraints::MAX_LENGTH_EMAIL);
|
||||
} elseif (filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
|
||||
throw new InvalidEmailException($email);
|
||||
}
|
||||
}
|
||||
$this->email = empty($email) ? null : $email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный телефон
|
||||
*
|
||||
* Тег ФФД - 1008
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPhone(): ?string
|
||||
{
|
||||
return $this->phone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает телефон
|
||||
*
|
||||
* Тег ФФД - 1008
|
||||
*
|
||||
* @param string|null $phone Номер телефона
|
||||
* @return $this
|
||||
* @throws TooLongPhoneException
|
||||
*/
|
||||
public function setPhone(?string $phone): Client
|
||||
{
|
||||
if (is_string($phone)) {
|
||||
$phone = preg_replace('/[^\d]/', '', trim($phone));
|
||||
if (mb_strlen($phone) > Constraints::MAX_LENGTH_CLIENT_PHONE) {
|
||||
throw new TooLongPhoneException($phone, Constraints::MAX_LENGTH_CLIENT_PHONE);
|
||||
}
|
||||
}
|
||||
$this->phone = empty($phone) ? null : "+$phone";
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный ИНН
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getInn(): ?string
|
||||
{
|
||||
return $this->inn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ИНН
|
||||
*
|
||||
* @param string|null $inn
|
||||
* @return $this
|
||||
* @throws InvalidInnLengthException Некорректная длина ИНН
|
||||
*/
|
||||
public function setInn(?string $inn): self
|
||||
{
|
||||
if (is_string($inn)) {
|
||||
$inn = preg_replace('/[^\d]/', '', trim($inn));
|
||||
if (preg_match_all(Constraints::PATTERN_INN, $inn) === 0) {
|
||||
throw new InvalidInnLengthException($inn);
|
||||
}
|
||||
}
|
||||
$this->inn = empty($inn) ? null : $inn;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize(): object
|
||||
{
|
||||
$json = [];
|
||||
$this->getName() && $json['name'] = $this->getName();
|
||||
$this->getEmail() && $json['email'] = $this->getEmail();
|
||||
$this->getPhone() && $json['phone'] = $this->getPhone();
|
||||
$this->getInn() && $json['inn'] = $this->getInn();
|
||||
return (object)$json;
|
||||
}
|
||||
}
|
||||
227
src/Entities/Company.php
Normal file
227
src/Entities/Company.php
Normal file
@@ -0,0 +1,227 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\{
|
||||
Constants\Constraints,
|
||||
Enums\SnoTypes,
|
||||
Exceptions\InvalidEmailException,
|
||||
Exceptions\InvalidInnLengthException,
|
||||
Exceptions\InvalidPaymentAddressException,
|
||||
Exceptions\InvalidSnoException,
|
||||
Exceptions\TooLongEmailException,
|
||||
Exceptions\TooLongPaymentAddressException};
|
||||
|
||||
/**
|
||||
* Класс, описывающий сущность компании-продавца
|
||||
*
|
||||
* @package AtolOnline\Entities
|
||||
*/
|
||||
class Company extends Entity
|
||||
{
|
||||
/**
|
||||
* @var string|null Почта. Тег ФФД - 1117.
|
||||
*/
|
||||
protected ?string $email;
|
||||
|
||||
/**
|
||||
* @var string|null Система налогообложения продавца. Тег ФФД - 1055.
|
||||
*/
|
||||
protected ?string $sno;
|
||||
|
||||
/**
|
||||
* @var string|null ИНН. Тег ФФД - 1018.
|
||||
*/
|
||||
protected ?string $inn;
|
||||
|
||||
/**
|
||||
* @var string|null Место расчётов (адрес интернет-магазина). Тег ФФД - 1187.
|
||||
*/
|
||||
protected ?string $payment_address;
|
||||
|
||||
/**
|
||||
* Company constructor.
|
||||
*
|
||||
* @param string $sno
|
||||
* @param string $inn
|
||||
* @param string $payment_address
|
||||
* @param string $email
|
||||
* @throws InvalidEmailException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws InvalidPaymentAddressException
|
||||
* @throws InvalidSnoException
|
||||
* @throws TooLongEmailException
|
||||
* @throws TooLongPaymentAddressException
|
||||
*/
|
||||
public function __construct(
|
||||
string $email,
|
||||
string $sno,
|
||||
string $inn,
|
||||
string $payment_address,
|
||||
) {
|
||||
$this->setEmail($email);
|
||||
$this->setSno($sno);
|
||||
$this->setInn($inn);
|
||||
$this->setPaymentAddress($payment_address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный email
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEmail(): string
|
||||
{
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает email
|
||||
*
|
||||
* @param string $email
|
||||
* @return $this
|
||||
* @throws TooLongEmailException Слишком длинный email
|
||||
* @throws InvalidEmailException Невалидный email
|
||||
*/
|
||||
public function setEmail(string $email): self
|
||||
{
|
||||
$email = preg_replace('/[\n\r\t]/', '', trim($email));
|
||||
if (mb_strlen($email) > Constraints::MAX_LENGTH_EMAIL) {
|
||||
throw new TooLongEmailException($email, Constraints::MAX_LENGTH_EMAIL);
|
||||
} elseif (empty($email) || filter_var($email, FILTER_VALIDATE_EMAIL) === false) {
|
||||
throw new InvalidEmailException($email);
|
||||
}
|
||||
$this->email = $email;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный тип налогообложения
|
||||
*
|
||||
* Тег ФФД - 1055
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSno(): string
|
||||
{
|
||||
return $this->sno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает тип налогообложения
|
||||
*
|
||||
* Тег ФФД - 1055
|
||||
*
|
||||
* @param string $sno
|
||||
* @return $this
|
||||
* @throws InvalidSnoException
|
||||
*/
|
||||
public function setSno(string $sno): Company
|
||||
{
|
||||
$sno = trim($sno);
|
||||
if (empty($sno) || !in_array($sno, SnoTypes::toArray())) {
|
||||
throw new InvalidSnoException($sno);
|
||||
}
|
||||
$this->sno = $sno;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный ИНН
|
||||
*
|
||||
* Тег ФФД - 1018
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getInn(): string
|
||||
{
|
||||
return $this->inn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает ИНН
|
||||
*
|
||||
* Тег ФФД - 1018
|
||||
*
|
||||
* @param string $inn
|
||||
* @return $this
|
||||
* @throws InvalidInnLengthException
|
||||
*/
|
||||
public function setInn(string $inn): self
|
||||
{
|
||||
$inn = preg_replace('/[^\d]/', '', trim($inn));
|
||||
if (empty($inn) || preg_match_all(Constraints::PATTERN_INN, $inn) === 0) {
|
||||
throw new InvalidInnLengthException($inn);
|
||||
}
|
||||
$this->inn = $inn;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает установленный адрес места расчётов
|
||||
*
|
||||
* Тег ФФД - 1187
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPaymentAddress(): string
|
||||
{
|
||||
return $this->payment_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает адрес места расчётов
|
||||
*
|
||||
* Тег ФФД - 1187
|
||||
*
|
||||
* @param string $payment_address
|
||||
* @return $this
|
||||
* @throws TooLongPaymentAddressException
|
||||
* @throws InvalidPaymentAddressException
|
||||
*/
|
||||
public function setPaymentAddress(string $payment_address): Company
|
||||
{
|
||||
$payment_address = trim($payment_address);
|
||||
if (empty($payment_address)) {
|
||||
throw new InvalidPaymentAddressException();
|
||||
} elseif (mb_strlen($payment_address) > Constraints::MAX_LENGTH_PAYMENT_ADDRESS) {
|
||||
throw new TooLongPaymentAddressException($payment_address, Constraints::MAX_LENGTH_PAYMENT_ADDRESS);
|
||||
}
|
||||
$this->payment_address = $payment_address;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @throws InvalidEmailException
|
||||
* @throws InvalidSnoException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws InvalidPaymentAddressException
|
||||
*/
|
||||
public function jsonSerialize(): object
|
||||
{
|
||||
return (object)[
|
||||
'email' => $this->email
|
||||
? $this->getEmail()
|
||||
: throw new InvalidEmailException(),
|
||||
'sno' => $this->sno
|
||||
? $this->getSno()
|
||||
: throw new InvalidSnoException(),
|
||||
'inn' => $this->inn
|
||||
? $this->getInn()
|
||||
: throw new InvalidInnLengthException(),
|
||||
'payment_address' => $this->payment_address
|
||||
? $this->getPaymentAddress()
|
||||
: throw new InvalidPaymentAddressException(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,65 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
/**
|
||||
* Класс CorrectionInfo, описывающий данные коррекции
|
||||
*
|
||||
* @package AtolOnline\Entities
|
||||
* Класс CorrectionInfo, описывающий данные чек коррекции
|
||||
*/
|
||||
class CorrectionInfo extends Entity
|
||||
{
|
||||
/**
|
||||
* @var int Тип коррекции. Тег ФФД - 1173.
|
||||
* @var string Тип коррекции. Тег ФФД - 1173.
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
protected string $type;
|
||||
|
||||
/**
|
||||
* @var string Дата документа основания для коррекции. Тег ФФД - 1178.
|
||||
*/
|
||||
protected $base_date;
|
||||
|
||||
protected string $base_date;
|
||||
|
||||
/**
|
||||
* @var string Номер документа основания для коррекции. Тег ФФД - 1179.
|
||||
*/
|
||||
protected $base_number;
|
||||
|
||||
/**
|
||||
* @var string Описание коррекции. Тег ФФД - 1177.
|
||||
*/
|
||||
protected $base_name;
|
||||
|
||||
protected string $base_number;
|
||||
|
||||
/**
|
||||
* CorrectionInfo constructor.
|
||||
*
|
||||
* @param string|null $type Тип коррекции
|
||||
* @param string|null $base_date Дата документа
|
||||
* @param string|null $type Тип коррекции
|
||||
* @param string|null $base_date Дата документа
|
||||
* @param string|null $base_number Номер документа
|
||||
* @param string|null $base_name Описание коррекции
|
||||
*/
|
||||
public function __construct(?string $type = null, ?string $base_date = null, ?string $base_number = null, ?string $base_name = null)
|
||||
{
|
||||
if ($type) {
|
||||
$this->setType($type);
|
||||
}
|
||||
if ($base_date) {
|
||||
$this->setDate($base_date);
|
||||
}
|
||||
if ($base_number) {
|
||||
$this->setNumber($base_number);
|
||||
}
|
||||
if ($base_name) {
|
||||
$this->setName($base_name);
|
||||
}
|
||||
public function __construct(
|
||||
?string $type = null,
|
||||
?string $base_date = null,
|
||||
?string $base_number = null
|
||||
) {
|
||||
$type && $this->setType($type);
|
||||
$base_date && $this->setDate($base_date);
|
||||
$base_number && $this->setNumber($base_number);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает номер документа основания для коррекции.
|
||||
* Тег ФФД - 1179.
|
||||
@@ -68,9 +56,9 @@ class CorrectionInfo extends Entity
|
||||
*/
|
||||
public function getNumber(): ?string
|
||||
{
|
||||
return $this->base_name;
|
||||
return $this->base_number;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает номер документа основания для коррекции.
|
||||
* Тег ФФД - 1179.
|
||||
@@ -78,36 +66,12 @@ class CorrectionInfo extends Entity
|
||||
* @param string $number
|
||||
* @return $this
|
||||
*/
|
||||
public function setNumber(string $number)
|
||||
public function setNumber(string $number): CorrectionInfo
|
||||
{
|
||||
$this->base_number = trim($number);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает описание коррекции.
|
||||
* Тег ФФД - 1177.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getName(): ?string
|
||||
{
|
||||
return $this->base_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает описание коррекции.
|
||||
* Тег ФФД - 1177.
|
||||
*
|
||||
* @param string $name
|
||||
* @return $this
|
||||
*/
|
||||
public function setName(string $name)
|
||||
{
|
||||
$this->base_name = trim($name);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает дату документа основания для коррекции.
|
||||
* Тег ФФД - 1178.
|
||||
@@ -118,7 +82,7 @@ class CorrectionInfo extends Entity
|
||||
{
|
||||
return $this->base_date;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает дату документа основания для коррекции.
|
||||
* Тег ФФД - 1178.
|
||||
@@ -126,12 +90,12 @@ class CorrectionInfo extends Entity
|
||||
* @param string $date Строка в формате d.m.Y
|
||||
* @return $this
|
||||
*/
|
||||
public function setDate(string $date)
|
||||
public function setDate(string $date): CorrectionInfo
|
||||
{
|
||||
$this->base_date = $date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает тип коррекции.
|
||||
* Тег ФФД - 1173.
|
||||
@@ -142,7 +106,7 @@ class CorrectionInfo extends Entity
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает тип коррекции.
|
||||
* Тег ФФД - 1173.
|
||||
@@ -150,22 +114,21 @@ class CorrectionInfo extends Entity
|
||||
* @param string $type
|
||||
* @return $this
|
||||
*/
|
||||
public function setType(string $type)
|
||||
public function setType(string $type): CorrectionInfo
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
public function jsonSerialize(): object
|
||||
{
|
||||
return [
|
||||
return (object)[
|
||||
'type' => $this->getType() ?? '', // обязателен
|
||||
'base_date' => $this->getDate() ?? '', // обязателен
|
||||
'base_number' => $this->getNumber() ?? '', // обязателен
|
||||
'base_name' => $this->getName() ?? '' // обязателен
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\Exceptions\AtolCashierTooLongException;
|
||||
use AtolOnline\Constants\Constraints;
|
||||
use AtolOnline\Exceptions\AtolException;
|
||||
use AtolOnline\Exceptions\AtolInvalidJsonException;
|
||||
use AtolOnline\Exceptions\BasicTooManyException;
|
||||
use AtolOnline\Exceptions\InvalidEmailException;
|
||||
use AtolOnline\Exceptions\InvalidInnLengthException;
|
||||
use AtolOnline\Exceptions\InvalidJsonException;
|
||||
use AtolOnline\Exceptions\TooHighPriceException;
|
||||
use AtolOnline\Exceptions\TooLongCashierException;
|
||||
use AtolOnline\Exceptions\TooLongEmailException;
|
||||
use AtolOnline\Exceptions\TooLongNameException;
|
||||
use AtolOnline\Exceptions\TooLongPaymentAddressException;
|
||||
use AtolOnline\Exceptions\TooLongPhoneException;
|
||||
use AtolOnline\Exceptions\TooLongUnitException;
|
||||
use AtolOnline\Exceptions\TooLongUserdataException;
|
||||
use AtolOnline\Exceptions\TooManyItemsException;
|
||||
use AtolOnline\Exceptions\TooManyPaymentsException;
|
||||
use AtolOnline\Exceptions\TooManyVatsException;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Класс, описывающий документ
|
||||
@@ -21,44 +38,44 @@ use AtolOnline\Exceptions\AtolInvalidJsonException;
|
||||
class Document extends Entity
|
||||
{
|
||||
/**
|
||||
* @var \AtolOnline\Entities\ItemArray Массив предметов расчёта
|
||||
* @var ItemArray Массив предметов расчёта
|
||||
*/
|
||||
protected $items;
|
||||
|
||||
protected ItemArray $items;
|
||||
|
||||
/**
|
||||
* @var \AtolOnline\Entities\VatArray Массив ставок НДС
|
||||
* @var VatArray Массив ставок НДС
|
||||
*/
|
||||
protected $vats;
|
||||
|
||||
protected VatArray $vats;
|
||||
|
||||
/**
|
||||
* @var \AtolOnline\Entities\PaymentArray Массив оплат
|
||||
* @var PaymentArray Массив оплат
|
||||
*/
|
||||
protected $payments;
|
||||
|
||||
protected PaymentArray $payments;
|
||||
|
||||
/**
|
||||
* @var \AtolOnline\Entities\Company Объект компании (продавца)
|
||||
* @var Company Объект компании (продавца)
|
||||
*/
|
||||
protected $company;
|
||||
|
||||
protected Company $company;
|
||||
|
||||
/**
|
||||
* @var \AtolOnline\Entities\Client Объект клиента (покупателя)
|
||||
* @var Client Объект клиента (покупателя)
|
||||
*/
|
||||
protected $client;
|
||||
|
||||
protected Client $client;
|
||||
|
||||
/**
|
||||
* @var int Итоговая сумма чека. Тег ФФД - 1020.
|
||||
* @var float Итоговая сумма чека. Тег ФФД - 1020.
|
||||
*/
|
||||
protected $total = 0;
|
||||
protected float $total = 0;
|
||||
|
||||
/**
|
||||
* @var string ФИО кассира. Тег ФФД - 1021.
|
||||
*/
|
||||
protected $cashier;
|
||||
|
||||
protected string $cashier;
|
||||
|
||||
/**
|
||||
* @var \AtolOnline\Entities\CorrectionInfo Данные коррекции
|
||||
* @var CorrectionInfo Данные коррекции
|
||||
*/
|
||||
protected $correction_info;
|
||||
protected CorrectionInfo $correction_info;
|
||||
|
||||
/**
|
||||
* Document constructor.
|
||||
@@ -69,66 +86,65 @@ class Document extends Entity
|
||||
$this->payments = new PaymentArray();
|
||||
$this->items = new ItemArray();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Удаляет все налоги из документа и предметов расчёта
|
||||
*
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException Слишком большая сумма
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws TooManyVatsException Слишком много ставок НДС
|
||||
*/
|
||||
public function clearVats()
|
||||
public function clearVats(): Document
|
||||
{
|
||||
$this->setVats([]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавляет новую ставку НДС в массив ставок НДС
|
||||
*
|
||||
* @param \AtolOnline\Entities\Vat $vat Объект ставки НДС
|
||||
* @param Vat $vat Объект ставки НДС
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws TooManyVatsException Слишком много ставок НДС
|
||||
*/
|
||||
public function addVat(Vat $vat)
|
||||
public function addVat(Vat $vat): Document
|
||||
{
|
||||
$this->vats->add($vat);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает массив ставок НДС
|
||||
*
|
||||
* @return \AtolOnline\Entities\Vat[]
|
||||
* @return Vat[]
|
||||
*/
|
||||
public function getVats(): array
|
||||
{
|
||||
return $this->vats->get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает массив ставок НДС
|
||||
*
|
||||
* @param \AtolOnline\Entities\Vat[] $vats Массив ставок НДС
|
||||
* @param Vat[] $vats Массив ставок НДС
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws \Exception
|
||||
* @throws TooManyVatsException Слишком много ставок НДС
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setVats(array $vats)
|
||||
public function setVats(array $vats): Document
|
||||
{
|
||||
$this->vats->set($vats);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавляет новую оплату в массив оплат
|
||||
*
|
||||
* @param \AtolOnline\Entities\Payment $payment Объект оплаты
|
||||
* @param Payment $payment Объект оплаты
|
||||
* @return $this
|
||||
* @throws \Exception
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException Слишком много оплат
|
||||
* @throws Exception
|
||||
* @throws TooManyPaymentsException Слишком много оплат
|
||||
*/
|
||||
public function addPayment(Payment $payment)
|
||||
public function addPayment(Payment $payment): Document
|
||||
{
|
||||
if (count($this->getPayments()) == 0 && !$payment->getSum()) {
|
||||
$payment->setSum($this->calcTotal());
|
||||
@@ -136,61 +152,61 @@ class Document extends Entity
|
||||
$this->payments->add($payment);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает массив оплат
|
||||
*
|
||||
* @return \AtolOnline\Entities\Payment[]
|
||||
* @return Payment[]
|
||||
*/
|
||||
public function getPayments(): array
|
||||
{
|
||||
return $this->payments->get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает массив оплат
|
||||
*
|
||||
* @param \AtolOnline\Entities\Payment[] $payments Массив оплат
|
||||
* @param Payment[] $payments Массив оплат
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException Слишком много оплат
|
||||
* @throws TooManyPaymentsException Слишком много оплат
|
||||
*/
|
||||
public function setPayments(array $payments)
|
||||
public function setPayments(array $payments): Document
|
||||
{
|
||||
$this->payments->set($payments);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавляет новый предмет расчёта в массив предметов расчёта
|
||||
*
|
||||
* @param \AtolOnline\Entities\Item $item Объект предмета расчёта
|
||||
* @param Item $item Объект предмета расчёта
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws TooManyItemsException Слишком много предметов расчёта
|
||||
*/
|
||||
public function addItem(Item $item)
|
||||
public function addItem(Item $item): Document
|
||||
{
|
||||
$this->items->add($item);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает массив предметов расчёта
|
||||
*
|
||||
* @return \AtolOnline\Entities\Item[]
|
||||
* @return Item[]
|
||||
*/
|
||||
public function getItems(): array
|
||||
{
|
||||
return $this->items->get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает массив предметов расчёта
|
||||
*
|
||||
* @param \AtolOnline\Entities\Item[] $items Массив предметов расчёта
|
||||
* @param Item[] $items Массив предметов расчёта
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws TooManyItemsException Слишком много предметов расчёта
|
||||
*/
|
||||
public function setItems(array $items)
|
||||
public function setItems(array $items): Document
|
||||
{
|
||||
$this->items->set($items);
|
||||
return $this;
|
||||
@@ -212,7 +228,7 @@ class Document extends Entity
|
||||
* @param Client|null $client
|
||||
* @return $this
|
||||
*/
|
||||
public function setClient(?Client $client)
|
||||
public function setClient(?Client $client): Document
|
||||
{
|
||||
$this->client = $client;
|
||||
return $this;
|
||||
@@ -234,7 +250,7 @@ class Document extends Entity
|
||||
* @param Company|null $company
|
||||
* @return $this
|
||||
*/
|
||||
public function setCompany(?Company $company)
|
||||
public function setCompany(?Company $company): Document
|
||||
{
|
||||
$this->company = $company;
|
||||
return $this;
|
||||
@@ -249,53 +265,55 @@ class Document extends Entity
|
||||
{
|
||||
return $this->cashier;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает ФИО кассира. Тег ФФД - 1021.
|
||||
*
|
||||
* @param string|null $cashier
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolCashierTooLongException
|
||||
* @throws TooLongCashierException
|
||||
*/
|
||||
public function setCashier(?string $cashier)
|
||||
public function setCashier(?string $cashier): Document
|
||||
{
|
||||
$cashier = trim($cashier);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($cashier) : strlen($cashier)) > 64) {
|
||||
throw new AtolCashierTooLongException($cashier, 64);
|
||||
if ($cashier !== null) {
|
||||
$cashier = trim($cashier);
|
||||
if (mb_strlen($cashier) > Constraints::MAX_LENGTH_CASHIER_NAME) {
|
||||
throw new TooLongCashierException($cashier, Constraints::MAX_LENGTH_CASHIER_NAME);
|
||||
}
|
||||
}
|
||||
$this->cashier = $cashier;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает данные коррекции
|
||||
*
|
||||
* @return \AtolOnline\Entities\CorrectionInfo|null
|
||||
* @return CorrectionInfo|null
|
||||
*/
|
||||
public function getCorrectionInfo(): ?CorrectionInfo
|
||||
{
|
||||
return $this->correction_info;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает данные коррекции
|
||||
*
|
||||
* @param \AtolOnline\Entities\CorrectionInfo|null $correction_info
|
||||
* @param CorrectionInfo|null $correction_info
|
||||
* @return $this
|
||||
*/
|
||||
public function setCorrectionInfo(?CorrectionInfo $correction_info)
|
||||
public function setCorrectionInfo(?CorrectionInfo $correction_info): Document
|
||||
{
|
||||
$this->correction_info = $correction_info;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Пересчитывает, сохраняет и возвращает итоговую сумму чека по всем позициям (включая НДС). Тег ФФД - 1020.
|
||||
*
|
||||
* @return float
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function calcTotal()
|
||||
public function calcTotal(): float
|
||||
{
|
||||
$sum = 0;
|
||||
$this->clearVats();
|
||||
@@ -315,32 +333,33 @@ class Document extends Entity
|
||||
{
|
||||
return $this->total;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Собирает объект документа из сырой json-строки
|
||||
*
|
||||
* @param string $json
|
||||
* @return \AtolOnline\Entities\Document
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||
* @throws \AtolOnline\Exceptions\AtolException
|
||||
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||
* @throws \AtolOnline\Exceptions\AtolInvalidJsonException
|
||||
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyException
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException
|
||||
* @throws \AtolOnline\Exceptions\AtolUnitTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolUserdataTooLongException
|
||||
* @return Document
|
||||
* @throws TooLongEmailException
|
||||
* @throws InvalidEmailException
|
||||
* @throws AtolException
|
||||
* @throws InvalidInnLengthException
|
||||
* @throws InvalidJsonException
|
||||
* @throws TooLongNameException
|
||||
* @throws TooLongPaymentAddressException
|
||||
* @throws TooLongPhoneException
|
||||
* @throws TooHighPriceException
|
||||
* @throws BasicTooManyException
|
||||
* @throws TooManyItemsException
|
||||
* @throws TooManyPaymentsException
|
||||
* @throws TooLongUnitException
|
||||
* @throws TooLongUserdataException
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function fromRaw(string $json)
|
||||
public static function fromRaw(string $json): Document
|
||||
{
|
||||
$array = json_decode($json, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new AtolInvalidJsonException();
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
$doc = new self();
|
||||
if (isset($array['company'])) {
|
||||
@@ -359,6 +378,14 @@ class Document extends Entity
|
||||
$array['client']['inn'] ?? null
|
||||
));
|
||||
}
|
||||
if (isset($array['correction_info'])) {
|
||||
$doc->setCorrectionInfo(new CorrectionInfo(
|
||||
$array['correction_info']['type'] ?? null,
|
||||
$array['correction_info']['base_date'] ?? null,
|
||||
$array['correction_info']['base_number'] ?? null,
|
||||
$array['correction_info']['base_name'] ?? null,
|
||||
));
|
||||
}
|
||||
if (isset($array['items'])) {
|
||||
foreach ($array['items'] as $ar_item) {
|
||||
$item = new Item(
|
||||
@@ -388,18 +415,30 @@ class Document extends Entity
|
||||
$doc->payments->add($payment);
|
||||
}
|
||||
}
|
||||
if (isset($array['vats'])) {
|
||||
foreach ($array['vats'] as $vat_payment) {
|
||||
$vat = new Vat();
|
||||
if (isset($vat_payment['type'])) {
|
||||
$vat->setType($vat_payment['type']);
|
||||
}
|
||||
if (isset($vat_payment['sum'])) {
|
||||
$vat->setSum($vat_payment['sum']);
|
||||
}
|
||||
$doc->vats->add($vat);
|
||||
}
|
||||
}
|
||||
if (isset($array['total']) && $array['total'] != $doc->calcTotal()) {
|
||||
throw new AtolException('Real total sum not equals to provided in JSON one');
|
||||
}
|
||||
return $doc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает массив для кодирования в json
|
||||
*
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
public function jsonSerialize(): array
|
||||
{
|
||||
if ($this->getCompany()) {
|
||||
$json['company'] = $this->getCompany()->jsonSerialize(); // обязательно
|
||||
@@ -1,28 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use JsonSerializable;
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* Абстрактное описание любой сущности, представляемой как JSON
|
||||
*
|
||||
* @package AtolOnline\Entities
|
||||
* Абстрактное описание любой сущности, представляемой как json
|
||||
*/
|
||||
abstract class Entity implements JsonSerializable
|
||||
abstract class Entity implements JsonSerializable, Stringable
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
* Возвращает строковое представление json-структуры объекта
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return json_encode($this->jsonSerialize(), JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\{Exceptions\AtolNameTooLongException,
|
||||
Exceptions\AtolPriceTooHighException,
|
||||
Exceptions\AtolTooManyException,
|
||||
Exceptions\AtolUnitTooLongException,
|
||||
Exceptions\AtolUserdataTooLongException,
|
||||
Traits\RublesKopeksConverter};
|
||||
use AtolOnline\{
|
||||
Constants\Constraints,
|
||||
Exceptions\BasicTooManyException,
|
||||
Exceptions\TooHighPriceException,
|
||||
Exceptions\TooLongNameException,
|
||||
Exceptions\TooLongUnitException,
|
||||
Exceptions\TooLongUserdataException};
|
||||
|
||||
/**
|
||||
* Предмет расчёта (товар, услуга)
|
||||
@@ -23,74 +26,72 @@ use AtolOnline\{Exceptions\AtolNameTooLongException,
|
||||
*/
|
||||
class Item extends Entity
|
||||
{
|
||||
use RublesKopeksConverter;
|
||||
|
||||
/**
|
||||
* @var string Наименование. Тег ФФД - 1030.
|
||||
*/
|
||||
protected $name;
|
||||
protected string $name;
|
||||
|
||||
/**
|
||||
* @var int Цена в копейках (с учётом скидок и наценок). Тег ФФД - 1079.
|
||||
*/
|
||||
protected $price = 0;
|
||||
protected int $price = 0;
|
||||
|
||||
/**
|
||||
* @var float Количество, вес. Тег ФФД - 1023.
|
||||
*/
|
||||
protected $quantity = 0.0;
|
||||
protected float $quantity = 0.0;
|
||||
|
||||
/**
|
||||
* @var float Сумма в копейках. Тег ФФД - 1043.
|
||||
*/
|
||||
protected $sum = 0;
|
||||
protected float $sum = 0;
|
||||
|
||||
/**
|
||||
* @var string Единица измерения количества. Тег ФФД - 1197.
|
||||
*/
|
||||
protected $measurement_unit;
|
||||
|
||||
protected string $measurement_unit;
|
||||
|
||||
/**
|
||||
* @var Vat Ставка НДС
|
||||
* @var Vat|null Ставка НДС
|
||||
*/
|
||||
protected $vat;
|
||||
protected ?Vat $vat;
|
||||
|
||||
/**
|
||||
* @var string Признак способа расчёта. Тег ФФД - 1214.
|
||||
*/
|
||||
protected $payment_method;
|
||||
protected string $payment_method;
|
||||
|
||||
/**
|
||||
* @var string Признак объекта расчёта. Тег ФФД - 1212.
|
||||
*/
|
||||
protected $payment_object;
|
||||
protected string $payment_object;
|
||||
|
||||
/**
|
||||
* @var string Дополнительный реквизит. Тег ФФД - 1191.
|
||||
*/
|
||||
protected $user_data;
|
||||
|
||||
protected string $user_data;
|
||||
|
||||
/**
|
||||
* Item constructor.
|
||||
*
|
||||
* @param string|null $name Наименование
|
||||
* @param float|null $price Цена за одну единицу
|
||||
* @param float|null $quantity Количество
|
||||
* @param string|null $name Наименование
|
||||
* @param float|null $price Цена за одну единицу
|
||||
* @param float|null $quantity Количество
|
||||
* @param string|null $measurement_unit Единица измерения
|
||||
* @param string|null $vat_type Ставка НДС
|
||||
* @param string|null $payment_object Признак
|
||||
* @param string|null $payment_method Способ расчёта
|
||||
* @throws AtolNameTooLongException Слишком длинное наименование
|
||||
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
|
||||
* @throws AtolTooManyException Слишком большое количество
|
||||
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
|
||||
* @param string|null $vat_type Ставка НДС
|
||||
* @param string|null $payment_object Признак
|
||||
* @param string|null $payment_method Способ расчёта
|
||||
* @throws TooLongNameException Слишком длинное наименование
|
||||
* @throws TooHighPriceException Слишком высокая цена за одну единицу
|
||||
* @throws BasicTooManyException Слишком большое количество
|
||||
* @throws TooLongUnitException Слишком длинное название единицы измерения
|
||||
*/
|
||||
public function __construct(
|
||||
?string $name = null,
|
||||
?float $price = null,
|
||||
?float $quantity = null,
|
||||
?string $measurement_unit = null,
|
||||
$vat_type = null,
|
||||
?string $vat_type = null,
|
||||
?string $payment_object = null,
|
||||
?string $payment_method = null
|
||||
) {
|
||||
@@ -122,23 +123,23 @@ class Item extends Entity
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устаналивает наименование. Тег ФФД - 1030.
|
||||
*
|
||||
* @param string $name Наименование
|
||||
* @return $this
|
||||
* @throws AtolNameTooLongException Слишком длинное имя/наименование
|
||||
* @throws TooLongNameException Слишком длинное имя/наименование
|
||||
*/
|
||||
public function setName(string $name)
|
||||
public function setName(string $name): self
|
||||
{
|
||||
$name = trim($name);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($name) : strlen($name)) > 128) {
|
||||
throw new AtolNameTooLongException($name, 128);
|
||||
if (mb_strlen($name) > Constraints::MAX_LENGTH_ITEM_NAME) {
|
||||
throw new TooLongNameException($name, Constraints::MAX_LENGTH_ITEM_NAME);
|
||||
}
|
||||
$this->name = $name;
|
||||
return $this;
|
||||
@@ -149,24 +150,24 @@ class Item extends Entity
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getPrice()
|
||||
public function getPrice(): float
|
||||
{
|
||||
return self::toRub($this->price);
|
||||
return rubles($this->price);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает цену в рублях. Тег ФФД - 1079.
|
||||
*
|
||||
* @param float $rubles Цена за одну единицу в рублях
|
||||
* @return $this
|
||||
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
|
||||
* @throws TooHighPriceException Слишком высокая цена за одну единицу
|
||||
*/
|
||||
public function setPrice(float $rubles)
|
||||
public function setPrice(float $rubles): Item
|
||||
{
|
||||
if ($rubles > 42949672.95) {
|
||||
throw new AtolPriceTooHighException($rubles, 42949672.95);
|
||||
throw new TooHighPriceException($rubles, 42949672.95);
|
||||
}
|
||||
$this->price = self::toKop($rubles);
|
||||
$this->price = kopeks($rubles);
|
||||
$this->calcSum();
|
||||
return $this;
|
||||
}
|
||||
@@ -180,22 +181,22 @@ class Item extends Entity
|
||||
{
|
||||
return $this->quantity;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает количество. Тег ФФД - 1023.
|
||||
*
|
||||
* @param float $quantity Количество
|
||||
* @param float $quantity Количество
|
||||
* @param string|null $measurement_unit Единица измерения количества
|
||||
* @return $this
|
||||
* @throws AtolTooManyException Слишком большое количество
|
||||
* @throws AtolPriceTooHighException Слишком высокая общая стоимость
|
||||
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
|
||||
* @throws BasicTooManyException Слишком большое количество
|
||||
* @throws TooHighPriceException Слишком высокая общая стоимость
|
||||
* @throws TooLongUnitException Слишком длинное название единицы измерения
|
||||
*/
|
||||
public function setQuantity(float $quantity, string $measurement_unit = null)
|
||||
public function setQuantity(float $quantity, string $measurement_unit = null): Item
|
||||
{
|
||||
$quantity = round($quantity, 3);
|
||||
if ($quantity > 99999.999) {
|
||||
throw new AtolTooManyException($quantity, 99999.999);
|
||||
throw new BasicTooManyException($quantity, 99999.999);
|
||||
}
|
||||
$this->quantity = $quantity;
|
||||
$this->calcSum();
|
||||
@@ -214,19 +215,19 @@ class Item extends Entity
|
||||
{
|
||||
return $this->measurement_unit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает единицу измерения количества. Тег ФФД - 1197.
|
||||
*
|
||||
* @param string $measurement_unit Единица измерения количества
|
||||
* @return $this
|
||||
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
|
||||
* @throws TooLongUnitException Слишком длинное название единицы измерения
|
||||
*/
|
||||
public function setMeasurementUnit(string $measurement_unit)
|
||||
public function setMeasurementUnit(string $measurement_unit): Item
|
||||
{
|
||||
$measurement_unit = trim($measurement_unit);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($measurement_unit) : strlen($measurement_unit)) > 16) {
|
||||
throw new AtolUnitTooLongException($measurement_unit, 16);
|
||||
if (mb_strlen($measurement_unit) > Constraints::MAX_LENGTH_MEASUREMENT_UNIT) {
|
||||
throw new TooLongUnitException($measurement_unit, Constraints::MAX_LENGTH_MEASUREMENT_UNIT);
|
||||
}
|
||||
$this->measurement_unit = $measurement_unit;
|
||||
return $this;
|
||||
@@ -249,7 +250,7 @@ class Item extends Entity
|
||||
* @return $this
|
||||
* @todo Проверка допустимых значений
|
||||
*/
|
||||
public function setPaymentMethod(string $payment_method)
|
||||
public function setPaymentMethod(string $payment_method): Item
|
||||
{
|
||||
$this->payment_method = trim($payment_method);
|
||||
return $this;
|
||||
@@ -272,30 +273,30 @@ class Item extends Entity
|
||||
* @return $this
|
||||
* @todo Проверка допустимых значений
|
||||
*/
|
||||
public function setPaymentObject(string $payment_object)
|
||||
public function setPaymentObject(string $payment_object): Item
|
||||
{
|
||||
$this->payment_object = trim($payment_object);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает ставку НДС
|
||||
*
|
||||
* @return \AtolOnline\Entities\Vat|null
|
||||
* @return Vat|null
|
||||
*/
|
||||
public function getVat(): ?Vat
|
||||
{
|
||||
return $this->vat;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает ставку НДС
|
||||
*
|
||||
* @param string|null $vat_type Тип ставки НДС. Передать null, чтобы удалить ставку.
|
||||
* @return $this
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
|
||||
* @throws TooHighPriceException
|
||||
*/
|
||||
public function setVatType(?string $vat_type)
|
||||
public function setVatType(?string $vat_type): Item
|
||||
{
|
||||
if ($vat_type) {
|
||||
$this->vat
|
||||
@@ -317,19 +318,19 @@ class Item extends Entity
|
||||
{
|
||||
return $this->user_data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает дополнительный реквизит. Тег ФФД - 1191.
|
||||
*
|
||||
* @param string $user_data Дополнительный реквизит. Тег ФФД - 1191.
|
||||
* @return $this
|
||||
* @throws AtolUserdataTooLongException Слишком длинный дополнительный реквизит
|
||||
* @throws TooLongUserdataException Слишком длинный дополнительный реквизит
|
||||
*/
|
||||
public function setUserData(string $user_data)
|
||||
public function setUserData(string $user_data): self
|
||||
{
|
||||
$user_data = trim($user_data);
|
||||
if ((function_exists('mb_strlen') ? mb_strlen($user_data) : strlen($user_data)) > 64) {
|
||||
throw new AtolUserdataTooLongException($user_data, 64);
|
||||
if (mb_strlen($user_data) > Constraints::MAX_LENGTH_USER_DATA) {
|
||||
throw new TooLongUserdataException($user_data, Constraints::MAX_LENGTH_USER_DATA);
|
||||
}
|
||||
$this->user_data = $user_data;
|
||||
return $this;
|
||||
@@ -342,24 +343,24 @@ class Item extends Entity
|
||||
*/
|
||||
public function getSum(): float
|
||||
{
|
||||
return self::toRub($this->sum);
|
||||
return rubles($this->sum);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Расчитывает стоимость и размер НДС на неё
|
||||
*
|
||||
* @return float
|
||||
* @throws AtolPriceTooHighException Слишком большая сумма
|
||||
* @throws TooHighPriceException Слишком большая сумма
|
||||
*/
|
||||
public function calcSum()
|
||||
public function calcSum(): float
|
||||
{
|
||||
$sum = $this->quantity * $this->price;
|
||||
if (self::toRub($sum) > 42949672.95) {
|
||||
throw new AtolPriceTooHighException($sum, 42949672.95);
|
||||
if (rubles($sum) > 42949672.95) {
|
||||
throw new TooHighPriceException($sum, 42949672.95);
|
||||
}
|
||||
$this->sum = $sum;
|
||||
if ($this->vat) {
|
||||
$this->vat->setSum(self::toRub($sum));
|
||||
$this->vat->setSum(rubles($sum));
|
||||
}
|
||||
return $this->getSum();
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\Exceptions\AtolTooManyItemsException;
|
||||
use AtolOnline\Exceptions\TooManyItemsException;
|
||||
|
||||
/**
|
||||
* Класс, описывающий массив предметов расчёта
|
||||
@@ -28,13 +30,13 @@ class ItemArray extends Entity
|
||||
/**
|
||||
* @var Item[] Массив предметов расчёта
|
||||
*/
|
||||
private $items = [];
|
||||
|
||||
private array $items = [];
|
||||
|
||||
/**
|
||||
* ItemArray constructor.
|
||||
*
|
||||
* @param Item[]|null $items Массив предметов расчёта
|
||||
* @throws AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws TooManyItemsException Слишком много предметов расчёта
|
||||
*/
|
||||
public function __construct(?array $items = null)
|
||||
{
|
||||
@@ -42,30 +44,30 @@ class ItemArray extends Entity
|
||||
$this->set($items);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает массив предметов расчёта
|
||||
*
|
||||
* @param Item[] $items Массив предметов расчёта
|
||||
* @return $this
|
||||
* @throws AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws TooManyItemsException Слишком много предметов расчёта
|
||||
*/
|
||||
public function set(array $items)
|
||||
public function set(array $items): ItemArray
|
||||
{
|
||||
if ($this->validateCount($items)) {
|
||||
$this->items = $items;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавляет предмет расчёта в массив
|
||||
*
|
||||
* @param Item $item Объект предмета расчёта
|
||||
* @return $this
|
||||
* @throws AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws TooManyItemsException Слишком много предметов расчёта
|
||||
*/
|
||||
public function add(Item $item)
|
||||
public function add(Item $item): ItemArray
|
||||
{
|
||||
if ($this->validateCount()) {
|
||||
$this->items[] = $item;
|
||||
@@ -78,7 +80,7 @@ class ItemArray extends Entity
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function get()
|
||||
public function get(): array
|
||||
{
|
||||
return $this->items;
|
||||
}
|
||||
@@ -94,19 +96,19 @@ class ItemArray extends Entity
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Проверяет количество предметов расчёта
|
||||
*
|
||||
* @param Item[]|null $items Если передать массив, то проверит количество его элементов.
|
||||
* Иначе проверит количество уже присвоенных элементов.
|
||||
* @return bool true если всё хорошо, иначе выбрасывает исключение
|
||||
* @throws AtolTooManyItemsException Слишком много предметов расчёта
|
||||
* @throws TooManyItemsException Слишком много предметов расчёта
|
||||
*/
|
||||
protected function validateCount(?array $items = null): bool
|
||||
{
|
||||
if ((!empty($items) && count($items) >= self::MAX_COUNT) || count($this->items) >= self::MAX_COUNT) {
|
||||
throw new AtolTooManyItemsException(count($items), self::MAX_COUNT);
|
||||
throw new TooManyItemsException(count($items), self::MAX_COUNT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
149
src/Entities/Kkt.php
Normal file
149
src/Entities/Kkt.php
Normal file
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\Exceptions\EmptyMonitorDataException;
|
||||
use AtolOnline\Exceptions\NotEnoughMonitorDataException;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Класс сущности ККТ, получаемой от монитора
|
||||
*
|
||||
* @property string|null serialNumber Заводской номер ККТ
|
||||
* @property string|null registrationNumber Регистрационный номер машины (РНМ)
|
||||
* @property string|null deviceNumber Номер автоматического устройства (внутренний идентификатор устройства)
|
||||
* @property DateTime|string|null fiscalizationDate Дата активации (фискализации) ФН с указанием таймзоны
|
||||
* @property DateTime|string|null fiscalStorageExpiration Дата замены ФН (Срок действия ФН), с указанием таймзоны
|
||||
* @property int|null signedDocuments Количество подписанных документов в ФН
|
||||
* @property float|null fiscalStoragePercentageUse Наполненость ФН в %
|
||||
* @property string|null fiscalStorageINN ИНН компании (указанный в ФН)
|
||||
* @property string|null fiscalStorageSerialNumber Заводской (серийный) номер ФН
|
||||
* @property string|null fiscalStoragePaymentAddress Адрес расчёта, указанный в ФН
|
||||
* @property string|null groupCode Код группы кассы
|
||||
* @property DateTime|string|null timestamp Время и дата формирования данных, UTC
|
||||
* @property bool|null isShiftOpened Признак открыта смена (true) или закрыта (false)
|
||||
* @property int|null shiftNumber Номер смены (или "Номер закрытой смены", когда смена закрыта)
|
||||
* @property int|null shiftReceipt Номер документа за смену (или "Кол-во чеков закрытой смены", когда смена закрыта)
|
||||
* @property int|null unsentDocs Количество неотправленных документов. Указывается, если значение отлично от 0.
|
||||
* @property DateTime|string|null firstUnsetDocTimestamp Дата первого неотправленного документа. Указывается, если
|
||||
* есть неотправленные документы.
|
||||
* @property int|null networkErrorCode Код ошибки сети
|
||||
* @see https://online.atol.ru/files/API_service_information.pdf Документация, стр 11
|
||||
*/
|
||||
final class Kkt extends Entity
|
||||
{
|
||||
/**
|
||||
* Сопоставление кодов сетевых ошибок ККТ с их описаниями
|
||||
*/
|
||||
public const ERROR_CODES = [
|
||||
0 => 'Нет ошибок',
|
||||
1 => 'Отсутствует физический канал связи',
|
||||
2 => 'Ошибка сетевых настроек или нет соединения с сервером ОФД',
|
||||
3 => 'Разрыв соединения при передаче документа на сервер',
|
||||
4 => 'Некорректный заголовок сессионного пакета',
|
||||
5 => 'Превышен таймаут ожидания квитанции',
|
||||
6 => 'Разрыв соединения при приеме квитанции',
|
||||
7 => 'Превышен таймаут передачи документа на сервер',
|
||||
8 => 'ОФД-процесс не иницилизирован',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string[] Список обязательных атрибутов
|
||||
*/
|
||||
private array $properties = [
|
||||
'serialNumber',
|
||||
'registrationNumber',
|
||||
'deviceNumber',
|
||||
'fiscalizationDate',
|
||||
'fiscalStorageExpiration',
|
||||
'signedDocuments',
|
||||
'fiscalStoragePercentageUse',
|
||||
'fiscalStorageINN',
|
||||
'fiscalStorageSerialNumber',
|
||||
'fiscalStoragePaymentAddress',
|
||||
'groupCode',
|
||||
'timestamp',
|
||||
'isShiftOpened',
|
||||
'shiftNumber',
|
||||
'shiftReceipt',
|
||||
//'unsentDocs',
|
||||
//'firstUnsetDocTimestamp',
|
||||
'networkErrorCode',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var string[] Массив атрибутов, которые кастуются к DateTime
|
||||
*/
|
||||
private array $timestamps = [
|
||||
'fiscalizationDate',
|
||||
'fiscalStorageExpiration',
|
||||
'firstUnsetDocTimestamp',
|
||||
'timestamp',
|
||||
];
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
*/
|
||||
public function __construct(protected \stdClass $data)
|
||||
{
|
||||
if (empty((array)$data)) {
|
||||
throw new EmptyMonitorDataException();
|
||||
}
|
||||
$diff = array_diff($this->properties, array_keys((array)$data));
|
||||
if (count($diff) !== 0) {
|
||||
throw new NotEnoughMonitorDataException($diff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Эмулирует обращение к атрибутам
|
||||
*
|
||||
* @param string $name
|
||||
* @return null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get(string $name)
|
||||
{
|
||||
if (empty($this->data?->$name)) {
|
||||
return null;
|
||||
}
|
||||
if (in_array($name, $this->timestamps)) {
|
||||
return new DateTime($this->data->$name);
|
||||
}
|
||||
return $this->data->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает объект с информацией о сетевой ошибке
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function getNetworkError(): object
|
||||
{
|
||||
return (object)[
|
||||
'code' => $this->data->networkErrorCode,
|
||||
'text' => self::ERROR_CODES[$this->data->networkErrorCode],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\Constants\PaymentTypes;
|
||||
use AtolOnline\Enums\PaymentTypes;
|
||||
|
||||
/**
|
||||
* Класс, описывающий оплату. Тег ФФД - 1031, 1081, 1215, 1216, 1217.
|
||||
@@ -21,12 +23,12 @@ class Payment extends Entity
|
||||
/**
|
||||
* @var int Тип оплаты
|
||||
*/
|
||||
protected $type;
|
||||
protected int $type;
|
||||
|
||||
/**
|
||||
* @var float Сумма оплаты
|
||||
*/
|
||||
protected $sum;
|
||||
protected float $sum;
|
||||
|
||||
/**
|
||||
* Payment constructor.
|
||||
@@ -56,7 +58,7 @@ class Payment extends Entity
|
||||
* @param int $type
|
||||
* @return $this
|
||||
*/
|
||||
public function setType(int $type)
|
||||
public function setType(int $type): Payment
|
||||
{
|
||||
$this->type = $type;
|
||||
return $this;
|
||||
@@ -78,7 +80,7 @@ class Payment extends Entity
|
||||
* @param float $sum
|
||||
* @return $this
|
||||
*/
|
||||
public function setSum(float $sum)
|
||||
public function setSum(float $sum): Payment
|
||||
{
|
||||
$this->sum = $sum;
|
||||
return $this;
|
||||
@@ -1,15 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\Exceptions\AtolTooManyPaymentsException;
|
||||
use AtolOnline\Exceptions\TooManyPaymentsException;
|
||||
|
||||
/**
|
||||
* Класс, описывающий массив оплат
|
||||
@@ -26,13 +28,13 @@ class PaymentArray extends Entity
|
||||
/**
|
||||
* @var Payment[] Массив оплат
|
||||
*/
|
||||
private $payments = [];
|
||||
|
||||
private array $payments = [];
|
||||
|
||||
/**
|
||||
* ItemArray constructor.
|
||||
*
|
||||
* @param Payment[]|null $payments Массив оплат
|
||||
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||
* @throws TooManyPaymentsException Слишком много оплат
|
||||
*/
|
||||
public function __construct(?array $payments = null)
|
||||
{
|
||||
@@ -40,30 +42,30 @@ class PaymentArray extends Entity
|
||||
$this->set($payments);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает массив оплат
|
||||
*
|
||||
* @param Payment[] $payments
|
||||
* @return $this
|
||||
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||
* @throws TooManyPaymentsException Слишком много оплат
|
||||
*/
|
||||
public function set(array $payments)
|
||||
public function set(array $payments): PaymentArray
|
||||
{
|
||||
if ($this->validateCount($payments)) {
|
||||
$this->payments = $payments;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавляет новую оплату к заданным
|
||||
*
|
||||
* @param Payment $payment Объект оплаты
|
||||
* @return $this
|
||||
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||
* @throws TooManyPaymentsException Слишком много оплат
|
||||
*/
|
||||
public function add(Payment $payment)
|
||||
public function add(Payment $payment): PaymentArray
|
||||
{
|
||||
if ($this->validateCount()) {
|
||||
$this->payments[] = $payment;
|
||||
@@ -76,7 +78,7 @@ class PaymentArray extends Entity
|
||||
*
|
||||
* @return Payment[]
|
||||
*/
|
||||
public function get()
|
||||
public function get(): array
|
||||
{
|
||||
return $this->payments;
|
||||
}
|
||||
@@ -92,19 +94,19 @@ class PaymentArray extends Entity
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Проверяет количество налоговых ставок
|
||||
*
|
||||
* @param Payment[]|null $payments Если передать массив, то проверит количество его элементов.
|
||||
* Иначе проверит количество уже присвоенных элементов.
|
||||
* @return bool true если всё хорошо, иначе выбрасывает исключение
|
||||
* @throws AtolTooManyPaymentsException Слишком много оплат
|
||||
* @throws TooManyPaymentsException Слишком много оплат
|
||||
*/
|
||||
protected function validateCount(?array $payments = null): bool
|
||||
{
|
||||
if ((!empty($payments) && count($payments) >= self::MAX_COUNT) || count($this->payments) >= self::MAX_COUNT) {
|
||||
throw new AtolTooManyPaymentsException(count($payments), self::MAX_COUNT);
|
||||
throw new TooManyPaymentsException(count($payments), self::MAX_COUNT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,15 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\{Constants\VatTypes, Traits\RublesKopeksConverter};
|
||||
use AtolOnline\Enums\VatTypes;
|
||||
|
||||
/**
|
||||
* Класс, описывающий ставку НДС
|
||||
@@ -18,22 +20,20 @@ use AtolOnline\{Constants\VatTypes, Traits\RublesKopeksConverter};
|
||||
*/
|
||||
class Vat extends Entity
|
||||
{
|
||||
use RublesKopeksConverter;
|
||||
|
||||
/**
|
||||
* @var string Выбранный тип ставки НДС. Тег ФФД - 1199, 1105, 1104, 1103, 1102, 1107, 1106.
|
||||
*/
|
||||
private $type;
|
||||
private string $type;
|
||||
|
||||
/**
|
||||
* @var int Сумма в копейках, от которой пересчитывается размер НДС
|
||||
*/
|
||||
private $sum_original = 0;
|
||||
private int $sum_original = 0;
|
||||
|
||||
/**
|
||||
* @var int Сумма НДС в копейках
|
||||
*/
|
||||
private $sum_final = 0;
|
||||
private int $sum_final = 0;
|
||||
|
||||
/**
|
||||
* Vat constructor.
|
||||
@@ -50,7 +50,8 @@ class Vat extends Entity
|
||||
}
|
||||
|
||||
/**
|
||||
* Устанавливает размер НДС от суммы в копейках
|
||||
* Устанавливает:
|
||||
* размер НДС от суммы в копейках
|
||||
*
|
||||
* @param string $type Тип ставки НДС
|
||||
* @param int $kopeks Копейки
|
||||
@@ -98,7 +99,7 @@ class Vat extends Entity
|
||||
* @param string $type Тип ставки НДС
|
||||
* @return $this
|
||||
*/
|
||||
public function setType(string $type)
|
||||
public function setType(string $type): Vat
|
||||
{
|
||||
$this->type = $type;
|
||||
$this->setFinal();
|
||||
@@ -110,9 +111,9 @@ class Vat extends Entity
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getFinalSum()
|
||||
public function getFinalSum(): float
|
||||
{
|
||||
return self::toRub($this->sum_final);
|
||||
return rubles($this->sum_final);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,9 +123,9 @@ class Vat extends Entity
|
||||
* @param float $rubles Сумма в рублях за предмет расчёта, из которой высчитывается размер НДС
|
||||
* @return $this
|
||||
*/
|
||||
public function setSum(float $rubles)
|
||||
public function setSum(float $rubles): Vat
|
||||
{
|
||||
$this->sum_original = self::toKop($rubles);
|
||||
$this->sum_original = kopeks($rubles);
|
||||
$this->setFinal();
|
||||
return $this;
|
||||
}
|
||||
@@ -136,7 +137,7 @@ class Vat extends Entity
|
||||
*/
|
||||
public function getSum(): float
|
||||
{
|
||||
return self::toRub($this->sum_original);
|
||||
return rubles($this->sum_original);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,9 +147,9 @@ class Vat extends Entity
|
||||
* @param float $rubles
|
||||
* @return $this
|
||||
*/
|
||||
public function addSum(float $rubles)
|
||||
public function addSum(float $rubles): Vat
|
||||
{
|
||||
$this->sum_original += self::toKop($rubles);
|
||||
$this->sum_original += kopeks($rubles);
|
||||
$this->setFinal();
|
||||
return $this;
|
||||
}
|
||||
@@ -162,7 +163,7 @@ class Vat extends Entity
|
||||
*/
|
||||
public function calc(float $rubles): float
|
||||
{
|
||||
return self::toRub(self::calculator($this->type, self::toKop($rubles)));
|
||||
return rubles(self::calculator($this->type, kopeks($rubles)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -179,7 +180,7 @@ class Vat extends Entity
|
||||
/**
|
||||
* Расчитывает и устанавливает итоговый размер ставки от исходной суммы в копейках
|
||||
*/
|
||||
protected function setFinal()
|
||||
protected function setFinal(): Vat
|
||||
{
|
||||
$this->sum_final = self::calculator($this->type, $this->sum_original);
|
||||
return $this;
|
||||
@@ -1,15 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Entities;
|
||||
|
||||
use AtolOnline\Exceptions\AtolTooManyVatsException;
|
||||
use AtolOnline\Exceptions\TooManyVatsException;
|
||||
|
||||
/**
|
||||
* Класс, описывающий массив ставок НДС
|
||||
@@ -26,13 +28,13 @@ class VatArray extends Entity
|
||||
/**
|
||||
* @var Vat[] Массив ставок НДС
|
||||
*/
|
||||
private $vats = [];
|
||||
|
||||
private array $vats = [];
|
||||
|
||||
/**
|
||||
* VatArray constructor.
|
||||
*
|
||||
* @param Vat[]|null $vats Массив ставок НДС
|
||||
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws TooManyVatsException Слишком много ставок НДС
|
||||
*/
|
||||
public function __construct(?array $vats = null)
|
||||
{
|
||||
@@ -40,30 +42,30 @@ class VatArray extends Entity
|
||||
$this->set($vats);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Устанавливает массив ставок НДС
|
||||
*
|
||||
* @param Vat[] $vats Массив ставок НДС
|
||||
* @return $this
|
||||
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws TooManyVatsException Слишком много ставок НДС
|
||||
*/
|
||||
public function set(array $vats)
|
||||
public function set(array $vats): VatArray
|
||||
{
|
||||
if ($this->validateCount($vats)) {
|
||||
$this->vats = $vats;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Добавляет новую ставку НДС в массив
|
||||
*
|
||||
* @param Vat $vat Объект ставки НДС
|
||||
* @return $this
|
||||
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws TooManyVatsException Слишком много ставок НДС
|
||||
*/
|
||||
public function add(Vat $vat)
|
||||
public function add(Vat $vat): VatArray
|
||||
{
|
||||
if ($this->validateCount()) {
|
||||
if (isset($this->vats[$vat->getType()])) {
|
||||
@@ -80,7 +82,7 @@ class VatArray extends Entity
|
||||
*
|
||||
* @return Vat[]
|
||||
*/
|
||||
public function get()
|
||||
public function get(): array
|
||||
{
|
||||
return $this->vats;
|
||||
}
|
||||
@@ -96,19 +98,19 @@ class VatArray extends Entity
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Проверяет количество налоговых ставок
|
||||
*
|
||||
* @param Vat[]|null $vats Если передать массив, то проверит количество его элементов.
|
||||
* Иначе проверит количество уже присвоенных элементов.
|
||||
* @return bool true если всё хорошо, иначе выбрасывает исключение
|
||||
* @throws AtolTooManyVatsException Слишком много ставок НДС
|
||||
* @throws TooManyVatsException Слишком много ставок НДС
|
||||
*/
|
||||
protected function validateCount(?array $vats = null): bool
|
||||
{
|
||||
if ((!empty($vats) && count($vats) >= self::MAX_COUNT) || count($this->vats) >= self::MAX_COUNT) {
|
||||
throw new AtolTooManyVatsException(count($vats), self::MAX_COUNT);
|
||||
throw new TooManyVatsException(count($vats), self::MAX_COUNT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,28 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие типы документов коррекции
|
||||
*
|
||||
* @package AtolOnline\Constants
|
||||
* Тег ФФД - 1173
|
||||
*
|
||||
* @see https://online.atol.ru/files/API_atol_online_v4.pdf Документация, стр 35 (correction_info)
|
||||
*/
|
||||
class CorrectionTypes
|
||||
final class CorrectionTypes extends Enum
|
||||
{
|
||||
/**
|
||||
* Самостоятельно
|
||||
*/
|
||||
const SELF = 'self';
|
||||
|
||||
|
||||
/**
|
||||
* По предписанию
|
||||
*/
|
||||
const INSTRUCTION = 'instruction';
|
||||
}
|
||||
}
|
||||
30
src/Enums/DocumentTypes.php
Normal file
30
src/Enums/DocumentTypes.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие типы документов
|
||||
*/
|
||||
final class DocumentTypes extends Enum
|
||||
{
|
||||
/**
|
||||
* Чек прихода, возврата прихода, расхода, возврата расхода
|
||||
*/
|
||||
const RECEIPT = 'receipt';
|
||||
|
||||
/**
|
||||
* Чек коррекции
|
||||
*/
|
||||
const CORRECTION = 'correction';
|
||||
}
|
||||
@@ -1,54 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие признаки способов расчёта. Тег ФФД - 1214.
|
||||
* Константы, определяющие признаки способов расчёта
|
||||
*
|
||||
* @package AtolOnline\Constants
|
||||
* Тег ФФД - 1214
|
||||
*
|
||||
* @see https://online.atol.ru/files/API_atol_online_v4.pdf Документация, стр 22 (payment_method)
|
||||
*/
|
||||
class PaymentMethods
|
||||
final class PaymentMethods extends Enum
|
||||
{
|
||||
/**
|
||||
* Предоплата 100% до передачи предмета расчёта
|
||||
*/
|
||||
const FULL_PREPAYMENT = 'full_prepayment';
|
||||
|
||||
|
||||
/**
|
||||
* Частичная предоплата до передачи предмета расчёта
|
||||
*/
|
||||
const PREPAYMENT = 'prepayment';
|
||||
|
||||
|
||||
/**
|
||||
* Аванс
|
||||
*/
|
||||
const ADVANCE = 'advance';
|
||||
|
||||
|
||||
/**
|
||||
* Полная оплата с учётом аванса/предоплаты в момент передачи предмета расчёта
|
||||
*/
|
||||
const FULL_PAYMENT = 'full_payment';
|
||||
|
||||
|
||||
/**
|
||||
* Частичный расчёт в момент передачи предмета расчёта (дальнейшая оплата в кредит)
|
||||
*/
|
||||
const PARTIAL_PAYMENT = 'partial_payment';
|
||||
|
||||
|
||||
/**
|
||||
* Передача предмета расчёта в кредит
|
||||
*/
|
||||
const CREDIT = 'credit';
|
||||
|
||||
|
||||
/**
|
||||
* Оплата кредита
|
||||
*/
|
||||
const CREDIT_PAYMENT = 'credit_payment';
|
||||
|
||||
}
|
||||
@@ -1,108 +1,161 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие признаки предметов расчёта. Тег ФФД - 1212.
|
||||
* Константы, определяющие признаки предметов расчёта
|
||||
*
|
||||
* @package AtolOnline\Constants
|
||||
* Тег ФФД - 1212
|
||||
*
|
||||
* @see https://online.atol.ru/files/API_atol_online_v4.pdf Документация, стр 23 (payment_object)
|
||||
*/
|
||||
class PaymentObjects
|
||||
final class PaymentObjects extends Enum
|
||||
{
|
||||
/**
|
||||
* Товар, кроме подакцизного
|
||||
*/
|
||||
const COMMODITY = 'commodity';
|
||||
|
||||
|
||||
/**
|
||||
* Товар подакцизный
|
||||
*/
|
||||
const EXCISE = 'excise';
|
||||
|
||||
|
||||
/**
|
||||
* Работа
|
||||
*/
|
||||
const JOB = 'job';
|
||||
|
||||
|
||||
/**
|
||||
* Услуга
|
||||
*/
|
||||
const SERVICE = 'service';
|
||||
|
||||
|
||||
/**
|
||||
* Ставка азартной игры
|
||||
*/
|
||||
const GAMBLING_BET = 'gambling_bet';
|
||||
|
||||
|
||||
/**
|
||||
* Выигрыш азартной игры
|
||||
*/
|
||||
const GAMBLING_PRIZE = 'gambling_prize';
|
||||
|
||||
|
||||
/**
|
||||
* Лотерея
|
||||
*/
|
||||
const LOTTERY = 'lottery';
|
||||
|
||||
|
||||
/**
|
||||
* Выигрыш лотереи
|
||||
*/
|
||||
const LOTTERY_PRIZE = 'lottery_prize';
|
||||
|
||||
|
||||
/**
|
||||
* Предоставление результатов интеллектуальной деятельности
|
||||
*/
|
||||
const INTELLECTUAL_ACTIVITY = 'intellectual_activity';
|
||||
|
||||
|
||||
/**
|
||||
* Платёж (задаток, кредит, аванс, предоплата, пеня, штраф, бонус и пр.)
|
||||
*/
|
||||
const PAYMENT = 'payment';
|
||||
|
||||
|
||||
/**
|
||||
* Агентское вознаграждение
|
||||
*/
|
||||
const AGENT_COMMISSION = 'agent_commission';
|
||||
|
||||
|
||||
/**
|
||||
* Составной предмет расчёта
|
||||
* @deprecated Более не используется согласно ФФД 1.05
|
||||
* @see https://online.atol.ru/files/API_atol_online_v4.pdf Документация, стр 25 (payment_object)
|
||||
*/
|
||||
const COMPOSITE = 'composite';
|
||||
|
||||
|
||||
/**
|
||||
* Другой предмет расчёта
|
||||
*/
|
||||
const ANOTHER = 'another';
|
||||
|
||||
|
||||
/**
|
||||
* Имущественное право
|
||||
*/
|
||||
const PROPERTY_RIGHT = 'property_right';
|
||||
|
||||
|
||||
/**
|
||||
* Внереализационный доход
|
||||
*/
|
||||
const NON_OPERATING_GAIN = 'non-operating_gain';
|
||||
|
||||
|
||||
/**
|
||||
* Страховые взносы
|
||||
*/
|
||||
const INSURANCE_PREMIUM = 'insurance_premium';
|
||||
|
||||
|
||||
/**
|
||||
* Торговый сбор
|
||||
*/
|
||||
const SALES_TAX = 'sales_tax';
|
||||
|
||||
|
||||
/**
|
||||
* Курортный сбор
|
||||
*/
|
||||
const RESORT_FEE = 'resort_fee';
|
||||
|
||||
/**
|
||||
* Взнос в счёт оплаты пени, штрафе, вознаграждении, бонусе и ином аналогичном предмете расчета
|
||||
*/
|
||||
const AWARD = 'award';
|
||||
|
||||
/**
|
||||
* Залог
|
||||
*/
|
||||
const DEPOSIT = 'deposit';
|
||||
|
||||
/**
|
||||
* Расход, уменьшающий доход (в соответствии со статьей 346.16 НК РФ)
|
||||
*/
|
||||
const EXPENSE = 'expense';
|
||||
|
||||
/**
|
||||
* Взнос на ОПС ИП
|
||||
*/
|
||||
const PEN_INSURANCE_IP = 'pension_insurance_ip';
|
||||
|
||||
/**
|
||||
* Взнос на ОПС
|
||||
*/
|
||||
const PEN_INSURANCE = 'pension_insurance';
|
||||
|
||||
/**
|
||||
* Взнос на ОМС ИП
|
||||
*/
|
||||
const MED_INSURANCE_IP = 'medical_insurance_ip';
|
||||
|
||||
/**
|
||||
* Взнос на ОМС
|
||||
*/
|
||||
const MED_INSURANCE = 'medical_insurance';
|
||||
|
||||
/**
|
||||
* Взнос на ОСС
|
||||
*/
|
||||
const SOC_INSURANCE = 'social_insurance';
|
||||
|
||||
/**
|
||||
* Платёж казино
|
||||
*/
|
||||
const CASINO_PAYMENT = 'casino_payment';
|
||||
}
|
||||
77
src/Enums/PaymentTypes.php
Normal file
77
src/Enums/PaymentTypes.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие виды оплат
|
||||
*
|
||||
* Теги ФФД: 1031, 1081, 1215, 1216, 1217
|
||||
*/
|
||||
final class PaymentTypes extends Enum
|
||||
{
|
||||
/**
|
||||
* Расчёт наличными. Тег ФФД - 1031.
|
||||
*/
|
||||
const CASH = 0;
|
||||
|
||||
/**
|
||||
* Расчёт безналичными. Тег ФФД - 1081.
|
||||
*/
|
||||
const ELECTRON = 1;
|
||||
|
||||
/**
|
||||
* Предварительная оплата (зачёт аванса). Тег ФФД - 1215.
|
||||
*/
|
||||
const PRE_PAID = 2;
|
||||
|
||||
/**
|
||||
* Предварительная оплата (кредит). Тег ФФД - 1216.
|
||||
*/
|
||||
const CREDIT = 3;
|
||||
|
||||
/**
|
||||
* Иная форма оплаты (встречное предоставление). Тег ФФД - 1217.
|
||||
*/
|
||||
const OTHER = 4;
|
||||
|
||||
/**
|
||||
* Расширенный типы оплаты (5)
|
||||
* Для каждого фискального типа оплаты можно указать расширенный тип оплаты
|
||||
*/
|
||||
const ADD_5 = 5;
|
||||
|
||||
/**
|
||||
* Расширенный типы оплаты (6)
|
||||
* Для каждого фискального типа оплаты можно указать расширенный тип оплаты
|
||||
*/
|
||||
const ADD_6 = 6;
|
||||
|
||||
/**
|
||||
* Расширенный типы оплаты (7)
|
||||
* Для каждого фискального типа оплаты можно указать расширенный тип оплаты
|
||||
*/
|
||||
const ADD_7 = 7;
|
||||
|
||||
/**
|
||||
* Расширенный типы оплаты (8)
|
||||
* Для каждого фискального типа оплаты можно указать расширенный тип оплаты
|
||||
*/
|
||||
const ADD_8 = 8;
|
||||
|
||||
/**
|
||||
* Расширенный типы оплаты (9)
|
||||
* Для каждого фискального типа оплаты можно указать расширенный тип оплаты
|
||||
*/
|
||||
const ADD_9 = 9;
|
||||
}
|
||||
@@ -1,48 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие типы операций (чеков)
|
||||
*
|
||||
* @package AtolOnline\Constants
|
||||
*/
|
||||
class ReceiptOperationTypes
|
||||
final class ReceiptOperationTypes extends Enum
|
||||
{
|
||||
/**
|
||||
* Приход (мы продали)
|
||||
*/
|
||||
const SELL = 'sell';
|
||||
|
||||
|
||||
/**
|
||||
* Возврат прихода (нам вернули предмет расчёта, мы вернули деньги)
|
||||
* Возврат прихода (нам вернули предмет расчёта, мы вернули средства)
|
||||
*/
|
||||
const SELL_REFUND = 'sell_refund';
|
||||
|
||||
|
||||
/**
|
||||
* Коррекция прихода
|
||||
*/
|
||||
const SELL_CORRECTION = 'sell_correction';
|
||||
|
||||
|
||||
/**
|
||||
* Расход (мы купили)
|
||||
*/
|
||||
const BUY = 'buy';
|
||||
|
||||
|
||||
/**
|
||||
* Возврат расхода (мы вернули предмет расчёта, нам вернули деньги)
|
||||
* Возврат расхода (мы вернули предмет расчёта, нам вернули средства)
|
||||
*/
|
||||
const BUY_REFUND = 'buy_refund';
|
||||
|
||||
|
||||
/**
|
||||
* Коррекция прихода
|
||||
* Коррекция прихода (догоняем неучтённые средства)
|
||||
*/
|
||||
const BUY_CORRECTION = 'buy_correction';
|
||||
}
|
||||
@@ -1,46 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие типы налогообложения
|
||||
*
|
||||
* @package AtolOnline\Constants
|
||||
* Тег ФДД - 1055
|
||||
*/
|
||||
class SnoTypes
|
||||
final class SnoTypes extends Enum
|
||||
{
|
||||
/**
|
||||
* Общая СН
|
||||
*/
|
||||
const OSN = 'osn';
|
||||
|
||||
|
||||
/**
|
||||
* Упрощенная СН (доходы)
|
||||
*/
|
||||
const USN_INCOME = 'usn_income';
|
||||
|
||||
|
||||
/**
|
||||
* Упрощенная СН (доходы минус расходы)
|
||||
*/
|
||||
const USN_INCOME_OUTCOME = 'usn_income_outcome';
|
||||
|
||||
|
||||
/**
|
||||
* Единый налог на вмененный доход
|
||||
*/
|
||||
const ENDV = 'envd';
|
||||
|
||||
|
||||
/**
|
||||
* Единый сельскохозяйственный налог
|
||||
*/
|
||||
const ESN = 'esn';
|
||||
|
||||
|
||||
/**
|
||||
* Патентная СН
|
||||
*/
|
||||
@@ -1,56 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline\Constants;
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Enums;
|
||||
|
||||
use MyCLabs\Enum\Enum;
|
||||
|
||||
/**
|
||||
* Константы, определяющие типы ставок НДС
|
||||
*
|
||||
* @package AtolOnline\Constants
|
||||
* Теги ФФД: 1199, 1105, 1104, 1103, 1102, 1107, 1106
|
||||
*/
|
||||
class VatTypes
|
||||
final class VatTypes extends Enum
|
||||
{
|
||||
/**
|
||||
* Без НДС
|
||||
*/
|
||||
const NONE = 'none';
|
||||
|
||||
|
||||
/**
|
||||
* НДС 0%
|
||||
*/
|
||||
const VAT0 = 'vat0';
|
||||
|
||||
|
||||
/**
|
||||
* НДС 10%
|
||||
*/
|
||||
const VAT10 = 'vat10';
|
||||
|
||||
|
||||
/**
|
||||
* НДС 18%
|
||||
*/
|
||||
const VAT18 = 'vat18';
|
||||
|
||||
|
||||
/**
|
||||
* НДС 20%
|
||||
*/
|
||||
const VAT20 = 'vat20';
|
||||
|
||||
|
||||
/**
|
||||
* НДС 10/110%
|
||||
*/
|
||||
const VAT110 = 'vat110';
|
||||
|
||||
|
||||
/**
|
||||
* НДС 18/118%
|
||||
*/
|
||||
const VAT118 = 'vat118';
|
||||
|
||||
|
||||
/**
|
||||
* НДС 20/120%
|
||||
*/
|
||||
@@ -1,12 +1,14 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Exception;
|
||||
@@ -14,37 +16,36 @@ use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при работе с АТОЛ Онлайн
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolException extends Exception
|
||||
{
|
||||
/**
|
||||
* @var int[] Теги ФФД
|
||||
*/
|
||||
protected $ffd_tags = null;
|
||||
|
||||
protected array $ffd_tags = [];
|
||||
|
||||
/**
|
||||
* AtolException constructor.
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param \Throwable|null $previous
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
$message = $message ?: $this->message;
|
||||
if ($this->getFfdTags()) {
|
||||
$message .= ' [FFD tags: '.implode(', ', $this->getFfdTags()).']';
|
||||
}
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Возвращает теги ФФД, с которыми связано исключение
|
||||
*
|
||||
* @return array|null
|
||||
* @return array
|
||||
*/
|
||||
protected function getFfdTags(): ?array
|
||||
protected function getFfdTags(): array
|
||||
{
|
||||
return $this->ffd_tags;
|
||||
}
|
||||
41
src/Exceptions/AuthFailedException.php
Normal file
41
src/Exceptions/AuthFailedException.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use AtolOnline\Api\KktResponse;
|
||||
use Exception;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при неудачной авторизации
|
||||
*/
|
||||
class AuthFailedException extends Exception
|
||||
{
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param KktResponse $response
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct(KktResponse $response, $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
$message = $response->isValid()
|
||||
? $message
|
||||
: '[' . $response->error->code . '] ' . $response->error->text .
|
||||
'. ERROR_ID: ' . $response->error->error_id .
|
||||
'. TYPE: ' . $response->error->type;
|
||||
$code = $response->isValid() ? $code : $response->error->code;
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,40 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинное что-либо
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolTooLongException extends AtolException
|
||||
class BasicTooLongException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'Parameter is too long';
|
||||
|
||||
|
||||
/**
|
||||
* AtolTooLongException constructor.
|
||||
*
|
||||
* @param $string
|
||||
* @param $max
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($string, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||
public function __construct($string, $max, $message = "", int $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message ?: $this->message.' (max length - '.$max.', actual length - '.
|
||||
(function_exists('mb_strlen') ? mb_strlen($string) : strlen($string)).')', $code, $previous);
|
||||
parent::__construct($message ?: $this->message . ' (max length - ' . $max . ', actual length - ' .
|
||||
mb_strlen($string), $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,40 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком большое количество чего-либо
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolTooManyException extends AtolException
|
||||
class BasicTooManyException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'Quantity is too high';
|
||||
|
||||
|
||||
/**
|
||||
* AtolTooManyException constructor.
|
||||
*
|
||||
* @param $quantity
|
||||
* @param $max
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
* @param float $quantity
|
||||
* @param float $max
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($quantity, $max, $message = "", $code = 0, Throwable $previous = null)
|
||||
public function __construct(float $quantity, float $max, $message = "", int $code = 0, Throwable $previous = null)
|
||||
{
|
||||
$message = $message ?: $this->message.' (max - '.$max.', actual - '.$quantity.')';
|
||||
parent::__construct($message, $code, $previous);
|
||||
parent::__construct(
|
||||
$message ?: $this->message . ' (max - ' . $max . ', actual - ' . $quantity . ')',
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке зарегистрировать документ без данных коррекции
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolCorrectionInfoException extends AtolException
|
||||
class EmptyCorrectionInfoException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
@@ -1,29 +1,29 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать пустой email
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolEmailEmptyException extends AtolException
|
||||
class EmptyEmailException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1008,
|
||||
1117,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
@@ -1,20 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать пустой логин ККТ
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolKktLoginEmptyException extends AtolException
|
||||
class EmptyLoginException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
23
src/Exceptions/EmptyMonitorDataException.php
Normal file
23
src/Exceptions/EmptyMonitorDataException.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке создать объект ККТ без данных от монитора
|
||||
*/
|
||||
class EmptyMonitorDataException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'Cannot create KKT entity without data from monitor';
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать пустой пароль ККТ
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolKktPasswordEmptyException extends AtolException
|
||||
class EmptyPasswordException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
23
src/Exceptions/InvalidCallbackUrlException.php
Normal file
23
src/Exceptions/InvalidCallbackUrlException.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать невалидный callback_url
|
||||
*/
|
||||
class InvalidCallbackUrlException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'Invalid callback URL';
|
||||
}
|
||||
38
src/Exceptions/InvalidDocumentTypeException.php
Normal file
38
src/Exceptions/InvalidDocumentTypeException.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use AtolOnline\Enums\DocumentTypes;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать некорректный тип документа
|
||||
*/
|
||||
class InvalidDocumentTypeException extends AtolException
|
||||
{
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($type = '', $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
$message ?: "Wrong document type: '$type'. Valid ones: " . implode(', ', DocumentTypes::toArray()),
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
41
src/Exceptions/InvalidEmailException.php
Normal file
41
src/Exceptions/InvalidEmailException.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при ошибке валидации email
|
||||
*/
|
||||
class InvalidEmailException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected array $ffd_tags = [
|
||||
1008,
|
||||
1117,
|
||||
];
|
||||
|
||||
/**
|
||||
* AtolEmailValidateException constructor.
|
||||
*
|
||||
* @param string $email
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct(string $email = '', $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message ?: "Invalid email: '$email'", $code, $previous);
|
||||
}
|
||||
}
|
||||
47
src/Exceptions/InvalidInnLengthException.php
Normal file
47
src/Exceptions/InvalidInnLengthException.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать ИНН некорректной длины
|
||||
*/
|
||||
class InvalidInnLengthException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected array $ffd_tags = [
|
||||
1016,
|
||||
1018,
|
||||
1226,
|
||||
1228,
|
||||
];
|
||||
|
||||
/**
|
||||
* AtolInnWrongLengthException constructor.
|
||||
*
|
||||
* @param string $inn
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($inn = '', $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
$message ?: 'INN length must be 10 or 12 digits only, actual is ' . strlen($inn),
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,36 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при работе с невалидным JSON
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolInvalidJsonException extends AtolException
|
||||
class InvalidJsonException extends AtolException
|
||||
{
|
||||
/**
|
||||
* AtolInnWrongLengthException constructor.
|
||||
*
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message ?: 'Invalid JSON: ['.json_last_error().'] '.json_last_error_msg(), $code, $previous);
|
||||
parent::__construct(
|
||||
$message ?: 'Invalid JSON: [' . json_last_error() . '] ' . json_last_error_msg(),
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
44
src/Exceptions/InvalidPaymentAddressException.php
Normal file
44
src/Exceptions/InvalidPaymentAddressException.php
Normal file
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать некорректный платёжный адрес
|
||||
*/
|
||||
class InvalidPaymentAddressException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected array $ffd_tags = [
|
||||
1187,
|
||||
];
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param string $address
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($address = '', $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
$message ?: "Wrong payment address: '$address'",
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
45
src/Exceptions/InvalidSnoException.php
Normal file
45
src/Exceptions/InvalidSnoException.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use AtolOnline\Enums\SnoTypes;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать некорректную СНО
|
||||
*/
|
||||
class InvalidSnoException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected array $ffd_tags = [
|
||||
1055,
|
||||
];
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param string $sno
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($sno = '', $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct(
|
||||
$message ?: "Wrong SNO: '$sno'. Valid ones: " . implode(', ', SnoTypes::toArray()),
|
||||
$code,
|
||||
$previous
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при ошибке валидации UUID
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolInvalidUuidException extends AtolException
|
||||
class InvalidUuidException extends AtolException
|
||||
{
|
||||
/**
|
||||
* AtolInvalidUuidException constructor.
|
||||
*
|
||||
* @param $uuid
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param \Throwable|null $previous
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct($uuid, $message = "", $code = 0, Throwable $previous = null)
|
||||
{
|
||||
38
src/Exceptions/NotEnoughMonitorDataException.php
Normal file
38
src/Exceptions/NotEnoughMonitorDataException.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке создать объект ККТ с неполными данными от монитора
|
||||
*/
|
||||
class NotEnoughMonitorDataException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'Cannot create KKT entity without these properties: ';
|
||||
|
||||
/**
|
||||
* Конструктор
|
||||
*
|
||||
* @param array $props_diff
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param Throwable|null $previous
|
||||
*/
|
||||
public function __construct(array $props_diff, $message = "", int $code = 0, Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message ?: $this->message . implode(', ', $props_diff), $code, $previous);
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком высокую цену (сумму)
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolPriceTooHighException extends AtolTooManyException
|
||||
class TooHighPriceException extends BasicTooManyException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1079,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
23
src/Exceptions/TooLongCallbackUrlException.php
Normal file
23
src/Exceptions/TooLongCallbackUrlException.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный callback_url
|
||||
*/
|
||||
class TooLongCallbackUrlException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'Callback URL is too long';
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинное имя кассира
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolCashierTooLongException extends AtolTooLongException
|
||||
class TooLongCashierException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1021,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
@@ -1,31 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный email
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolEmailTooLongException extends AtolTooLongException
|
||||
class TooLongEmailException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1008,
|
||||
1117,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'Email is is too long';
|
||||
protected $message = 'Email is too long';
|
||||
}
|
||||
@@ -1,20 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный логин ККТ
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolKktLoginTooLongException extends AtolTooLongException
|
||||
class TooLongLoginException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинное имя
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolNameTooLongException extends AtolTooLongException
|
||||
class TooLongNameException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1026,
|
||||
1030,
|
||||
1085,
|
||||
23
src/Exceptions/TooLongPasswordException.php
Normal file
23
src/Exceptions/TooLongPasswordException.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный пароль ККТ
|
||||
*/
|
||||
class TooLongPasswordException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
protected $message = 'KKT password is too long';
|
||||
}
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный платёжный адрес
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolPaymentAddressTooLongException extends AtolException
|
||||
class TooLongPaymentAddressException extends AtolException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1187,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный телефон
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolPhoneTooLongException extends AtolTooLongException
|
||||
class TooLongPhoneException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1008,
|
||||
1073,
|
||||
1074,
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный телефон
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolUnitTooLongException extends AtolTooLongException
|
||||
class TooLongUnitException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1197,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
@@ -1,28 +1,28 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке указать слишком длинный дополнительный реквизит
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolUserdataTooLongException extends AtolTooLongException
|
||||
class TooLongUserdataException extends BasicTooLongException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1191,
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
*/
|
||||
@@ -1,20 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке добавить слишком много предметов расчёта в массив
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolTooManyItemsException extends AtolTooManyException
|
||||
class TooManyItemsException extends BasicTooManyException
|
||||
{
|
||||
/**
|
||||
* @var string Сообщение об ошибке
|
||||
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке добавить слишком много платежей в массив
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolTooManyPaymentsException extends AtolTooManyException
|
||||
class TooManyPaymentsException extends BasicTooManyException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1031,
|
||||
1081,
|
||||
1215,
|
||||
@@ -1,25 +1,25 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline\Exceptions;
|
||||
|
||||
/**
|
||||
* Исключение, возникающее при попытке добавить слишком много ставок НДС в массив
|
||||
*
|
||||
* @package AtolOnline\Exceptions
|
||||
*/
|
||||
class AtolTooManyVatsException extends AtolTooManyException
|
||||
class TooManyVatsException extends BasicTooManyException
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected $ffd_tags = [
|
||||
protected array $ffd_tags = [
|
||||
1102,
|
||||
1103,
|
||||
1104,
|
||||
55
src/Helpers.php
Normal file
55
src/Helpers.php
Normal file
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnline;
|
||||
|
||||
/**
|
||||
* Класс с функциями-хелперами
|
||||
*/
|
||||
final class Helpers
|
||||
{
|
||||
/**
|
||||
* Конвертирует копейки в рубли, оставляя только 2 знака после запятой
|
||||
*
|
||||
* @param int|null $kopeks Копейки
|
||||
* @return float Рубли
|
||||
*/
|
||||
public static function KopToRub(?int $kopeks): float
|
||||
{
|
||||
return round(abs((int)$kopeks) / 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Конвертирует рубли в копейки, учитывая только 2 знака после запятой
|
||||
*
|
||||
* @param float|null $rubles Рубли
|
||||
* @return int Копейки
|
||||
*/
|
||||
public static function RubToKop(?float $rubles): int
|
||||
{
|
||||
return (int)round(abs((float)$rubles) * 100, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Генерирует случайную строку указанной длины
|
||||
*
|
||||
* @param int $length Длина, по умолчнанию 8
|
||||
* @param bool $with_digits Включать ли цифры
|
||||
* @return string
|
||||
*/
|
||||
public static function randomStr(int $length = 8, bool $with_digits = true): string
|
||||
{
|
||||
$alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' . ($with_digits ? '0123456789' : '');
|
||||
$result = '';
|
||||
for ($i = 0; $i < abs($length); $i++) {
|
||||
$result .= $alphabet[mt_rand(0, strlen($alphabet) - 1)];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
58
src/TestEnvParams.php
Normal file
58
src/TestEnvParams.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnline;
|
||||
|
||||
/**
|
||||
* Константы, определяющие параметры тестовой среды для ФФД 1.05
|
||||
*
|
||||
* @see https://online.atol.ru/files/ffd/test_sreda.txt Параметры настройки тестовых сред
|
||||
*/
|
||||
class TestEnvParams
|
||||
{
|
||||
/**
|
||||
* Возвращает данные для работы с тестовой средой АТОЛ Онлайн ФФД 1.05
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function FFD105(): array
|
||||
{
|
||||
return [
|
||||
'endpoint' => 'https://testonline.atol.ru/possystem/v4/',
|
||||
'company_name' => 'АТОЛ',
|
||||
'inn' => '5544332219',
|
||||
'payment_address' => 'https://v4.online.atol.ru',
|
||||
'group' => 'v4-online-atol-ru_4179',
|
||||
'login' => 'v4-online-atol-ru',
|
||||
'password' => 'iGFFuihss',
|
||||
'endpoint_ofd' => 'https://consumer.1-ofd-test.ru/v1',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает данные для работы с тестовой средой АТОЛ Онлайн ФФД 1.2
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function FFD12(): array
|
||||
{
|
||||
return [
|
||||
'endpoint' => 'https://testonline.atol.ru/possystem/v5/',
|
||||
'company_name' => 'АТОЛ',
|
||||
'inn' => '5544332219',
|
||||
'payment_address' => 'https://v5.online.atol.ru',
|
||||
'group' => 'v5-online-atol-ru_5179',
|
||||
'login' => 'v5-online-atol-ru',
|
||||
'password' => 'zUr0OxfI',
|
||||
'endpoint_ofd' => '',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\Entities\Entity;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Support\Collection;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@@ -16,48 +23,167 @@ use PHPUnit\Framework\TestCase;
|
||||
class BasicTestCase extends TestCase
|
||||
{
|
||||
/**
|
||||
* Проверяет наличие подключения к ресурсу по URL
|
||||
*
|
||||
* @param string $url
|
||||
* @param int $code
|
||||
* @return bool
|
||||
*/
|
||||
public function setUp(): void
|
||||
protected function ping(string $url, int $code): bool
|
||||
{
|
||||
//parent::setUp();
|
||||
defined('ATOL_KKT_GROUP') ?: define('ATOL_KKT_GROUP', 'v4-online-atol-ru_4179');
|
||||
defined('ATOL_KKT_LOGIN') ?: define('ATOL_KKT_LOGIN', 'v4-online-atol-ru');
|
||||
defined('ATOL_KKT_PASS') ?: define('ATOL_KKT_PASS', 'iGFFuihss');
|
||||
defined('ATOL_CALLBACK_URL') ?: define('ATOL_CALLBACK_URL', 'http://example.com/callback');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @return $this
|
||||
*/
|
||||
public function checkAtolEntity(Entity $entity)
|
||||
{
|
||||
$this->assertJson((string)$entity);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function tearDown(): void
|
||||
{
|
||||
//parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает случайную строку указанной длины
|
||||
*
|
||||
* @param int $length
|
||||
* @return string
|
||||
*/
|
||||
protected static function randomString($length = 8)
|
||||
{
|
||||
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
$string = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$string .= $characters[mt_rand(0, strlen($characters) - 1)];
|
||||
try {
|
||||
$result = (new Client([
|
||||
'http_errors' => false,
|
||||
'timeout' => 3,
|
||||
]))->request('GET', $url);
|
||||
} catch (GuzzleException) {
|
||||
return false;
|
||||
}
|
||||
return $string;
|
||||
return $result->getStatusCode() === $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет доступность API мониторинга
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isMonitoringOnline(): bool
|
||||
{
|
||||
return $this->ping('https://testonline.atol.ru/api/auth/v1/gettoken', 400);
|
||||
}
|
||||
|
||||
/**
|
||||
* Пропускает текущий тест если API мониторинга недоступен
|
||||
*/
|
||||
protected function skipIfMonitoringIsOffline(): void
|
||||
{
|
||||
if (!$this->isMonitoringOnline()) {
|
||||
$this->markTestSkipped($this->getName() . ': Monitoring API is inaccessible. Skipping test.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует является ли объект приводимым к json-строке согласно схеме АТОЛ Онлайн
|
||||
*
|
||||
* @param Entity $entity
|
||||
* @param array $json_structure
|
||||
* @covers \AtolOnline\Entities\Entity::jsonSerialize
|
||||
* @covers \AtolOnline\Entities\Entity::__toString
|
||||
*/
|
||||
public function assertAtolable(Entity $entity, array $json_structure = []): void
|
||||
{
|
||||
$this->assertIsObject($entity);
|
||||
$this->assertIsObject($entity->jsonSerialize());
|
||||
$this->assertIsString((string)$entity);
|
||||
$this->assertJson((string)$entity);
|
||||
if ($json_structure) {
|
||||
$this->assertEquals(json_encode($json_structure), (string)$entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует идентичность двух классов
|
||||
*
|
||||
* @param object|string $expected
|
||||
* @param object|string $actual
|
||||
*/
|
||||
public function assertIsSameClass(object|string $expected, object|string $actual): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
is_object($expected) ? $expected::class : $expected,
|
||||
is_object($actual) ? $actual::class : $actual
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует наследование класса (объекта) от указанных классов
|
||||
*
|
||||
* @param string[] $parents
|
||||
* @param object|string $actual
|
||||
*/
|
||||
public function assertExtendsClasses(array $parents, object|string $actual): void
|
||||
{
|
||||
$this->checkClassesIntersection($parents, $actual, 'class_parents');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует имплементацию классом (объектом) указанных интерфейсов
|
||||
*
|
||||
* @param string[] $parents
|
||||
* @param object|string $actual
|
||||
*/
|
||||
public function assertImplementsInterfaces(array $parents, object|string $actual): void
|
||||
{
|
||||
$this->checkClassesIntersection($parents, $actual, 'class_implements');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует использование классом (объектом) указанных трейтов
|
||||
*
|
||||
* @param string[] $parents
|
||||
* @param object|string $actual
|
||||
*/
|
||||
public function assertUsesTraits(array $parents, object|string $actual): void
|
||||
{
|
||||
$this->checkClassesIntersection($parents, $actual, 'class_uses');
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет пересечение классов указанной функцией SPL
|
||||
*
|
||||
* @param object|string $class Класс для проверки на вхождение, или объект, класс коего нужно проверить
|
||||
* @param array $classes Массив классов, вхождение в который нужно проверить
|
||||
* @param string $function class_parents|class_implements|class_uses
|
||||
*/
|
||||
protected function checkClassesIntersection(array $classes, object|string $class, string $function): void
|
||||
{
|
||||
$actual_classes = is_object($class) ? $function($class) : [$class::class];
|
||||
$this->assertIsArray($actual_classes);
|
||||
$this->assertNotEmpty(array_intersect($classes, $actual_classes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует, является ли объект коллекцией
|
||||
*
|
||||
* @param mixed $expected
|
||||
*/
|
||||
public function assertIsCollection(mixed $expected): void
|
||||
{
|
||||
$this->assertIsObject($expected);
|
||||
$this->assertIsIterable($expected);
|
||||
$this->assertIsSameClass($expected, Collection::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Провайдер валидных телефонов
|
||||
*
|
||||
* @return array<array<string, string>>
|
||||
*/
|
||||
public function providerValidPhones(): array
|
||||
{
|
||||
return [
|
||||
['+79991234567', '+79991234567'],
|
||||
['79991234567', '+79991234567'],
|
||||
['89991234567', '+89991234567'],
|
||||
['+7 999 123 45 67', '+79991234567'],
|
||||
['+7 (999) 123-45-67', '+79991234567'],
|
||||
["+7 %(?9:9\"9')abc\r123\n45\t67\0", '+79991234567'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Провайдер валидных email-ов
|
||||
*
|
||||
* @return array<array<string>>
|
||||
*/
|
||||
public function providerValidEmails(): array
|
||||
{
|
||||
return [
|
||||
['abc@mail.com'],
|
||||
['abc-d@mail.com'],
|
||||
['abc.def@mail.com'],
|
||||
['abc.def@mail.org'],
|
||||
['abc.def@mail-archive.com'],
|
||||
];
|
||||
}
|
||||
}
|
||||
318
tests/ClientTest.php
Normal file
318
tests/ClientTest.php
Normal file
@@ -0,0 +1,318 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\{
|
||||
Entities\Client,
|
||||
Exceptions\InvalidEmailException,
|
||||
Exceptions\InvalidInnLengthException,
|
||||
Exceptions\TooLongEmailException,
|
||||
Exceptions\TooLongNameException,
|
||||
Exceptions\TooLongPhoneException,
|
||||
Helpers
|
||||
};
|
||||
|
||||
/**
|
||||
* Набор тестов для проверки работы класс покупателя
|
||||
*/
|
||||
class ClientTest extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Провайдер строк, которые приводятся к null
|
||||
*
|
||||
* @return array<array<string|null>>
|
||||
*/
|
||||
public function providerNullableStrings(): array
|
||||
{
|
||||
return [
|
||||
[''],
|
||||
[' '],
|
||||
[null],
|
||||
["\n\r\t"],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Провайдер телефонов, которые приводятся к null
|
||||
*
|
||||
* @return array<array<string>>
|
||||
*/
|
||||
public function providerNullablePhones(): array
|
||||
{
|
||||
return array_merge(
|
||||
$this->providerNullableStrings(),
|
||||
[
|
||||
[Helpers::randomStr(10, false)],
|
||||
["asdfgvs \n\rtt\t*/(*&%^*$%"],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Провайдер невалидных email-ов
|
||||
*
|
||||
* @return array<array<string>>
|
||||
*/
|
||||
public function providerInvalidEmails(): array
|
||||
{
|
||||
return [
|
||||
['@example'],
|
||||
[Helpers::randomStr(15)],
|
||||
['@example.com'],
|
||||
['abc.def@mail'],
|
||||
['.abc@mail.com'],
|
||||
['example@example'],
|
||||
['abc..def@mail.com'],
|
||||
['abc.def@mail..com'],
|
||||
['abc.def@mail#archive.com'],
|
||||
];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Тестирует приведение покупателя к json
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::jsonSerialize
|
||||
*/
|
||||
public function testAtolable(): void
|
||||
{
|
||||
$this->assertAtolable(new Client());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует конструктор покупателя без передачи значений
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::jsonSerialize
|
||||
*/
|
||||
public function testConstructorWithoutArgs(): void
|
||||
{
|
||||
$this->assertEquals('{}', (string)(new Client()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует конструктор с передачей значений (внутри работают сеттеры)
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::jsonSerialize
|
||||
* @covers \AtolOnline\Entities\Client::setName
|
||||
* @covers \AtolOnline\Entities\Client::setPhone
|
||||
* @covers \AtolOnline\Entities\Client::setEmail
|
||||
* @covers \AtolOnline\Entities\Client::setInn
|
||||
*/
|
||||
public function testConstructorWithArgs(): void
|
||||
{
|
||||
$customer = new Client(
|
||||
'John Doe',
|
||||
'john@example.com',
|
||||
'+1/22/99*73s dsdas654 5s6', // +122997365456
|
||||
'+fasd3\qe3fs_=nac99013928czc' // 3399013928
|
||||
);
|
||||
$this->assertAtolable($customer, [
|
||||
'name' => 'John Doe',
|
||||
'email' => 'john@example.com',
|
||||
'phone' => '+122997365456',
|
||||
'inn' => '3399013928',
|
||||
]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Тестирует установку имён покупателя, которые приводятся к null
|
||||
*
|
||||
* @param mixed $name
|
||||
* @dataProvider providerNullableStrings
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setName
|
||||
* @covers \AtolOnline\Entities\Client::getName
|
||||
* @throws TooLongNameException
|
||||
*/
|
||||
public function testNullableNames(mixed $name): void
|
||||
{
|
||||
$customer = (new Client())->setName($name);
|
||||
$this->assertNull($customer->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку валидного имени покупателя
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setName
|
||||
* @covers \AtolOnline\Entities\Client::getName
|
||||
* @throws TooLongNameException
|
||||
*/
|
||||
public function testValidName(): void
|
||||
{
|
||||
$name = Helpers::randomStr();
|
||||
$customer = (new Client())->setName($name);
|
||||
$this->assertEquals($name, $customer->getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку невалидного имени покупателя
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setName
|
||||
* @covers \AtolOnline\Exceptions\TooLongNameException
|
||||
* @throws TooLongNameException
|
||||
*/
|
||||
public function testInvalidName(): void
|
||||
{
|
||||
$this->expectException(TooLongNameException::class);
|
||||
(new Client())->setName(Helpers::randomStr(400));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Тестирует установку телефонов покупателя, которые приводятся к null
|
||||
*
|
||||
* @param mixed $phone
|
||||
* @dataProvider providerNullablePhones
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setPhone
|
||||
* @covers \AtolOnline\Entities\Client::getPhone
|
||||
* @throws TooLongPhoneException
|
||||
*/
|
||||
public function testNullablePhones(mixed $phone): void
|
||||
{
|
||||
$customer = (new Client())->setPhone($phone);
|
||||
$this->assertNull($customer->getPhone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку валидного телефона покупателя
|
||||
*
|
||||
* @dataProvider providerValidPhones
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setPhone
|
||||
* @covers \AtolOnline\Entities\Client::getPhone
|
||||
* @throws TooLongPhoneException
|
||||
*/
|
||||
public function testValidPhone(string $input, string $output): void
|
||||
{
|
||||
$customer = (new Client())->setPhone($input);
|
||||
$this->assertEquals($output, $customer->getPhone());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку невалидного телефона покупателя
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setPhone
|
||||
* @covers \AtolOnline\Exceptions\TooLongPhoneException
|
||||
* @throws TooLongPhoneException
|
||||
*/
|
||||
public function testInvalidPhone(): void
|
||||
{
|
||||
$this->expectException(TooLongPhoneException::class);
|
||||
(new Client())->setPhone('99999999999999999999999999999999999999999999999999999999999999999999999999');
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Тестирует установку валидных email-ов покупателя
|
||||
*
|
||||
* @param mixed $email
|
||||
* @dataProvider providerValidEmails
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setEmail
|
||||
* @covers \AtolOnline\Entities\Client::getEmail
|
||||
* @throws TooLongEmailException
|
||||
* @throws InvalidEmailException
|
||||
*/
|
||||
public function testValidEmails(mixed $email): void
|
||||
{
|
||||
$customer = (new Client())->setEmail($email);
|
||||
$this->assertEquals($email, $customer->getEmail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку слишком длинного email покупателя
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setEmail
|
||||
* @covers \AtolOnline\Exceptions\TooLongEmailException
|
||||
* @throws TooLongEmailException
|
||||
* @throws InvalidEmailException
|
||||
*/
|
||||
public function testTooLongEmail(): void
|
||||
{
|
||||
$this->expectException(TooLongEmailException::class);
|
||||
(new Client())->setEmail(Helpers::randomStr(65));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку невалидного email покупателя
|
||||
*
|
||||
* @param mixed $email
|
||||
* @dataProvider providerInvalidEmails
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setEmail
|
||||
* @covers \AtolOnline\Exceptions\InvalidEmailException
|
||||
* @throws TooLongEmailException
|
||||
* @throws InvalidEmailException
|
||||
*/
|
||||
public function testInvalidEmail(mixed $email): void
|
||||
{
|
||||
$this->expectException(InvalidEmailException::class);
|
||||
(new Client())->setEmail($email);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Тестирует исключение о корректной длине ИНН
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setInn
|
||||
* @covers \AtolOnline\Entities\Client::getInn
|
||||
* @throws InvalidInnLengthException
|
||||
*/
|
||||
public function testValidInn(): void
|
||||
{
|
||||
$customer = (new Client())->setInn('1234567890');
|
||||
$this->assertEquals('1234567890', $customer->getInn());
|
||||
$customer = $customer->setInn('123456789012');
|
||||
$this->assertEquals('123456789012', $customer->getInn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о некорректной длине ИНН (10 цифр)
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setInn
|
||||
* @covers \AtolOnline\Exceptions\InvalidInnLengthException
|
||||
* @throws InvalidInnLengthException
|
||||
*/
|
||||
public function testInvalidInn10(): void
|
||||
{
|
||||
$this->expectException(InvalidInnLengthException::class);
|
||||
(new Client())->setInn('12345678901');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о некорректной длине ИНН (12 цифр)
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Client
|
||||
* @covers \AtolOnline\Entities\Client::setInn
|
||||
* @covers \AtolOnline\Exceptions\InvalidInnLengthException
|
||||
* @throws InvalidInnLengthException
|
||||
*/
|
||||
public function testInvalidInn12(): void
|
||||
{
|
||||
$this->expectException(InvalidInnLengthException::class);
|
||||
(new Client())->setInn('1234567890123');
|
||||
}
|
||||
}
|
||||
134
tests/CompanyTest.php
Normal file
134
tests/CompanyTest.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\{
|
||||
Entities\Company,
|
||||
Enums\SnoTypes,
|
||||
Exceptions\InvalidEmailException,
|
||||
Exceptions\InvalidInnLengthException,
|
||||
Exceptions\InvalidPaymentAddressException,
|
||||
Exceptions\InvalidSnoException,
|
||||
Exceptions\TooLongEmailException,
|
||||
Exceptions\TooLongPaymentAddressException,
|
||||
Helpers};
|
||||
|
||||
/**
|
||||
* Набор тестов для проверки работы класс продавца
|
||||
*/
|
||||
class CompanyTest extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Тестирует конструктор с сеттерами и приведение к json с геттерами
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Company
|
||||
* @covers \AtolOnline\Entities\Company::jsonSerialize
|
||||
* @covers \AtolOnline\Entities\Company::setEmail
|
||||
* @covers \AtolOnline\Entities\Company::setSno
|
||||
* @covers \AtolOnline\Entities\Company::setInn
|
||||
* @covers \AtolOnline\Entities\Company::setPaymentAddress
|
||||
* @covers \AtolOnline\Entities\Company::getEmail
|
||||
* @covers \AtolOnline\Entities\Company::getSno
|
||||
* @covers \AtolOnline\Entities\Company::getInn
|
||||
* @covers \AtolOnline\Entities\Company::getPaymentAddress
|
||||
*/
|
||||
public function testConstructor()
|
||||
{
|
||||
$this->assertAtolable(new Company(
|
||||
$email = 'company@example.com',
|
||||
$sno = SnoTypes::OSN,
|
||||
$inn = '1234567890',
|
||||
$payment_address = 'https://example.com',
|
||||
), [
|
||||
'email' => $email,
|
||||
'sno' => $sno,
|
||||
'inn' => $inn,
|
||||
'payment_address' => $payment_address,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном email
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Company
|
||||
* @covers \AtolOnline\Entities\Company::setEmail
|
||||
* @covers \AtolOnline\Exceptions\TooLongEmailException
|
||||
*/
|
||||
public function testEmailTooLongException()
|
||||
{
|
||||
$this->expectException(TooLongEmailException::class);
|
||||
new Company(Helpers::randomStr(65), SnoTypes::OSN, '1234567890', 'https://example.com');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о невалидном email
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Company
|
||||
* @covers \AtolOnline\Entities\Company::setEmail
|
||||
* @covers \AtolOnline\Exceptions\InvalidEmailException
|
||||
*/
|
||||
public function testInvalidEmailException()
|
||||
{
|
||||
$this->expectException(InvalidEmailException::class);
|
||||
new Company('company@examas%^*.com', SnoTypes::OSN, '1234567890', 'https://example.com');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном платёжном адресе
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Company
|
||||
* @covers \AtolOnline\Entities\Company::setSno
|
||||
* @covers \AtolOnline\Exceptions\InvalidSnoException
|
||||
*/
|
||||
public function testInvalidSnoException()
|
||||
{
|
||||
$this->expectException(InvalidSnoException::class);
|
||||
new Company('company@example.com', 'test', '1234567890', 'https://example.com');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном платёжном адресе
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Company
|
||||
* @covers \AtolOnline\Entities\Company::setInn
|
||||
* @covers \AtolOnline\Exceptions\InvalidInnLengthException
|
||||
*/
|
||||
public function testInvalidInnLengthException()
|
||||
{
|
||||
$this->expectException(InvalidInnLengthException::class);
|
||||
new Company('company@example.com', SnoTypes::OSN, Helpers::randomStr(13), 'https://example.com');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном платёжном адресе
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Company
|
||||
* @covers \AtolOnline\Entities\Company::setPaymentAddress
|
||||
* @covers \AtolOnline\Exceptions\TooLongPaymentAddressException
|
||||
*/
|
||||
public function testTooLongPaymentAddressException()
|
||||
{
|
||||
$this->expectException(TooLongPaymentAddressException::class);
|
||||
new Company('company@example.com', SnoTypes::OSN, '1234567890', Helpers::randomStr(257));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о невалидном платёжном адресе
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Company
|
||||
* @covers \AtolOnline\Entities\Company::setPaymentAddress
|
||||
* @covers \AtolOnline\Exceptions\InvalidPaymentAddressException
|
||||
*/
|
||||
public function testInvalidPaymentAddressException()
|
||||
{
|
||||
$this->expectException(InvalidPaymentAddressException::class);
|
||||
new Company('company@example.com', SnoTypes::OSN, '1234567890', '');
|
||||
}
|
||||
}
|
||||
123
tests/HelpersTest.php
Normal file
123
tests/HelpersTest.php
Normal file
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\Helpers;
|
||||
|
||||
/**
|
||||
* Набор тестов для проверки работы функций-хелперов
|
||||
*/
|
||||
class HelpersTest extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Провайдер копеек для перевода в рубли
|
||||
*
|
||||
* @return array<array<int|null, float>>
|
||||
*/
|
||||
public function providerKopeksToRubles(): array
|
||||
{
|
||||
return [
|
||||
[null, 0],
|
||||
[0, 0],
|
||||
[1, 0.01],
|
||||
[12, 0.12],
|
||||
[123, 1.23],
|
||||
[1234, 12.34],
|
||||
[12345, 123.45],
|
||||
[-1, 0.01],
|
||||
[-12, 0.12],
|
||||
[-123, 1.23],
|
||||
[-1234, 12.34],
|
||||
[-12345, 123.45],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Провайдер рублей для перевода в копейки
|
||||
*
|
||||
* @return array<array<float|null, int>>
|
||||
*/
|
||||
public function providerRublesToKopeks(): array
|
||||
{
|
||||
return [
|
||||
[null, 0],
|
||||
[0, 0],
|
||||
[0.01, 1],
|
||||
[0.12, 12],
|
||||
[1.23, 123],
|
||||
[12.34, 1234],
|
||||
[123.45, 12345],
|
||||
[-0.01, 1],
|
||||
[-0.12, 12],
|
||||
[-1.23, 123],
|
||||
[-12.34, 1234],
|
||||
[-123.45, 12345],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Провайдер для тестирования генерации рандомной строки
|
||||
*
|
||||
* @return array<array<int, int>>
|
||||
*/
|
||||
public function providerRandomStr(): array
|
||||
{
|
||||
return [
|
||||
[0, 0],
|
||||
[1, 1],
|
||||
[5, 5],
|
||||
[-1, 1],
|
||||
[-5, 5],
|
||||
];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Тестирует перевод копеек в рубли
|
||||
*
|
||||
* @dataProvider providerKopeksToRubles
|
||||
* @covers \AtolOnline\Helpers::KopToRub
|
||||
*/
|
||||
public function testKopeksToRubles(?int $kopeks, float $rubles): void
|
||||
{
|
||||
$result = Helpers::KopToRub($kopeks);
|
||||
$this->assertIsFloat($result);
|
||||
$this->assertEquals($result, $rubles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует перевод копеек в рубли
|
||||
*
|
||||
* @dataProvider providerRublesToKopeks
|
||||
* @covers \AtolOnline\Helpers::RubToKop
|
||||
*/
|
||||
public function testRublesToKopeks(?float $rubles, int $kopeks): void
|
||||
{
|
||||
$result = Helpers::RubToKop($rubles);
|
||||
$this->assertIsInt($result);
|
||||
$this->assertEquals($result, $kopeks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует длину рандомной строки
|
||||
*
|
||||
* @param int $input
|
||||
* @param int $output
|
||||
* @dataProvider providerRandomStr
|
||||
*/
|
||||
public function testRandomString(int $input, int $output): void
|
||||
{
|
||||
$result = Helpers::randomStr($input);
|
||||
$this->assertIsString($result);
|
||||
$this->assertEquals($output, strlen($result));
|
||||
// тестировать на наличие цифр быссмысленно
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
use AtolOnline\{Constants\PaymentMethods,
|
||||
Constants\PaymentObjects,
|
||||
Constants\VatTypes,
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\{
|
||||
Entities\Item,
|
||||
Exceptions\AtolNameTooLongException,
|
||||
Exceptions\AtolPriceTooHighException,
|
||||
Exceptions\AtolTooManyException,
|
||||
Exceptions\AtolUnitTooLongException,
|
||||
Exceptions\AtolUserdataTooLongException};
|
||||
Enums\PaymentMethods,
|
||||
Enums\PaymentObjects,
|
||||
Enums\VatTypes,
|
||||
Exceptions\BasicTooManyException,
|
||||
Exceptions\TooHighPriceException,
|
||||
Exceptions\TooLongNameException,
|
||||
Exceptions\TooLongUnitException,
|
||||
Exceptions\TooLongUserdataException,};
|
||||
|
||||
/**
|
||||
* Class ItemTest
|
||||
*/
|
||||
class ItemTest extends BasicTestCase
|
||||
class ItemTestTodo extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Тестирует установку параметров через конструктор
|
||||
*
|
||||
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||
* @throws AtolOnline\Exceptions\AtolTooManyException
|
||||
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||
* @throws AtolOnline\Exceptions\TooLongNameException
|
||||
* @throws AtolOnline\Exceptions\TooHighPriceException
|
||||
* @throws AtolOnline\Exceptions\BasicTooManyException
|
||||
* @throws AtolOnline\Exceptions\TooLongUnitException
|
||||
*/
|
||||
public function testConstructor()
|
||||
{
|
||||
@@ -41,7 +44,7 @@ class ItemTest extends BasicTestCase
|
||||
PaymentObjects::COMMODITY,
|
||||
PaymentMethods::FULL_PAYMENT
|
||||
);
|
||||
$this->checkAtolEntity($item);
|
||||
$this->assertAtolable($item);
|
||||
$this->assertEquals('Банан', $item->getName());
|
||||
$this->assertEquals(65.99, $item->getPrice());
|
||||
$this->assertEquals(2.74, $item->getQuantity());
|
||||
@@ -50,15 +53,15 @@ class ItemTest extends BasicTestCase
|
||||
$this->assertEquals(PaymentObjects::COMMODITY, $item->getPaymentObject());
|
||||
$this->assertEquals(PaymentMethods::FULL_PAYMENT, $item->getPaymentMethod());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Тестирует установку параметров через сеттеры
|
||||
*
|
||||
* @throws AtolOnline\Exceptions\AtolNameTooLongException
|
||||
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
|
||||
* @throws AtolOnline\Exceptions\AtolTooManyException
|
||||
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
|
||||
* @throws AtolOnline\Exceptions\AtolUserdataTooLongException
|
||||
* @throws AtolOnline\Exceptions\TooLongNameException
|
||||
* @throws AtolOnline\Exceptions\TooHighPriceException
|
||||
* @throws AtolOnline\Exceptions\BasicTooManyException
|
||||
* @throws AtolOnline\Exceptions\TooLongUnitException
|
||||
* @throws AtolOnline\Exceptions\TooLongUserdataException
|
||||
*/
|
||||
public function testSetters()
|
||||
{
|
||||
@@ -71,7 +74,7 @@ class ItemTest extends BasicTestCase
|
||||
$item->setPaymentObject(PaymentObjects::COMMODITY);
|
||||
$item->setPaymentMethod(PaymentMethods::FULL_PAYMENT);
|
||||
$item->setUserData('Some user data');
|
||||
$this->checkAtolEntity($item);
|
||||
$this->assertAtolable($item);
|
||||
$this->assertEquals('Банан', $item->getName());
|
||||
$this->assertEquals(65.99, $item->getPrice());
|
||||
$this->assertEquals(2.74, $item->getQuantity());
|
||||
@@ -81,11 +84,11 @@ class ItemTest extends BasicTestCase
|
||||
$this->assertEquals(PaymentMethods::FULL_PAYMENT, $item->getPaymentMethod());
|
||||
$this->assertEquals('Some user data', $item->getUserData());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Тестирует установку ставки НДС разными путями
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
|
||||
* @throws TooHighPriceException
|
||||
*/
|
||||
public function testSetVat()
|
||||
{
|
||||
@@ -95,66 +98,66 @@ class ItemTest extends BasicTestCase
|
||||
$item->setVatType(VatTypes::VAT20);
|
||||
$this->assertEquals(VatTypes::VAT20, $item->getVat()->getType());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном наименовании
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||
* @throws TooLongNameException
|
||||
*/
|
||||
public function testAtolNameTooLongException()
|
||||
{
|
||||
$item = new Item();
|
||||
$this->expectException(AtolNameTooLongException::class);
|
||||
$item->setName(self::randomString(130));
|
||||
$this->expectException(TooLongNameException::class);
|
||||
$item->setName(Helpers::randomStr(130));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком высоком количестве
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
|
||||
* @throws \AtolOnline\Exceptions\AtolTooManyException
|
||||
* @throws \AtolOnline\Exceptions\AtolUnitTooLongException
|
||||
* @throws TooHighPriceException
|
||||
* @throws BasicTooManyException
|
||||
* @throws TooLongUnitException
|
||||
*/
|
||||
public function testAtolQuantityTooHighException()
|
||||
{
|
||||
$item = new Item();
|
||||
$this->expectException(AtolTooManyException::class);
|
||||
$this->expectException(BasicTooManyException::class);
|
||||
$item->setQuantity(100000.1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком высокой цене
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
|
||||
* @throws TooHighPriceException
|
||||
*/
|
||||
public function testAtolPriceTooHighException()
|
||||
{
|
||||
$item = new Item();
|
||||
$this->expectException(AtolPriceTooHighException::class);
|
||||
$this->expectException(TooHighPriceException::class);
|
||||
$item->setPrice(42949673.1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинных польз. данных
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolUserdataTooLongException
|
||||
* @throws TooLongUserdataException
|
||||
*/
|
||||
public function testAtolUserdataTooLongException()
|
||||
{
|
||||
$item = new Item();
|
||||
$this->expectException(AtolUserdataTooLongException::class);
|
||||
$this->expectException(TooLongUserdataException::class);
|
||||
$item->setUserData('User data User data User data User data User data User data User data');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинной единице измерения
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolUnitTooLongException
|
||||
* @throws TooLongUnitException
|
||||
*/
|
||||
public function testAtolUnitTooLongException()
|
||||
{
|
||||
$item = new Item();
|
||||
$this->expectException(AtolUnitTooLongException::class);
|
||||
$this->expectException(TooLongUnitException::class);
|
||||
$item->setMeasurementUnit('кг кг кг кг кг кг кг кг кг ');
|
||||
}
|
||||
}
|
||||
153
tests/KktEntityTest.php
Normal file
153
tests/KktEntityTest.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\Entities\Kkt;
|
||||
use AtolOnline\Exceptions\EmptyMonitorDataException;
|
||||
use AtolOnline\Exceptions\NotEnoughMonitorDataException;
|
||||
use DateTime;
|
||||
use Exception;
|
||||
|
||||
class KktEntityTest extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* @var array Данные для создания объекта ККТ
|
||||
*/
|
||||
private array $sample_data = [
|
||||
'serialNumber' => '00107703864827',
|
||||
'registrationNumber' => '0000000003027865',
|
||||
'deviceNumber' => 'KKT024219',
|
||||
'fiscalizationDate' => '2019-07-22T14:03:00+00:00',
|
||||
'fiscalStorageExpiration' => '2020-11-02T21:00:00+00:00',
|
||||
'signedDocuments' => 213350,
|
||||
'fiscalStoragePercentageUse' => 85.34,
|
||||
'fiscalStorageINN' => '3026455760',
|
||||
'fiscalStorageSerialNumber' => '9999078902004339',
|
||||
'fiscalStoragePaymentAddress' => 'test.qa.ru',
|
||||
'groupCode' => 'test-qa-ru_14605',
|
||||
'timestamp' => '2019-12-05T10:45:30+00:00',
|
||||
'isShiftOpened' => true,
|
||||
'shiftNumber' => 126,
|
||||
'shiftReceipt' => 2278,
|
||||
//'unsentDocs' => 123,
|
||||
'firstUnsetDocTimestamp' => 'there must be timestamp, but we want to get exception here to get string',
|
||||
'networkErrorCode' => 2,
|
||||
];
|
||||
|
||||
/**
|
||||
* Тестирует создание объекта ККТ с валидными данными
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Kkt::__construct
|
||||
* @covers \AtolOnline\Entities\Kkt::__get
|
||||
* @covers \AtolOnline\Entities\Kkt::jsonSerialize
|
||||
* @covers \AtolOnline\Entities\Kkt::__toString
|
||||
* @throws Exception
|
||||
*/
|
||||
public function testConstructor(): void
|
||||
{
|
||||
$kkt = new Kkt((object)$this->sample_data);
|
||||
$this->assertIsSameClass(Kkt::class, $kkt);
|
||||
$this->assertAtolable($kkt);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение при попытке создать объект ККТ без данных от монитора
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Kkt::__construct
|
||||
* @covers \AtolOnline\Exceptions\EmptyMonitorDataException
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
*/
|
||||
public function testEmptyMonitorDataException(): void
|
||||
{
|
||||
$this->expectException(EmptyMonitorDataException::class);
|
||||
new Kkt((object)[]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение при попытке создать объект ККТ без данных от монитора
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Kkt::__construct
|
||||
* @covers \AtolOnline\Exceptions\NotEnoughMonitorDataException
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
*/
|
||||
public function testNotEnoughMonitorDataException(): void
|
||||
{
|
||||
$this->expectException(NotEnoughMonitorDataException::class);
|
||||
new Kkt((object)[
|
||||
'fiscalizationDate' => '2021-11-20T10:21:00+00:00',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует получение атрибутов через магический геттер
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Kkt::__get
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
*/
|
||||
public function testMagicGetter(): void
|
||||
{
|
||||
$kkt = new Kkt((object)$this->sample_data);
|
||||
|
||||
// string
|
||||
$this->assertNotNull($kkt->serialNumber);
|
||||
$this->assertIsString($kkt->serialNumber);
|
||||
$this->assertEquals($this->sample_data['serialNumber'], $kkt->serialNumber);
|
||||
|
||||
// int
|
||||
$this->assertNotNull($kkt->signedDocuments);
|
||||
$this->assertIsInt($kkt->signedDocuments);
|
||||
|
||||
// float
|
||||
$this->assertNotNull($kkt->signedDocuments);
|
||||
$this->assertIsFloat($kkt->fiscalStoragePercentageUse);
|
||||
|
||||
// null
|
||||
$this->assertNull($kkt->unsentDocs);
|
||||
|
||||
// DateTime
|
||||
$this->assertNotNull($kkt->fiscalizationDate);
|
||||
$this->assertIsSameClass(DateTime::class, $kkt->fiscalizationDate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение при попытке получить некорректный DateTime через магический геттер
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Kkt::__get
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
*/
|
||||
public function testDateTimeException(): void
|
||||
{
|
||||
$this->expectException(Exception::class);
|
||||
(new Kkt((object)$this->sample_data))->firstUnsetDocTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует получение данных о сетевой ошибке
|
||||
*
|
||||
* @covers \AtolOnline\Entities\Kkt::getNetworkError
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
*/
|
||||
public function testGetNetworkError(): void
|
||||
{
|
||||
$kkt = new Kkt((object)$this->sample_data);
|
||||
$this->assertIsObject($kkt->getNetworkError());
|
||||
$this->assertEquals((object)[
|
||||
'code' => $kkt->networkErrorCode,
|
||||
'text' => $kkt::ERROR_CODES[$kkt->networkErrorCode],
|
||||
], $kkt->getNetworkError());
|
||||
}
|
||||
}
|
||||
343
tests/KktMonitorTest.php
Normal file
343
tests/KktMonitorTest.php
Normal file
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\Api\AtolClient;
|
||||
use AtolOnline\Api\KktMonitor;
|
||||
use AtolOnline\Api\KktResponse;
|
||||
use AtolOnline\Entities\Kkt;
|
||||
use AtolOnline\Exceptions\AuthFailedException;
|
||||
use AtolOnline\Exceptions\EmptyLoginException;
|
||||
use AtolOnline\Exceptions\EmptyMonitorDataException;
|
||||
use AtolOnline\Exceptions\EmptyPasswordException;
|
||||
use AtolOnline\Exceptions\NotEnoughMonitorDataException;
|
||||
use AtolOnline\Exceptions\TooLongLoginException;
|
||||
use AtolOnline\Exceptions\TooLongPasswordException;
|
||||
use AtolOnline\Helpers;
|
||||
use AtolOnline\TestEnvParams;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
|
||||
/**
|
||||
* Набор тестов для проверки работы API-клиента на примере монитора ККТ
|
||||
*/
|
||||
class KktMonitorTest extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Возвращает объект клиента для тестирования с тестовым API АТОЛ
|
||||
*
|
||||
* @return KktMonitor
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
private function newTestClient(): KktMonitor
|
||||
{
|
||||
$credentials = TestEnvParams::FFD105();
|
||||
return (new KktMonitor(true))
|
||||
->setLogin($credentials['login'])
|
||||
->setPassword($credentials['password']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует успешное создание объекта монитора без аргументов конструктора
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
*/
|
||||
public function testConstructorWithoutArgs(): void
|
||||
{
|
||||
$client = new KktMonitor();
|
||||
$this->assertIsObject($client);
|
||||
$this->assertIsSameClass(KktMonitor::class, $client);
|
||||
$this->assertExtendsClasses([AtolClient::class], $client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует успешное создание объекта монитора с аргументами конструктора
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::setLogin
|
||||
* @covers \AtolOnline\Api\KktMonitor::getLogin
|
||||
* @covers \AtolOnline\Api\KktMonitor::setPassword
|
||||
* @covers \AtolOnline\Api\KktMonitor::getPassword
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function testConstructorWithArgs(): void
|
||||
{
|
||||
$client = new KktMonitor(false, 'login', 'password', []);
|
||||
$this->assertIsObject($client);
|
||||
$this->assertIsSameClass(KktMonitor::class, $client);
|
||||
$this->assertExtendsClasses([AtolClient::class], $client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку и возврат логина
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::getLogin
|
||||
* @covers \AtolOnline\Api\KktMonitor::setLogin
|
||||
* @throws EmptyLoginException
|
||||
* @throws TooLongLoginException
|
||||
*/
|
||||
public function testLogin(): void
|
||||
{
|
||||
$client = new KktMonitor(login: 'login');
|
||||
$this->assertEquals('login', $client->getLogin());
|
||||
|
||||
$client = new KktMonitor();
|
||||
$this->assertNull($client->getLogin());
|
||||
|
||||
$client->setLogin('login');
|
||||
$this->assertEquals('login', $client->getLogin());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение при попытке передать пустой логин в конструктор
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::setLogin
|
||||
* @covers \AtolOnline\Exceptions\EmptyLoginException
|
||||
*/
|
||||
public function testEmptyLoginException(): void
|
||||
{
|
||||
$this->expectException(EmptyLoginException::class);
|
||||
new KktMonitor(login: '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение при попытке передать слишком длинный логин в конструктор
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::setLogin
|
||||
* @covers \AtolOnline\Exceptions\TooLongLoginException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function testTooLongLoginException(): void
|
||||
{
|
||||
$this->expectException(TooLongLoginException::class);
|
||||
new KktMonitor(login: Helpers::randomStr(101));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку и возврат пароля
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::getPassword
|
||||
* @covers \AtolOnline\Api\KktMonitor::setPassword
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function testPassword(): void
|
||||
{
|
||||
$client = new KktMonitor(password: 'password');
|
||||
$this->assertEquals('password', $client->getPassword());
|
||||
|
||||
$client = new KktMonitor();
|
||||
$this->assertNull($client->getPassword());
|
||||
|
||||
$client->setPassword('password');
|
||||
$this->assertEquals('password', $client->getPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение при попытке передать пустой пароль в конструктор
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::setPassword
|
||||
* @covers \AtolOnline\Exceptions\EmptyPasswordException
|
||||
*/
|
||||
public function testEmptyPasswordException(): void
|
||||
{
|
||||
$this->expectException(EmptyPasswordException::class);
|
||||
new KktMonitor(password: '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение при попытке передать слишком длинный пароль в конструктор
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::setPassword
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function testConstructorWithLongPassword(): void
|
||||
{
|
||||
$this->expectException(TooLongPasswordException::class);
|
||||
new KktMonitor(password: Helpers::randomStr(101));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует установку тестового режима
|
||||
*
|
||||
* @covers \AtolOnline\Api\KktMonitor::__construct
|
||||
* @covers \AtolOnline\Api\KktMonitor::isTestMode
|
||||
* @covers \AtolOnline\Api\KktMonitor::setTestMode
|
||||
*/
|
||||
public function testTestMode(): void
|
||||
{
|
||||
$client = new KktMonitor();
|
||||
$this->assertTrue($client->isTestMode());
|
||||
|
||||
$client = new KktMonitor(true);
|
||||
$this->assertTrue($client->isTestMode());
|
||||
|
||||
$client = new KktMonitor(false);
|
||||
$this->assertFalse($client->isTestMode());
|
||||
|
||||
$client = (new KktMonitor())->setTestMode();
|
||||
$this->assertTrue($client->isTestMode());
|
||||
|
||||
$client = (new KktMonitor())->setTestMode(true);
|
||||
$this->assertTrue($client->isTestMode());
|
||||
|
||||
$client = (new KktMonitor())->setTestMode(false);
|
||||
$this->assertFalse($client->isTestMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует авторизацию
|
||||
*
|
||||
* @covers \AtolOnline\Api\AtolClient::getHeaders
|
||||
* @covers \AtolOnline\Api\KktMonitor::sendRequest
|
||||
* @covers \AtolOnline\Api\KktMonitor::getAuthEndpoint
|
||||
* @covers \AtolOnline\Api\KktMonitor::doAuth
|
||||
* @covers \AtolOnline\Api\KktMonitor::auth
|
||||
* @covers \AtolOnline\Exceptions\AuthFailedException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
* @throws AuthFailedException
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function testAuth(): void
|
||||
{
|
||||
$this->skipIfMonitoringIsOffline();
|
||||
$result = $this->newTestClient()->auth();
|
||||
$this->assertTrue($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует возврат токена после авторизации
|
||||
*
|
||||
* @depends testAuth
|
||||
* @covers \AtolOnline\Api\KktMonitor::setToken
|
||||
* @covers \AtolOnline\Api\KktMonitor::getToken
|
||||
* @covers \AtolOnline\Exceptions\AuthFailedException
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws GuzzleException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function testGetToken(): void
|
||||
{
|
||||
$client = new KktMonitor();
|
||||
$this->assertNull($client->getToken());
|
||||
|
||||
$this->skipIfMonitoringIsOffline();
|
||||
$client = $this->newTestClient();
|
||||
$client->auth();
|
||||
$this->assertIsString($client->getToken());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует возврат объекта последнего ответа от API
|
||||
*
|
||||
* @depends testAuth
|
||||
* @covers \AtolOnline\Api\KktMonitor::getResponse
|
||||
* @covers \AtolOnline\Exceptions\AuthFailedException
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws GuzzleException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function testGetResponse(): void
|
||||
{
|
||||
$this->skipIfMonitoringIsOffline();
|
||||
$client = $this->newTestClient();
|
||||
$client->auth();
|
||||
$this->assertIsSameClass(KktResponse::class, $client->getResponse());
|
||||
}
|
||||
|
||||
/**
|
||||
* [Мониторинг] Тестирует получение данных о всех ККТ
|
||||
*
|
||||
* @depends testAuth
|
||||
* @covers \AtolOnline\Api\KktMonitor::getMainEndpoint
|
||||
* @covers \AtolOnline\Api\AtolClient::getUrlToMethod
|
||||
* @covers \AtolOnline\Api\KktMonitor::fetchAll
|
||||
* @covers \AtolOnline\Api\KktMonitor::getAll
|
||||
* @covers \AtolOnline\Exceptions\AuthFailedException
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws GuzzleException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
*/
|
||||
public function testMonitorGetAll(): void
|
||||
{
|
||||
$this->skipIfMonitoringIsOffline();
|
||||
$client = $this->newTestClient();
|
||||
$client->auth();
|
||||
$kkts = $client->getAll();
|
||||
$this->assertNotEmpty($client->getResponse()->getContent());
|
||||
$this->assertIsCollection($kkts);
|
||||
$this->assertTrue($kkts->count() > 0);
|
||||
$this->assertIsSameClass(Kkt::class, $kkts->random());
|
||||
}
|
||||
|
||||
/**
|
||||
* [Мониторинг] Тестирует получение данных о конкретной ККТ
|
||||
*
|
||||
* @depends testAuth
|
||||
* @covers \AtolOnline\Api\KktMonitor::getMainEndpoint
|
||||
* @covers \AtolOnline\Api\AtolClient::getUrlToMethod
|
||||
* @covers \AtolOnline\Api\KktMonitor::fetchOne
|
||||
* @covers \AtolOnline\Api\KktMonitor::getOne
|
||||
* @covers \AtolOnline\Entities\Kkt::__construct
|
||||
* @covers \AtolOnline\Entities\Kkt::__get
|
||||
* @covers \AtolOnline\Entities\Kkt::jsonSerialize
|
||||
* @covers \AtolOnline\Entities\Kkt::__toString
|
||||
* @throws AuthFailedException
|
||||
* @throws EmptyLoginException
|
||||
* @throws EmptyPasswordException
|
||||
* @throws GuzzleException
|
||||
* @throws TooLongLoginException
|
||||
* @throws TooLongPasswordException
|
||||
* @throws EmptyMonitorDataException
|
||||
* @throws NotEnoughMonitorDataException
|
||||
*/
|
||||
public function testMonitorGetOne(): void
|
||||
{
|
||||
$this->skipIfMonitoringIsOffline();
|
||||
$client = $this->newTestClient();
|
||||
$client->auth();
|
||||
$serial_number = $client->getAll()->first()->serialNumber;
|
||||
$kkt = $client->getOne($serial_number);
|
||||
$this->assertNotEmpty($client->getResponse());
|
||||
$this->assertIsSameClass(Kkt::class, $kkt);
|
||||
$this->assertAtolable($kkt);
|
||||
$this->assertNotNull($kkt->serialNumber);
|
||||
$this->assertEquals($serial_number, $kkt->serialNumber);
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
use AtolOnline\{Entities\Client,
|
||||
Exceptions\AtolEmailTooLongException,
|
||||
Exceptions\AtolEmailValidateException,
|
||||
Exceptions\AtolInnWrongLengthException,
|
||||
Exceptions\AtolNameTooLongException,
|
||||
Exceptions\AtolPhoneTooLongException
|
||||
};
|
||||
|
||||
/**
|
||||
* Class ClientTest
|
||||
*/
|
||||
class ClientTest extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Тестирует установку параметров
|
||||
*/
|
||||
public function testConstructor()
|
||||
{
|
||||
$customer = new Client(
|
||||
'John Doe',
|
||||
'+1/22/99*73s dsdas654 5s6', // +122997365456
|
||||
'john@example.com',
|
||||
'+fasd3\qe3fs_=nac99013928czc' // 3399013928
|
||||
);
|
||||
$this->checkAtolEntity($customer);
|
||||
$this->assertEquals('John Doe', $customer->getName());
|
||||
$this->assertEquals('+122997365456', $customer->getPhone());
|
||||
$this->assertEquals('john@example.com', $customer->getEmail());
|
||||
$this->assertEquals('3399013928', $customer->getInn());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном имени
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
|
||||
*/
|
||||
public function testAtolNameTooLongException()
|
||||
{
|
||||
$customer = new Client();
|
||||
$this->expectException(AtolNameTooLongException::class);
|
||||
$customer->setName(self::randomString(257));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном телефоне
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
|
||||
*/
|
||||
public function testAtolPhoneTooLongException()
|
||||
{
|
||||
$customer = new Client();
|
||||
$this->expectException(AtolPhoneTooLongException::class);
|
||||
$customer->setPhone('99999999999999999999999999999999999999999999999999999999999999999999999999');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинной почте
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||
*/
|
||||
public function testAtolEmailTooLongException()
|
||||
{
|
||||
$customer = new Client();
|
||||
$this->expectException(AtolEmailTooLongException::class);
|
||||
$customer->setEmail(self::randomString(65));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о некорректной почте
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||
*/
|
||||
public function testAtolEmailValidateException()
|
||||
{
|
||||
$customer = new Client();
|
||||
$this->expectException(AtolEmailValidateException::class);
|
||||
$customer->setEmail(self::randomString(15));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о некорректной длине ИНН
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||
*/
|
||||
public function testAtolInnWrongLengthException()
|
||||
{
|
||||
$company = new Client();
|
||||
$this->expectException(AtolInnWrongLengthException::class);
|
||||
$company->setInn('123456789');
|
||||
$company->setInn('1234567890123');
|
||||
}
|
||||
}
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
use AtolOnline\{Constants\SnoTypes,
|
||||
Entities\Company,
|
||||
Exceptions\AtolEmailTooLongException,
|
||||
Exceptions\AtolEmailValidateException,
|
||||
Exceptions\AtolInnWrongLengthException,
|
||||
Exceptions\AtolPaymentAddressTooLongException
|
||||
};
|
||||
|
||||
/**
|
||||
* Class CompanyTest
|
||||
*/
|
||||
class CompanyTest extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Тестирует установку параметров через конструктор
|
||||
*/
|
||||
public function testConstructor()
|
||||
{
|
||||
$company = new Company(
|
||||
SnoTypes::OSN,
|
||||
'5544332219',
|
||||
'https://v4.online.atol.ru',
|
||||
'company@example.com'
|
||||
);
|
||||
$this->checkAtolEntity($company);
|
||||
$this->assertEquals(SnoTypes::OSN, $company->getSno());
|
||||
$this->assertEquals('5544332219', $company->getInn());
|
||||
$this->assertEquals('https://v4.online.atol.ru', $company->getPaymentAddress());
|
||||
$this->assertEquals('company@example.com', $company->getEmail());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о некорректной длине ИНН
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
|
||||
*/
|
||||
public function testAtolInnWrongLengthException()
|
||||
{
|
||||
$company = new Company();
|
||||
$this->expectException(AtolInnWrongLengthException::class);
|
||||
$company->setInn('321');
|
||||
$company->setInn('1234567890123');
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинном платёжном адресе
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException
|
||||
*/
|
||||
public function testAtolPaymentAddressTooLongException()
|
||||
{
|
||||
$company = new Company();
|
||||
$this->expectException(AtolPaymentAddressTooLongException::class);
|
||||
$company->setPaymentAddress(self::randomString(257));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о слишком длинной почте
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||
*/
|
||||
public function testAtolEmailTooLongException()
|
||||
{
|
||||
$company = new Company();
|
||||
$this->expectException(AtolEmailTooLongException::class);
|
||||
$company->setEmail(self::randomString(65));
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует исключение о некорректной почте
|
||||
*
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
|
||||
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
|
||||
*/
|
||||
public function testAtolEmailValidateException()
|
||||
{
|
||||
$company = new Company();
|
||||
$this->expectException(AtolEmailValidateException::class);
|
||||
$company->setEmail(self::randomString(15));
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Unit;
|
||||
|
||||
use AtolOnline\Api\CorrectionSchema;
|
||||
use AtolOnline\Api\SellSchema;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SchemaTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* Тестирует корректность работы объекта схемы документа
|
||||
* прихода, возврата прихода, расхода, возврата расхода
|
||||
*/
|
||||
public function testSellSchema()
|
||||
{
|
||||
$this->assertIsObject(SellSchema::get());
|
||||
$this->assertJson(SellSchema::json());
|
||||
}
|
||||
|
||||
/**
|
||||
* Тестирует корректность работы объекта схемы документа
|
||||
* коррекции прихода, коррекции расхода
|
||||
*/
|
||||
public function testCorrectionSchema()
|
||||
{
|
||||
$this->assertIsObject(CorrectionSchema::get());
|
||||
$this->assertJson(CorrectionSchema::json());
|
||||
}
|
||||
}
|
||||
@@ -1,39 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Copyright (c) Антон Аксенов (aka Anthony Axenov)
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Антон Аксенов (Anthony Axenov)
|
||||
*
|
||||
* This code is licensed under MIT.
|
||||
* Этот код распространяется по лицензии MIT.
|
||||
* https://github.com/anthonyaxenov/atol-online/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
use AtolOnline\{Constants\VatTypes, Entities\Vat};
|
||||
namespace AtolOnlineTests;
|
||||
|
||||
use AtolOnline\{
|
||||
Entities\Vat,
|
||||
Enums\VatTypes};
|
||||
|
||||
/**
|
||||
* Class VatTest
|
||||
*/
|
||||
class VatTest extends BasicTestCase
|
||||
class VatTestTodo extends BasicTestCase
|
||||
{
|
||||
/**
|
||||
* Тестирует каждый тип ставки НДС
|
||||
*
|
||||
* @dataProvider vatProvider
|
||||
* @param string $vat_type Тип НДС
|
||||
* @param float $sum Исходная сумма
|
||||
* @param float $expected_set Ожидаемый результат после установки суммы
|
||||
* @param float $expected_add Ожидаемый результат после прибавления 20р
|
||||
* @param string $vat_type Тип НДС
|
||||
* @param float $sum Исходная сумма
|
||||
* @param float $expected_set Ожидаемый результат после установки суммы
|
||||
* @param float $expected_add Ожидаемый результат после прибавления 20р
|
||||
*/
|
||||
public function testVat(string $vat_type, float $sum, float $expected_set, float $expected_add)
|
||||
{
|
||||
$vat = new Vat($vat_type);
|
||||
$this->assertEquals(0, $vat->getFinalSum(), 'Test '.$vat_type.' | 1 step');
|
||||
$this->assertEquals(0, $vat->getFinalSum(), 'Test ' . $vat_type . ' | 1 step');
|
||||
$vat->setSum($sum);
|
||||
$this->assertEquals($expected_set, $vat->getFinalSum(), 'Test '.$vat_type.' | 2 step');
|
||||
$this->assertEquals($expected_set, $vat->getFinalSum(), 'Test ' . $vat_type . ' | 2 step');
|
||||
$vat->addSum(20);
|
||||
$this->assertEquals($expected_add, $vat->getFinalSum(), 'Test '.$vat_type.' | 3 step');
|
||||
$this->assertEquals($expected_add, $vat->getFinalSum(), 'Test ' . $vat_type . ' | 3 step');
|
||||
$vat->addSum(-20);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Провайдер данных для тестирования разных типов ставок НДС
|
||||
*
|
||||
Reference in New Issue
Block a user