7 Commits

11 changed files with 260 additions and 86 deletions

View File

@@ -1,6 +1,9 @@
name: Composer and phpunit tests name: Build
on: [push] on:
push:
branches:
- master
jobs: jobs:
build: 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/). Библиотека для фискализации чеков по 54-ФЗ через [облачную ККТ АТОЛ](https://online.atol.ru/).
Текущая поддерживаемая версия API: **5.1** Текущая поддерживаемая версия API: **5.1**

View File

@@ -3,7 +3,6 @@
"description": "Library to use cloud cash register in e-commerce according to Russian Federal Law #54", "description": "Library to use cloud cash register in e-commerce according to Russian Federal Law #54",
"license": "MIT", "license": "MIT",
"type": "library", "type": "library",
"version": "0.2.1-b",
"keywords": [ "keywords": [
"54-fz", "54-fz",
"kkt", "kkt",

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", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "dae801b00d2c80c28d290f676970945b", "content-hash": "20b642fe60192cf1e67c9aa8dca27440",
"packages": [ "packages": [
{ {
"name": "guzzlehttp/guzzle", "name": "guzzlehttp/guzzle",
"version": "6.5.2", "version": "6.5.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/guzzle.git", "url": "https://github.com/guzzle/guzzle.git",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82" "reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/43ece0e75098b7ecd8d13918293029e555a50f82", "url": "https://api.github.com/repos/guzzle/guzzle/zipball/a4a1b6930528a8f7ee03518e6442ec7a44155d9d",
"reference": "43ece0e75098b7ecd8d13918293029e555a50f82", "reference": "a4a1b6930528a8f7ee03518e6442ec7a44155d9d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-json": "*", "ext-json": "*",
"guzzlehttp/promises": "^1.0", "guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1", "guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5" "php": ">=5.5",
"symfony/polyfill-intl-idn": "1.17.0"
}, },
"require-dev": { "require-dev": {
"ext-curl": "*", "ext-curl": "*",
@@ -32,7 +33,6 @@
"psr/log": "^1.1" "psr/log": "^1.1"
}, },
"suggest": { "suggest": {
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware" "psr/log": "Required for using the Log middleware"
}, },
"type": "library", "type": "library",
@@ -71,7 +71,7 @@
"rest", "rest",
"web service" "web service"
], ],
"time": "2019-12-23T11:57:10+00:00" "time": "2020-05-25T19:35:05+00:00"
}, },
{ {
"name": "guzzlehttp/promises", "name": "guzzlehttp/promises",
@@ -466,16 +466,16 @@
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.15.0", "version": "v1.17.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git", "url": "https://github.com/symfony/polyfill-ctype.git",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14" "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/4719fa9c18b0464d399f1a63bf624b42b6fa8d14", "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"reference": "4719fa9c18b0464d399f1a63bf624b42b6fa8d14", "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -487,7 +487,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.15-dev" "dev-master": "1.17-dev"
} }
}, },
"autoload": { "autoload": {
@@ -520,7 +520,183 @@
"polyfill", "polyfill",
"portable" "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": [ "packages-dev": [
@@ -732,24 +908,21 @@
}, },
{ {
"name": "phpdocumentor/reflection-common", "name": "phpdocumentor/reflection-common",
"version": "2.0.0", "version": "2.1.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionCommon.git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.1" "php": ">=7.1"
}, },
"require-dev": {
"phpunit/phpunit": "~6"
},
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
@@ -780,7 +953,7 @@
"reflection", "reflection",
"static analysis" "static analysis"
], ],
"time": "2018-08-07T13:53:10+00:00" "time": "2020-04-27T09:25:28+00:00"
}, },
{ {
"name": "phpdocumentor/reflection-docblock", "name": "phpdocumentor/reflection-docblock",
@@ -1198,16 +1371,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "8.5.3", "version": "8.5.5",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf" "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/67750516bc02f300e2742fed2f50177f8f37bedf", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/63dda3b212a0025d380a745f91bdb4d8c985adb7",
"reference": "67750516bc02f300e2742fed2f50177f8f37bedf", "reference": "63dda3b212a0025d380a745f91bdb4d8c985adb7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1277,7 +1450,7 @@
"testing", "testing",
"xunit" "xunit"
], ],
"time": "2020-03-31T08:52:04+00:00" "time": "2020-05-22T13:51:52+00:00"
}, },
{ {
"name": "sebastian/code-unit-reverse-lookup", "name": "sebastian/code-unit-reverse-lookup",
@@ -1936,16 +2109,16 @@
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "1.7.0", "version": "1.8.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozart/assert.git", "url": "https://github.com/webmozart/assert.git",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598" "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", "url": "https://api.github.com/repos/webmozart/assert/zipball/ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"reference": "aed98a490f9a8f78468232db345ab9cf606cf598", "reference": "ab2cb0b3b559010b75981b1bdce728da3ee90ad6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1953,7 +2126,7 @@
"symfony/polyfill-ctype": "^1.8" "symfony/polyfill-ctype": "^1.8"
}, },
"conflict": { "conflict": {
"vimeo/psalm": "<3.6.0" "vimeo/psalm": "<3.9.1"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^4.8.36 || ^7.5.13" "phpunit/phpunit": "^4.8.36 || ^7.5.13"
@@ -1980,7 +2153,7 @@
"check", "check",
"validate" "validate"
], ],
"time": "2020-02-14T12:15:55+00:00" "time": "2020-04-18T12:12:48+00:00"
} }
], ],
"aliases": [], "aliases": [],

View File

@@ -118,7 +118,7 @@ class Kkt extends Client
if (!$this->isTestMode()) { if (!$this->isTestMode()) {
if (empty($login)) { if (empty($login)) {
throw new AtolKktLoginEmptyException(); throw new AtolKktLoginEmptyException();
} elseif (strlen($login) > 100) { } elseif ((function_exists('mb_strlen') ? mb_strlen($login) : strlen($login)) > 100) {
throw new AtolKktLoginTooLongException($login, 100); throw new AtolKktLoginTooLongException($login, 100);
} }
} }

View File

@@ -89,7 +89,7 @@ class Client extends Entity
public function setName(string $name) public function setName(string $name)
{ {
$name = trim($name); $name = trim($name);
if (strlen($name) > 256) { if ((function_exists('mb_strlen') ? mb_strlen($name) : strlen($name)) > 256) {
throw new AtolNameTooLongException($name, 256); throw new AtolNameTooLongException($name, 256);
} }
$this->name = $name; $this->name = $name;
@@ -119,7 +119,7 @@ class Client extends Entity
public function setPhone(string $phone) public function setPhone(string $phone)
{ {
$phone = preg_replace("/[^0-9+]/", '', $phone); $phone = preg_replace("/[^0-9+]/", '', $phone);
if (strlen($phone) > 64) { if ((function_exists('mb_strlen') ? mb_strlen($phone) : strlen($phone)) > 64) {
throw new AtolPhoneTooLongException($phone, 64); throw new AtolPhoneTooLongException($phone, 64);
} }
$this->phone = $phone; $this->phone = $phone;

View File

@@ -115,7 +115,7 @@ class Company extends Entity
public function setPaymentAddress(string $payment_address) public function setPaymentAddress(string $payment_address)
{ {
$payment_address = trim($payment_address); $payment_address = trim($payment_address);
if (strlen($payment_address) > 256) { if ((function_exists('mb_strlen') ? mb_strlen($payment_address) : strlen($payment_address)) > 256) {
throw new AtolPaymentAddressTooLongException($payment_address, 256); throw new AtolPaymentAddressTooLongException($payment_address, 256);
} }
$this->payment_address = $payment_address; $this->payment_address = $payment_address;

View File

@@ -338,60 +338,57 @@ class Document extends Entity
*/ */
public static function fromRaw(string $json) public static function fromRaw(string $json)
{ {
$object = json_decode($json); $array = json_decode($json, true);
if (json_last_error() !== JSON_ERROR_NONE) { if (json_last_error() !== JSON_ERROR_NONE) {
throw new AtolInvalidJsonException(); throw new AtolInvalidJsonException();
} }
$doc = new self(); $doc = new self();
if ($object->company) { if (isset($array['company'])) {
$doc->setCompany(new Company( $doc->setCompany(new Company(
$object->company->sno ?? null, $array['company']['sno'] ?? null,
$object->company->inn ?? null, $array['company']['inn'] ?? null,
$object->company->payment_address ?? null, $array['company']['payment_address'] ?? null,
$object->company->email ?? null $array['company']['email'] ?? null
)); ));
} }
if ($object->client) { if (isset($array['client'])) {
$doc->setClient(new Client( $doc->setClient(new Client(
$object->client->name ?? null, $array['client']['name'] ?? null,
$object->client->phone ?? null, $array['client']['phone'] ?? null,
$object->client->email ?? null, $array['client']['email'] ?? null,
$object->client->inn ?? null $array['client']['inn'] ?? null
)); ));
} }
if ($object->items) { if (isset($array['items'])) {
foreach ($object->items as $obj_item) { foreach ($array['items'] as $ar_item) {
$item = new Item( $item = new Item(
$obj_item->name ?? null, $ar_item['name'] ?? null,
$obj_item->price ?? null, $ar_item['price'] ?? null,
$obj_item->quantity ?? null, $ar_item['quantity'] ?? null,
$obj_item->measurement_unit ?? null, $ar_item['measurement_unit'] ?? null,
$obj_item->vat->type ?? null, $ar_item['vat']['type'] ?? null,
$obj_item->payment_object ?? null, $ar_item['payment_object'] ?? null,
$obj_item->payment_method ?? null $ar_item['payment_method'] ?? null
); );
if (!empty($obj_item->user_data)) { if (!empty($ar_item['user_data'])) {
$item->setUserData($obj_item->user_data ?? null); $item->setUserData($ar_item['user_data'] ?? null);
} }
$doc->addItem($item); $doc->addItem($item);
} }
} }
if ($object->payments) { if (isset($array['payments'])) {
foreach ($object->payments as $obj_payment) { foreach ($array['payments'] as $ar_payment) {
$doc->payments->add(new Payment( $payment = new Payment();
$obj_payment->type, if (isset($ar_payment['type'])) {
$obj_payment->sum $payment->setType($ar_payment['type']);
)); }
if (isset($ar_payment['sum'])) {
$payment->setSum($ar_payment['sum']);
}
$doc->payments->add($payment);
} }
} }
//if ($object->vats) { if ($array['total'] != $doc->calcTotal()) {
// foreach ($object->vats as $obj_vat) {
// $doc->vats->add(new Vat(
// $obj_vat->type
// ));
// }
//}
if ($object->total != $doc->calcTotal()) {
throw new AtolException('Real total sum not equals to provided in JSON one'); throw new AtolException('Real total sum not equals to provided in JSON one');
} }
return $doc; return $doc;
@@ -404,11 +401,11 @@ class Document extends Entity
*/ */
public function jsonSerialize() public function jsonSerialize()
{ {
$json = [ $json['company'] = $this->getCompany()->jsonSerialize();// обязательно
'company' => $this->getCompany()->jsonSerialize(), // обязательно $json['payments'] = $this->payments->jsonSerialize(); // обязательно
'payments' => $this->payments->jsonSerialize(), // обязательно if ($this->getCashier()) {
'cashier' => $this->getCashier() ?? '', $json['cashier'] = $this->getCashier();
]; }
if ($this->getCorrectionInfo()) { if ($this->getCorrectionInfo()) {
$json['correction_info'] = $this->getCorrectionInfo()->jsonSerialize(); // обязательно для коррекционных $json['correction_info'] = $this->getCorrectionInfo()->jsonSerialize(); // обязательно для коррекционных
} else { } else {

View File

@@ -137,7 +137,7 @@ class Item extends Entity
public function setName(string $name) public function setName(string $name)
{ {
$name = trim($name); $name = trim($name);
if (strlen($name) > 128) { if ((function_exists('mb_strlen') ? mb_strlen($name) : strlen($name)) > 128) {
throw new AtolNameTooLongException($name, 128); throw new AtolNameTooLongException($name, 128);
} }
$this->name = $name; $this->name = $name;
@@ -328,7 +328,7 @@ class Item extends Entity
public function setUserData(string $user_data) public function setUserData(string $user_data)
{ {
$user_data = trim($user_data); $user_data = trim($user_data);
if (strlen($user_data) > 64) { if ((function_exists('mb_strlen') ? mb_strlen($user_data) : strlen($user_data)) > 64) {
throw new AtolUserdataTooLongException($user_data, 64); throw new AtolUserdataTooLongException($user_data, 64);
} }
$this->user_data = $user_data; $this->user_data = $user_data;

View File

@@ -44,7 +44,7 @@ trait HasEmail
public function setEmail(string $email) public function setEmail(string $email)
{ {
$email = trim($email); $email = trim($email);
if (strlen($email) > 64) { if ((function_exists('mb_strlen') ? mb_strlen($email) : strlen($email)) > 64) {
throw new AtolEmailTooLongException($email, 64); throw new AtolEmailTooLongException($email, 64);
} }
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {

View File

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