При работе с системой маркировки «Честный знак» часто возникает необходимость программно получать актуальный статус кодов маркировки, наименование товара и сведения о текущем владельце. В этой статье мы подробно рассмотрим, как реализовать такую интеграцию в 1С, используя как прямое взаимодействие с API True API, так и встроенные механизмы конфигурации 1С. Мы также уделим внимание критически важному аспекту — управлению токенами авторизации.
Для решения задачи получения информации о коде маркировки (КМ) (поможет обработка для проверки КМ при складских операциях), такой как наименование артикула (товара) и его текущий владелец, существуют два основных подхода, которые мы разберем поэтапно:
Этот подход предполагает формирование и отправку HTTP-запросов напрямую к серверу «Честного знака». Он требует аккуратной работы с авторизацией, формированием тела запроса в формате JSON и последующей обработкой полученного ответа.
Прежде чем отправлять запросы к API «Честного знака», нам потребуется получить токен авторизации. Этот токен выступает в роли идентификатора и подтверждения наших прав на доступ к данным. В True API Честного знака для аутентификации используется JWT-токен (JSON Web Token), который имеет ограниченный срок действия (обычно до 10 часов). После истечения этого срока токен необходимо получать повторно.
Для получения аутентификационного токена обычно используются методы Единой аутентификации, описанные в документации TrueAPI, такие как auth/key и auth/simpleSignIn. Для этого, как правило, требуется формирование подписанных данных с использованием квалифицированной электронной подписи (КЭП). Токен также можно сгенерировать в личном кабинете «Честного знака» в разделе «Профиль», на вкладке «Данные участника» (кнопка «Сгенерировать токен» для контрольно-кассовой техники), при этом каждая организация должна иметь свой токен. Такой токен может быть использован, например, для работы приложения для проверки маркировки в разрешительном режиме.
Рассмотрим функцию ПолучитьТокен(), которая извлекает уже сохраненный токен для конкретной организации и проверяет его срок действия:
Функция ПолучитьТокен(Организация)
УстановитьПривилегированныйРежим(Истина);
ДанныеКлючаСессии = ИнтерфейсАвторизацииИСМПСлужебный.ПолучитьСохраненныеДанныеКлючаСессии(
ИнтерфейсИСМПКлиентСервер.ИмяДанныхКлючаСессии(Перечисления.ТипыТокеновАвторизации.ИСМП));
Если ДанныеКлючаСессии = Неопределено Тогда
Возврат "";
КонецЕсли;
Данные = ДанныеКлючаСессии[Организация];
Если Данные = Неопределено Тогда
Возврат "";
КонецЕсли;
ДействуетДо = МестноеВремя(Данные.ДействуетДо, ЧасовойПоясСеанса);
Если ДействуетДо <= ТекущаяДата Тогда
Сообщить("Нужно актуализировать токен для организации " + Организация.Наименование + " закончился: " + ДействуетДо);
Возврат "";
КонецЕсли;
Возврат Данные.КлючСессии;
КонецФункции
Если токен не найден или просрочен, потребуется его актуализация. Для актуализации токена в типовых конфигурациях 1С может использоваться функция ИнтерфейсАвторизацииИСМПКлиент.ЗапроситьКлючСессии, которая отвечает за получение нового токена, часто требуя взаимодействия с пользователем для выбора сертификата.
После получения актуального токена, мы можем приступить к формированию и отправке запроса. Стоит отметить, что помимо получения информации о конкретных кодах, существует и обратная задача — запросить список кодов маркировки по заданным фильтрам, что также может быть реализовано через API. Для получения же информации о статусе кода маркировки, наименовании товара и данных разрешительной документации используется метод /api/v3/true-api/cises/info.
Важно учитывать, что данный метод имеет ограничения: до 50 запросов в секунду и не более 1000 кодов идентификации (КИ) в одном запросе. Поэтому при работе с большим количеством кодов необходимо реализовывать пакетную отправку данных.
Давайте рассмотрим процедуру ДополнитьТЗИнформациейПоЧестномуЗнаку(), которая демонстрирует формирование запроса:
Процедура ДополнитьТЗИнформациейПоЧестномуЗнаку(ТЗ, Организация, Отказ)
Токен = ПолучитьТокен(Организация);
Если ПустаяСтрока(Токен) Тогда
Отказ = Истина;
Возврат;
КонецЕсли;
ТЗ.Колонки.Добавить("productName");
ТЗ.Колонки.Добавить("tnVedEaes");
ТЗ.Колонки.Добавить("certDoc_number");
ТЗ.Колонки.Добавить("certDoc_type");
ТЗ.Колонки.Добавить("certDoc_date");
Соединение = Новый HTTPСоединение("markirovka.crpt.ru", 443,,,,,Новый ЗащищенноеСоединениеOpenSSL);
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json; charset=UTF-8");
Заголовки.Вставить("Accept", "application/json");
HTTPЗапрос = Новый HTTPЗапрос("/api/v3/true-api/cises/info",Заголовки);
HTTPЗапрос.Заголовки.Вставить("Authorization","Bearer "+Токен);
//-- тело запроса
сч = 0;
МассивУпаковок = Новый Массив;
Для Каждого эл Из ТЗ Цикл
МассивУпаковок.Добавить(эл.ШтрихкодУпаковки);
Если МассивУпаковок.Количество > 0 И сч > 0 И сч % 999 = 0 Тогда //не больше 1000 записей в теле запроса
ОтправитьЗапросВСервисИОбработатьРезультат(Соединение, HTTPЗапрос, МассивУпаковок, ТЗ, Отказ);
МассивУпаковок.Очистить;
КонецЕсли;
сч = сч + 1;
КонецЦикла;
Если МассивУпаковок.Количество > 0 Тогда //доотправляем еще неотправленные данные
ОтправитьЗапросВСервисИОбработатьРезультат(Соединение, HTTPЗапрос, МассивУпаковок, ТЗ, Отказ);
КонецЕсли;
КонецПроцедуры
В этой процедуре мы:
ТЗ) новые колонки для хранения информации о товаре и сертификатах.HTTPСоединение с сервером «Честного знака» (markirovka.crpt.ru) по защищенному протоколу HTTPS (порт 443) с использованием ЗащищенноеСоединениеOpenSSL.HTTPЗапрос, указывая нужный адрес (/api/v3/true-api/cises/info) и устанавливая необходимые заголовки, включая Authorization с нашим токеном.МассивУпаковок.МассивУпаковок достигает 999 (чтобы не превысить лимит в 1000, учитывая, что счётчик начинается с 0), вызываем процедуру отправки и очищаем массив для следующей партии.После отправки запроса нам необходимо корректно обработать полученный ответ от «Честного знака». Ответ приходит в формате JSON, который мы должны распарсить и извлечь нужные данные.
Процедура ОтправитьЗапросВСервисИОбработатьРезультат() выполняет отправку запроса и разбирает полученный ответ:
Процедура ОтправитьЗапросВСервисИОбработатьРезультат(Соединение, HTTPЗапрос, МассивУпаковок, ТЗ, Отказ)
Запись_JSON = Новый ЗаписьJSON;
Запись_JSON.УстановитьСтроку();
ЗаписатьJSON(Запись_JSON, МассивУпаковок);
СтрокаДляЗапроса = Запись_JSON.Закрыть();
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаДляЗапроса,КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
Если Ответ.КодСостояния = 200 Тогда
Чтение_JSON = Новый ЧтениеJSON;
Чтение_JSON.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
ОтветНаЗапрос = ПрочитатьJSON(Чтение_JSON, Ложь);
Для Каждого СтруктураОтвета Из ОтветНаЗапрос Цикл
cisInfo = СтруктураОтвета.cisInfo;
Если cisInfo.generalPackageType <> "UNIT" Тогда
Сообщить("Код маркировки: " + cisInfo.cis + " не является кодом маркировки индивидуально упаковки!");
Продолжить;
КонецЕсли;
//Проверим что исходный код упаковки есть в ТЗ
СтрокаТЗ = ТЗ.Найти(cisInfo.requestedCis, "ШтрихкодУпаковки");
Если СтрокаТЗ = Неопределено Тогда
Сообщить("Код маркировки: " + cisInfo.cis + " не найден в ТЗ из УПД!");
Продолжить;
КонецЕсли;
Попытка
//Если перемаркировка, то сведений о сертификате соответствия может не быть
ДекларацияМассив = cisInfo.certDoc;
Исключение
ДекларацияМассив = Новый Массив;
КонецПопытки;
Если ДекларацияМассив.Количество > 0 Тогда
Декларация = ДекларацияМассив[0];
Иначе
Декларация = Неопределено;
КонецЕсли;
СтрокаТЗ.productName = cisInfo.productName;
СтрокаТЗ.tnVedEaes = cisInfo.tnVedEaes;
Если Декларация <> Неопределено Тогда
СтрокаТЗ.certDoc_number = Декларация.number;
СтрокаТЗ.certDoc_type = Декларация.type;
СтрокаТЗ.certDoc_date = Декларация.date;
КонецЕсли;
КонецЦикла;
Иначе
Сообщить("Код ответа на запрос: "+Ответ.КодСостояния +" - ошибка!" );
Отказ = Истина;
Возврат;
КонецЕсли;
КонецПроцедуры
В этой процедуре мы выполняем следующие действия:
МассивУпаковок в строку JSON и устанавливаем её как тело HTTP-запроса.Соединение.ОтправитьДляОбработки(HTTPЗапрос).Ответ.КодСостояния равен 200, значит запрос выполнен успешно.ПрочитатьJSON().cisInfo.cisInfo.generalPackageType. Если это не индивидуальная упаковка ("UNIT"), выводим предупреждение.ТЗ), которая часто формируется на основе данных из электронного УПД, по коду маркировки. Процесс обмена такими документами можно автоматизировать с помощью решений для групповой выгрузки и загрузки файлов для ЭДО.cisInfo.productName (наименование товара) и cisInfo.tnVedEaes (код ТН ВЭД).cisInfo.certDoc). Если их нет (например, при перемаркировке), обрабатываем исключение.ТЗ) полученными данными.Важно отметить, что информация о текущем владельце кода маркировки по методу /cises/info доступна только самому владельцу, ФОИВ (федеральным органам исполнительной власти), Оператору-ЦРПТ и Администратору системы. Если вам нужны данные о владельце для ваших кодов, вы получите их в рамках этого запроса. Для получения других сведений о владельце или товарных знаках могут существовать отдельные методы API, как правило, с более строгими ограничениями по приватности.
/cises/info содержится информация о наименовании товара (productName), коде ТН ВЭД (tnVedEaes) и данных разрешительной документации./codes/check (публичный тип приватности) с ограничениями 2 запроса в секунду и до 1000 КМ в запросе.В типовых конфигурациях 1С для работы с «Честным знаком» часто реализованы собственные сервисные функции, которые значительно упрощают взаимодействие с ИС МП, скрывая низкоуровневые HTTP-запросы — есть готовая обработка для интеграции 1С с системой ЦРПТ.
Одной из таких удобных функций является ИнтерфейсИСМП.СтатусыКодовМаркировки(). Она позволяет получить статусы по массиву штрихкодов без необходимости вручную формировать HTTP-запросы и разбирать JSON.
Рассмотрим пример использования этой функции:
СтруктураШтрихкода = ШтрихкодированиеИС.НоваяСтруктураОбработкиШтрихкода(ШтрихкодУпаковки.ЗначениеШтрихкода, Перечисления.ВидыПродукцииИС.ЛегкаяПромышленность);
МассивКодов = Новый Массив;
МассивКодов.Добавить(СтруктураШтрихкода);
Результат = ИнтерфейсИСМП.СтатусыКодовМаркировки(МассивКодов, Организация);
В этом примере мы:
ШтрихкодированиеИС.НоваяСтруктураОбработкиШтрихкода(), указывая сам штрихкод и вид продукции.МассивКодов.ИнтерфейсИСМП.СтатусыКодовМаркировки(), передавая ей массив кодов и объект Организация.Результат — структуру с текущими статусами кодов маркировки.Этот метод значительно быстрее в реализации и менее требователен к знанию деталей API.
При использовании встроенных функций 1С могут возникнуть сложности, особенно связанные с инициализацией сессии и получением токенов. Например, в рабочей базе вы можете столкнуться с ошибкой "Попытка получения неинициализированного значения параметра сеанса".
Выясним причину этой проблемы: ошибка "Попытка получения неинициализированного значения параметра сеанса" обычно возникает, когда система пытается получить данные из параметров сеанса (например, ПараметрыСеанса.ДанныеКлючаСессииИСМП), которые еще не были установлены или инициализированы для текущей сессии. Это может происходить, если:
Для решения этой проблемы необходимо убедиться, что перед использованием функций, зависящих от параметров сеанса или токенов авторизации, эти токены были получены и сохранены. Это может потребовать предварительного вызова функций для получения или актуализации токена, например, ИнтерфейсАвторизацииИСМПКлиент.ЗапроситьКлючСессии(), которая часто требует интерактивного взаимодействия с пользователем (выбора сертификата). Если необходимо выполнять действия в фоновом режиме, следует предусмотреть механизм актуализации токена, который не требует участия пользователя (например, с использованием сертификата, установленного на сервере 1С под учетной записью, от имени которой запускаются регламентные задания).
Управление токенами авторизации является одним из наиболее важных аспектов при интеграции с «Честным знаком».
Как мы уже выяснили, JWT-токен имеет ограниченный срок действия (до 10 часов). Если не обновлять токен своевременно, все последующие запросы к API будут завершаться ошибкой авторизации. Для поддержания бесперебойной работы интеграции необходимо реализовать механизм периодической проверки и обновления токена.
«Честный знак» планирует переход на Единый токен авторизации в формате UUID к осени 2026 года. Новый формат токена обеспечит повышенную безопасность и стабильность работы системы и уже используется в некоторых версиях 1С:Бухгалтерии.
Особую сложность представляет обновление токена в регламентных заданиях, которые выполняются на сервере без участия пользователя. В этом случае невозможно интерактивно выбрать сертификат или ввести пароль.
Мы можем проверить срок действия токена перед его использованием, как показано в сообщении 11:
ДанныеКлючаСессии = ИнтерфейсАвторизацииИСМПСлужебный.ПолучитьСохраненныеДанныеКлючаСессии("ДанныеКлючаСессииИСМП");
Если ДанныеКлючаСессии = Неопределено
или ДанныеКлючаСессии.Получить(Справочники.Организации.НайтиПоНаименованию("Организация")).ДействуетДо < ТекущаяДата Тогда
// Надо запрашивать ключ, в регламентном задании!
КонецЕсли;
Если токен просрочен или отсутствует, нам потребуется его запросить. Для этого обычно используется функция ИнтерфейсАвторизацииИСМПКлиент.ЗапроситьКлючСессии(). Однако, если сертификат установлен только на сервере под учетной записью, под которой крутятся регламентные задания, и не требует интерактивного подтверждения, эта функция может быть вызвана и в фоновом режиме. В противном случае, потребуется настроить сертификат таким образом, чтобы он был доступен для автоматического использования, или реализовать механизм, который будет получать токен в интерактивной сессии и сохранять его для последующего использования регламентными заданиями.
При работе с API «Честного знака» важно учитывать ряд общих рекомендаций, которые помогут избежать ошибок и обеспечить стабильную работу:
Следуя этим рекомендациям и используя представленные примеры кода, вы сможете успешно интегрировать вашу систему 1С с API «Честного знака» для эффективного управления кодами маркировки и получения необходимой информации о товарах.