При внедрении обязательной маркировки товаров (например, табака или обуви) возникает необходимость интеграции учетных систем с True API ГИС МТ «Честный знак». Несмотря на то, что платформа 1С 7.7 считается устаревшей, интеграцию можно успешно реализовать. Рассмотрим подробнее, как авторизоваться в API, подписать данные электронной подписью (ЭЦП) и выполнить разагрегацию (получение кодов вложенных пачек из кода транспортной упаковки или блока).
Одной из частых проблем является использование неверных адресов (URL) для отправки запросов. Проанализируем ситуацию: для разных товарных групп и контуров (тестовый/промышленный) адреса отличаются.
https://ismotp.crptech.ru/api/v3/true-apihttps://int01.gismt.crpt.tech/api/v3/true-apihttps://ismp.crpt.ru/api/v3/Для табака метод авторизации выглядит как /auth/simpleSignIn, тогда как для других групп (молоко и др.) может использоваться /auth/cert.
Авторизация в True API состоит из двух этапов. Сначала необходимо запросить уникальный идентификатор и строку данных, которую предстоит подписать. Выясним причину ошибки: запрос должен идти по защищенному протоколу с правильными заголовками, иначе API может вернуть HTML-страницу вместо JSON.
Посмотрим на пример функции для получения ключей:
Функция ВернутьПаруЗапрТокена(УРЛ, ПрефиксВерсии)
WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Option(2,"utf-8");
WinHttp.SetTimeouts(0, 0, 0, 0);
Url = "https://" + УРЛ + ПрефиксВерсии + "auth/key";
WinHttp.Open("GET", Url, 1);
WinHttp.SetRequestHeader("Content-Type", "application/json");
WinHttp.SetRequestHeader("Accept-Charset", "utf-8");
WinHttp.Send();
Рез = WinHttp.WaitForResponse(40);
Если Рез = -1 Тогда
Ответ = СокрЛП(WinHttp.ResponseText());
КонецЕсли;
// Используем парсер JSON для разбора ответа
СЗ = глРазборJSON(Ответ);
Возврат СЗ;
КонецФункции
Полученную строку data необходимо подписать вашей ЭЦП. В старых реализациях часто использовалась библиотека CAPICOM, но она не поддерживает современные ГОСТ-алгоритмы и аппаратные токены (Рутокен, JaCarta). Разберем по шагам создание открепленной подписи (Detached) в формате Base64 с использованием актуального CAdESCOM.CPSigner.
Функция ComОбъектСертификатаПоОтпечатку(Отпечаток)
CAPICOM_CURRENT_USER_STORE = 2; // Ветка "Личное"
CAPICOM_MY_STORE = "My";
CAPICOM_STORE_OPEN_READ_ONLY = 0;
CAPICOM_CERTIFICATE_FIND_SHA1_HASH = 0;
oStore = СоздатьОбъект("CAdESCOM.Store");
oStore.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_READ_ONLY);
Certificates = oStore.Certificates.Find(CAPICOM_CERTIFICATE_FIND_SHA1_HASH, Отпечаток);
ComОбъект = Certificates.Item(1);
oStore.Close();
Возврат ComОбъект;
КонецФункции
Функция ПодписатьТекст(ТекстДляПодписи, Отпечаток)
CADESCOM_BASE64_TO_BINARY = 1;
CADESCOM_CADES_TYPE = 1; // Усовершенствованная подпись
bDetached = 1; // 1 - Открепленная подпись
EncodingType = 0;
oSigner = СоздатьОбъект("CAdESCOM.CPSigner");
oSigner.Options = 2;
oSigner.Certificate = ComОбъектСертификатаПоОтпечатку(Отпечаток);
oSignedData = СоздатьОбъект("CAdESCOM.CadesSignedData");
oSignedData.ContentEncoding = CADESCOM_BASE64_TO_BINARY;
// Функция Кодировать() переводит строку в Base64
oSignedData.Content = Кодировать(ТекстДляПодписи);
sSignedMessage = oSignedData.SignCades(oSigner, CADESCOM_CADES_TYPE, bDetached, EncodingType);
// Очистка от переносов строк, если они появились
sSignedMessage = СтрЗаменить(sSignedMessage, Симв(13), "");
sSignedMessage = СтрЗаменить(sSignedMessage, Симв(10), "");
Возврат sSignedMessage;
КонецФункции
После подписания мы формируем JSON-тело с оригинальным uuid и подписанной строкой data. Отправляем это POST-запросом.
Процедура ПолучитьТокен()
WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
WinHttp.Open("POST", "https://ismotp.crptech.ru/api/v3/true-api/auth/simpleSignIn", 1);
WinHttp.SetRequestHeader("Content-Type", "application/json");
WinHttp.SetRequestHeader("Accept-Charset", "utf-8");
СтрокаЗапроса = "{""uuid"": """ + СокрЛП(uuid) + """,""data"": """ + ПодписаннаяДата + """}";
WinHttp.Send(СтрокаЗапроса);
WinHttp.WaitForResponse(40);
РезультатСтр = WinHttp.ResponseText();
// Извлекаем "token" из JSON ответа
КонецПроцедуры
Важно: Полученный токен обычно живет около 10 часов. Его нужно подставлять во все последующие запросы в заголовок Authorization: Bearer [Ваш_Токен]. При частых запросах система может вернуть ошибку 429 Too Many Requests — в этом случае делайте паузу (например, с помощью внешней компоненты FormEx или 1С++) и повторяйте запрос.
Когда товар приходит в транспортной упаковке (коробах или блоках), учетной системе нужно знать коды каждой пачки. Для этого используется API-метод агрегации. Запрос делается по конкретному штрихкоду упаковки (перед запросом из ШК нужно удалить криптохвост до первого спецсимвола GS).
Процедура Разагрегация()
token = ПолучитьТокенЦРПТ(); // Наша функция авторизации
КодУпаковки = ОтрезатьЛишнееОтСтрМаркировки(СокрЛП(КодМаркировки));
WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1");
Url = "https://ismotp.crptech.ru/api/v3/true-api/cises/aggregated/list?codes=" + КодУпаковки;
WinHttp.Open("GET", Url, 0);
WinHttp.SetRequestHeader("Authorization", "Bearer " + token);
WinHttp.SetRequestHeader("Content-Type", "application/json");
WinHttp.Send();
Ответ = WinHttp.ResponseText();
СзКодов = глРазборJSON(Ответ);
Если СзКодов.РазмерСписка() > 0 Тогда
// Обрабатываем полученный массив вложенных марок (пачек)
Сообщить("Успешно получены коды пачек!");
КонецЕсли;
КонецПроцедуры
Стоит отметить, что метод возвращает только первый слой вложенности. Если вы запрашиваете короб, в ответе будут блоки. Чтобы получить пачки, потребуется выполнить повторный цикл запросов по кодам блоков. Для табачной продукции сервер нормально воспринимает коды как со скобками (01) и (21), так и без них, возвращая ответ в аналогичном формате.