Пакет предоставляет возможность работы по проверке чеков через официальное API ФНС (Федеральной Налоговая службы России).
- Установка
- Аутентификация
- Создать Ticket (кассовый чек)
- Создание SOAP Client
- Проверка или информация по чеку
- Response в готовой структуре
- Алгоритмы обработки timeout
- Дополнительная информация от автора
- Угостить чаем 😌
composer require agoalofalife/fnsapi
Для начала работы с сервисом, вам необходимо получить временный токен. На момент написания документации, время его жизни был один час.
$cachePSR16 = new Sarahman\SimpleCache\FileSystemCache(__DIR__);
$master_token = 'ourMasterToken';
$auth = new Fns\Auth\AuthRequest($master_token, $cachePSR16);
$auth->authenticate();
Вам надо передать мастер токен, который выдали в ФНС и хранилище, которое реализует PSR-16.
В хранилище будет своевременно обновляться новый токен, который реализуется в PSR-16 параметром ttl.
PSR-16 позволяет использовать пакет во многих современных фреймворках и т.д
Класс имеет исключение UnexpectedValueException в случае если токен не будет получен.
Время жизни токена устанавливается в соответствии с вашей настройкой PHP: Настройка во время выполнения - Manual date.timezone Рекомендуется проверить ваш файл php.ini и установить соответствующую временную зону.
Для того чтобы получить информацию по чеку, вам надо создать объект класса Ticket
Подробнее о данных написано в коде и официальной документации ФНС.
$ticket = new \Fns\Ticket();
$ticket->setDate('2019-12-16T12:22:00');
$ticket->setFiscalDocumentId(11222);
$ticket->setFiscalSign(111111122);
$ticket->setFn(1234000123440000);
$ticket->setSum(11220);
$ticket->setTypeOperation(1);
// случайные данные
Отлично мы создали чек и заполнили его данными. Теперь надо создать SOAP client. Это очень осведомленный клиент, он знает что мы работает с ФНС, поэтому он требует:
- Уникальную строку, для сессии. Это строка будет кодироваться в base64(который примерно на 30% увеличивают длину), не должна превышать 160 символов.
- И то же хранилище данных, PSR-16, тот созданный объект, который передавался для получения временного токена.
- Включить режим debug(по-умолчанию false), можно просматривать запросы с помощью таких методов как
__getLastRequest
и так далее.
$client = new \Fns\ClientSoap('uniqueStringOrNumber', $cache);
Отлично, вы создали чек и клиента. И уже все готово для работы! Осталось уже выбрать:
- Проверить чек
\Fns\GetMessage\CheckTicketRequest
- Получить по нему подробную информацию
\Fns\GetMessage\GetTicketRequest
Для справки
API ФНС реализованно через асинхроннсть.
Для начала вам надо отправить запрос для получения `MessageId`
с информацией по чеку и типом(проверка или полной информацией по чеку)
Далее новым запросом с `MessageId` получить информацию.
Нюанс заключается в том, что последующий запрос, имеет время исполнения и сетевые задержки.
К примеру вы можете получить информацию по `MessageId` в течении 60 секунд.
Для своей реализации обработки timeout читайте в разделе Алгоритмы обработки timeout
-
создание обьекта с типом запроса
-
Внедрить свою стратегию обработки timeout реализующий интерфейс
Fns\Contracts\TimeoutStrategyHandler
-
Создать объект
SendMessageRequest
передать клиента которого мы создали ранее и объект конкретного запроса. -
Передать чек
-
И выполнить запрос
execute
который возвращает интерфейсResponseSendMessage
-
Получить информацию по запросу код и тело ответа.
$message = new \Fns\GetMessage\GetTicketRequest();
$message->setTimeoutStrategy(new ExponentialBackoff($message));
// можно установить свое максимальное значение time out
$message->setTimeoutStrategy(new ExponentialBackoff($message), 600000000);
$request = new SendMessageRequest($client, $message);
$request->setTicket($ticket);
$response = $request->execute();
if ($response->getCode() === 200) {
dump(json_decode($response->getBody()));
// или получить в виде структуры
$response->getReceipt();
}
Ответ возвращается в json или в обекте Receipt.
Ответ по чеку можно получить в виде готовой структуры, которая содержит:
- Класс Receipt
- Класс ProductCollection
- Класс Product
и решает такие проблемы как:
- Более явное получение данных
- Инкапсуляция преобразования их для более простой модификации и безболезности в клиентском коде.
но вы всегда можете получить сырой вариант.
Для получения информации что чек корректен, достаточно сравнить код ответа с кодом 200.
Из старой документации
если 200, то "Отправленные данные корректны"
если 400, то "Формат отправленных данных некорректен"
если 406, то "Данные не прошли проверку"
если 503, то "Сервис недоступен".
Из старой документации
Содержимое ФД, если код возврата равен 200
если 400, то "Формат отправленных данных некорректен"
если 404, то "Чек не найден"
если 406, то "Данные не прошли проверку"
если 453, то "Чек неккоректен".
Из нового сервиса опытным путем:
452 - Запрос не соответствует формату hsm
454 - Обращение к hsm было произведено и получен отрицательный результат проверки
455 - Не найдены данные в сервисе поиска чека
531 - "" (Происходит когда были отпроавлены неккоректные данные)
528 - Фискальный признак не может быть проверен, поскольку в hsm отсутствует необходимый ключ
531 - "" (Происходит когда были отпроавлены неккоректные данные)
После обновления API пока не предоставлен конечный список ответов!
Чтобы получить информацию по чеку, надо сделать запрос SendMessageRequest
c параметром messageId
При первом(вторым и т.д) запросе, сразу после получения messageId
, может отсутствовать информацию по чеку.
По-умолчанию в пакете реализовывается Exponential Backoff
Вы можете реализовать свой алгоритм реализуя интерфейс Fns\Contracts\TimeoutStrategyHandler\TimeoutStrategyHandler
Для контроля процесса выполнения запроса и его результата, передайте в конструктор Fns\Contracts\RequestsManager
Для примера вы можете реализовать свой алгоритм Interval
Который будет опрашивать сервер через константный промежуток времени.
В данный момент все выполняется в синхронном режиме.
Можно разделить процесс получения messageId
и информации по нему, на два различных процесса.
Для начальной версии пакета, пока остаётся так.
Этот пакет был создан для экономии вашего времени на безвозмездной основе. Надеюсь у меня получилось это сделать и я буду рад любым формам спасибо. Звезда или скромный донат - окажут мне поддержку и веру в людей. https://money.yandex.ru/to/410019109036855