Как передать дату с часовым поясом в XDTO при интеграции с внешними системами?

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

При реализации интеграции 1С с внешними веб-сервисами (например, ЭТП ГПБ, государственные информационные системы) разработчики часто сталкиваются с жестким требованием к формату даты. Внешняя система ожидает формат dateTime с обязательным указанием часового пояса, например: 2023-10-13T09:00:00+03:00. Однако стандартный механизм 1С при работе через WSПрокси и ОбъектXDTO часто «обрезает» временную зону, отправляя дату в упрощенном виде. Разберем, почему это происходит и какими способами можно решить эту задачу.

Анализируем причину проблемы: 1С и стандарты XML

В платформе 1С:Предприятие тип данных Дата универсален и не хранит в себе информацию о смещении часового пояса. Когда мы присваиваем значение свойству ОбъектXDTO, которое в схеме определено как xs:dateTime, происходит автоматическая сериализация. Платформа преобразует внутреннюю дату 1С в строку XML. Так как в самой дате 1С пояса нет, сериализатор либо игнорирует его, либо использует настройки сервера, но зачастую на выходе мы получаем 2023-10-13T09:00:00 без заветного суффикса +03:00. Попытки программно добавить пояс к строке перед присвоением не помогают, так как фабрика XDTO при создании объекта снова конвертирует строку в дату и «забывает» о добавленных символах.

Способ №1: Изменение типа данных в XDTO-пакете (Самый эффективный)

Если внешняя система требует строгого текстового соответствия, а стандартный dateTime в 1С ведет себя некорректно, мы можем прибегнуть к хитрости. Рассмотрим алгоритм действий:

  1. Скачаем файл описания сервиса WSDL (или XSD схемы) на локальный диск.
  2. Откроем файл в текстовом редакторе и найдем определения полей, которые вызывают ошибку.
  3. Заменим тип данных этих полей с type="xs:dateTime" на type="xs:string". Это заставит 1С воспринимать эти поля как обычные строки.
  4. В конфигурации 1С создадим WSСсылку, указав путь к нашему измененному локальному файлу.
  5. Теперь при формировании запроса мы можем передавать дату как строку, сформированную вручную с любым нужным нам смещением.

Проанализируем пример формирования такой строки кода:


// Формируем дату в формате ISO 8601 с добавлением пояса вручную
ДатаДляОтправки = Формат(ТекущаяДата(), "ДФ=yyyy-MM-ddTHH:mm:ss") + "+03:00";
// Теперь, так как в схеме тип поля — string, 1С передаст значение «как есть»
ОбъектXDTO.date_start_registration = ДатаДляОтправки;

Способ №2: Ручное формирование XML-тела и использование HTTP-соединения

В некоторых случаях использование WSПрокси становится слишком ограниченным (например, когда помимо дат возникают проблемы с префиксами пространств имен типа d2p1, которые не принимает сервер). В такой ситуации выясним причину отказа от высокоуровневых объектов и перейдем к работе с HTTPСоединение. Это дает полный контроль над каждым байтом отправляемого XML.

Рассмотрим пример функции для отправки произвольного XML-запроса:


Функция ОтправитьЗапросВручную(ДанныеXML, ПараметрыСервера)
    HTTPЗапрос = Новый HTTPЗапрос(ПараметрыСервера.Ресурс);
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");
    // Если это SOAP, обязательно указываем SOAPAction
    HTTPЗапрос.Заголовки.Вставить("SOAPAction", "http://ws.etp-gpb.ru/ProcedurePublish");
    
    HTTPЗапрос.УстановитьТелоИзСтроки(ДанныеXML, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
    
    Соединение = Новый HTTPСоединение(ПараметрыСервера.Адрес, ПараметрыСервера.Порт, , , , 60, Новый ЗащищенноеСоединениеOpenSSL());
    
    Попытка
        Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
        Если Ответ.КодСостояния = 200 Тогда
            Возврат Ответ.ПолучитьТелоКакСтроку();
        Иначе
            ЗаписьЖурналаРегистрации("Ошибка интеграции", УровеньЖурналаРегистрации.Ошибка, , , Ответ.ПолучитьТелоКакСтроку());
            Возврат Неопределено;
        КонецЕсли;
    Исключение
        Сообщить("Ошибка связи: " + ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
КонецФункции

Способ №3: Промежуточная конвертация через ЗаписьXML

Рассмотрим ситуацию, когда мы всё же хотим использовать ФабрикаXDTO для сборки основной структуры, но нам нужно точечно подправить итоговый текст. Мы можем собрать объект XDTO, сериализовать его в строку, заменить в тексте значения дат и отправить полученную строку.

Посмотрим на пример реализации такого «костыля»:


// 1. Собираем объект через фабрику
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку("UTF-8");
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, МойОбъектXDTO);
СтрокаXML = ЗаписьXML.Закрыть();

// 2. Исправляем даты и префиксы через СтрЗаменить
// Добавляем часовой пояс к датам, которые 1С выгрузила без него
СтрокаXML = СтрЗаменить(СтрокаXML, "2023-10-13T09:00:00", "2023-10-13T09:00:00+03:00");

// Если сервер не понимает префиксы d2p1, меняем их на стандартные
СтрокаXML = СтрЗаменить(СтрокаXML, "d2p1:", "ns:");
СтрокаXML = СтрЗаменить(СтрокаXML, "xmlns:d2p1", "xmlns:ns");

// 3. Отправляем исправленную строку через HTTPСоединение (см. Способ №2)

Работа с префиксами пространств имен

Часто проблема с датами идет рука об руку с проблемой именования префиксов. 1С генерирует префиксы автоматически (d2p1, d2p2). Если принимающая сторона (например, Oracle Web Services) требует конкретный префикс ns, это можно настроить в свойствах самого XDTO-пакета в Конфигураторе. В поле «Префикс» для соответствующего URI пространства имен нужно жестко прописать требуемое значение. Однако помните, что согласно стандарту XML, имя префикса не должно иметь значения, важен только URI. Если сервер выдает ошибку именно на имя префикса — это признак нестрогого следования стандартам на стороне сервера, и здесь поможет только ручная правка XML-текста перед отправкой.

Важный совет: При отладке таких интеграций всегда используйте инструменты перехвата трафика, такие как Fiddler или встроенный в 1С ЖурналРегистрации, куда записывайте полное тело исходящего XML. Это позволит вам точно увидеть, в какой момент пропадает часовой пояс и соответствует ли структура запроса требованиям WSDL.

Подводя итог, наиболее «чистым» решением для программиста 1С является Способ №1 (подмена типов в локальной схеме). Он позволяет сохранить удобство работы с объектами XDTO и при этом гарантирует, что строковое значение даты с поясом дойдет до сервера в неизменном виде.

← На главную