В процессе интеграции с системой «Честный ЗНАК» для реализации разрешительного режима (True API) программисты часто сталкиваются с ошибками 400 BAD_REQUEST, 401 Unauthorized или 500 Internal Server Error. Эти ошибки могут быть вызваны как неверным форматом JSON-пакета, так и глобальными изменениями в архитектуре самой системы маркировки. В данной статье мы подробно проанализируем причины возникновения этих проблем и разберем по шагам, как правильно настроить запрос информации о коде маркировки (КМ).
Разберем одну из самых распространенных и «глупых» ошибок, которая приводит к ответу 400 BAD_REQUEST "Failed to read HTTP message". При формировании тела запроса программисты часто передают код маркировки как одиночную строку, в то время как документация True API требует передачи массива кодов, даже если проверяется всего одна единица товара.
Посмотрим на ошибочный вариант кода:
Запрос.УстановитьТелоИзСтроки("{ ""codes"": """ + СокрЛП(КодМаркировки) + """ }", КодировкаТекста.UTF8);
В данном примере параметр codes является строкой. Выясним причину ошибки: сервер ожидает структуру массива (квадратные скобки). Проанализируем верный вариант формирования тела запроса:
Запрос.УстановитьТелоИзСтроки("{ ""codes"": [""" + СокрЛП(КодМаркировки) + """] }", КодировкаТекста.UTF8);
Именно наличие квадратных скобок [] делает JSON-структуру валидной для метода /codes/check. Если вы используете несколько кодов, они должны перечисляться через запятую внутри этих скобок.
Следующий критический момент связан с передачей полной строки кода маркировки, содержащей криптохвост. Коды маркировки формата GS1 содержат непечатные символы-разделители (ASCII 29), которые в учетных системах часто отображаются некорректно или теряются. Для корректной проверки в Честном ЗНАКе эти символы должны быть экранированы.
Рассмотрим ситуацию: если в коде присутствуют группы данных 8005, 93 или 240, перед ними обязательно должен стоять символ-разделитель. В строке JSON его необходимо заменять на последовательность \u001d.
Проанализируем пример преобразования:
Исходный код: 010460620309799921yEM1!K9800526900093CbP6240FA083231.05
То, что нужно отправить в запросе:
010460620309799921yEM1!K9\u001d8005269000\u001d93CbP6\u001d240FA083231.05
Без этой замены сервер может вернуть ошибку валидации кода или сообщить, что код не найден, так как его структура будет нарушена при передаче по протоколу HTTP (это особенно актуально при проверке кода маркировки шин).
Важно учитывать, что старый адрес сервера markirovka.crpt.ru для прямой проверки кодов перед продажей больше не является оптимальным. Начиная с февраля 2024 года, Честный ЗНАК активно использует CDN-хосты для распределения нагрузки и минимизации задержек.
Рассмотрим алгоритм работы с CDN:
https://cdn.crpt.ru/api/v1/clusters.HTTPСоединение вместо статичного адреса.Если вы продолжаете использовать markirovka.crpt.ru, вы можете сталкиваться с периодическими ошибками 404 или 503. В сложных схемах работы может потребоваться установка нескольких локальных модулей «Честный ЗНАК» на одном компьютере.
Ошибка 401 Unknown X-Api-Key часто сбивает с толку. Проанализируем причины ее возникновения. Для работы разрешительного режима (в том числе через мобильное приложение для Android) используется не тот динамический токен, который мы получаем при авторизации через УКЭП, а статический Токен для контрольно-кассовой техники.
Где его найти и как использовать:
X-API-KEY вашего HTTP-запроса.Обратите внимание: токен для промышленного контура не будет работать в «песочнице» (sandbox), и наоборот. Для каждой среды необходимо получать свой ключ.
После получения успешного ответа от True API, данные проверки необходимо передать в кассовое ПО для формирования корректного чека. Если вы используете драйверы Атол или аналогичные, вам потребуется заполнить специфические теги в соответствии с форматом фискальных данных 1.2.
Посмотрим на основные теги, которые должны быть заполнены:
Передача этих данных гарантирует, что в фискальном накопителе сохранится информация о проверке, что является обязательным требованием, которое должно поддерживать ваше рабочее место кассира.
Соберем все вышесказанное в единый пример кода для выполнения запроса. Рассмотрим использование объекта HTTPЗапрос:
// Подготовка заголовков
ЗаголовокHTTP = Новый Соответствие;
ЗаголовокHTTP.Вставить("Content-Type", "application/json; charset=utf-8");
ЗаголовокHTTP.Вставить("X-API-KEY", ТокенДляККТ);
// Формирование тела запроса с экранированием символа GS
// КодМаркировки должен содержать \u001d вместо символа с кодом 29
ТекстЗапроса = "{ ""codes"": [""" + ЭкранированныйКод + """], ""inn"": """ + ИННОрганизации + """ }";
// Настройка соединения с учетом CDN
СерверCDN = "cdn.provider.ru"; // Полученный ранее из списка кластеров
Соединение = Новый HTTPСоединение(СерверCDN, 443, , , , 5, Новый ЗащищенноеСоединениеOpenSSL);
URLЗапроса = "api/v4/true-api/codes/check";
Запрос = Новый HTTPЗапрос(URLЗапроса, ЗаголовокHTTP);
Запрос.УстановитьТелоИзСтроки(ТекстЗапроса, КодировкаТекста.UTF8);
Попытка
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
ТекстОтвета = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
// Обработка результата проверки
Иначе
Сообщить("Ошибка запроса: " + Ответ.КодСостояния);
КонецЕсли;
Исключение
Сообщить("Ошибка связи с сервером: " + ОписаниеОшибки());
КонецПопытки;
Проанализировав данную ситуацию, мы видим, что стабильная работа с маркировкой требует внимания к деталям: от структуры JSON-массива до правильной обработки спецсимволов в коде. Регулярно обновляйте список CDN-хостов и следите за актуальностью вашего Токена ККТ, чтобы избежать простоев на кассовых узлах.