В современной практике автоматизации документооборота часто возникает потребность перенести процессы подписания и обмена электронными документами с локальных машин пользователей на сервер 1С. Это необходимо для настройки регламентных заданий, реализации массовой рассылки документов по ЭДО или работы в клиент-серверной архитектуре, где у пользователей нет локальных ключей ЭЦП.
Однако типовая внешняя обработка интеграции (в частности, модуль для Контур.Диадок) по умолчанию спроектирована для работы в клиентском контексте. Она ищет сертификаты в личном хранилище текущего пользователя Windows (где запущен клиент 1С) и использует клиентские методы работы с компонентой. При попытке запустить такие процедуры на сервере мы сталкиваемся с тем, что модуль "не видит" установленные там сертификаты.
Разберем подробно, как адаптировать модуль ЭДО для работы в серверном контексте, какие предварительные настройки окружения требуются и какие именно изменения необходимо внести в программный код обработки.
Прежде чем мы перейдем к редактированию кода 1С, нам необходимо убедиться, что серверная машина технически готова к выполнению подписи файлов методами криптографии. Без выполнения этих условий любые изменения в конфигураторе будут бесполезны.
Рассмотрим чеклист администратора для подготовки сервера:
USR1CV8).
Если сертификаты установлены под учетной записью администратора, который настраивает сервер по RDP, служба 1С их не увидит. Для установки сертификатов в профиль пользователя службы часто используют утилиту csptools или запускают оснастку сертификатов от имени сервисного пользователя.
Стандартный модуль Диадока имеет сложную структуру. Он состоит из внешней обработки, внутри которой "зашито" ядро интеграции. Основная проблема заключается в том, что инициализация работы с компонентой происходит на клиенте.
Проанализируем логику работы формы авторизации:
Модуль_ЯдроНаКлиенте().Наша задача — перенести эту логику в контекст &НаСервере, чтобы обработка обращалась к хранилищу сертификатов сервера.
Для реализации задуманного нам потребуется внести изменения в код внешней обработки (Diadoc_x_xx_x.epf). Разберем процесс на примере формы авторизации, так как именно с нее начинается работа.
Откроем форму ВнешняяОбработка.КонтурЭДО.Форма.АвторизацияУправляемая (путь может незначительно отличаться в разных версиях модуля).
В модуле формы найдем процедуру, отвечающую за заполнение списка доступных сертификатов. Обычно она называется ЗаполнитьТаблицуСертификатов. По умолчанию она выполняется на клиенте.
Изменим директиву компиляции и переопределим способ получения ядра:
&НаСервере // Меняем &НаКлиенте на &НаСервере
Процедура ЗаполнитьТаблицуСертификатов()
// Старый код инициализации ядра комментируем
// Модуль_Ядро = Модуль_ЯдроНаКлиенте();
// Добавляем инициализацию серверного ядра
Модуль_Ядро = Модуль_ЯдроНаСервере();
// Далее идет стандартный код процедуры...
// Внимание! Здесь могут возникать ошибки вызова клиентских методов.
// Их необходимо закомментировать или адаптировать.
КонецПроцедуры
Функция Модуль_ЯдроНаСервере() обычно уже существует в модуле объекта обработки, так как разработчики закладывали возможность серверных вызовов, но не использовали их в форме авторизации.
После того как мы получили список сертификатов с сервера, нам необходимо научить обработку авторизовываться и получать данные о соединении также на стороне сервера. Это особенно важно, если в дальнейшем планируется отправка УПД через API в автоматическом режиме. Для этого найдем и изменим контекст следующих функций в модуле формы.
Функция получения текущего соединения (авторизации по сертификату):
&НаСервере // Было &НаКлиенте
Функция ТекущееСоединение(ОтпечатокСертификата)
// Все вызовы методов ядра перенаправляем на серверный экземпляр
ДанныеСертификата = Модуль_ЯдроНаСервере().Сертификаты_ДанныеСертификата(ОтпечатокСертификата);
ОписаниеСертификата = Модуль_ЯдроНаСервере().Сертификаты_ОписаниеСертификата(ДанныеСертификата);
// Получение тела сертификата для передачи в API
СертBase64 = Модуль_ЯдроНаСервере().Сертификаты_СертификатВBase64(ОтпечатокСертификата);
// Самый важный этап - авторизация и получение токена
РасшифрованныйТокен = Модуль_ЯдроНаСервере().Авторизация_ПоСертификату(ОтпечатокСертификата);
ГОСТСертификата = Модуль_ЯдроНаСервере().ПолучитьГОСТСертификата(ОтпечатокСертификата);
// Возврат структуры соединения
// ...
КонецФункции
Аналогичным образом поступим с функцией описания соединения:
&НаСервере // Было &НаКлиенте
Функция ОписаниеСоединения()
// Логика функции остается, меняется только контекст выполнения
// и источник получения объекта модуля ядра
КонецФункции
При переносе кода на сервер мы неизбежно столкнемся с методами, которые запрещены в серверном контексте. Внимательно проанализируем код внутри переносимых процедур.
Сообщить работает на сервере, но методы вроде ПоказатьПредупреждение работать не будут. Их нужно убрать или заменить.Если вы хотите избежать прямой правки файла обработки (чтобы не терять возможность легкого обновления), можно попробовать использовать механизм расширений. Рассмотрим идею перехвата инициализации ядра.
Можно создать расширение, которое будет перехватывать создание объекта обработки и подменять логику. Пример функции для модуля расширения:
Функция ОбработкаМодуляЯдра() Экспорт
// Проверяем, нужно ли использовать кастомизированную логику
Если ИспользуетсяРасширениеКонтурДиадок() Тогда
// Создаем обработку из расширения
Результат = Обработки.КонтурДиадокЯдро.Создать();
Иначе
// Стандартный путь создания из внешней обработки
ФайлЯдра = ФайлМодуляЯдра();
Результат = ВнешниеОбработки_СоздатьБезПредупреждений(ФайлЯдра);
КонецЕсли;
Возврат Результат;
КонецФункции
Однако, учитывая сложность структуры модуля Диадока (вложенность обработок), вариант с прямой модификацией файла epf и последующим его внедрением в конфигурацию как внутренней обработки часто оказывается более надежным и простым в отладке.
После того как мы научили обработку "видеть" сертификаты сервера и создавать соединение в контексте &НаСервере, мы можем реализовать полностью автоматический документооборот.
Для этого создадим Общий модуль (например, ИнтеграцияЭДОСервер) с флагами "Сервер", "Вызов сервера. В нем опишем экспортную процедуру для Регламентного задания.
Сценарий работы регламентного задания:
Обработка = Обработки.КонтурЭДО.Создать();Обработка.АвторизоватьсяПоСертификату(Отпечаток);Рассмотрим вопрос производительности. Если объем документов велик (например, тысячи накладных в сутки), фоновое подписание позволяет разгрузить операторов. Однако не стоит запускать задание слишком часто (каждые несколько секунд), чтобы не создавать избыточную нагрузку на сервер постоянной инициализацией COM-объектов и криптопровайдера. Оптимальный интервал — раз в 10-15 минут или по расписанию в нерабочее время.
Перевод модуля ЭДО на серверную сторону вполне реален и часто необходим для крупного бизнеса, особенно когда требуется групповая выгрузка и загрузка файлов из 1С в XML для ЭДО по приказам №820 и №970. Основные шаги:
ЗаполнитьТаблицуСертификатов, ТекущееСоединение) на &НаСервере.Модуль_ЯдроНаКлиенте() на Модуль_ЯдроНаСервере().Такой подход позволяет исключить человеческий фактор при подписании типовых документов и существенно ускорить процессы обмена.