{"id":17180424,"url":"https://github.com/agoalofalife/fnsapi","last_synced_at":"2025-06-21T22:39:27.688Z","repository":{"id":56942112,"uuid":"230281878","full_name":"agoalofalife/fnsapi","owner":"agoalofalife","description":"Взаимодействие с API ФНС России по SOAP","archived":false,"fork":false,"pushed_at":"2021-10-04T10:49:49.000Z","size":113,"stargazers_count":4,"open_issues_count":1,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-13T17:12:50.432Z","etag":null,"topics":["fns","soap"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/agoalofalife.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"custom":"https://money.yandex.ru/to/410019109036855"}},"created_at":"2019-12-26T14:58:43.000Z","updated_at":"2024-06-25T08:32:46.000Z","dependencies_parsed_at":"2022-08-21T07:20:36.241Z","dependency_job_id":null,"html_url":"https://github.com/agoalofalife/fnsapi","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoalofalife%2Ffnsapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoalofalife%2Ffnsapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoalofalife%2Ffnsapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/agoalofalife%2Ffnsapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/agoalofalife","download_url":"https://codeload.github.com/agoalofalife/fnsapi/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248750126,"owners_count":21155687,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["fns","soap"],"created_at":"2024-10-15T00:29:34.749Z","updated_at":"2025-04-13T17:12:53.400Z","avatar_url":"https://github.com/agoalofalife.png","language":"PHP","funding_links":["https://money.yandex.ru/to/410019109036855"],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eFns API SOAP\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n \u003ca href=\"https://scrutinizer-ci.com/g/agoalofalife/fnsapi/?branch=master\"\u003e\u003cimg src=\"https://scrutinizer-ci.com/g/agoalofalife/fnsapi/badges/quality-score.png?b=master\"\u003e\u003c/a\u003e\n \u003c/p\u003e\n\nПакет предоставляет возможность работы по проверке чеков через [официальное API](https://www.nalog.ru/files/kkt/pdf/%D0%A2%D0%B5%D1%85%D0%BD%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B5%20%D1%83%D1%81%D0%BB%D0%BE%D0%B2%D0%B8%D1%8F%20%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F.pdf) ФНС (Федеральной Налоговая службы России).\n\n\n- [Установка](#Installation)\n- [Аутентификация](#auth)\n- [Создать Ticket (кассовый чек)](#create_ticket)\n- [Создание SOAP Client](#create_soap_client)\n- [Проверка или информация по чеку](#check_or_info_ticket)\n- [Response в готовой структуре](#response_in_strucutre)\n- [Алгоритмы обработки timeout](#strategy_timout)\n- [Дополнительная информация от автора](#note_from_author)\n- [Угостить чаем 😌](#donate)\n\n\u003ca name=\"Installation\"\u003e\u003c/a\u003e\n## Установка\n`composer require agoalofalife/fnsapi`\n\n\u003ca name=\"auth\"\u003e\u003c/a\u003e\n\n## Аутентификация\nДля начала работы с сервисом, вам необходимо получить временный токен.\nНа момент написания документации, время его жизни был один час.\n\n```php\n$cachePSR16 = new Sarahman\\SimpleCache\\FileSystemCache(__DIR__);\n$master_token = 'ourMasterToken';\n$auth = new Fns\\Auth\\AuthRequest($master_token, $cachePSR16);\n$auth-\u003eauthenticate();\n```\n\nВам надо передать мастер токен, который выдали в ФНС и  хранилище, которое реализует PSR-16.\n\nВ хранилище будет своевременно обновляться новый токен,  [который реализуется в PSR-16](https://github.com/php-fig/simple-cache/blob/master/src/CacheInterface.php#L34) параметром ttl.\n\nPSR-16 позволяет использовать пакет во многих современных фреймворках и т.д\n\nКласс имеет исключение UnexpectedValueException  в случае если токен не будет получен.\n\n#### Временная зона\nВремя жизни токена устанавливается в соответствии с вашей настройкой [PHP: Настройка во время выполнения - Manual](https://www.php.net/manual/ru/datetime.configuration.php#ini.date.timezone)\ndate.timezone\nРекомендуется проверить ваш файл php.ini и установить соответствующую временную зону.\n\n\u003ca name=\"create_ticket\"\u003e\u003c/a\u003e\n##  Создать Ticket (кассовый чек)\nДля того чтобы получить информацию по чеку, вам надо создать объект класса `Ticket`\nПодробнее о данных написано в коде и официальной документации ФНС.\n\n```php\n$ticket = new \\Fns\\Ticket();\n$ticket-\u003esetDate('2019-12-16T12:22:00');\n$ticket-\u003esetFiscalDocumentId(11222);\n$ticket-\u003esetFiscalSign(111111122);\n$ticket-\u003esetFn(1234000123440000);\n$ticket-\u003esetSum(11220);\n$ticket-\u003esetTypeOperation(1);\n// случайные данные\n```\n\u003ca name=\"create_soap_client\"\u003e\u003c/a\u003e\n## Создание SOAP Client\nОтлично мы создали чек и заполнили его данными. \nТеперь надо создать SOAP client.\nЭто очень осведомленный клиент, он знает что мы работает с ФНС, поэтому он требует:\n- Уникальную строку, для сессии. Это строка будет кодироваться  в base64(который примерно на 30% увеличивают длину), не должна превышать 160 символов.\n- И то же хранилище данных, PSR-16, тот созданный объект, который передавался для получения временного токена.\n- Включить режим debug(по-умолчанию false), можно просматривать запросы с помощью таких методов как `__getLastRequest` и так далее.\n\n```php\n$client = new \\Fns\\ClientSoap('uniqueStringOrNumber', $cache);\n```\n\n\u003ca name=\"check_or_info_ticket\"\u003e\u003c/a\u003e\n## Проверка или информация по чеку\nОтлично, вы создали чек и клиента.\nИ уже все готово для работы!\nОсталось уже выбрать:\n- Проверить чек `\\Fns\\GetMessage\\CheckTicketRequest`\n- Получить по нему подробную информацию `\\Fns\\GetMessage\\GetTicketRequest`\n\n\n```\nДля справки\nAPI ФНС реализованно через асинхроннсть.\nДля начала вам надо отправить запрос для получения `MessageId`\nс информацией по чеку и типом(проверка или полной информацией по чеку)\nДалее новым запросом с  `MessageId` получить информацию.\n\nНюанс заключается в том, что последующий запрос, имеет время исполнения и сетевые задержки.\nК примеру вы можете получить информацию по `MessageId` в течении 60 секунд.\nДля своей реализации обработки timeout читайте в разделе  Алгоритмы обработки timeout\n```\n\n- создание обьекта с типом запроса\n- Внедрить свою стратегию обработки timeout реализующий интерфейс  `Fns\\Contracts\\TimeoutStrategyHandler`\n\n- Создать объект `SendMessageRequest` передать клиента которого мы создали ранее и объект конкретного запроса.\n- Передать чек\n- И выполнить запрос `execute` который возвращает интерфейс `ResponseSendMessage`\n- Получить информацию по запросу код и тело ответа.\n\n```php\n$message = new \\Fns\\GetMessage\\GetTicketRequest();\n$message-\u003esetTimeoutStrategy(new ExponentialBackoff($message));\n// можно установить свое максимальное значение time out\n$message-\u003esetTimeoutStrategy(new ExponentialBackoff($message), 600000000);\n\n$request = new SendMessageRequest($client, $message);\n$request-\u003esetTicket($ticket);\n$response = $request-\u003eexecute();\n\nif ($response-\u003egetCode() === 200) {\n    dump(json_decode($response-\u003egetBody()));\n    // или получить в виде структуры\n    $response-\u003egetReceipt();\n}\n```\n\nОтвет возвращается в json или в обекте Receipt.\n\n\u003ca name=\"response_in_strucutre\"\u003e\u003c/a\u003e\n#### Response в готовой структуре\nОтвет по чеку можно получить в виде готовой структуры, которая содержит:\n- Класс Receipt\n- Класс ProductCollection\n- Класс Product \n\nи решает такие проблемы как:\n- Более явное получение данных\n- Инкапсуляция преобразования их для более простой модификации и безболезности в клиентском коде.\n\n но вы всегда можете получить сырой вариант.\n\n####  Проверка чека  CheckTicketRequest\nДля получения информации что чек корректен, достаточно сравнить код ответа с кодом 200.\n\n```\nИз старой документации\nесли 200, то \"Отправленные данные корректны\"\nесли 400, то \"Формат отправленных данных некорректен\"\nесли 406, то \"Данные не прошли проверку\"\nесли 503, то \"Сервис недоступен\".\n```\n\n#### Получении информации по чеку GetTicketRequest\n\n```\nИз старой документации\nСодержимое ФД, если код возврата равен 200\nесли 400, то \"Формат отправленных данных некорректен\"\nесли 404, то \"Чек не найден\"\nесли 406, то \"Данные не прошли проверку\"\nесли 453, то \"Чек неккоректен\".\n```\n\n```\nИз нового сервиса опытным путем:\n452 - Запрос не соответствует формату hsm\n454 - Обращение к hsm было произведено и получен отрицательный результат проверки\n455 - Не найдены данные в сервисе поиска чека\n531 - \"\" (Происходит когда были отпроавлены неккоректные данные)\n\n528 - Фискальный признак не может быть проверен, поскольку в hsm отсутствует необходимый ключ\n531 - \"\" (Происходит когда были отпроавлены неккоректные данные)\n```\n\n```\nПосле обновления API пока не предоставлен конечный список ответов!\n```\n\n\u003ca name=\"strategy_timout\"\u003e\u003c/a\u003e\n## Алгоритмы обработки timeout\nЧтобы получить информацию по чеку, надо сделать запрос `SendMessageRequest` c параметром `messageId`\nПри первом(вторым и т.д) запросе, сразу после получения `messageId`, может отсутствовать информацию по чеку.\nПо-умолчанию в пакете реализовывается [Exponential Backoff](https://ru.wikipedia.org/wiki/%D0%9D%D0%BE%D1%80%D0%BC%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D1%80%D0%B0%D1%81%D0%BF%D1%80%D0%B5%D0%B4%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5)\n\nВы можете реализовать свой алгоритм реализуя интерфейс `Fns\\Contracts\\TimeoutStrategyHandler\\TimeoutStrategyHandler`\n\nДля контроля процесса выполнения запроса и его результата, передайте в конструктор `Fns\\Contracts\\RequestsManager`\n\nДля примера вы можете реализовать свой алгоритм `Interval`\nКоторый будет опрашивать сервер через константный промежуток времени.\n\n\u003ca name=\"note_from_author\"\u003e\u003c/a\u003e\n## Дополнительная информация от автора\nВ данный момент все выполняется в синхронном режиме.\n Можно разделить процесс получения `messageId` и информации по нему, на два различных процесса.\nДля начальной версии пакета, пока остаётся так.\n\n\u003ca name=\"donate\"\u003e\u003c/a\u003e\n##  Угостить чаем 😌\nЭтот пакет был создан для экономии вашего времени на безвозмездной основе.\nНадеюсь у меня получилось это сделать и я буду рад любым формам спасибо.\nЗвезда или скромный донат - окажут мне поддержку и веру в людей.\nhttps://money.yandex.ru/to/410019109036855\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagoalofalife%2Ffnsapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fagoalofalife%2Ffnsapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fagoalofalife%2Ffnsapi/lists"}