43 Commits

Author SHA1 Message Date
8d9f218280 Мелкофиксы по документации и roadmap 2020-06-07 20:12:50 +08:00
9ed999f9fc Улучшен класс Kkt
+ setCallbackUrl(): валидация
* setLogin() и setPassword() более не зависят от тестового режима
* setPassword(): выброс AtolKktPasswordTooLongException
* auth(): выброс AtolAuthFailedException
* valid_strlen()
* Constraints::MAX_LENGTH_LOGIN
* Constraints::MAX_LENGTH_PASSWORD
* Constraints::PATTERN_CALLBACK_URL
* phpdoc
* исправление опечаток при выбросе некоторых исключений
2020-06-07 20:12:50 +08:00
989c06a383 Улучшен класс Item
* valid_strlen()
* Constraints::MAX_LENGTH_ITEM_NAME
* Constraints::MAX_LENGTH_MEASUREMENT_UNIT
* Constraints::MAX_LENGTH_USER_DATA
2020-06-07 20:12:23 +08:00
9bd99c81a9 Улучшен класс Document
* валидация в setCashier() только если передан не-null
* valid_strlen()
* Constraints::MAX_LENGTH_CASHIER_NAME
* phpdoc
2020-06-07 20:12:23 +08:00
2943d93962 Улучшен класс Company
* valid_strlen()
* Constraints::MAX_LENGTH_PAYMENT_ADDRESS
* phpdoc
2020-06-07 20:12:23 +08:00
8eb309bc58 Улучшен класс Сlient
* valid_strlen()
* Constraints::MAX_LENGTH_CLIENT_NAME
* Constraints::MAX_LENGTH_CLIENT_PHONE
* phpdoc
2020-06-07 20:12:23 +08:00
b74f652127 Улучшен trait HasInn
* Constraints::PATTERN_INN
* phpdoc
2020-06-07 20:12:23 +08:00
1061914a5f Улучшен trait HasEmail
* valid_strlen()
* Constraints::MAX_LENGTH_EMAIL
* phpdoc
2020-06-07 20:12:23 +08:00
5424726a97 Мелкофиксы в исключениях
* использование valid_strlen() в AtolInnWrongLengthException и AtolTooLongException
* фикс опечатки в AtolEmailTooLongException
2020-06-07 20:12:23 +08:00
2b3713db69 Новые исключения
+ AtolAuthFailedException
+ AtolCallbackUrlTooLongException
+ AtolInvalidCallbackUrlException
+ AtolKktPasswordTooLongException
2020-06-07 20:12:23 +08:00
a6b57115b6 Новый класс Constraints 2020-06-07 20:12:23 +08:00
12e0e49c9b Удалёно всё, что связано со схемами 2020-06-07 20:12:22 +08:00
3ffab562f8 Новый файл helpers 2020-06-07 20:12:22 +08:00
c05e013a5a Освежил документацию в части работы с объектом Kkt 2020-06-04 22:29:36 +08:00
e282de7e08 Вернул назад переопределение параметров компании при тестовом режиме: ИНН, адрес места расчётов
Также появился новый класс с константами тестовых параметров
2020-06-04 22:12:34 +08:00
c14b680be4 Проброс external_id на регистрацию документа 2020-06-01 04:12:23 +08:00
7558cb6638 Убрал схему Атола валидации количества НДС, оплат и предметов 2020-06-01 03:58:31 +08:00
d3fe2cba9a Удалена перезапись компании в тестовом режиме. Новый метод Kkt::setAuthToken() 2020-06-01 03:26:25 +08:00
e70a65fa44 Улучшен метод Kkt::registerDocument
+ теперь принимает любой собственного external_id, если пусто - сгенерирует uuid
* исправлен недостаток полей компании в тестовом режиме
* уточнения phpdoc
2020-05-30 04:29:44 +08:00
ba5166f2cf Метод Kkt::getAuthToken() теперь открыт 2020-05-30 03:45:06 +08:00
93f5186b15 Перезапись компании в документе при тестовом режиме 2020-05-30 01:59:24 +08:00
f2b4952aa5 Установка адреса callback для тестового режима 2020-05-30 01:59:24 +08:00
7899daf421 Снова фикс ошибок при приведении документа к json-строке 2020-05-30 01:59:23 +08:00
4cf6e81d5f Исправлены тесты компании и клиента 2020-05-29 22:24:15 +08:00
9d7dd75cd9 Испарвлен тест на длину имени предмета расчёта 2020-05-29 22:15:47 +08:00
4d7e5dd76e Фикс возвращаемого значения KktResponse::getContent() 2020-05-29 22:06:04 +08:00
0f658d38a9 Фикс ошибок при приведении докумнета к json-строке 2020-05-29 22:05:35 +08:00
ca32fe5923 Повсюду улучшена проверка длин строк 2020-05-28 22:56:26 +08:00
9ea1c81666 Скорректирован Document::jsonSerialize() - не выдаёт пустого кассира 2020-05-28 22:55:53 +08:00
12b98dcdac Document::fromRaw() теперь парсит входящий json как массив, а не объект 2020-05-28 22:55:27 +08:00
1fec446ce0 Фикс тестов НДС 2020-05-28 01:31:37 +08:00
6256c14522 Обновления в composer.lock 2020-05-28 01:25:27 +08:00
7dff642f0a Бейджик в readme + фикс composer.json 2020-05-28 01:14:53 +08:00
670f440620 Github actions только на мастере 2020-05-28 01:13:08 +08:00
3385420005 Merge branch 'dev'. Мнда, я забыл слить изменения... 2020-05-28 00:56:31 +08:00
ff42eebb8c [RELEASE] v0.2.1-b 2020-05-28 00:53:18 +08:00
9121d44a26 Merge branch 'master' into dev 2020-05-28 00:43:28 +08:00
600a505c83 Генерация объекта документа по сырой json-строке 2020-05-28 00:41:58 +08:00
4fccf7809d Небольшие правки по Item (улучшена проверка длины ед. изм.) 2020-05-28 00:41:01 +08:00
2d29ff3994 Фикс исключения некорректного UUID в методе Kkt::getDocumentStatus() 2020-05-28 00:39:42 +08:00
954843e3ad Фикс исключения превышения количества ставок НДС в массиве 2020-05-28 00:38:48 +08:00
a619b06a48 Исправлен расчёт НДС для документа 2020-05-28 00:38:16 +08:00
0bb194b1f8 Улучшены исключения
- добавлены теги ФФД для удобства
- тексты исключений переведены на англ. язык во избежание проблем с кодировками
- новые исключения TooMany и TooLong для удобства, подходящие по смыслу исключения унаследованы от них
2020-05-27 23:10:30 +08:00
61 changed files with 1215 additions and 631 deletions

View File

@@ -1,6 +1,9 @@
name: Composer and phpunit tests
name: Build
on: [push]
on:
push:
branches:
- master
jobs:
build:

View File

@@ -1,5 +1,7 @@
# АТОЛ Онлайн
![Build](https://github.com/anthonyaxenov/atol-online/workflows/Build/badge.svg?branch=master)
Библиотека для фискализации чеков по 54-ФЗ через [облачную ККТ АТОЛ](https://online.atol.ru/).
Текущая поддерживаемая версия API: **5.1**

View File

@@ -26,8 +26,6 @@
- [ ] Тесты для регистрации документа возврата расхода
- [ ] Тесты для регистрации документа коррекции расхода
- [ ] Вообще все расчёты вообще везде должны быть строго в копейках. Рубли (дроби) должны быть только в JSON-представлениях
- [ ] Валидатор схемы для документов прихода, возврата прихода, расхода, возврата расхода
- [ ] Валидатор схемы для документов коррекции прихода, коррекции расхода
## Поддержка методов API (регистрация документов)
@@ -65,3 +63,18 @@
- [x] Пoддержка `correction.vats` (обязательный)
- [x] Пoддержка `correction.correction_info` (обязательный)
- [x] Пoддержка `correction.cashier`
## Не будут реализовываться
### Валидация генерируемых документов согласно актуальной схемы API
- Валидатор схемы для документов прихода, возврата прихода, расхода, возврата расхода
- Валидатор схемы для документов коррекции прихода, коррекции расхода
1. Отказ обусловлен скоростью выполнения.
Базовая реализация, которая была начата, подразумевала синглтон, который кешировал однажды полученную схему.
Практика показала, что этот единичный запрос может существенно тормозить работу сервера и в течение долгого времени
не отдавать ответ клиенту.
2. Такая валидация подходит в том случае, если бы при разработке использовалась концепция IoC.
До версии пакета 2.0.0 таких серьёзных имзенений не планируется.

View File

@@ -3,9 +3,14 @@
"description": "Library to use cloud cash register in e-commerce according to Russian Federal Law #54",
"license": "MIT",
"type": "library",
"version": "0.1.1-b",
"keywords": [
"54-fz",
"kkt",
"e-commerce",
"cash",
"cash register",
"payment",
"payment system",
"atol",
"atol-online"
],
@@ -41,6 +46,9 @@
"src/AtolOnline/Traits/",
"src/AtolOnline/Constants/",
"tests/"
],
"files": [
"src/helpers.php"
]
}
}

239
composer.lock generated
View File

@@ -4,27 +4,28 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "dae801b00d2c80c28d290f676970945b",
"content-hash": "20b642fe60192cf1e67c9aa8dca27440",
"packages": [
{
"name": "guzzlehttp/guzzle",
"version": "6.5.2",
"version": "6.5.4",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82"
"reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/a4a1b6930528a8f7ee03518e6442ec7a44155d9d",
"reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5"
"php": ">=5.5",
"symfony/polyfill-intl-idn": "1.17.0"
},
"require-dev": {
"ext-curl": "*",
@@ -32,7 +33,6 @@
"psr/log": "^1.1"
},
"suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
@@ -71,7 +71,7 @@
"rest",
"web service"
],
"time": "2019-12-23T11:57:10+00:00"
"time": "2020-05-25T19:35:05+00:00"
},
{
"name": "guzzlehttp/promises",
@@ -466,16 +466,16 @@
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.15.0",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14"
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"shasum": ""
},
"require": {
@@ -487,7 +487,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.15-dev"
"dev-master": "1.17-dev"
}
},
"autoload": {
@@ -520,7 +520,183 @@
"polyfill",
"portable"
],
"time": "2020-02-27T09:26:54+00:00"
"time": "2020-05-12T16:14:59+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/3bff59ea7047e925be6b7f2059d60af31bb46d6a",
"reference": "3bff59ea7047e925be6b7f2059d60af31bb46d6a",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
"symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php72": "^1.10"
},
"suggest": {
"ext-intl": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.17-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"intl",
"polyfill",
"portable",
"shim"
],
"time": "2020-05-12T16:47:27+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c",
"reference": "fa79b11539418b02fc5e1897267673ba2c19419c",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"suggest": {
"ext-mbstring": "For best performance"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.17-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Mbstring\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for the Mbstring extension",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"mbstring",
"polyfill",
"portable",
"shim"
],
"time": "2020-05-12T16:47:27+00:00"
},
{
"name": "symfony/polyfill-php72",
"version": "v1.17.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "f048e612a3905f34931127360bdd2def19a5e582"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/f048e612a3905f34931127360bdd2def19a5e582",
"reference": "f048e612a3905f34931127360bdd2def19a5e582",
"shasum": ""
},
"require": {
"php": ">=5.3.3"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.17-dev"
}
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
},
"files": [
"bootstrap.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"time": "2020-05-12T16:47:27+00:00"
}
],
"packages-dev": [
@@ -732,24 +908,21 @@
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.0.0",
"version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a"
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"require-dev": {
"phpunit/phpunit": "~6"
},
"type": "library",
"extra": {
"branch-alias": {
@@ -780,7 +953,7 @@
"reflection",
"static analysis"
],
"time": "2018-08-07T13:53:10+00:00"
"time": "2020-04-27T09:25:28+00:00"
},
{
"name": "phpdocumentor/reflection-docblock",
@@ -1198,16 +1371,16 @@
},
{
"name": "phpunit/phpunit",
"version": "8.5.3",
"version": "8.5.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf"
"reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67750516bc02f300e2742fed2f50177f8f37bedf",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/63dda3b212a0025d380a745f91bdb4d8c985adb7",
"reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7",
"shasum": ""
},
"require": {
@@ -1277,7 +1450,7 @@
"testing",
"xunit"
],
"time": "2020-03-31T08:52:04+00:00"
"time": "2020-05-22T13:51:52+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
@@ -1936,16 +2109,16 @@
},
{
"name": "webmozart/assert",
"version": "1.7.0",
"version": "1.8.0",
"source": {
"type": "git",
"url": "https://github.com/webmozart/assert.git",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598"
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598",
"url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"shasum": ""
},
"require": {
@@ -1953,7 +2126,7 @@
"symfony/polyfill-ctype": "^1.8"
},
"conflict": {
"vimeo/psalm": "<3.6.0"
"vimeo/psalm": "<3.9.1"
},
"require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13"
@@ -1980,7 +2153,7 @@
"check",
"validate"
],
"time": "2020-02-14T12:15:55+00:00"
"time": "2020-04-18T12:12:48+00:00"
}
],
"aliases": [],

View File

@@ -46,10 +46,10 @@ $customer = (new AtolOnline\Entities\Client())
* `AtolEmailValidateException` (если email невалиден).
Метод `setInn()` чистит входную строку от всех символов, кроме цифр, и проверяет длину (либо 10, либо 12 цифр).
Выбрасывает исключение `AtolInnWrongLengthException` (если длина строка ИНН некорректна).
Выбрасывает исключение `AtolInnWrongLengthException` (если длина ИНН некорректна).
Метод `setName()` проверяет входную строку на длину (до 256 символов).
Выбрасывает исключение `AtolNameTooLongException` (если слишком длинное наименование).
Выбрасывает исключение `AtolNameTooLongException` (если слишком длинное имя).
Метод `setPhone()` чистит входную строку от всех символов, кроме цифр и знака `+`, и проверяет длину (до 64 символов).
Выбрасывает исключение `AtolPhoneTooLongException` (если слишком длинный номер телефона).

View File

@@ -46,7 +46,7 @@ $company = (new AtolOnline\Entities\Company())
* `AtolEmailValidateException` (если email невалиден).
Метод `setInn()` чистит входную строку от всех символов, кроме цифр, и проверяет длину (либо 10, либо 12 цифр).
Выбрасывает исключение `AtolInnWrongLengthException` (если длина строка ИНН некорректна).
Выбрасывает исключение `AtolInnWrongLengthException` (если длина ИНН некорректна).
Метод `setPaymentAddress()` проверяет длину (до 256 символов).
Выбрасывает исключение `AtolPaymentAddressTooLongException` (если слишком длинный адрес места расчётов).

View File

@@ -164,4 +164,4 @@ $json_array = $doc->jsonSerialize();
---
[Вернуться к содержанию](readme.md)
[Вернуться к содержанию](readme.md)

View File

@@ -49,12 +49,18 @@ $kkt->getGroup();
Эти параметры нужно задать [объекту компании](/docs/company.md), который будет передаваться в документах через эту ККТ.
<a name='testmode'></a>
## Тестовый режим
На самом деле, в АТОЛ Онлайн нет понятия *тестовая операция* или чего-то в этом духе.
АТОЛ предоставляет нам отдельную тестовую ККТ.
АТОЛ предоставляет нам отдельную тестовую среду (ККТ).
[Её настройки](https://online.atol.ru/files/ffd/test_sreda.txt) уже указаны в коде библиотеки.
*Под тестовым режимом работы подразумевается использование этой тестовой ККТ.*
*Под тестовым режимом работы подразумевается использование другой (тестовой) ККТ.*
При включенном тестовом режиме:
* меняется логин, пароль и группа (для обращения на тестовую ККТ)
* между авторизацией и операцией над документом, в `Company` документа переопределяется ИНН, СНО и адрес места
расчётов на те, что указаны в [параметрах тестовой среды](https://online.atol.ru/files/ffd/test_sreda.txt).
В библиотеке есть переключатель настроек ККТ.
С его помощью можете поменять вашу боевую ККТ на тестовую и наоборот.
@@ -70,13 +76,43 @@ $kkt->setTestMode(false); // выключить
> Если вы включили тестовый режим (как показано выше), то используются именно эта ККТ, а не ваша.
> После выключения тестового режима настройки доступа к ККТ меняются на ваши (используется уже ваша ККТ).
Если по каким-то причинам у вас не получится использовать тестовый режим, вы можете проводить свои тесты в боевом режиме (на собственной ККТ).
Для включения тестового режима необязательно задавать параметры боевой ККТ.
Если по каким-то причинам у вас не получится использовать тестовый режим, вы можете проводить свои тесты в боевом
режиме (на собственной ККТ).
В этом случае важно понимать следующее:
1. сразу после оформления документа **прихода** необходимо оформлять точно такой же документ **возврата прихода**;
2. [вы обязательно забудете о пункте 1](http://murphy-law.net.ru/basics.html);
3. пп. 1 и 2 в любом случае скажутся на ваших финансовых отчётах;
4. вся ответственность за пп. 1-3 и последствия ложится только на вас.
## Авторизация на ККТ
Перед первым запросом на ККТ происходит аутентификация на сервере по логину и паролю.
В ответ приходит авторизационный токен, срок жизни коего равен **24 часам**.
После первой успешной операции возможно получить этот токен следующим образом:
```php
$kkt->getAuthToken(); // вернёт строку длиной 128 символа
```
Этот токен можно сохранить и переиспользовать в течение всего срока его жизни.
Спустя это время следует получить новый токен.
Для дальнейшего использования однажды полученный токен следует указывать следующим образом:
```php
$kkt->setAuthToken($token_string);
```
Если токен был установлен перед выполнением операции, то при выполнении операции будет использоваться именно он, а новый
запрашиваться не будет. Если операция завершится ошибочно из-за истёкшего токена, следует повторить операцию без
использования метода `setAuthToken()`, либо обнулив его следующим образом:
```php
$kkt->setAuthToken(null);
```
## Регистрация документа
Для регистрации документа **прихода** необходимо вызвать метод `sell()`:
@@ -106,29 +142,64 @@ $result = $kkt->buyRefund($document);
Для операций, перечисленных выше, документы не должны содержать [данных коррекции](/docs/documents.md#correction).
Тогда как для операций коррекции, которые описаны ниже, эти данные должны присутствовать.
Для регистрации документа **коррекции прихода** необходимо вызвать метод `sellRefund()`:
Для регистрации документа **коррекции прихода** необходимо вызвать метод `sellCorrection()`:
```php
$result = $kkt->sellCorrection($document);
```
Для регистрации документа **коррекции расхода** необходимо вызвать метод `buyRefund()`:
Для регистрации документа **коррекции расхода** необходимо вызвать метод `buyCorrection()`:
```php
$result = $kkt->buyCorrection($document);
```
Любой из перечисленных выше шести методов может выбросить исключение `AtolAuthFailedException` при ошибке
аутентификации или авторизации.
### Собственный идентификатор документа
Каждый документ, переданный на ККТ для регистрации, всегда имеет свой идентификатор, абсолютно уникальный среди всех
документов когда-либо регистрировавшихся на ККТ, даже если при регистрации были ошибки.
По умолчанию это UUID версии 4.
Чтобы использовать собственный идентификатор, следует передать нужное строковое значение вторым параметром в любой из
шести описанных выше методов, например:
```php
$kkt->sell($document, $my_unique_id);
$kkt->sellRefund($document, $my_unique_id);
$kkt->buy($document, $my_unique_id);
$kkt->buyRefund($document, $my_unique_id);
$kkt->sellCorrection($document, $my_unique_id);
$kkt->buyCorrection($document, $my_unique_id);
```
Если `$my_unique_id` равен `null` или пустой строке, то будет сгенерирован новый UUID.
Узнать его можно будет только в ответе от ККТ.
### Передача callback_url
Перед регистрацией документа можно указать `callback_url`.
АТОЛ отправит на указанный URL результат регистрации.
Вам необходимо расположить по этому адресу скрипт, обрабатывающий этот результат.
По этому адресу должен располагаться код, который будет обрабатывать этот результат.
```php
$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`.
@@ -138,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-декодированное тело ответа
@@ -158,7 +229,7 @@ $err_text = $result->error->text;
Проверка корректности ответа (отсутствия ошибок) работает через метод `isValid()`:
```php
$kkt->isValid(); // вернёт true, если ошибок нет
$kkt->getLastResponse()->isValid(); // вернёт true, если ошибок нет
```
## Проверка статуса документа

View File

@@ -9,12 +9,19 @@
namespace AtolOnline\Api;
use AtolOnline\{Entities\Document,
use AtolOnline\{Constants\Constraints,
Constants\TestEnvParams,
Entities\Company,
Entities\Document,
Exceptions\AtolAuthFailedException,
Exceptions\AtolCallbackUrlTooLongException,
Exceptions\AtolCorrectionInfoException,
Exceptions\AtolInvalidCallbackUrlException,
Exceptions\AtolInvalidUuidException,
Exceptions\AtolKktLoginEmptyException,
Exceptions\AtolKktLoginTooLongException,
Exceptions\AtolKktPasswordEmptyException,
Exceptions\AtolUuidValidateException,
Exceptions\AtolKktPasswordTooLongException,
Exceptions\AtolWrongDocumentTypeException
};
use GuzzleHttp\Client;
@@ -58,6 +65,7 @@ class Kkt extends Client
* @throws \AtolOnline\Exceptions\AtolKktLoginEmptyException Логин ККТ не может быть пустым
* @throws \AtolOnline\Exceptions\AtolKktLoginTooLongException Слишком длинный логин ККТ
* @throws \AtolOnline\Exceptions\AtolKktPasswordEmptyException Пароль ККТ не может быть пустым
* @throws \AtolOnline\Exceptions\AtolKktPasswordTooLongException Слишком длинный пароль ККТ
* @see https://guzzle.readthedocs.io/en/latest/request-options.html
*/
public function __construct(
@@ -115,12 +123,10 @@ class Kkt extends Client
*/
public function setLogin(string $login)
{
if (!$this->isTestMode()) {
if (empty($login)) {
throw new AtolKktLoginEmptyException();
} elseif (strlen($login) > 100) {
throw new AtolKktLoginTooLongException($login, 100);
}
if (empty($login)) {
throw new AtolKktLoginEmptyException();
} elseif (valid_strlen($login) > Constraints::MAX_LENGTH_LOGIN) {
throw new AtolKktLoginTooLongException($login, Constraints::MAX_LENGTH_LOGIN);
}
$this->kkt_config['prod']['login'] = $login;
return $this;
@@ -142,13 +148,14 @@ class Kkt extends Client
* @param string $password
* @return $this
* @throws \AtolOnline\Exceptions\AtolKktPasswordEmptyException Пароль ККТ не может быть пустым
* @throws \AtolOnline\Exceptions\AtolKktPasswordTooLongException Слишком длинный пароль ККТ
*/
public function setPassword(string $password)
{
if (!$this->isTestMode()) {
if (empty($password)) {
throw new AtolKktPasswordEmptyException();
}
if (empty($password)) {
throw new AtolKktPasswordEmptyException();
} elseif (valid_strlen($password) > Constraints::MAX_LENGTH_PASSWORD) {
throw new AtolKktPasswordTooLongException($password, Constraints::MAX_LENGTH_PASSWORD);
}
$this->kkt_config['prod']['pass'] = $password;
return $this;
@@ -169,10 +176,17 @@ class Kkt extends Client
*
* @param string $url
* @return $this
* @throws \AtolOnline\Exceptions\AtolCallbackUrlTooLongException Слишком длинный Callback URL
* @throws \AtolOnline\Exceptions\AtolInvalidCallbackUrlException Невалидный Callback URL
*/
public function setCallbackUrl(string $url)
{
$this->kkt_config['prod']['callback_url'] = $url;
if (valid_strlen($url) > Constraints::MAX_LENGTH_CALLBACK_URL) {
throw new AtolCallbackUrlTooLongException($url, Constraints::MAX_LENGTH_CALLBACK_URL);
} elseif (preg_match(Constraints::PATTERN_CALLBACK_URL, $url)) {
throw new AtolInvalidCallbackUrlException();
}
$this->kkt_config[$this->isTestMode() ? 'test' : 'prod']['callback_url'] = $url;
return $this;
}
@@ -221,105 +235,135 @@ class Kkt extends Client
/**
* Регистрирует документ прихода
*
* @param \AtolOnline\Entities\Document $document
* @param \AtolOnline\Entities\Document $document Объект документа
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
* @return \AtolOnline\Api\KktResponse
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \AtolOnline\Exceptions\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException Некорректная длина ИНН
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function sell(Document $document)
public function sell(Document $document, ?string $external_id = null)
{
if ($document->getCorrectionInfo()) {
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
}
return $this->registerDocument('sell', 'receipt', $document);
return $this->registerDocument('sell', 'receipt', $document, $external_id);
}
/**
* Регистрирует документ возврата прихода
*
* @param \AtolOnline\Entities\Document $document
* @param \AtolOnline\Entities\Document $document Объект документа
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
* @return \AtolOnline\Api\KktResponse
* @throws \AtolOnline\Exceptions\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException Некорректная длина ИНН
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException Слишком большая сумма
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function sellRefund(Document $document)
public function sellRefund(Document $document, ?string $external_id = null)
{
if ($document->getCorrectionInfo()) {
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
throw new AtolCorrectionInfoException('Invalid operation on correction document');
}
return $this->registerDocument('sell_refund', 'receipt', $document->clearVats());
return $this->registerDocument('sell_refund', 'receipt', $document->clearVats(), $external_id);
}
/**
* Регистрирует документ коррекции прихода
*
* @param \AtolOnline\Entities\Document $document
* @param \AtolOnline\Entities\Document $document Объект документа
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
* @return \AtolOnline\Api\KktResponse
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \AtolOnline\Exceptions\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе отсутствуют данные коррекции
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException Некорректная длина ИНН
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function sellCorrection(Document $document)
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);
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\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException Некорректная длина ИНН
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function buy(Document $document)
public function buy(Document $document, ?string $external_id = null)
{
if ($document->getCorrectionInfo()) {
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
throw new AtolCorrectionInfoException('Invalid operation on correction document');
}
return $this->registerDocument('buy', 'receipt', $document);
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\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе есть данные коррекции
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException Некорректная длина ИНН
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
* @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)
public function buyRefund(Document $document, ?string $external_id = null)
{
if ($document->getCorrectionInfo()) {
throw new AtolCorrectionInfoException('Некорректная операция над документом коррекции');
throw new AtolCorrectionInfoException('Invalid operation on correction document');
}
return $this->registerDocument('buy_refund', 'receipt', $document->clearVats());
return $this->registerDocument('buy_refund', 'receipt', $document->clearVats(), $external_id);
}
/**
* Регистрирует документ коррекции расхода
*
* @param Document $document
* @param \AtolOnline\Entities\Document $document
* @param string|null $external_id Уникальный код документа (если не указан, то будет создан UUID)
* @return \AtolOnline\Api\KktResponse
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \AtolOnline\Exceptions\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolCorrectionInfoException В документе отсутствуют данные коррекции
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException Некорректная длтина ИНН
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function buyCorrection(Document $document)
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);
return $this->registerDocument('buy_correction', 'correction', $document, $external_id);
}
/**
@@ -327,13 +371,15 @@ class Kkt extends Client
*
* @param string $uuid UUID регистрации
* @return \AtolOnline\Api\KktResponse
* @throws \AtolOnline\Exceptions\AtolUuidValidateException Некорректный UUID документа
* @throws \AtolOnline\Exceptions\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolInvalidUuidException Некорректный UUID документа
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function getDocumentStatus(string $uuid)
{
$uuid = trim($uuid);
if (!Uuid::isValid($uuid)) {
throw new AtolUuidValidateException($uuid);
throw new AtolInvalidUuidException($uuid);
}
$this->auth();
return $this->sendAtolRequest('GET', 'report/'.$uuid);
@@ -347,7 +393,9 @@ class Kkt extends Client
* @param int $retry_count Количество попыток
* @param int $timeout Таймаут в секундах между попытками
* @return \AtolOnline\Api\KktResponse
* @throws \AtolOnline\Exceptions\AtolException Некорректный UUID документа
* @throws \AtolOnline\Exceptions\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolInvalidUuidException Некорректный UUID документа
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function pollDocumentStatus(string $uuid, int $retry_count = 5, int $timeout = 1)
{
@@ -364,6 +412,28 @@ class Kkt extends Client
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;
}
/**
* Сбрасывает настройки ККТ по умолчанию
*/
@@ -374,9 +444,9 @@ class Kkt extends Client
$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'] = 'v4-online-atol-ru_4179';
$this->kkt_config['test']['login'] = 'v4-online-atol-ru';
$this->kkt_config['test']['pass'] = 'iGFFuihss';
$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'] = '';
}
@@ -390,7 +460,7 @@ class Kkt extends Client
{
$headers['Content-type'] = 'application/json; charset=utf-8';
if ($this->getAuthToken()) {
$headers['Token'] = $this->auth_token;
$headers['Token'] = $this->getAuthToken();
}
return $headers;
}
@@ -429,6 +499,7 @@ class Kkt extends Client
* @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)
@@ -449,6 +520,8 @@ class Kkt extends Client
* Производит авторизацию на ККТ и получает токен доступа для дальнейших HTTP-запросов
*
* @return bool
* @throws \AtolOnline\Exceptions\AtolAuthFailedException Ошибка авторизации
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function auth()
{
@@ -458,7 +531,7 @@ class Kkt extends Client
'pass' => $this->getPassword(),
]);
if (!$result->isValid() || !$result->getContent()->token) {
return false;
throw new AtolAuthFailedException($result);
}
$this->auth_token = $result->getContent()->token;
}
@@ -468,36 +541,36 @@ class Kkt extends Client
/**
* Отправляет документ на регистрацию
*
* @param string $api_method Метод API
* @param string $type Тип документа: receipt, correction
* @param \AtolOnline\Entities\Document $document Объект документа
* @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\AtolAuthFailedException Ошибка авторизации
* @throws \AtolOnline\Exceptions\AtolWrongDocumentTypeException Некорректный тип документа
* @throws \Exception
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException Некорректная длина ИНН
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function registerDocument(string $api_method, string $type, Document $document)
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();
$data = [
'timestamp' => date('d.m.y H:i:s'),
'external_id' => Uuid::uuid4()->toString(),
'service' => ['callback_url' => $this->getCallbackUrl()],
$type => $document,
];
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);
}
/**
* Возвращает текущий токен авторизации
*
* @return string
*/
protected function getAuthToken()
{
return $this->auth_token;
}
}

View File

@@ -81,9 +81,9 @@ class KktResponse implements JsonSerializable
/**
* Возвращает объект результата запроса
*
* @return \stdClass
* @return stdClass|null
*/
public function getContent(): stdClass
public function getContent(): ?stdClass
{
return $this->content;
}

View File

@@ -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());
}
}

View File

@@ -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';
}

View File

@@ -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';
}

View File

@@ -0,0 +1,76 @@
<?php
namespace AtolOnline\Constants;
/**
* Класс с константами ограничений: максимальные длины, правила валидации значений
*
* @package AtolOnline\Constants
*/
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а-яА-Я\-\.\?\,\'\/\\\+&=%\$#_]*)?$";
}

View File

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

View File

@@ -9,7 +9,7 @@
namespace AtolOnline\Entities;
use AtolOnline\{Exceptions\AtolNameTooLongException, Exceptions\AtolPhoneTooLongException, Traits\HasEmail, Traits\HasInn};
use AtolOnline\{Constants\Constraints, Exceptions\AtolNameTooLongException, Exceptions\AtolPhoneTooLongException, Traits\HasEmail, Traits\HasInn};
/**
* Класс Client, описывающий сущность покупателя
@@ -46,11 +46,11 @@ class Client extends Entity
* @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
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException Слишком длинный email
* @throws \AtolOnline\Exceptions\AtolEmailValidateException Невалидный email
* @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)
{
@@ -89,8 +89,8 @@ class Client extends Entity
public function setName(string $name)
{
$name = trim($name);
if (strlen($name) > 256) {
throw new AtolNameTooLongException($name, 256);
if (valid_strlen($name) > Constraints::MAX_LENGTH_CLIENT_NAME) {
throw new AtolNameTooLongException($name, Constraints::MAX_LENGTH_CLIENT_NAME);
}
$this->name = $name;
return $this;
@@ -119,8 +119,8 @@ class Client extends Entity
public function setPhone(string $phone)
{
$phone = preg_replace("/[^0-9+]/", '', $phone);
if (strlen($phone) > 64) {
throw new AtolPhoneTooLongException($phone, 64);
if (valid_strlen($phone) > Constraints::MAX_LENGTH_CLIENT_PHONE) {
throw new AtolPhoneTooLongException($phone, Constraints::MAX_LENGTH_CLIENT_PHONE);
}
$this->phone = $phone;
return $this;

View File

@@ -9,7 +9,8 @@
namespace AtolOnline\Entities;
use AtolOnline\{Exceptions\AtolEmailTooLongException,
use AtolOnline\{Constants\Constraints,
Exceptions\AtolEmailTooLongException,
Exceptions\AtolEmailValidateException,
Exceptions\AtolInnWrongLengthException,
Exceptions\AtolPaymentAddressTooLongException,
@@ -52,10 +53,10 @@ class Company extends Entity
* @param string|null $inn
* @param string|null $paymentAddress
* @param string|null $email
* @throws AtolEmailTooLongException
* @throws AtolEmailValidateException
* @throws AtolInnWrongLengthException
* @throws AtolPaymentAddressTooLongException
* @throws AtolEmailTooLongException Слишком длинный email
* @throws AtolEmailValidateException Невалидный email
* @throws AtolInnWrongLengthException Некорректная длина ИНН
* @throws AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
*/
public function __construct(string $sno = null, string $inn = null, string $paymentAddress = null, string $email = null)
{
@@ -110,13 +111,13 @@ class Company extends Entity
*
* @param string $payment_address
* @return $this
* @throws AtolPaymentAddressTooLongException
* @throws AtolPaymentAddressTooLongException Слишком длинный адрес места расчётов
*/
public function setPaymentAddress(string $payment_address)
{
$payment_address = trim($payment_address);
if (strlen($payment_address) > 256) {
throw new AtolPaymentAddressTooLongException($payment_address, 256);
if (valid_strlen($payment_address) > Constraints::MAX_LENGTH_PAYMENT_ADDRESS) {
throw new AtolPaymentAddressTooLongException($payment_address, Constraints::MAX_LENGTH_PAYMENT_ADDRESS);
}
$this->payment_address = $payment_address;
return $this;

View File

@@ -9,7 +9,10 @@
namespace AtolOnline\Entities;
use AtolOnline\Constants\Constraints;
use AtolOnline\Exceptions\AtolCashierTooLongException;
use AtolOnline\Exceptions\AtolException;
use AtolOnline\Exceptions\AtolInvalidJsonException;
/**
* Класс, описывающий документ
@@ -60,10 +63,6 @@ class Document extends Entity
/**
* Document constructor.
*
* @throws \AtolOnline\Exceptions\AtolTooManyItemsException Слишком много предметов расчёта
* @throws \AtolOnline\Exceptions\AtolTooManyPaymentsException Слишком много оплат
* @throws \AtolOnline\Exceptions\AtolTooManyVatsException Слишком много ставок НДС
*/
public function __construct()
{
@@ -82,10 +81,6 @@ class Document extends Entity
public function clearVats()
{
$this->setVats([]);
foreach ($this->getItems() as &$item) {
$item->setVatType(null);
}
$this->calcTotal();
return $this;
}
@@ -98,11 +93,7 @@ class Document extends Entity
*/
public function addVat(Vat $vat)
{
if (count($this->getVats()) == 0 && !$vat->getSum()) {
$vat->setSum($this->calcTotal());
}
$this->vats->add($vat);
$this->calcTotal();
return $this;
}
@@ -127,7 +118,6 @@ class Document extends Entity
public function setVats(array $vats)
{
$this->vats->set($vats);
$this->calcTotal();
return $this;
}
@@ -210,9 +200,9 @@ class Document extends Entity
/**
* Возвращает заданного клиента (покупателя)
*
* @return Client
* @return Client|null
*/
public function getClient(): Client
public function getClient(): ?Client
{
return $this->client;
}
@@ -232,9 +222,9 @@ class Document extends Entity
/**
* Возвращает заданную компанию (продавца)
*
* @return Company
* @return Company|null
*/
public function getCompany(): Company
public function getCompany(): ?Company
{
return $this->company;
}
@@ -270,9 +260,11 @@ class Document extends Entity
*/
public function setCashier(?string $cashier)
{
$cashier = trim($cashier);
if (strlen($cashier) > 64) {
throw new AtolCashierTooLongException($cashier);
if ($cashier !== null) {
$cashier = trim($cashier);
if (valid_strlen($cashier) > Constraints::MAX_LENGTH_CASHIER_NAME) {
throw new AtolCashierTooLongException($cashier, Constraints::MAX_LENGTH_CASHIER_NAME);
}
}
$this->cashier = $cashier;
return $this;
@@ -309,11 +301,10 @@ class Document extends Entity
public function calcTotal()
{
$sum = 0;
$this->clearVats();
foreach ($this->items->get() as $item) {
$sum += $item->calcSum();
}
foreach ($this->vats->get() as $vat) {
$vat->setSum($sum);
$this->addVat(new Vat($item->getVat()->getType(), $item->getSum()));
}
return $this->total = round($sum, 2);
}
@@ -329,21 +320,108 @@ class Document extends Entity
}
/**
* @inheritDoc
* Собирает объект документа из сырой 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
*/
public static function fromRaw(string $json)
{
$array = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new AtolInvalidJsonException();
}
$doc = new self();
if (isset($array['company'])) {
$doc->setCompany(new Company(
$array['company']['sno'] ?? null,
$array['company']['inn'] ?? null,
$array['company']['payment_address'] ?? null,
$array['company']['email'] ?? null
));
}
if (isset($array['client'])) {
$doc->setClient(new Client(
$array['client']['name'] ?? null,
$array['client']['phone'] ?? null,
$array['client']['email'] ?? null,
$array['client']['inn'] ?? null
));
}
if (isset($array['items'])) {
foreach ($array['items'] as $ar_item) {
$item = new Item(
$ar_item['name'] ?? null,
$ar_item['price'] ?? null,
$ar_item['quantity'] ?? null,
$ar_item['measurement_unit'] ?? null,
$ar_item['vat']['type'] ?? null,
$ar_item['payment_object'] ?? null,
$ar_item['payment_method'] ?? null
);
if (!empty($ar_item['user_data'])) {
$item->setUserData($ar_item['user_data'] ?? null);
}
$doc->addItem($item);
}
}
if (isset($array['payments'])) {
foreach ($array['payments'] as $ar_payment) {
$payment = new Payment();
if (isset($ar_payment['type'])) {
$payment->setType($ar_payment['type']);
}
if (isset($ar_payment['sum'])) {
$payment->setSum($ar_payment['sum']);
}
$doc->payments->add($payment);
}
}
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
*/
public function jsonSerialize()
{
$json = [
'company' => $this->getCompany()->jsonSerialize(), // обязательно
'payments' => $this->payments->jsonSerialize(), // обязательно
'cashier' => $this->getCashier() ?? '',
];
if ($this->getCompany()) {
$json['company'] = $this->getCompany()->jsonSerialize(); // обязательно
}
if ($this->getPayments()) {
$json['payments'] = $this->payments->jsonSerialize(); // обязательно
}
if ($this->getCashier()) {
$json['cashier'] = $this->getCashier();
}
if ($this->getCorrectionInfo()) {
$json['correction_info'] = $this->getCorrectionInfo()->jsonSerialize(); // обязательно для коррекционных
} else {
$json['client'] = $this->getClient()->jsonSerialize(); // обязательно для некоррекционных
$json['items'] = $this->items->jsonSerialize(); // обязательно для некоррекционных
if ($this->getClient()) {
$json['client'] = $this->getClient()->jsonSerialize(); // обязательно для некоррекционных
}
if ($this->getItems()) {
$json['items'] = $this->items->jsonSerialize(); // обязательно для некоррекционных
}
$json['total'] = $this->calcTotal(); // обязательно для некоррекционных
}
if ($this->getVats()) {
@@ -351,4 +429,4 @@ class Document extends Entity
}
return $json;
}
}
}

View File

@@ -9,9 +9,10 @@
namespace AtolOnline\Entities;
use AtolOnline\{Exceptions\AtolNameTooLongException,
use AtolOnline\{Constants\Constraints,
Exceptions\AtolNameTooLongException,
Exceptions\AtolPriceTooHighException,
Exceptions\AtolQuantityTooHighException,
Exceptions\AtolTooManyException,
Exceptions\AtolUnitTooLongException,
Exceptions\AtolUserdataTooLongException,
Traits\RublesKopeksConverter
@@ -83,7 +84,7 @@ class Item extends Entity
* @param string|null $payment_method Способ расчёта
* @throws AtolNameTooLongException Слишком длинное наименование
* @throws AtolPriceTooHighException Слишком высокая цена за одну единицу
* @throws AtolQuantityTooHighException Слишком большое количество
* @throws AtolTooManyException Слишком большое количество
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
*/
public function __construct(
@@ -101,17 +102,17 @@ class Item extends Entity
if ($price) {
$this->setPrice($price);
}
if ($payment_object) {
$this->setPaymentObject($payment_object);
}
if ($quantity) {
$this->setQuantity($quantity);
}
if ($measurement_unit) {
$this->setMeasurementUnit($measurement_unit);
}
if ($vat_type) {
$this->setVatType($vat_type);
}
if ($measurement_unit) {
$this->setMeasurementUnit($measurement_unit);
if ($payment_object) {
$this->setPaymentObject($payment_object);
}
if ($payment_method) {
$this->setPaymentMethod($payment_method);
@@ -138,8 +139,8 @@ class Item extends Entity
public function setName(string $name)
{
$name = trim($name);
if (strlen($name) > 128) {
throw new AtolNameTooLongException($name, 128);
if (valid_strlen($name) > Constraints::MAX_LENGTH_ITEM_NAME) {
throw new AtolNameTooLongException($name, Constraints::MAX_LENGTH_ITEM_NAME);
}
$this->name = $name;
return $this;
@@ -188,7 +189,7 @@ class Item extends Entity
* @param float $quantity Количество
* @param string|null $measurement_unit Единица измерения количества
* @return $this
* @throws AtolQuantityTooHighException Слишком большое количество
* @throws AtolTooManyException Слишком большое количество
* @throws AtolPriceTooHighException Слишком высокая общая стоимость
* @throws AtolUnitTooLongException Слишком длинное название единицы измерения
*/
@@ -196,7 +197,7 @@ class Item extends Entity
{
$quantity = round($quantity, 3);
if ($quantity > 99999.999) {
throw new AtolQuantityTooHighException($quantity, 99999.999);
throw new AtolTooManyException($quantity, 99999.999);
}
$this->quantity = $quantity;
$this->calcSum();
@@ -226,8 +227,8 @@ class Item extends Entity
public function setMeasurementUnit(string $measurement_unit)
{
$measurement_unit = trim($measurement_unit);
if (strlen($measurement_unit) > 16) {
throw new AtolUnitTooLongException($measurement_unit, 16);
if (valid_strlen($measurement_unit) > Constraints::MAX_LENGTH_MEASUREMENT_UNIT) {
throw new AtolUnitTooLongException($measurement_unit, Constraints::MAX_LENGTH_MEASUREMENT_UNIT);
}
$this->measurement_unit = $measurement_unit;
return $this;
@@ -329,8 +330,8 @@ class Item extends Entity
public function setUserData(string $user_data)
{
$user_data = trim($user_data);
if (strlen($user_data) > 64) {
throw new AtolUserdataTooLongException($user_data, 64);
if (valid_strlen($user_data) > Constraints::MAX_LENGTH_USER_DATA) {
throw new AtolUserdataTooLongException($user_data, Constraints::MAX_LENGTH_USER_DATA);
}
$this->user_data = $user_data;
return $this;

View File

@@ -106,7 +106,7 @@ class ItemArray extends Entity
protected function validateCount(?array $items = null): bool
{
if ((!empty($items) && count($items) >= self::MAX_COUNT) || count($this->items) >= self::MAX_COUNT) {
throw new AtolTooManyItemsException(self::MAX_COUNT);
throw new AtolTooManyItemsException(count($items), self::MAX_COUNT);
}
return true;
}

View File

@@ -9,7 +9,6 @@
namespace AtolOnline\Entities;
use AtolOnline\Api\SellSchema;
use AtolOnline\Exceptions\AtolTooManyPaymentsException;
/**
@@ -19,6 +18,11 @@ use AtolOnline\Exceptions\AtolTooManyPaymentsException;
*/
class PaymentArray extends Entity
{
/**
* Максимальное количество элементов массива
*/
public const MAX_COUNT = 10;
/**
* @var Payment[] Массив оплат
*/
@@ -99,9 +103,8 @@ class PaymentArray extends Entity
*/
protected function validateCount(?array $payments = null): bool
{
$max_items = SellSchema::get()->properties->receipt->properties->payments->maxItems;
if ((!empty($payments) && count($payments) >= $max_items) || count($this->payments) >= $max_items) {
throw new AtolTooManyPaymentsException($max_items);
if ((!empty($payments) && count($payments) >= self::MAX_COUNT) || count($this->payments) >= self::MAX_COUNT) {
throw new AtolTooManyPaymentsException(count($payments), self::MAX_COUNT);
}
return true;
}

View File

@@ -26,12 +26,12 @@ class Vat extends Entity
private $type;
/**
* @var int Сумма в копейках, от которой пересчитывается размер налога
* @var int Сумма в копейках, от которой пересчитывается размер НДС
*/
private $sum_original = 0;
/**
* @var int Сумма налога в копейках
* @var int Сумма НДС в копейках
*/
private $sum_final = 0;
@@ -66,18 +66,19 @@ class Vat extends Entity
case VatTypes::VAT0:
return 0;
case VatTypes::VAT10:
return $kopeks * 10 / 100;
//return $kopeks * 10 / 100;
case VatTypes::VAT110:
return $kopeks * 10 / 110;
case VatTypes::VAT18:
return $kopeks * 18 / 100;
//return $kopeks * 18 / 100;
case VatTypes::VAT118:
return $kopeks * 18 / 118;
case VatTypes::VAT20:
return $kopeks * 20 / 100;
//return $kopeks * 20 / 100;
case VatTypes::VAT120:
return $kopeks * 20 / 120;
}
return 0;
}
/**

View File

@@ -9,7 +9,6 @@
namespace AtolOnline\Entities;
use AtolOnline\Api\SellSchema;
use AtolOnline\Exceptions\AtolTooManyVatsException;
/**
@@ -19,6 +18,11 @@ use AtolOnline\Exceptions\AtolTooManyVatsException;
*/
class VatArray extends Entity
{
/**
* Максимальное количество элементов массива
*/
public const MAX_COUNT = 6;
/**
* @var Vat[] Массив ставок НДС
*/
@@ -62,7 +66,11 @@ class VatArray extends Entity
public function add(Vat $vat)
{
if ($this->validateCount()) {
$this->vats[] = $vat;
if (isset($this->vats[$vat->getType()])) {
$this->vats[$vat->getType()]->addSum($vat->getSum());
} else {
$this->vats[$vat->getType()] = $vat;
}
}
return $this;
}
@@ -99,9 +107,8 @@ class VatArray extends Entity
*/
protected function validateCount(?array $vats = null): bool
{
$max_items = SellSchema::get()->properties->receipt->properties->vats->maxItems;
if ((!empty($vats) && count($vats) >= $max_items) || count($this->vats) >= $max_items) {
throw new AtolTooManyVatsException($max_items);
if ((!empty($vats) && count($vats) >= self::MAX_COUNT) || count($this->vats) >= self::MAX_COUNT) {
throw new AtolTooManyVatsException(count($vats), self::MAX_COUNT);
}
return true;
}

View File

@@ -0,0 +1,41 @@
<?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 AtolOnline\Api\KktResponse;
use Exception;
use Throwable;
/**
* Исключение, возникающее при работе с АТОЛ Онлайн
*
* @package AtolOnline\Exceptions
*/
class AtolAuthFailedException extends Exception
{
/**
* AtolAuthFailedException constructor.
*
* @param \AtolOnline\Api\KktResponse $last_response
* @param string $message
* @param int $code
* @param \Throwable|null $previous
*/
public function __construct(KktResponse $last_response, $message = "", $code = 0, Throwable $previous = null)
{
$message = $last_response->isValid()
? $message
: '['.$last_response->error->code.'] '.$last_response->error->text.
'. ERROR_ID: '.$last_response->error->error_ID.
'. TYPE: '.$last_response->error->type;
$code = $last_response->isValid() ? $code : $last_response->error->code;
parent::__construct($message, $code, $previous);
}
}

View File

@@ -0,0 +1,23 @@
<?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;
/**
* Исключение, возникающее при попытке указать слишком длинный callback_url
*
* @package AtolOnline\Exceptions
*/
class AtolCallbackUrlTooLongException extends AtolTooLongException
{
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Callback URL is too long';
}

View File

@@ -9,26 +9,22 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинное имя кассира
*
* @package AtolOnline\Exceptions
*/
class AtolCashierTooLongException extends AtolException
class AtolCashierTooLongException extends AtolTooLongException
{
/**
* AtolCashierTooLongException constructor.
*
* @param $name
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($name, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинное имя кассира (макс. длина 64, фактически '.strlen($name).'): '.$name;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1021,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Cashier name is too long';
}

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке зарегистрировать документ без данных коррекции
*
@@ -19,15 +17,7 @@ use Throwable;
class AtolCorrectionInfoException extends AtolException
{
/**
* AtolNoCorrectionInfoException constructor.
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @var string Сообщение об ошибке
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'В документе отсутствуют данные коррекции';
parent::__construct($message, $code, $previous);
}
protected $message = 'Document must have correction info';
}

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать пустой email
*
@@ -19,15 +17,15 @@ use Throwable;
class AtolEmailEmptyException extends AtolException
{
/**
* AtolEmailEmptyException constructor.
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Email не может быть пустым';
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1008,
1117,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Email cannot be empty';
}

View File

@@ -9,27 +9,23 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинный email
*
* @package AtolOnline\Exceptions
*/
class AtolEmailTooLongException extends AtolException
class AtolEmailTooLongException extends AtolTooLongException
{
/**
* AtolEmailTooLongException constructor.
*
* @param $email
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($email, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинный email (макс. длина '.$max.', фактически '.strlen($email).'): '.$email;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1008,
1117,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Email is too long';
}

View File

@@ -18,6 +18,14 @@ use Throwable;
*/
class AtolEmailValidateException extends AtolException
{
/**
* @inheritDoc
*/
protected $ffd_tags = [
1008,
1117,
];
/**
* AtolEmailValidateException constructor.
*
@@ -28,7 +36,6 @@ class AtolEmailValidateException extends AtolException
*/
public function __construct($email, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Некорректный email: '.$email;
parent::__construct($message, $code, $previous);
parent::__construct($message ?: 'Invalid email: '.$email, $code, $previous);
}
}

View File

@@ -10,6 +10,7 @@
namespace AtolOnline\Exceptions;
use Exception;
use Throwable;
/**
* Исключение, возникающее при работе с АТОЛ Онлайн
@@ -18,5 +19,33 @@ use Exception;
*/
class AtolException extends Exception
{
/**
* @var int[] Теги ФФД
*/
protected $ffd_tags = null;
/**
* AtolException constructor.
*
* @param string $message
* @param int $code
* @param \Throwable|null $previous
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
if ($this->getFfdTags()) {
$message .= ' [FFD tags: '.implode(', ', $this->getFfdTags()).']';
}
parent::__construct($message, $code, $previous);
}
/**
* Возвращает теги ФФД, с которыми связано исключение
*
* @return array|null
*/
protected function getFfdTags(): ?array
{
return $this->ffd_tags;
}
}

View File

@@ -18,6 +18,16 @@ use Throwable;
*/
class AtolInnWrongLengthException extends AtolException
{
/**
* @inheritDoc
*/
protected $ffd_tags = [
1016,
1018,
1226,
1228,
];
/**
* AtolInnWrongLengthException constructor.
*
@@ -28,7 +38,7 @@ class AtolInnWrongLengthException extends AtolException
*/
public function __construct($inn, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Длина ИНН должна быть 10 или 12 цифр, фактически '.strlen($inn).': '.$inn;
parent::__construct($message, $code, $previous);
parent::__construct($message ?: 'INN length must be 10 or 12 digits only, but actual is '.
valid_strlen($inn), $code, $previous);
}
}

View File

@@ -0,0 +1,23 @@
<?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;
/**
* Исключение, возникающее при попытке указать невалидный callback_url
*
* @package AtolOnline\Exceptions
*/
class AtolInvalidCallbackUrlException extends AtolException
{
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Invalid callback URL';
}

View File

@@ -0,0 +1,32 @@
<?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;
/**
* Исключение, возникающее при работе с невалидным JSON
*
* @package AtolOnline\Exceptions
*/
class AtolInvalidJsonException extends AtolException
{
/**
* AtolInnWrongLengthException constructor.
*
* @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);
}
}

View File

@@ -16,10 +16,10 @@ use Throwable;
*
* @package AtolOnline\Exceptions
*/
class AtolUuidValidateException extends AtolException
class AtolInvalidUuidException extends AtolException
{
/**
* AtolUuidValidateException constructor.
* AtolInvalidUuidException constructor.
*
* @param $uuid
* @param string $message
@@ -28,7 +28,6 @@ class AtolUuidValidateException extends AtolException
*/
public function __construct($uuid, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Некорректный UUID: '.$uuid;
parent::__construct($message, $code, $previous);
parent::__construct($message ?: 'Invalid UUID: '.$uuid, $code, $previous);
}
}

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать пустой логин ККТ
*
@@ -19,15 +17,7 @@ use Throwable;
class AtolKktLoginEmptyException extends AtolException
{
/**
* AtolKktLoginEmptyException constructor.
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @var string Сообщение об ошибке
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Логин ККТ не может быть пустым';
parent::__construct($message, $code, $previous);
}
protected $message = 'KKT login cannot be empty';
}

View File

@@ -9,27 +9,15 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинный логин ККТ
*
* @package AtolOnline\Exceptions
*/
class AtolKktLoginTooLongException extends AtolException
class AtolKktLoginTooLongException extends AtolTooLongException
{
/**
* AtolKktLoginTooLongException constructor.
*
* @param $login
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @var string Сообщение об ошибке
*/
public function __construct($login, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинный логин ККТ (макс. длина '.$max.', фактически '.strlen($login).'): '.$login;
parent::__construct($message, $code, $previous);
}
protected $message = 'KKT login is too long';
}

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать пустой пароль ККТ
*
@@ -19,15 +17,7 @@ use Throwable;
class AtolKktPasswordEmptyException extends AtolException
{
/**
* AtolKktPasswordEmptyException constructor.
*
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @var string Сообщение об ошибке
*/
public function __construct($message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Пароль ККТ не может быть пустым';
parent::__construct($message, $code, $previous);
}
protected $message = 'KKT password cannot be empty';
}

View File

@@ -0,0 +1,23 @@
<?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;
/**
* Исключение, возникающее при попытке указать слишком длинный пароль ККТ
*
* @package AtolOnline\Exceptions
*/
class AtolKktPasswordTooLongException extends AtolTooLongException
{
/**
* @var string Сообщение об ошибке
*/
protected $message = 'KKT password is too long';
}

View File

@@ -9,27 +9,26 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинное имя
*
* @package AtolOnline\Exceptions
*/
class AtolNameTooLongException extends AtolException
class AtolNameTooLongException extends AtolTooLongException
{
/**
* AtolNameTooLongException constructor.
*
* @param $name
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($name, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинное имя/наименование (макс. длина '.$max.', фактически '.strlen($name).'): '.$name;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1026,
1030,
1085,
1225,
1227,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Name is too long';
}

View File

@@ -9,8 +9,6 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинный платёжный адрес
*
@@ -19,17 +17,14 @@ use Throwable;
class AtolPaymentAddressTooLongException extends AtolException
{
/**
* AtolPaymentAddressTooLongException constructor.
*
* @param $address
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($address, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинный адрес (макс. длина '.$max.', фактически '.strlen($address).'): '.$address;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1187,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Payment address is too long';
}

View File

@@ -9,27 +9,26 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинный телефон
*
* @package AtolOnline\Exceptions
*/
class AtolPhoneTooLongException extends AtolException
class AtolPhoneTooLongException extends AtolTooLongException
{
/**
* AtolPhoneTooLongException constructor.
*
* @param $phone
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($phone, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинный телефон (макс. длина '.$max.', фактически '.strlen($phone).'): '.$phone;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1008,
1073,
1074,
1075,
1171,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Phone is too long';
}

View File

@@ -9,27 +9,22 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком высокую цену (сумму)
*
* @package AtolOnline\Exceptions
*/
class AtolPriceTooHighException extends AtolException
class AtolPriceTooHighException extends AtolTooManyException
{
/**
* AtolPriceTooHighException constructor.
*
* @param $price
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($price, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком большая сумма (макс. '.$max.'): '.$price;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1079,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Price is too high';
}

View File

@@ -0,0 +1,40 @@
<?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 AtolTooLongException 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
*/
public function __construct($string, $max, $message = "", $code = 0, Throwable $previous = null)
{
parent::__construct($message ?: $this->message.' (max length - '.$max.', actual length - '.
valid_strlen($string), $code, $previous);
}
}

View File

@@ -12,14 +12,19 @@ namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком большое количество
* Исключение, возникающее при попытке указать слишком большое количество чего-либо
*
* @package AtolOnline\Exceptions
*/
class AtolQuantityTooHighException extends AtolException
class AtolTooManyException extends AtolException
{
/**
* AtolQuantityTooHighException constructor.
* @var string Сообщение об ошибке
*/
protected $message = 'Quantity is too high';
/**
* AtolTooManyException constructor.
*
* @param $quantity
* @param $max
@@ -29,7 +34,7 @@ class AtolQuantityTooHighException extends AtolException
*/
public function __construct($quantity, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком большое количество (макс. '.$max.'): '.$quantity;
$message = $message ?: $this->message.' (max - '.$max.', actual - '.$quantity.')';
parent::__construct($message, $code, $previous);
}
}

View File

@@ -9,26 +9,15 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке добавить слишком много предметов расчёта в массив
*
* @package AtolOnline\Exceptions
*/
class AtolTooManyItemsException extends AtolException
class AtolTooManyItemsException extends AtolTooManyException
{
/**
* AtolTooManyItemsException constructor.
*
* @param int $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @var string Сообщение об ошибке
*/
public function __construct($max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком много предметов расчёта (макс. '.$max.')';
parent::__construct($message, $code, $previous);
}
protected $message = 'Too many items';
}

View File

@@ -9,26 +9,25 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке добавить слишком много ставок НДС в массив
* Исключение, возникающее при попытке добавить слишком много платежей в массив
*
* @package AtolOnline\Exceptions
*/
class AtolTooManyPaymentsException extends AtolException
class AtolTooManyPaymentsException extends AtolTooManyException
{
/**
* AtolTooManyPaymentsException constructor.
*
* @param int $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком много платежей (макс. '.$max.')';
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1031,
1081,
1215,
1217,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Too many payments';
}

View File

@@ -9,26 +9,27 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке добавить слишком много ставок НДС в массив
*
* @package AtolOnline\Exceptions
*/
class AtolTooManyVatsException extends AtolException
class AtolTooManyVatsException extends AtolTooManyException
{
/**
* AtolTooManyVatsException constructor.
*
* @param int $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком много ставок НДС (макс. '.$max.')';
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1102,
1103,
1104,
1105,
1106,
1107,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Too many vats';
}

View File

@@ -9,27 +9,22 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинный телефон
*
* @package AtolOnline\Exceptions
*/
class AtolUnitTooLongException extends AtolException
class AtolUnitTooLongException extends AtolTooLongException
{
/**
* AtolUnitTooLongException constructor.
*
* @param $unit
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($unit, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинное название единицы измерения (макс. длина '.$max.', фактически '.strlen($unit).'): '.$unit;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1197,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'Measurement unit is too long';
}

View File

@@ -9,27 +9,22 @@
namespace AtolOnline\Exceptions;
use Throwable;
/**
* Исключение, возникающее при попытке указать слишком длинный телефон
* Исключение, возникающее при попытке указать слишком длинный дополнительный реквизит
*
* @package AtolOnline\Exceptions
*/
class AtolUserdataTooLongException extends AtolException
class AtolUserdataTooLongException extends AtolTooLongException
{
/**
* AtolUserdataTooLongException constructor.
*
* @param $data
* @param $max
* @param string $message
* @param int $code
* @param Throwable|null $previous
* @inheritDoc
*/
public function __construct($data, $max, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Слишком длинный дополнительный реквизит (макс. длина '.$max.', фактически '.strlen($data).'): '.$data;
parent::__construct($message, $code, $previous);
}
protected $ffd_tags = [
1191,
];
/**
* @var string Сообщение об ошибке
*/
protected $message = 'User data is too long';
}

View File

@@ -28,7 +28,6 @@ class AtolWrongDocumentTypeException extends AtolException
*/
public function __construct($type, $message = "", $code = 0, Throwable $previous = null)
{
$message = $message ?: 'Некорректный тип документа: ожидался \'receipt\' или \'correction\', указан \''.$type.'\'';
parent::__construct($message, $code, $previous);
parent::__construct($message ?: "Wrong document type: 'receipt' or 'correction' expected, but '$type' provided", $code, $previous);
}
}

View File

@@ -9,7 +9,7 @@
namespace AtolOnline\Traits;
use AtolOnline\{Exceptions\AtolEmailTooLongException, Exceptions\AtolEmailValidateException};
use AtolOnline\{Constants\Constraints, Exceptions\AtolEmailTooLongException, Exceptions\AtolEmailValidateException};
/**
* Добавляет объекту функционал для работы с email
@@ -38,16 +38,15 @@ trait HasEmail
*
* @param string $email
* @return $this
* @throws AtolEmailTooLongException
* @throws AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException Слишком длинный email
* @throws \AtolOnline\Exceptions\AtolEmailValidateException Невалидный email
*/
public function setEmail(string $email)
{
$email = trim($email);
if (strlen($email) > 64) {
throw new AtolEmailTooLongException($email, 64);
}
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
if (valid_strlen($email) > Constraints::MAX_LENGTH_EMAIL) {
throw new AtolEmailTooLongException($email, Constraints::MAX_LENGTH_EMAIL);
} elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new AtolEmailValidateException($email);
}
$this->email = $email;

View File

@@ -9,6 +9,7 @@
namespace AtolOnline\Traits;
use AtolOnline\Constants\Constraints;
use AtolOnline\Exceptions\AtolInnWrongLengthException;
/**
@@ -39,12 +40,12 @@ trait HasInn
*
* @param string $inn
* @return $this
* @throws AtolInnWrongLengthException
* @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) {
if (preg_match_all(Constraints::PATTERN_INN, $inn) == 0) {
throw new AtolInnWrongLengthException($inn);
}
$this->inn = $inn;

16
src/helpers.php Normal file
View File

@@ -0,0 +1,16 @@
<?php
if (!function_exists('valid_strlen')) {
/**
* Возвращает корректную длину строки
*
* @param string $value
* @return int
*/
function valid_strlen(string $value): int
{
return function_exists('mb_strlen')
? mb_strlen($value)
: strlen($value);
}
}

View File

@@ -42,7 +42,22 @@ class BasicTestCase extends TestCase
*/
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)];
}
return $string;
}
}

View File

@@ -13,10 +13,9 @@ use AtolOnline\{Constants\PaymentMethods,
Entities\Item,
Exceptions\AtolNameTooLongException,
Exceptions\AtolPriceTooHighException,
Exceptions\AtolQuantityTooHighException,
Exceptions\AtolTooManyException,
Exceptions\AtolUnitTooLongException,
Exceptions\AtolUserdataTooLongException
};
Exceptions\AtolUserdataTooLongException};
/**
* Class ItemTest
@@ -28,7 +27,7 @@ class ItemTest extends BasicTestCase
*
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
*/
public function testConstructor()
@@ -57,7 +56,7 @@ class ItemTest extends BasicTestCase
*
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolTooManyException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws AtolOnline\Exceptions\AtolUserdataTooLongException
*/
@@ -86,10 +85,7 @@ class ItemTest extends BasicTestCase
/**
* Тестирует установку ставки НДС разными путями
*
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
*/
public function testSetVat()
{
@@ -103,40 +99,33 @@ class ItemTest extends BasicTestCase
/**
* Тестирует исключение о слишком длинном наименовании
*
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
*/
public function testAtolNameTooLongException()
{
$item = new Item();
$this->expectException(AtolNameTooLongException::class);
$item->setName('Банан Банан Банан Банан Банан Банан Банан Банан Банан Банан Банан Банан');
$item->setName(self::randomString(130));
}
/**
* Тестирует исключение о слишком высоком количестве
*
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
* @throws \AtolOnline\Exceptions\AtolTooManyException
* @throws \AtolOnline\Exceptions\AtolUnitTooLongException
*/
public function testAtolQuantityTooHighException()
{
$item = new Item();
$this->expectException(AtolQuantityTooHighException::class);
$this->expectException(AtolTooManyException::class);
$item->setQuantity(100000.1);
}
/**
* Тестирует исключение о слишком высокой цене
*
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws \AtolOnline\Exceptions\AtolPriceTooHighException
*/
public function testAtolPriceTooHighException()
{
@@ -148,11 +137,7 @@ class ItemTest extends BasicTestCase
/**
* Тестирует исключение о слишком длинных польз. данных
*
* @throws AtolOnline\Exceptions\AtolUserdataTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws \AtolOnline\Exceptions\AtolUserdataTooLongException
*/
public function testAtolUserdataTooLongException()
{
@@ -164,10 +149,7 @@ class ItemTest extends BasicTestCase
/**
* Тестирует исключение о слишком длинной единице измерения
*
* @throws AtolOnline\Exceptions\AtolNameTooLongException
* @throws AtolOnline\Exceptions\AtolPriceTooHighException
* @throws AtolOnline\Exceptions\AtolQuantityTooHighException
* @throws AtolOnline\Exceptions\AtolUnitTooLongException
* @throws \AtolOnline\Exceptions\AtolUnitTooLongException
*/
public function testAtolUnitTooLongException()
{

View File

@@ -22,12 +22,6 @@ class ClientTest extends BasicTestCase
{
/**
* Тестирует установку параметров
*
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
*/
public function testConstructor()
{
@@ -48,30 +42,18 @@ class ClientTest extends BasicTestCase
* Тестирует исключение о слишком длинном имени
*
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
*/
public function testAtolNameTooLongException()
{
$customer = new Client();
$this->expectException(AtolNameTooLongException::class);
$customer->setName('John Doe John Doe John Doe John Doe John Doe '.
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
'Doe John Doe John Doe John Doe John DoeJohn Doe John Doe John Doe '.
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
'Doe John Doe John Doe John Doe John Doe John Doe John Doe');
$customer->setName(self::randomString(257));
}
/**
* Тестирует исключение о слишком длинном телефоне
*
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
*/
public function testAtolPhoneTooLongException()
{
@@ -84,42 +66,32 @@ class ClientTest extends BasicTestCase
* Тестирует исключение о слишком длинной почте
*
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
*/
public function testAtolEmailTooLongException()
{
$customer = new Client();
$this->expectException(AtolEmailTooLongException::class);
$customer->setEmail('johnjohnjohnjohnjohnjohndoedoedoedoe@exampleexampleexampleexample.com');
$customer->setEmail(self::randomString(65));
}
/**
* Тестирует исключение о некорректной почте
*
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
*/
public function testAtolEmailValidateException()
{
$customer = new Client();
$this->expectException(AtolEmailValidateException::class);
$customer->setEmail('John Doe');
$customer->setEmail(self::randomString(15));
}
/**
* Тестирует исключение о некорректной длине ИНН
*
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
* @throws \AtolOnline\Exceptions\AtolNameTooLongException
* @throws \AtolOnline\Exceptions\AtolPhoneTooLongException
*/
public function testAtolInnWrongLengthException()
{

View File

@@ -22,11 +22,6 @@ class CompanyTest extends BasicTestCase
{
/**
* Тестирует установку параметров через конструктор
*
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
* @throws AtolOnline\Exceptions\AtolEmailValidateException
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
*/
public function testConstructor()
{
@@ -46,10 +41,7 @@ class CompanyTest extends BasicTestCase
/**
* Тестирует исключение о некорректной длине ИНН
*
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
* @throws AtolOnline\Exceptions\AtolEmailValidateException
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
* @throws \AtolOnline\Exceptions\AtolInnWrongLengthException
*/
public function testAtolInnWrongLengthException()
{
@@ -62,49 +54,38 @@ class CompanyTest extends BasicTestCase
/**
* Тестирует исключение о слишком длинном платёжном адресе
*
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
* @throws AtolOnline\Exceptions\AtolEmailValidateException
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws \AtolOnline\Exceptions\AtolPaymentAddressTooLongException
*/
public function testAtolPaymentAddressTooLongException()
{
$company = new Company();
$this->expectException(AtolPaymentAddressTooLongException::class);
$company->setPaymentAddress('John Doe John Doe John Doe John Doe '.
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
'Doe John Doe John Doe John Doe John DoeJohn Doe John Doe John Doe John Doe '.
'John Doe John Doe John Doe John Doe John Doe John Doe John Doe John Doe John '.
'Doe John Doe John Doe John Doe John Doe');
$company->setPaymentAddress(self::randomString(257));
}
/**
* Тестирует исключение о слишком длинной почте
*
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
* @throws AtolOnline\Exceptions\AtolEmailValidateException
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
*/
public function testAtolEmailTooLongException()
{
$company = new Company();
$this->expectException(AtolEmailTooLongException::class);
$company->setEmail('johnjohnjohnjohnjohnjohndoedoedoedoe@exampleexampleexampleexample.com');
$company->setEmail(self::randomString(65));
}
/**
* Тестирует исключение о некорректной почте
*
* @throws AtolOnline\Exceptions\AtolEmailValidateException
* @throws AtolOnline\Exceptions\AtolEmailTooLongException
* @throws AtolOnline\Exceptions\AtolInnWrongLengthException
* @throws AtolOnline\Exceptions\AtolPaymentAddressTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailTooLongException
* @throws \AtolOnline\Exceptions\AtolEmailValidateException
*/
public function testAtolEmailValidateException()
{
$company = new Company();
$this->expectException(AtolEmailValidateException::class);
$company->setEmail('John Doe');
$company->setEmail(self::randomString(15));
}
}

View File

@@ -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());
}
}

View File

@@ -44,8 +44,8 @@ class VatTest extends BasicTestCase
return [
[VatTypes::NONE, 100, 0, 0],
[VatTypes::VAT0, 100, 0, 0],
[VatTypes::VAT10, 100, 10, 12],
[VatTypes::VAT18, 100, 18, 21.6],
[VatTypes::VAT10, 100, 9.09, 10.9],
[VatTypes::VAT18, 100, 15.25, 18.3],
];
}
}