Как настроить интеграцию 1С с системой AITS-прослеживаемость (Республика Беларусь)?

Программист Управленческий учет Промышленность, строительство и АПК
← На главную

Разберем детально процесс настройки обмена данными между учетной системой на базе 1С и государственной информационной системой AITS (Animal Identification Traceability System) Республики Беларусь. Эта система обязательна к использованию для предприятий агропромышленного комплекса и мясокомбинатов. Рассмотрим особенности архитектуры, методы авторизации, способы отправки XML-файлов и типовые проблемы, с которыми сталкиваются разработчики при внедрении.

Особенности системы AITS и интеграция с ФГИС «Меркурий»

Система AITS состоит из нескольких подсистем, среди которых нас в первую очередь интересует «AITS-Прослеживаемость». Она отвечает за учет движения сырья, производство готовой продукции и отгрузки. Важно понимать, что жесткие требования к заполнению данных продиктованы необходимостью бесшовной интеграции с российской системой «Меркурий» через шлюз обмена данными.

Проанализируем основные идентификаторы, которые нам потребуются для корректного формирования запросов:

  1. GUIN (Глобальный уникальный идентификатор партии) — основной тег для отслеживания конкретной партии сырья или готовой продукции.
  2. GLN (Global Location Number) — используется для идентификации контрагентов, поставщиков сырья, самого предприятия и его складов.
  3. GTIN (Global Trade Item Number) — необходим для идентификации видов выпускаемой продукции (данные берутся из белорусского Банка электронных паспортов товаров ePass).

Если цепочка «сырье — готовая продукция — отгрузка» не будет строго связана в AITS, система не сможет автоматически сгенерировать электронный ветеринарный сертификат для экспорта.

Авторизация и получение токена в 1С 8.х

Посмотрим на пример реализации авторизации на платформе 1С:Предприятие 8. Для получения токена (AuthToken) нам необходимо выполнить GET-запрос к сервису авторизации.

Разберем код, который отправляет HTTP-запрос и парсит полученный JSON-ответ средствами платформы:


// Работа с JSON
&НаКлиенте
Функция jsonПрочитатьПлатформой(Значение)
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(Значение);
    Результат = Неопределено;
    СформироватьДерево(ЧтениеJSON, Результат);
    ЧтениеJSON.Закрыть;
    Возврат Результат;
КонецФункции

&НаКлиенте
Процедура СформироватьДерево(ЧтениеJSON, Дерево)
    ИмяСвойства = Неопределено;
    Пока ЧтениеJSON.Прочитать() Цикл
        TипJSON = ЧтениеJSON.ТипТекущегоЗначения;
        Если TипJSON = ТипЗначенияJSON.НачалоОбъекта ИЛИ TипJSON = ТипЗначенияJSON.НачалоМассива Тогда
            НовыйОбъект = ?(TипJSON = ТипЗначенияJSON.НачалоОбъекта, Новый Соответствие, Новый Массив);
            Если ТипЗнч(Дерево) = Тип("Массив") Тогда
                Дерево.Добавить(НовыйОбъект);
            ИначеЕсли ТипЗнч(Дерево) = Тип("Соответствие") И ЗначениеЗаполнено(ИмяСвойства) Тогда
                Дерево.Вставить(ИмяСвойства, НовыйОбъект);
            КонецЕсли;
            СформироватьДерево(ЧтениеJSON, НовыйОбъект);
            Если Дерево = Неопределено Тогда
                Дерево = НовыйОбъект;
            КонецЕсли;
        ИначеЕсли TипJSON = ТипЗначенияJSON.ИмяСвойства Тогда
            ИмяСвойства = ЧтениеJSON.ТекущееЗначение;
        ИначеЕсли TипJSON = ТипЗначенияJSON.Число ИЛИ TипJSON = ТипЗначенияJSON.Строка ИЛИ TипJSON = ТипЗначенияJSON.Булево ИЛИ TипJSON = ТипЗначенияJSON.Null Тогда
            Если ТипЗнч(Дерево) = Тип("Массив") Тогда
                Дерево.Добавить(ЧтениеJSON.ТекущееЗначение);
            ИначеЕсли ТипЗнч(Дерево) = Тип("Соответствие") Тогда
                Дерево.Вставить(ИмяСвойства, ЧтениеJSON.ТекущееЗначение);
            КонецЕсли;
        Иначе
            Возврат;
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

// Функция отправки HTTP-запроса
Функция ОтправитьHTTPЗапрос(Хост, Ресурс) Экспорт
    Соединение = Новый HTTPСоединение(Хост);
    Заголовки = Новый Соответствие;
    Заголовки.Вставить("host", Хост);
    Запрос = Новый HTTPЗапрос(Ресурс, Заголовки);
    Ответ = Неопределено;
    Попытка
        Ответ = Соединение.Получить(Запрос);
    Исключение
        Сообщить(ОписаниеОшибки());
    КонецПопытки;
    Возврат Ответ;
КонецФункции

// Процедура авторизации
Процедура ВыполнитьАвторизацию(СтруктураНастроек, Токен) Экспорт
    Порт = СтруктураНастроек.ПортСервера;
    Хост = СтруктураНастроек.АдресСервера + ":" + Порт;
    Логин = СтруктураНастроек.Логин;
    Пароль = СтруктураНастроек.Пароль;
    Ресурс = "/trace/services/Auth.svc/auth?login=" + Логин + "&pwd=" + Пароль;
    
    Ответ = ОтправитьHTTPЗапрос(Хост, Ресурс);
    Если Ответ <> Неопределено Тогда
        СтруктурированныйОтвет = jsonПрочитатьПлатформой(Ответ.ПолучитьТелоКакСтроку());
        ПредставлениеОтвета = СтруктурированныйОтвет.Получить("Status");
        КодОтвета = СтруктурированныйОтвет.Получить("Code");
        ТокенДанные = СтруктурированныйОтвет.Получить("Data");
        
        Если ПредставлениеОтвета = "OK" Тогда
            // ВАЖНО: Обработка бага API со слешами в токене
            Токен = СтрЗаменить(ТокенДанные, "\/", "/");
            Сообщить("Авторизация пройдена успешно");
        Иначе
            Сообщить ("Авторизация не пройдена, Код ошибки: " + КодОтвета);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Важное замечание: API системы AITS иногда возвращает токен, в котором экранированы символы косой черты (\/). Если отправить такой токен обратно, сервер вернет ошибку «Некорректный AuthToken». Именно поэтому перед использованием токена мы применяем функцию СтрЗаменить(ТокенДанные, "\/", "/"). Также стоит учитывать, что сервис может работать нестабильно, поэтому иногда авторизацию приходится повторять в цикле (до 3-5 попыток), если сервер отвергает правильный токен.

Отправка данных (XML) через COM-объекты (1С 7.7 / 1С 8.х)

Рассмотрим метод загрузки XML-файлов с данными о партиях (сырье, продукция, отгрузки) через POST-запрос с использованием WinHttp.WinHttpRequest.5.1 и ADODB.Stream. Данный подход универсален и работает как в 1С 7.7, так и в более новых версиях платформы (через вызов Новый COMОбъект).


Процедура ОтправитьФайлВАИТС(ПутьКФайлу, Токен, АдресСайта)
    // Чтение файла в правильной кодировке
    oADOStream = Новый COMОбъект("ADODB.Stream"); // Для 7.7: СоздатьОбъект("ADODB.Stream")
    oADOStream.Type = 1; 
    oADOStream.Open();
    oADOStream.LoadFromFile(ПутьКФайлу);
    
    // Инициализация HTTP-соединения
    Соединение = Новый COMОбъект("WinHttp.WinHttpRequest.5.1"); 
    Соединение.Option(2, "utf-8");
    Соединение.Open("POST", АдресСайта, 0);
    
    // Установка обязательных заголовков
    Соединение.SetRequestHeader("AuthToken", Токен);
    Соединение.SetRequestHeader("Content-Type", "text/xml");
    Соединение.SetRequestHeader("isinsert", 0); // 0 - обновление, 1 - вставка
    
    // Отправка файла
    Попытка
        Соединение.Send(oADOStream);
    Исключение
        Сообщить("Ошибка отправки запроса!");
        Возврат;
    КонецПопытки;
    
    // Проверка статуса ответа
    Если Соединение.Status = 200 Тогда
        Сообщить("Ответ сервера: " + Соединение.ResponseText);
    Иначе
        Сообщить("HTTP Ошибка: " + Соединение.Status + " - " + Соединение.StatusText);
    КонецЕсли;
КонецПроцедуры

Обратим внимание на обязательные HTTP-заголовки. Если не передать Content-Type: text/xml, сервер вернет внутреннюю ошибку или ошибку формата данных. Заголовок isinsert указывает системе, создаем ли мы новую запись или обновляем существующую.

Пакетная обработка и проверка статусов

Для предприятий с большим документооборотом отправка файлов по одному вручную неэффективна. Разберем алгоритм автоматизированной пакетной отправки ТТН и производственных документов:

  1. Формируем отдельный XML-файл (или пакет данных) под каждый документ 1С (приход, производство, отгрузка).
  2. Для каждого файла генерируем уникальный идентификатор отправки — requestGuid (он должен быть уникальным при каждом POST-запросе, даже если мы обновляем данные).
  3. Отправляем файлы в цикле (желательно с небольшой паузой Пауза(1000) между отправками, чтобы не перегрузить сервер AITS).
  4. Сохраняем связку «Документ 1С - requestGuid» в регистр сведений.
  5. Отдельным регламентным заданием или по кнопке проверяем статусы обработки на портале AITS по сохраненным requestGuid. Если ответ положительный, помечаем документ как успешно переданный.

Решение нештатных ситуаций бизнес-логики

Выясним причину частой проблемы: как выгрузить партию, если мы предприятие-посредник, и поставщик не передал нам GUIN партии сырья? В системе AITS существует недокументированный функционал. Если GUIN партии неизвестен, разработчики рекомендуют вместо него передавать тег GLN производителя. В этом случае сервер будет осуществлять поиск и привязку по связке: дата партии + номер партии + GLN производителя.

В случае, если система постоянно выдает ошибку «Идентификатор запроса 'RequestGuid' не является уникальным» при попытке обновить данные (параметр UPDATE), убедитесь, что вы генерируете новый RequestGuid именно для сессии связи, а не берете старый GUID самого документа или исходного файла.

← На главную