Почему не работает отбор при отправке GET запроса с JSON из 1С в WooCommerce, хотя в Postman все работает?

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

При интеграции 1С с внешними системами, такими как интернет-магазины на WooCommerce (WordPress), мы часто сталкиваемся с ситуацией, когда отлаженный в Postman запрос отказывается работать при запуске из кода 1С. Одна из самых неочевидных проблем возникает при использовании метода GET с телом запроса в формате JSON.

В этой статье мы подробно разберем ситуацию, когда 1С успешно соединяется с сервером, проходит авторизацию, но игнорирует переданные фильтры (например, возвращает весь список заказов вместо отобранных по дате), в то время как аналогичный запрос через Postman отрабатывает корректно. Мы проанализируем причины такого поведения и рассмотрим надежные методы решения.

Суть проблемы: различия в обработке HTTP-запросов

Рассмотрим сценарий: мы пытаемся получить список заказов из WooCommerce, отфильтрованный по дате. Для этого формируется JSON-структура с параметрами отбора:


{
    "after": "2022-12-01T00:00:00",
    "before": "2022-12-31T23:59:59",
    "per_page": 100,
    "page": 1
}

В Postman мы выбираем метод GET, вставляем этот JSON в тело (Body) и получаем корректный ответ. Однако, когда мы используем штатный объект HTTPЗапрос в платформе 1С, сервер магазина возвращает нам список всех заказов, как будто тело запроса было пустым.

Почему так происходит? Дело не всегда в коде 1С. Согласно спецификации HTTP (RFC 7231), метод GET предназначен для запроса данных, и наличие тела сообщения в нем не имеет определенной семантики. Это означает, что веб-серверы (Nginx, Apache) и промежуточные узлы (прокси, фаерволы) имеют полное право игнорировать тело GET-запроса.

Postman и объект WinHttp.WinHttpRequest формируют пакеты таким образом, что некоторые серверы их пропускают. Штатный HTTPЗапрос в 1С работает иначе (например, может использовать специфические заголовки или chunked-кодирование), из-за чего строго настроенные веб-серверы (особенно Nginx) просто отрезают тело запроса перед передачей его в PHP-скрипт магазина.

Решение 1: Перенос параметров в строку запроса (Рекомендуемое)

Самым правильным и надежным решением является отказ от передачи JSON в теле GET-запроса. Большинство API, включая WooCommerce, ожидают параметры фильтрации в URL-строке (Query Parameters).

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

Было (нестабильный вариант):


// Формируем JSON
ТелоЗапроса = "{""after"": ""2022-12-01T00:00:00"", ... }";

Заголовки = Новый Соответствие;
Заголовки.Вставить("Content-Type", "application/json");

HTTPЗапрос = Новый HTTPЗапрос("/wp-json/wc/v3/orders", Заголовки);
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса);

Ответ = Соединение.Получить(HTTPЗапрос);

Стало (Правильный вариант):

Мы формируем строку параметров и добавляем её к URL ресурса через знак вопроса.


// Подготавливаем параметры
ПараметрыСтрокой = "?after=2022-12-01T00:00:00&before=2022-12-31T23:59:59&per_page=100&page=1";

// Обратите внимание: URL теперь содержит параметры
АдресРесурса = "/wp-json/wc/v3/orders" + ПараметрыСтрокой;

HTTPЗапрос = Новый HTTPЗапрос(АдресРесурса);
// Content-Type и тело запроса больше не нужны для GET

Ответ = Соединение.Получить(HTTPЗапрос);

Такой подход гарантированно работает на любых веб-серверах и не зависит от настроек Nginx или Apache на стороне клиента, так как параметры являются частью URL, а не тела пакета.

Решение 2: Использование COM-объекта WinHttp (Только для Windows)

Если по каким-то причинам переписать логику формирования параметров сложно, или вы уверены, что API принимает только JSON в теле GET (что бывает крайне редко), можно воспользоваться системным объектом Windows.

Как отметили участники обсуждения, использование WinHttp.WinHttpRequest.5.1 позволяет обойти ограничения, которые накладывает штатный HTTPЗапрос или настройки платформы 1С.

Пример реализации через COM-объект:


// Создаем COM-объект
WinHttp = Новый COMОбъект("WinHttp.WinHttpRequest.5.1");

// Инициализируем запрос
// Важно: укажите полный адрес, включая протокол и домен
Url = "https://example.com/wp-json/wc/v3/orders";
WinHttp.Open("GET", Url, Ложь);

// Устанавливаем заголовки (включая авторизацию, если она не в URL)
WinHttp.SetRequestHeader("Content-Type", "application/json");
WinHttp.SetRequestHeader("Authorization", "Basic " + Base64Строка("key:secret"));

// Отправляем запрос с телом
ТвойДжейсон = "{...}"; 
WinHttp.Send(ТвойДжейсон);

Если WinHttp.Status = 200 Тогда
    Результат = WinHttp.ResponseText;
Иначе
    Сообщить("Ошибка: " + WinHttp.Status + " " + WinHttp.ResponseText);
КонецЕсли;

Важно: Этот метод будет работать только если сервер 1С работает под управлением ОС Windows. На Linux-серверах использование COM-объектов невозможно.

Решение 3: Работа с двоичными данными

Иногда проблема кроется в том, как платформа 1С кодирует строку перед отправкой. Если сервер очень чувствителен к кодировке или наличию BOM (Byte Order Mark), можно попробовать сформировать тело запроса через двоичные данные. Это дает полный контроль над тем, что именно уходит в сеть.

Попробуем модифицировать работу с HTTPЗапрос:


ТелоСтрокой = "{... ваш JSON ...}";

// Преобразуем строку в двоичные данные UTF-8 без BOM
// Иногда помогает явное указание кодировки
ТелоДвоичные = ПолучитьДвоичныеДанныеИзСтроки(ТелоСтрокой, "UTF-8", Ложь);

HTTPЗапрос = Новый HTTPЗапрос("/wp-json/wc/v3/orders");
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");

// Устанавливаем тело именно из двоичных данных
HTTPЗапрос.УстановитьТелоИзДвоичныхДанных(ТелоДвоичные);

Ответ = Соединение.Получить(HTTPЗапрос);

Этот метод помогает устранить проблемы с кодировкой, но если веб-сервер на стороне получателя настроен на игнорирование тела в GET-запросах, этот способ не поможет.

Чек-лист для диагностики проблемы

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

  1. Проверьте документацию API. Если метод позволяет передавать параметры в URL (Query String), всегда используйте этот вариант для GET-запросов.
  2. Если используется метод POST, убедитесь, что вы правильно указываете заголовки Content-Type и Content-Length (последний 1С рассчитывает автоматически, но иногда полезно проверить).
  3. Сравните заголовки, отправляемые из Postman и из 1С. В 1С их можно посмотреть, если использовать прокси-сниффер (например, Fiddler) или настроив технологический журнал.
  4. Учитывайте, что тестовый и "боевой" серверы клиента могут иметь разные настройки (разные версии PHP, разные веб-серверы Nginx/Apache, наличие WAF), что и приводит к различиям в обработке нестандартных запросов.

Резюмируя: наиболее устойчивым решением является отказ от тела в GET-запросах в пользу параметров URL. Это соответствует стандартам веб-разработки и гарантирует совместимость с любыми серверными конфигурациями.

← На главную