Как исправить ошибкую «Ошибка подписи» при отправке документов через API ЭДО Лайт?

Программист 1С v8.3 (Управляемые формы) Торговля и дистрибуция
← На главную

Работа с API ЭДО Лайт в системе «Честный ЗНАК» часто сопровождается трудностями при выполнении процедуры подписания исходящих документов. Одной из самых распространенных проблем, с которой сталкиваются разработчики при интеграции 1С, является ошибка «Ошибка подписи» при попытке подтвердить ранее созданный черновик. Давайте разберем, почему это происходит и как правильно реализовать этот процесс, чтобы избежать искажения данных.

Разбор причины ошибки: почему «строки» — это плохо

Основная проблема при работе с API через 1С заключается в неявном преобразовании типов данных. Многие разработчики пытаются получать содержимое XML-файла и передавать подпись, конвертируя данные в строки (например, используя кодировки windows-1251 или UTF-8). Однако в процессе такой конвертации происходят изменения байтового представления документа, которые нарушают целостность подписи. В результате сервер ГИС МТ получает данные, которые не соответствуют контрольной сумме исходного черновика.

Золотое правило интеграции с ЭДО Лайт: отказывайтесь от любых преобразований в строковые форматы. Работайте исключительно с ДвоичныеДанные на всех этапах: от получения контента черновика до отправки сформированного пакета подписи.

Решение №1: Прямая работа с двоичными данными

Чтобы избежать перекодировок, необходимо использовать методы HTTPОтвет.ПолучитьТелоКакДвоичныеДанные() для получения файла и HTTPЗапрос.УстановитьТелоИзДвоичныхДанных() для его отправки. Рассмотрим пример корректной функции отправки подписи:


Функция ПодписатьИОтправитьДокументВЭДОЛайт(ВыбранныйСертификат, Токен, ИД_ЭДО) Экспорт
    Результат = Новый Структура("Выполнено,ТекстОшибки", Ложь, "");
    
    // Получаем контент документа как двоичные данные
    HTTPСоединение = Новый HTTPСоединение(ПолучитьАдресГИС_МТ, 443, , , , , Новый ЗащищенноеСоединениеOpenSSL);
    URLЗапроса = СтрШаблон("/api/v1/outgoing-documents/%1/content", ИД_ЭДО);
    HTTPЗапрос = Новый HTTPЗапрос(URLЗапроса, ЗаголовокHTTP);
    HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод("GET", HTTPЗапрос);
    ДВXMLДокумент = HTTPОтвет.ПолучитьТелоКакДвоичныеДанные();
    
    // Подписываем (используя присоединенную или открепленную подпись в зависимости от требований метода)
    ПодписанныйДокументБинар = ПодписатьСертификатомДвоичныеДанные(ВыбранныйСертификат, ДВXMLДокумент);
    
    // Отправляем результат
    URLЗапроса = СтрШаблон("/api/v1/outgoing-documents/%1/signature", ИД_ЭДО);
    HTTPЗапрос = Новый HTTPЗапрос(URLЗапроса);
    HTTPЗапрос.Заголовки.Вставить("Authorization", "Bearer " + Токен);
    HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ПодписанныйДокументБинар);
    
    HTTPОтвет = HTTPСоединение.ВызватьHTTPМетод("POST", HTTPЗапрос);
    // Обработка ответа...
КонецФункции

Решение №2: Использование метода multipart/form-data

Если метод последовательного подписания черновика вызывает ошибки, рекомендуется использовать передачу данных и подписи одним пакетом через multipart/form-data. Это позволяет серверу гарантированно связать файл и его электронную подпись в рамках одной транзакции.

При использовании этого подхода мы самостоятельно формируем тело запроса, используя разделитель (boundary). Важно правильно указать Content-Type с параметром boundary.


// Пример формирования multipart-запроса
Р = "---------------------------Boundary_String_12345";
Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Р);
Тело = "--" + Р + Символы.ПС + 
       "Content-Disposition: form-data; name=""content""; filename=""doc.xml""" + Символы.ПС +
       "Content-Type: application/xml" + Символы.ПС + Символы.ПС +
       ДанныеФайла + Символы.ПС +
       "--" + Р + Символы.ПС +
       "Content-Disposition: form-data; name=""signature""" + Символы.ПС +
       "Content-Type: text/plain" + Символы.ПС + Символы.ПС +
       Base64Строка(Подпись) + Символы.ПС +
       "--" + Р + "--";

Важные рекомендации для успешной интеграции

  1. Проверка кодировок: Никогда не используйте ПолучитьТелоКакСтроку("windows-1251") при работе с контентом API. Получайте данные только в бинарном виде.
  2. Синхронизация данных: Если API сообщает, что документ не совпадает, убедитесь, что вы получаете именно ту версию документа, которая хранится на сервере в статусе «Черновик» через метод GET /api/v1/outgoing-documents/%1/content.
  3. Роуминг: Если ваши контрагенты не видят отправленные документы (например, в СБИС или Диадок), напомните им, что они должны инициировать настройку роуминга со своей стороны, выбрав оператора «ЦРПТ» (ЭДО Лайт).
  4. Инструменты: Для работы с сертификатами и подписью используйте объекты CAdESCOM.CPSigner, встроенные в компоненты КриптоПро, обеспечивая корректное формирование присоединенной или открепленной подписи согласно спецификации вашего метода API.

Следуя этим рекомендациям и исключив строковые преобразования из своего кода, вы сможете добиться стабильной работы с API ЭДО Лайт и избавиться от ошибок подписи навсегда.

← На главную