Как реализовать подписание входящих УПД в ЭДО Лайт через API в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Работа с электронным документооборотом (ЭДО) в устаревших или самописных конфигурациях на платформе 1С 7.7 сопряжена с рядом технических сложностей: от отсутствия штатных средств формирования HTTP-запросов до нюансов работы с криптографией. В данной статье мы подробно разберем, как реализовать автоматическое подписание входящих универсальных передаточных документов (УПД) через API «ЭДО Лайт» (сервис от «Честного знака»), включая получение подписи отправителя и формирование корректного multipart/form-data запроса.

Алгоритм документооборота при получении УПД

Прежде чем приступать к написанию кода, проанализируем регламент взаимодействия. По регламенту ФНС, после получения входящего УПД покупатель должен сформировать и отправить в ответ «Титул покупателя» (техническое название: информация покупателя). Для этого необходимо:

  1. Получить XML-файл входящего УПД и открепленную электронную подпись (ЭЦП) продавца, которой подписан этот файл.
  2. Сформировать ответный XML-файл (Титул покупателя), в тело которого вставляются реквизиты документа и сведения о подписи продавца.
  3. Подписать сформированный XML своей (покупателя) открепленной подписью.
  4. Отправить на сервер API пакет данных, содержащий: doc_id документа, сам XML титула и свою подпись в формате Base64.

Где взять подпись отправителя (продавца)

Одной из главных проблем при работе с API ЭДО Лайт является поиск открепленной подписи отправителя. Рассмотрим наиболее надежные способы ее получения без ручного скачивания из личного кабинета:

Формирование открепленной подписи в 1С 7.7

Для подписания файлов в 1С 7.7 рекомендуется использовать объект CAdESCOM.CadesSignedData (требуется установленный КриптоПро CSP и плагин). Проанализируем пример функции на языке JScript, вызываемой из 1С, которая формирует открепленную подпись в Base64:


// Скрипт для формирования открепленной подписи через CADESCOM
СтрКода = "function SignFile(FileName, Cert, OutFileName) {
|   var InStream = new ActiveXObject('ADODB.Stream');
|   InStream.Type = 1; // binary
|   InStream.Open();
|   InStream.LoadFromFile(FileName);
|   var InData = InStream.Read(-1);
|
|   var Signer = new ActiveXObject('CAdESCOM.CpSigner');
|   Signer.Certificate = Cert;
|   Signer.Options = 2; // CAPICOM_CERTIFICATE_INCLUDE_END_ENTITY_ONLY
|
|   var SignedData = new ActiveXObject('CAdESCOM.CadesSignedData');
|   SignedData.Content = InData;
|
|   // Параметр 2: 1 - открепленная подпись, Параметр 3: 0 - кодировка Base64
|   var OutSignedData = SignedData.SignCades(Signer, 1, 1, 0);
|
|   var OutStream = new ActiveXObject('ADODB.Stream');
|   OutStream.Type = 2; // text
|   OutStream.CharSet = 'US-ASCII';
|   OutStream.Open();
|   OutStream.WriteText(OutSignedData);
|   OutStream.SaveToFile(OutFileName, 2);
|   OutStream.Close();
|   return 0;
|}";

Отправка данных на сервер через API

Метод отправки титула требует передачи данных в формате multipart/form-data. Платформа 1С 7.7 не имеет встроенных средств для комфортной работы с этим типом запросов (объекты WinHttp часто искажают бинарные данные). Оптимальное решение — использование внешней компоненты curl1c (известной как «Карлик»).

Рассмотрим пример формирования запроса на подписание:


Процедура ОтправитьТитул(ПутьКТитулу, ИдДокумента, ПутьКПодписи)
    Карлик = СоздатьОбъект("Карлик");
    Карлик.УстановитьПараметр("URL", "https://edo-gismt.crpt.ru/api/v1/incoming-documents/xml/upd/title");
    Карлик.УстановитьПараметр("CUSTOMREQUEST", "POST");
    
    // Установка авторизации (токен должен быть получен заранее)
    Карлик.УстановитьПараметр("HTTPHEADER", "Authorization: Bearer " + ТекТокен);
    Карлик.УстановитьПараметр("HTTPHEADER", "Content-Type: multipart/form-data");
    
    Запрос = Карлик.СоздатьЗапрос();
    
    // Читаем содержимое файлов в строки
    ТекстТитула = ЧитатьФайлВСтроку(ПутьКТитулу, "windows-1251");
    ТекстПодписи = ЧитатьФайлВСтроку(ПутьКПодписи, "ascii");
    
    // Добавляем части multipart-запроса
    // Параметры: ИмяПоля, ИмяФайла, ТипКонтента, Данные
    Запрос.Добавить("content", "title.xml", "application/xml", ТекстТитула);
    Запрос.Добавить("doc_id", , "text/plain", ИдДокумента);
    Запрос.Добавить("signature", , "text/plain", ТекстПодписи);
    
    КодОшибки = Карлик.Выполнить();
    Если КодОшибки <> 200 Тогда
        Сообщить("Ошибка API: " + Карлик.Приемник.Данные);
    Иначе
        Сообщить("Титул успешно отправлен");
    КонецЕсли;
КонецПроцедуры

Типичные ошибки и способы их решения

Ошибка кодировки: "Element type 'Р' must be followed by..."

Выясним причину этой ошибки. Она возникает, когда XML-файл титула передается на сервер в кодировке UTF-8, хотя в заголовке XML указано windows-1251, или наоборот. Сервер Честного знака очень чувствителен к этому.

Решение: Убедитесь, что при чтении XML-файла из 1С и передаче его в объект запроса сохраняется оригинальная кодировка windows-1251. Не используйте парсеры, которые автоматически перекодируют данные в UTF-8 при сохранении. Если вы используете ADODB.Stream, всегда явно указывайте CharSet = 'windows-1251'.

Конфликт MSXML DOM и curl1c

Проанализируем ситуацию, когда при выполнении запроса платформа 1С 7.7 аварийно завершает работу (Runtime Error). Часто это связано с одновременным использованием объекта MSXML2.DOMDocument для парсинга и внешней компоненты для HTTP-запросов в одной процедуре. Компоненты могут конфликтовать в адресном пространстве памяти.

Решение: Попробуйте заменить MSXML DOM на использование анализатора XML из библиотеки v7plus.dll для разбора входящих данных. Если же вам необходимо использовать MSXML, старайтесь уничтожать объект (присваивать 0) перед вызовом методов отправки запроса.

Автоматическое квитирование

Важно помнить, что кроме Титула покупателя, регламент ЭДО требует отправки «Извещения о получении». В ЭДО Лайт при первом вызове метода получения контента УПД через API, сервер автоматически создает неподписанное событие извещения. Его также нужно найти в списке /unsigned-events, подписать и отправить обратно, иначе документооборот не будет считаться завершенным (статус останется «Просмотрен»).

Работа с ZIP-архивами в 1С 7.7

Для извлечения подписей и XML из архива документооборота потребуется работа с ZIP. Поскольку в 7.7 нет встроенного объекта ZipArchive, можно использовать:

Пример использования DialMail для извлечения файлов по маске:


ZIP = СоздатьОбъект("AddIn.ZIP");
ZIP.КаталогИзвлечения = "C:\Temp\";
// Извлекаем файлы, содержащие GUID документа в имени
КолФайлов = ZIP.Извлечь( , "*" + GUID + "*.*", ПутьКАрхиву);

Таким образом, комбинируя современные средства криптографии, внешние компоненты для работы с сетью и классические приемы программирования в 1С 7.7, можно построить полноценную и надежную систему работы с ЭДО Лайт, не уступающую возможностям современных конфигураций на платформе 8.3.

← На главную