Почему не работает HTTP-запрос при отправке XML из 1С и сервер возвращает пустой файл?

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

Интеграция систем 1С с веб-сайтами (интернет-магазинами) — одна из наиболее частых задач разработчика. Однако при реализации обмена данными по протоколу HTTP нередко возникают ситуации, когда, казалось бы, верный код не приносит ожидаемого результата. Вроде бы соединение устанавливается, код состояния возвращается успешный (200 OK), но данные на сайте не обновляются, а файл ответа от сервера приходит абсолютно пустым или содержит совершенно незапланированную информацию.

В этой статье мы подробно разберем по шагам, почему возникает эта проблема, проанализируем неочевидные ошибки в коде 1С при работе с объектами HTTPСоединение и HTTPЗапрос, а также рассмотрим, как правильно спроектировать надежный обмен данными.

Выясняем причину: почему теряются POST-данные?

Для начала проанализируем ситуацию, с которой часто сталкиваются разработчики при интеграции с CMS (например, MstarProject, Bitrix и другими движками, использующими протокол CommerceML). Код отправки выглядит стандартно: формируется XML-файл, упаковывается в тело запроса, указываются параметры в строке запроса типа ?action=exchange&type=sale&mode=price, и вызывается метод ОтправитьДляОбработки().

Однако при выполнении такого запроса могут происходить три критические ошибки, которые полностью блокируют передачу данных.

1. Отсутствие скрипта-обработчика (маршрутизация веб-сервера)

В некорректных примерах путь запроса часто выглядит так:

Запрос = "?action=exchange&type=sale&mode=price";

Обратите внимание: здесь отсутствует имя исполняемого скрипта на сервере. Запрос отправляется на корень сайта. Когда веб-сервер (Nginx или Apache) получает POST-запрос на корневую директорию, он выполняет внутреннее перенаправление (Rewrite) или принудительный внешний редирект (301 или 302 код ответа) на стандартный индексный файл (например, index.php или exchange.php).

При любом подобном перенаправлении (особенно при переходе с HTTP на HTTPS) происходит критическая вещь: POST-запрос на уровне веб-сервера принудительно преобразуется в GET-запрос. При этом тело запроса (наш XML-файл с ценами и товарами) полностью отбрасывается! Веб-сервер передает скрипту только параметры из адресной строки. Скрипт отрабатывает GET-запрос по умолчанию и возвращает стандартную XML-структуру (например, выгрузку заказов с сайта), из-за чего разработчик видит в файле ответа «чужие» или старые данные вместо подтверждения загрузки.

2. Ошибки позиционирования параметров в HTTPСоединение

Посмотрим на классическую ошибку в объявлении соединения:

HTTPСоединение = Новый HTTPСоединение(АдресСайта,,Логин,Пароль,,Истина);

Давайте разберем параметры конструктора HTTPСоединение по позициям:

  1. Сервер (АдресСайта)
  2. Порт
  3. ИмяПользователя (Логин)
  4. Пароль
  5. Прокси
  6. Таймаут
  7. ЗащищенноеСоединение

В приведенном примере разработчик передал значение Истина в качестве 6-го параметра. Соответственно, платформа 1С восприняла его как таймаут соединения. Так как таймаут ожидает число (количество секунд), булево Истина приводится к единице. Соединение с таймаутом в 1 секунду будет постоянно обрываться при любых задержках сети.

Кроме того, седьмой параметр — защищенное соединение (SSL) — остался пустым. Если сайт работает по защищенному протоколу HTTPS (порт 443), а мы пытаемся подключиться через обычный HTTP (порт 80), сервер вернет редирект 301. И мы снова вернемся к проблеме потери тела POST-запроса.

3. Нарушение пошагового протокола обмена CommerceML

Большинство современных движков сайтов не позволяют просто так отправить файл «в лоб» без предварительной авторизации. Стандартный обмен CommerceML требует соблюдения строгой последовательности шагов:

  1. Авторизация (mode=checkauth): Отправка GET-запроса для получения сессионной куки (Cookie) и подтверждения прав доступа.
  2. Инициализация (mode=init): Запрос параметров обмена (разрешенный размер файла, поддержка сжатия zip).
  3. Загрузка файла (mode=file): Непосредственно POST-запрос с передачей файла и обязательным указанием Cookie авторизации в заголовках.

Попытка передать файл напрямую, минуя первые шаги, часто приводит к тому, что система безопасности сайта (или сам скрипт обмена) просто игнорирует входящие данные.


Разберем по шагам правильную реализацию HTTP POST-запроса

Теперь, когда мы проанализировали причины ошибок, рассмотрим, как написать надежный и правильный код для отправки данных из 1С на сайт.

Шаг 1. Формирование XML-файла без лишних символов (BOM)

Некоторые PHP-парсеры на стороне сайта чувствительны к наличию BOM-символов (Byte Order Mark) в начале файла UTF-8. Настоятельно рекомендуется отключать вывод BOM при записи XML в 1С. Для этого используется параметр Ложь в объекте ПараметрыЗаписиXML.


ЗаписьXML = Новый ЗаписьXML;
ИмяФайлаЗапроса = КаталогВременныхФайлов() + "price.xml";
ПараметрыЗаписиXML = Новый ПараметрыЗаписиXML("utf-8", , Ложь); // Отключаем BOM

ЗаписьXML.ОткрытьФайл(ИмяФайлаЗапроса, ПараметрыЗаписиXML);    
ЗаписьXML.ЗаписатьОбъявлениеXML();    
ЗаписьXML.ЗаписатьНачалоЭлемента("КоммерческаяИнформация");
ЗаписьXML.ЗаписатьАтрибут("ДатаФормирования", Формат(ТекущаяДата(),"ДФ=yyyy-MM-dd"));
ЗаписьXML.ЗаписатьАтрибут("ВерсияСхемы", "2.04");

ЗаписьXML.ЗаписатьНачалоЭлемента("Товары");
ЗаписьXML.ЗаписатьНачалоЭлемента("Товар");
ЗаписьXML.ЗаписатьАтрибут("Код", "12345");        
ЗаписьXML.ЗаписатьАтрибут("Цена", "817");
ЗаписьXML.ЗаписатьАтрибут("Название", "Тестовый товар");
ЗаписьXML.ЗаписатьКонецЭлемента(); // Товар   
ЗаписьXML.ЗаписатьКонецЭлемента(); // Товары
ЗаписьXML.ЗаписатьКонецЭлемента(); // КоммерческаяИнформация
ЗаписьXML.Закрыть();

Шаг 2. Инициализация защищенного HTTPS-соединения

Для создания стабильного соединения необходимо явно указать использование SSL-протокола и задать адекватный таймаут (например, 30 секунд), чтобы исключить обрывы связи при передаче больших файлов.


АдресСайта = "fomoco.com"; // Указываем только домен без http/https
Логин = "man_1C";
Пароль = "МойПароль";

// Используем безопасное соединение SSL
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
Таймаут = 30; // Секунды

HTTPСоединение = Новый HTTPСоединение(
    АдресСайта, 
    , // Порт определится автоматически по типу соединения (443 для HTTPS)
    Логин, 
    Пароль, 
    , // Прокси
    Таймаут, 
    ЗащищенноеСоединение
);

Шаг 3. Подготовка запроса с точным путем к скрипту

Вместо отправки запроса в «пустоту» корня сайта, мы должны точно адресовать его конкретному скрипту-приемнику (например, /exchange.php или /1c_exchange.php), который отвечает за обработку интеграции.

Также хорошей практикой является явное указание заголовка Content-Length. Веб-серверы используют его для контроля целостности передаваемых данных.


// Указываем точный путь к скрипту-обработчику сайта
ПутьКРесурсу = "/exchange.php?action=exchange&type=sale&mode=price";

HTTPЗапрос = Новый HTTPЗапрос(ПутьКРесурсу);

// Формируем заголовки запроса
Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "text/xml; charset=utf-8");

// Вычисляем размер файла для Content-Length
ФайлОтправки = Новый Файл(ИмяФайлаЗапроса);
РазмерФайла = ФайлОтправки.Размер();
Заголовки.Вставить("Content-Length", Строка(РазмерФайла));

HTTPЗапрос.Заголовки = Заголовки;

// Помещаем файл XML в тело POST-запроса
HTTPЗапрос.УстановитьИмяФайлаТела(ИмяФайлаЗапроса);

Шаг 4. Отправка и обработка ответа сервера

Выполняем отправку данных методом POST с помощью функции ОтправитьДляОбработки(). После получения ответа обязательно считываем содержимое временного файла, чтобы понять, как сервер отреагировал на наши данные.


ИмяФайлаОтвета = ПолучитьИмяВременногоФайла("xml");

Попытка
    Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос, ИмяФайлаОтвета);
    
    Если Ответ.КодСостояния = 200 Тогда
        // Читаем тело ответа сервера из файла
        ТекстовыйФайлОтвета = Новый ТекстовыйДокумент;
        ТекстовыйФайлОтвета.Прочитать(ИмяФайлаОтвета, КодировкаТекста.UTF8);
        ТекстОтвета = ТекстовыйФайлОтвета.ПолучитьТекст();
        
        Сообщить("Файл успешно передан. Код состояния: 200");
        Сообщить("Ответ сервера: " + ТекстОтвета);
    Иначе
        Сообщить("Ошибка при передаче! Код состояния сервера: " + Ответ.КодСостояния);
    КонецЕсли;
Исключение
    Сообщить("Не удалось установить связь с сервером. Описание ошибки: " + ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

// Очищаем временные файлы
УдалитьФайлы(ИмяФайлаЗапроса);
УдалитьФайлы(ИмяФайлаОтвета);

Как отлаживать HTTP-запросы в 1С?

Если код написан верно, но данные все равно не доходят, воспользуйтесь проверенными инструментами локализации сетевых проблем:

Используя предложенные методики настройки HTTPСоединение, вы сможете избежать досадных ошибок с потерей данных и настроить быструю, защищенную и стабильную выгрузку XML из 1С на любой внешний веб-ресурс.

← На главную