20 May 2018

Универсальный API для получения информации по чекам

Open sourceAPI

UPD: после обновления на стороне ФНС АПИ перестал работать.


Соответствующая задача создана. Как будет время посмотрю.

Привет жителям Хабра.

В данной статье хотелось бы рассказать про API для получения чеков, которое нам не предоставила всеми любимая ФНС.

Когда только появились QR-коды на чеках я подумал «Вау, как круто! Ты сканируешь код и видишь если не всю инфу по чеку, то ссылку на него». И какого же было мое разочарование, когда просканировав такой код я увидел что-то вроде

t=20180518T220500&s=975.88&fn=8710000101125654&i=99456&fp=1250448795&n=1

Но расстраиваться я не стал и подумал, что ФНС позаботилась о нас и предоставила API для получения такой информации. Погуглив некоторое время я понял, что ФНС нам предоставила только мобильное приложение для проверки чека и просмотра той информации, что поступила к ним от магазина.

Но! Между магазином и налоговой имеется ещё одно звено — ОФД — те, кто обрабатывают информацию по чекам, полученную от магазинов, и отправляют в налоговую. Вот они то и предоставляют API для получения нужной нам информации. Не все. И не всегда бесплатно.

Судя по информации из википедии по состоянию на 1 марта 2018 зарегистрировано 17 ОФД. Допустим 10 из них предоставляют открытое и бесплатное API. Учитывая то, что мы не знаем с каким ОФД работает конкретный магазин, нужно будет пройтись по API 10 операторов фискальных данных. Далеко не лучший вариант.

Спустя какое-то время, я случайно наткнулся на приложение (не от ФНС), которое по QR-коду с чека получает информацию по чеку. Не будут же они «пробегать» по всем ОФД и собирать оттуда информацию — подумал я. Снова отправился в гугл и наткнулся на такой ответ.

Казалось, после этого ответа можно заканчивать импровизированное расследование, но у меня оставались ещё вопросы:

  • Что будет, если использовать другие заголовки?
  • Что делать, если пользователь не зарегистрирован? Скачивать мобильное приложение и регистрироваться? (Сайт ФНС не предоставляет возможности зарегистрироваться в этом контексте)
  • А если забыл пароль?

Запустив Android Device Monitor и SoapUI я начал разбираться. Выкладываю здесь всю обобщенную информацию, что удалось получить. ФНС предоставляет следующее публичное API:

Регистрация
POST
https://proverkacheka.nalog.ru:9999/v1/mobile/users/signup
Content-Type: application/json; charset=UTF-8

Содержимое:

{"email":"some@mail.com","name":"SomeName","phone":"+79991234567"}

Все параметры обязательные.

Если результат успешен, то пользователь создается, СМС с паролем отправляется на указанный номер, а в ответ возвращается 204 No content.

Если пользователь уже существует, то возвращается 409 Conflict и сообщение «user exists».
Если номер телефона некорректный, то возвращается 500 Internal Server Error и сообщение «failed with code 20101».

Если адрес электронной почты некорректный, то возвращается 400 Bad Request и сообщение "[«Object didn't pass validation for format email: <адрес электронной почты, который вы указали>»]".
Если адрес электронной почты уже используется, а телефон нет, то ошибок не возникает и регистрация проходит успешно.

Логин
GET
https://proverkacheka.nalog.ru:9999/v1/mobile/users/login

В заголовке передается Pre-emptive Basic Authorization, где в качестве username передается номер телефона, в виде "+79991234567", а в качестве пароля — код, полученный в смс при регистрации или восстановлении пароля.

Если все хорошо, то вернется 200 OK и сообщение в виде json

{
   "email": "<адрес электронной почты, указанный при регистрации>",
   "name": "<имя, указанное при регистрации>"
}

Если указать некорректный номер телефона или пароль, то вернется 403 Forbidden и сообщение «the user was not found or the specified password was not correct».

Если не указать номер телефона и/или пароль, то не вернется ничего.

Восстановление пароля
POST
https://proverkacheka.nalog.ru:9999/v1/mobile/users/restore
Content-Type: application/json; charset=UTF-8

Содержимое:

{"phone":"+79991234567"}

Если номер телефона найден, то возвращается 204 No Content и на телефон приходит СМС с новым паролем.

Если номер телефона не найден или номер некорректный, то возвращается 404 Not Found и сообщение «the user was not found».

Проверка существования чека
GET
https://proverkacheka.nalog.ru:9999/v1/ofds/*/inns/*/fss/<номер ФН>/operations/<вид кассового чека>/tickets/<номер ФД>?fiscalSign=<номер ФПД>&date=2018-05-17T17:57:00&sum=3900
Где

  • Номер ФН (Фискальный Номер) — 16-значный номер. Например 8710000100518392
  • Номер ФД (Фискальный документ) — до 10 знаков. Например 54812
  • Номер ФПД (Фискальный Признак Документа, также известный как ФП) — до 10 знаков. Например 3522207165
  • Вид кассового чека. В чеке помечается как n=1 (приход) и n=2 (возврат прихода)
  • Дата — дата с чека. Формат может отличаться. Я пробовал переворачивать дату (т.е. 17-05-2018), ставить вместо Т пробел, удалять секунды
  • Сумма — сумма с чека в копейках

Если чек найден, то вернется 204 No Content.
Если чек не найден, то вернется 406 Not Acceptable.
Если дата/сумма некорректная или не совпадает с датой/суммой, указанной в чеке, то возвращается 406 Not Acceptable. При этом секунды не учитываются.
Если не указать параметр дата/сумма, то возвращается 400 Bad Request и сообщение "[«Missing required property: <property_name>»]".

Получение детальной информации по чеку
GET
https://proverkacheka.nalog.ru:9999/v1/inns/*/kkts/*/fss/<Номер ФН>/tickets/<Номер ФД>?fiscalSign=<Номер ФПД>&sendToEmail=no
Где

  • Номер ФН (Фискальный Номер) — 16-значный номер. Например 8710000100518392
  • Номер ФД (Фискальный документ) — до 10 знаков. Например 54812
  • Номер ФПД (Фискальный Признак Документа, также известный как ФП) — до 10 знаков. Например 3522207165

Также обязательно указать хотя бы пустые заголовки device-id и device-os
Если указаны некорректные данные пользователя, то возвращается 403 Forbidden и сообщение «the user was not found or the specified password was not correct».

Если не указать номер телефона и/или пароль, то ничего не вернется.

Если чек не найден, то возвращается 406 Not Acceptable. Также чек может быть не найден, если он был получен достаточно давно. ФНС не хранит информацию по чекам за все время. На момент написания этой статьи ФНС хранила детальную информацию порядка 2-3 месяцев.

Если перед вызовом данного метода не происходила проверка существования чека, то вернется 202 Accepted (без сообщений и любого содержимого). При повторном вызове информация по чеку вернется.

Если в параметре «sendToEmail» попытаться подставить значение «yes», то вернется 500 Internal Server Error и сообщение «connect ECONNREFUSED 127.0.0.1:465». При попытке подставить другие значения («true», 1 и т.д.) вернется 400 Bad Request и сообщение "[«No enum match for: <значение, которое пытались передать>»]".

Если всё хорошо, то вернется 200 ОК и содержимое в формате json примерно такого вида:

{"document": {"receipt": {
   "operationType": 1,
   "fiscalSign": 3522207165,
   "dateTime": "2018-05-17T17:57:00",
   "rawData": "AwAzAREEEAA4NzEwMDAwMTAwNTE4MzEzDQQUADAwMDExOTM1MTQwNDE0MDUgICAg+gMMADc4MjU3MDYwODYgIBAEBAAJ2gAA9AMEAGzC/Vo1BAYAMQTSDyLSDgQEABYBAAASBAQAogAAAB4EAQAB/AMCADwPPAQPAD0EAwCKrqQ+BAQARzYzNyMERQAGBCcAKjM0OTIyNzcgTkVTVC6MruAuTUFYSUIukZKQgJeAkoWLLjE0MKyrNwQCAJ8P/wMEAAZAQg8TBAIAnw9PBAIAbAH9Aw4AhK6ro+PopaKgIICtraAHBAIAPA85BAEAAE8EAgBsARgEDACAo+Cu4q7goyCOjo7xAyoANjIwMDE3LCCjLiCFqqDipeCoraHj4KMsIOOrLiCAp6itoCwgpC4gMTimHwQBAAE=",
   "totalSum": 3900,
   "nds10": 364,
   "userInn": "7825706086",
   "taxationType": 1,
   "operator": "<Данные кассира>",
   "fiscalDocumentNumber": 54812,
   "properties": [   {
      "value": "G637",
      "key": "Код"
   }],
   "receiptCode": 3,
   "requestNumber": 162,
   "user": "Агроторг ООО",
   "kktRegId": "0001193514041405",
   "fiscalDriveNumber": "8710000100518392",
   "items": [   {
      "sum": 3999,
      "price": 3999,
      "name": "*3492277 NEST.Мор.MAXIB.СТРАЧАТЕЛ.140мл",
      "quantity": 1,
      "nds10": 364
   }],
   "ecashTotalSum": 0,
   "retailPlaceAddress": "620017, г. Екатеринбург, ул. Азина, д. 18ж",
   "cashTotalSum": 3900,
   "shiftNumber": 278
}}}

Где

  • все суммы указаны в копейках
  • данные кассира в разных магазинах имеют разные форматы (в одном случае может вернуться «Фамилия Имя», в другом «Фамилия И. должность»
  • порядок элементов может меняться
  • разные магазины используют разные наборы параметров и, если какой-то параметр возвращается в чеке от одного магазина, то не факт, что этот параметр будет в чеке от другого магазина
  • формат адреса магазина может различаться

Ещё один пример возвращаемого чека
{"document": {"receipt": {
   "cashTotalSum": 0,
   "fiscalSign": 1301551154,
   "nds18": 4859,
   "operationType": 1,
   "userInn": "7728029110",
   "dateTime": "2018-05-18T22:05:00",
   "fiscalDocumentNumber": 12654,
   "receiptCode": 3,
   "ecashTotalSum": 97588,
   "nds10": 5976,
   "requestNumber": 395,
   "retailPlaceAddress": "г.Екатеринбург, ул.Сулимова, д.50",
   "fiscalDriveNumber": "871000010459859",
   "taxationType": 1,
   "user": "АО ТД Перекресток",
   "operator": "<Данные кассира>",
   "items":    [
            {
         "sum": 3799,
         "quantity": 1,
         "price": 3799,
         "name": "18074 Укроп пакет 100г",
         "nds10": 345
      },
            {
         "sum": 7490,
         "quantity": 0.872,
         "nds18": 1143,
         "name": "2000339 Яблоки СЕЗОН.ПРЕДЛОЖЕНИЕ 1кг",
         "price": 8590
      }
   ],
   "totalSum": 97588,
   "rawData": "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",
   "shiftNumber": 262,
   "kktRegId": "0001248888049341"
}}}



Особого смысла в логине я не вижу, но он используется в их мобильном приложении. Возможно, в дальнейшем он для чего-нибудь пригодится.

Кому интересен пример реализации подключения к этому API, вот ссылка на гитхаб проект библиотеки, написанной на C#.

По всем вопросам или замечаниям прошу в комментарии.

UPD После небольшой проверки выяснилось, что ФНС не хранит детальную информацию по всем чекам. По крайней мере у меня 22.05.2018 не удалось получить полный чек от декабря 2017, января и февраля 2018, при том, что у ОФД эта информация имеется и мобильное приложение ФНС сообщает, что чек корректен. За март 2018 чек получить уже удалось.

UPD Как заметили пользователи IvanG и neoman36, n=1 это «Вид кассового чека». 1 — значит «приход», 2 — «Возврат прихода». Это же число надо вставлять при проверке существования чека.

UPD Как заметил пользователь Echo77, начиная с декабря 2018 года API стал возвращать код ответа 451 «Illegal public API usage», поэтому теперь прежде чем запрашивать чек, необходимо делать запрос на проверку существования чека.

UPD По замечанию пользователя Actie, в ответ на этот вопрос на тостере, в конце 2018 года ФНС выпустила официальный API «Проверка чека». «Доступ к API дают если написать заявление, заверить электронной подписью, рассказать зачем и как будешь использовать.» (с)

Документация для получения токена

Получить токен физическому лицу, насколько понимаю, невозможно. Только юр. лицо или ИП. Также при написании заявления необходимо явно указать с каких IP адресов будешь запрашивать информацию по чекам.
Этот же пользователь (организация(?)) — Actie реализовали gem для Ruby. Но опять же замечу, что использовать его без токена не получится. Ссылка на репозиторий.
В этом же репозитории указано, что при большом количестве проверок API, описанный в данной статье, работает не стабильно. Лично я не проверял.

UPD Как заметил один из пользователей — после большого количества запросов появляется ошибка блокировки аккаунта. На 25.03.2020 лимит составляет около 25 запросов в сутки. Раньше такого лимита вроде бы не было.
Tags:ФНСпроверка чекауниверсальный апи для проверки чекаAPI
Hubs: Open source API
+31
73.8k 212
Comments 82
Popular right now
Back-end разработчик (Laravel, REST API)
from 100,000 to 140,000 ₽GBMSRemote job
QA Engineer
from 120,000 to 150,000 ₽СофтТелематикаМосква
Java API Developer
from 3,300 to 5,000 $AWWCOR Inc.Remote job
Senior Frontend Engineer
from 160,000 to 220,000 ₽Jamakase TechnologiesRemote job