Интеграция с сервисом электронного документооборота (ЭДО) Диадок через HTTP API — задача, требующая глубокого понимания принципов криптографии и структуры протокола Контура. Одной из наиболее сложных подзадач является подписание входящих документов (есть готовый модуль юридически значимого ЭДО для 1С), когда необходимо не просто отправить файл, а сформировать корректный патч сообщения с валидной электронной подписью (ЭП). В рамках данной статьи мы подробно разберем, как реализовать этот процесс на платформе 1С:Предприятие 8.3, используя универсальные методы организации API, начиная от авторизации по сертификату и заканчивая отправкой подписи на сервер.
Прежде чем приступать к подписанию, необходимо получить авторизационный токен. Подобная аутентификация стандартными средствами 1С в Диадоке состоит из двух этапов: получения зашифрованного токена и его подтверждения. Рассмотрим этот механизм подробнее.
Сначала мы обращаемся к методу V3/Authenticate, передавая в теле запроса открытый ключ сертификата (файл .cer). В ответ сервер присылает данные, зашифрованные на этом сертификате. Нам необходимо расшифровать их локально, используя закрытый ключ.
Важный нюанс: расшифрованные данные перед отправкой в метод подтверждения (AuthenticateConfirm) должны быть закодированы в Base64, а затем обязательно обработаны функцией URL-кодирования. Правильная обработка параметров критична, когда реализуется надежная выгрузка и механизмы получения токенов доступа для интеграции с внешними системами. Если этого не сделать, символы "+" или "/" в строке Base64 будут интерпретированы сервером некорректно, что приведет к ошибке 400 или 403.
Проанализируем пример функции для получения токена:
Функция ПолучитьТокенПоСертификату(КлючРазработчика, ОтпечатокСертификата) Экспорт
// 1. Получаем объект сертификата из хранилища 1С
СертификатКриптографии = НайтиСертификатПоОтпечатку(ОтпечатокСертификата);
HTTPСоединение = УстановитьHTTPСоединениеССерверомДиадок();
// 2. Запрос на первичную аутентификацию
ЗапросHTTP = Новый HTTPЗапрос("V3/Authenticate?type=certificate");
ЗапросHTTP.Заголовки.Вставить("Authorization", "DiadocAuth ddauth_api_client_id=" + КлючРазработчика);
ЗапросHTTP.Заголовки.Вставить("Content-type", "application/octet-stream");
// Передаем бинарное содержимое сертификата
ЗапросHTTP.УстановитьТелоИзДвоичныхДанных(СертификатКриптографии.Выгрузить());
Ответ = HTTPСоединение.ОтправитьДляОбработки(ЗапросHTTP);
Если Ответ.КодСостояния = 200 Тогда
ЗашифрованныеДанные = Ответ.ПолучитьТелоКакДвоичныеДанные();
// 3. Расшифровка полученных данных
МенеджерКриптографии = Новый МенеджерКриптографии("", "", 80); // 80 - тип провайдера для ГОСТ 2012
МенеджерКриптографии.ПарольДоступаКЗакрытомуКлючу = "ВашПароль";
РасшифрованныеДанные = МенеджерКриптографии.Расшифровать(ЗашифрованныеДанные);
// 4. Подготовка данных для подтверждения
// Важно: убираем переносы строк из Base64 и кодируем в URL
СтрокаBase64 = Base64Строка(РасшифрованныеДанные);
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ВК, "");
СтрокаBase64 = СтрЗаменить(СтрокаBase64, Символы.ПС, "");
РасшифрованныеДанныеURL = КодироватьСтрокуВURL(СтрокаBase64);
// 5. Финальное подтверждение (AuthenticateConfirm)
РесурсConfirm = СтрШаблон("V2/AuthenticateConfirm?token=%1", РасшифрованныеДанныеURL);
ЗапросConfirm = Новый HTTPЗапрос(РесурсConfirm);
ЗапросConfirm.Заголовки.Вставить("Authorization", "DiadocAuth ddauth_api_client_id=" + КлючРазработчика);
ОтветConfirm = HTTPСоединение.ОтправитьДляОбработки(ЗапросConfirm);
Возврат ОтветConfirm.ПолучитьТелоКакСтроку(); // Это и есть наш токен
КонецЕсли;
КонецФункции
Для подписания входящего документа в Диадоке используется метод PostMessagePatch — для этой задачи есть автоматизация получения и архивации документов из Диадок через API. Одной из частых проблем является ошибка "Invalid signature". Выясним причину: Диадок ожидает подпись в формате CMS SignedData в DER-кодировке. Более того, подпись должна быть отсоединенной (detached), то есть не содержать в себе исходные данные документа.
Хотя подпись файла методами криптографии возможна с помощью встроенного объекта МенеджерКриптографии, иногда его работа с определенными версиями КриптоПро (например, 4.0) приводит к формированию структуры, которую сервер Диадока считает невалидной. В таких случаях, чтобы обеспечить корректную работу с криптографией в 1С и шифрованием, рекомендуется использовать COM-объект библиотеки CAdESCOM.
Рассмотрим по шагам, как программно создать отсоединенную подпись через CAdESCOM:
Функция СформироватьОтсоединеннуюПодпись(ДвоичныеДанныеДокумента, ОтпечатокСертификата)
// Инициализируем работу с хранилищем сертификатов через COM
Store = Новый COMОбъект("CAdESCOM.Store");
Store.Open(2); // 2 = CAPICOM_CURRENT_USER_STORE
// Ищем нужный сертификат по отпечатку
FoundCert = Неопределено;
Для Каждого ТекущийСертификат Из Store.Certificates Цикл
Если ВРег(СтрЗаменить(ТекущийСертификат.Thumbprint, " ", "")) = ВРег(ОтпечатокСертификата) Тогда
FoundCert = ТекущийСертификат;
Прервать;
КонецЕсли;
КонецЦикла;
Если FoundCert = Неопределено Тогда
ВызватьИсключение "Сертификат не найден в личном хранилище пользователя.";
КонецЕсли;
// Настраиваем объект подписания
Signer = Новый COMОбъект("CAdESCOM.CPSigner");
Signer.Certificate = FoundCert;
Signer.CheckCertificate = Истина;
// Создаем объект для формирования данных подписи
SignedData = Новый COMОбъект("CAdESCOM.CadesSignedData");
// Устанавливаем исходные данные, которые подписываем
SignedData.Content = Base64Строка(ДвоичныеДанныеДокумента);
// Формируем подпись
// 1 - CADESCOM_CADES_BES (базовая подпись)
// Истина - Признак отсоединенной подписи (Detached)
// 0 - Кодировка возвращаемого значения (0 = CADESCOM_ENCODE_ANY, фактически вернет Base64)
РезультатПодписи = SignedData.SignCades(Signer, 1, Истина);
Возврат РезультатПодписи;
КонецФункции
После того как мы получили токен и сформировали строку подписи, нам необходимо отправить эти данные на сервер. Для этого формируется JSON-структура MessagePatchToPost. Проанализируем ключевые поля этой структуры:
ParentEntityId (ID самого документа внутри сообщения) и Signature (наша подпись в Base64).Рассмотрим пример формирования тела запроса:
Процедура ОтправитьПодписьВДиадок(Токен, КлючРазработчика, MessageId, EntityId, ТекстПодписиBase64)
HTTPСоединение = УстановитьHTTPСоединениеССерверомДиадок();
ЗапросHTTP = Новый HTTPЗапрос("V3/PostMessagePatch");
// Формируем заголовки авторизации
AuthHeader = СтрШаблон("DiadocAuth ddauth_api_client_id=%1, ddauth_token=%2", КлючРазработчика, Токен);
ЗапросHTTP.Заголовки.Вставить("Authorization", AuthHeader);
ЗапросHTTP.Заголовки.Вставить("Content-type", "application/json; charset=utf-8");
// Собираем структуру патча
Патч = Новый Структура;
Патч.Вставить("BoxId", "Ваш_BoxId");
Патч.Вставить("MessageId", MessageId);
ПодписьСтруктура = Новый Структура;
ПодписьСтруктура.Вставить("ParentEntityId", EntityId);
ПодписьСтруктура.Вставить("Signature", ТекстПодписиBase64);
МассивПодписей = Новый Массив;
МассивПодписей.Добавить(ПодписьСтруктура);
Патч.Вставить("Signatures", МассивПодписей);
// Сериализация в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, Патч);
ТелоЗапроса = ЗаписьJSON.Закрыть();
ЗапросHTTP.УстановитьТелоИзСтроки(ТелоЗапроса);
Ответ = HTTPСоединение.ОтправитьДляОбработки(ЗапросHTTP);
Если Ответ.КодСостояния = 200 Тогда
Сообщить("Документ успешно подписан!");
Иначе
Сообщить("Ошибка при подписании: " + Ответ.ПолучитьТелоКакСтроку());
КонецЕсли;
КонецПроцедуры
При работе с неформализованными документами (PDF, Excel, Word) важно учитывать статус документооборота. Если вы являетесь отправителем и хотите, чтобы контрагент обязательно подписал документ, при первичной отправке через метод PostMessage необходимо установить флаг NeedRecipientSignature = true в структуре вложения DocumentAttachment.
Если этот флаг не установлен, Диадок может перевести документ в статус "Документооборот завершен" сразу после получения его контрагентом, даже если тот не поставил ответную подпись. Это критично для юридически значимых договоров и соглашений.
Рекомендация по версии КриптоПро: на практике замечено, что использование КриптоПро CSP 5.0 снимает ряд проблем с совместимостью алгоритмов подписи (ГОСТ 2001/2012) при взаимодействии с API. Если ваша задача подразумевает более сложные механизмы, такие как подпись RSA с хешированием SHA512 или реализация на мобильных платформах, правильный выбор криптопровайдера становится решающим фактором успеха.
Таким образом, для успешного подписания входящих документов в Диадок через HTTP API необходимо обеспечить корректную URL-кодировку токена, использовать библиотеку CAdESCOM для создания отсоединенной CMS-подписи и правильно соотнести MessageId и EntityId в JSON-запросе к серверу.