Нет документации по API? Не беда!
Захожу на сайт ЛК самозанятого, открываю консоль разработчика (вкладка Network → Fetch/XHR), авторизуюсь и наблюдаю что-то страшное... Здесь отображаются все запросы, которые браузер отправляет на сервер.
Регистрирую покупку вручную, к списку добавляется запрос income
, а на экране появился чек.
Нажимаем на income
и разбираем подробнее:
Это POST-запрос, принимающий JSON с данными клиента (вкладка Payload) и возвращающий УИД чека (вкладка Response/Preview)
Сам чек появляется через GET-запрос print
, он также появился в списке, а во вкладке Preview доступно его изображение.
URL запроса print
: https://lknpd.nalog.ru/api/v1/receipt/ваш_ИНН/УИД_чека/print
Авторизация
ЛК самозанятого использует OAuth2 с Bearer-токеном. При каждом запросе нужно передавать access_token
в заголовке, его можно увидеть в любом запросе из списка.
Этот токен живёт 1 час, поэтому его нужно регулярно обновлять.
Как получить access_token?
Через запрос на /api/v1/auth/token
с таким JSON:
{
"deviceInfo": {
"sourceDeviceId": "*******",
"sourceType": "WEB",
"appVersion": "1.0.0",
"metaDetails": {
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"
}
},
"refreshToken": "ваш_refresh_token"
}
Как видим, что в запросе для получения access_token
закрался еще один refresh_token.
Да кто этот ваш refresh_token?
Это токен обновления, который живёт около года. Получить его можно:
-
Через POST запрос на
/api/v1/auth/lkfl
, где тело:{ "deviceInfo": { "sourceDeviceId": "*******", "sourceType": "WEB", "appVersion": "1.0.0", "metaDetails": { "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36"} }, "username": "*******", "password": "*******" }
В ответе будет refresh_token.
-
"Ленивым" способом: взять из запроса
verify
из списка при авторизации и записать в регистр сведений ТокеныАвторизации или в константу, но его всё равно нужно обновлять раз в год вручную.
Логика работы с токенами
Перед каждым запросом проверяю:
-
Не истёк ли
refresh_token
-
Не истёк ли
access_token
При необходимости обновляю их.
Пример кода на 1С для обновления access_token
:
Функция AccessToken(Соединение, RefreshToken) Экспорт
МенеджерЗаписи = РегистрыСведений.ТокеныАвторизации.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Ресурс = Соединение.Сервер;
МенеджерЗаписи.ТипТокена = Перечисления.ТипыТокенов.AccessToken;
МенеджерЗаписи.Прочитать();
Если Не ИстекСрокДействия(МенеджерЗаписи.СрокДействия) И МенеджерЗаписи.Токен <> Неопределено Тогда
Возврат МенеджерЗаписи.Токен;
Иначе
JSONАвторизации = ПолучитьJSONАвторизации(RefreshToken); //строка json вида из пункта access_token
ЗапросPOST = Новый HTTPЗапрос();
ЗапросPOST.АдресРесурса = "/api/v1/auth/token";
ЗапросPOST.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
ЗапросPOST.УстановитьТелоИзСтроки(JSONАвторизации, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(ЗапросPOST);
Если Ответ.КодСостояния = 200 Тогда
ОтветСтрокой = Ответ.ПолучитьТелоКакСтроку();
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ОтветСтрокой);
Объект = ПрочитатьJSON(Чтение, Истина);
Token = Объект["token"];
МенеджерЗаписи.СрокДействия = ТекущаяДатаСеанса() + 3600;
МенеджерЗаписи.Токен = Token;
МенеджерЗаписи.Записать();
Возврат Token;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецЕсли;
КонецФункции
Пример формирования продажи:
JSONПродажи = ПолучитьJSONПродажи(Источник.Услуга, Источник.Оплачено); //строка json вида из пункта запроса income
ЗапросPOST = Новый HTTPЗапрос();
ЗапросPOST.АдресРесурса = "/api/v1/income";
ЗапросPOST.Заголовки.Вставить("Authorization", "Bearer " + AccessToken);
ЗапросPOST.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
ЗапросPOST.УстановитьТелоИзСтроки(JSONПродажи, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = HTTP.ОтправитьДляОбработки(ЗапросPOST);
Если Ответ.КодСостояния = 200 Тогда
ОтветСтрокой = Ответ.ПолучитьТелоКакСтроку();
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(ОтветСтрокой);
Объект = ПрочитатьJSON(Чтение, Истина);
IDЧека = Объект["approvedReceiptUuid"];
// Отправка чека ученику в Telegram
ОбменТелеграм.ЗаписатьСсылкуВОчередьОтправки(
"Чек оплаты занятия",
"https://lknpd.nalog.ru/api/v1/receipt/" + INN + "/" + IDЧека + "/print",
ОбщегоНазначенияСервер.РеквизитОбъекта(Источник.Ученик, "ТелеграмID"));
Иначе
ЗаписьЖурналаРегистрации("ФормированиеЧекаОплаты",
УровеньЖурналаРегистрации.Ошибка,
Источник.Занятие,
,
СтрШаблон("Ошибка формирования чека оплаты. Код состояния: %1, Тело: %2",
Ответ.КодСостояния,
ОтветСтрокой));
КонецЕсли;
Вступайте в нашу телеграмм-группу Инфостарт