При настройке интеграции между 1С:Предприятие и веб-сайтами на платформе 1С-Битрикс (или любыми другими PHP-бэкендами) разработчики часто сталкиваются с ситуацией, когда отправленный JSON-запрос воспринимается сервером некорректно. В отладчике 1С мы видим правильную JSON-строку, но техническая поддержка со стороны сайта утверждает, что к ним приходят «непонятные символы», например, строки, начинающиеся с a:1:{...}. Также часто возникает путаница с тем, что аналогичный запрос из программы Postman проходит успешно, а из 1С — нет.
В этой статье мы подробно разберем причины такого поведения, проанализируем разницу в формировании HTTP-запросов и рассмотрим правильный алгоритм отправки данных в формате JSON из 1С.
Прежде чем переходить к коду, давайте разберемся, что именно видит принимающая сторона. Если разработчики Битрикса говорят, что тело запроса изменилось и показывают строку вида a:1:{...}, это важная диагностическая информация.
Данный префикс — это результат работы стандартной функции PHP serialize(). Это означает, что:
Это наводит нас на мысль, что проблема не в том, что 1С «ломает» данные по пути, а в том, как именно веб-сервер интерпретирует входящий поток байт. Часто принимающая сторона ожидает JSON, но из-за отсутствия метаданных пытается разобрать его как параметры обычной веб-формы, что и приводит к некорректному формированию массива данных на входе PHP-скрипта.
Первое, на что стоит обратить внимание при формировании тела запроса из строки — это кодировка и наличие метки порядка байтов (BOM). Стандарт JSON (RFC 8259) не рекомендует использовать BOM, и многие парсеры могут выдавать ошибку синтаксиса, если строка начинается с невидимых символов EF BB BF.
В платформе 1С метод УстановитьТелоИзСтроки объекта HTTPЗапрос позволяет явно управлять этим параметром. Давайте посмотрим, как гарантированно отправить «чистый» UTF-8 без BOM. Это считается хорошей практикой (best practice) при любых HTTP-обменах.
// Создаем тело запроса в формате JSON
СтрокаJSON = "{\"product\": \"item1\", \"amount\": 100}";
// Создаем объект запроса
ЗапросHTTP = Новый HTTPЗапрос("/api/endpoint");
// Явно указываем кодировку UTF-8 и отключаем использование BOM
ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаJSON, "UTF-8", ИспользованиеByteOrderMark.НеИспользовать);
Использование ИспользованиеByteOrderMark.НеИспользовать гарантирует, что в начало потока не будут добавлены лишние байты. Однако, как показывает практика, одного этого действия часто недостаточно. Если сервер продолжает видеть данные как «кашу» или пустой массив, проблема лежит глубже — в заголовках запроса.
Это самая распространенная причина, по которой запросы из Postman работают, а из 1С — нет. Давайте разберем механику процесса.
Когда вы используете Postman и выбираете тип тела Raw -> JSON, программа «умная»: она автоматически добавляет к вашему запросу HTTP-заголовок:
Content-Type: application/json
Платформа 1С работает на более низком уровне. Объект HTTPЗапрос — это чистый лист. Если вы положили в тело запроса JSON-строку, но не сказали серверу, что это JSON, сервер (особенно на базе PHP/Apache/Nginx) по умолчанию будет считать, что вы отправляете данные обычной HTML-формы (формат application/x-www-form-urlencoded).
Что происходит на сервере Битрикс без заголовка:
Content-Type: application/json.{"a":1} как набор параметров вида key=value.$_POST формируется некорректно (либо пустой, либо ключ — это вся строка целиком).serialize(), получается структура a:1:{...}, которую и видят разработчики сайта.Для корректной передачи данных необходимо явно указать серверу тип передаваемого контента. В 1С это делается через коллекцию заголовков объекта HTTPЗапрос. Рассмотрим полный, рабочий пример кода, который решает проблему искажения данных.
// 1. Подготовка данных (сериализация в JSON средствами 1С)
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ДанныеДляОтправки = Новый Структура("Sum, Comment", "100.00", "Оплата заказа");
ЗаписатьJSON(ЗаписьJSON, ДанныеДляОтправки);
СтрокаJSON = ЗаписьJSON.Закрыть();
// 2. Создание запроса
Ресурс = "/rest/api/order/add";
ЗапросHTTP = Новый HTTPЗапрос(Ресурс);
// 3. ВАЖНО: Установка заголовков
// Сообщаем серверу, что отправляем именно JSON
ЗапросHTTP.Заголовки.Вставить("Content-Type", "application/json");
// Также хорошим тоном является указание желаемой кодировки в заголовке,
// хотя application/json по стандарту подразумевает UTF-8
ЗапросHTTP.Заголовки.Вставить("Charset", "UTF-8");
// 4. Установка тела запроса
// Используем метод с отключением BOM для максимальной совместимости
ЗапросHTTP.УстановитьТелоИзСтроки(СтрокаJSON,КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// 5. Отправка
Соединение = Новый HTTPСоединение("example.com", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL);
Попытка
Ответ = Соединение.ОтправитьДляОбработки(ЗапросHTTP);
// Обработка ответа...
Исключение
Сообщить("Ошибка отправки: " + ОписаниеОшибки());
КонецПопытки;
В переписке часто возникает недопонимание терминов. Фраза «1С не сериализует данные» технически неверна, если вы уже сформировали JSON-строку. 1С прекрасно сериализует объекты в строку JSON с помощью объекта ЗаписьJSON.
Когда разработчики Битрикса говорят подобное, они обычно имеют в виду, что их внутренние методы (например, Context::getCurrent()->getRequest()->getJsonList()) не отрабатывают автоматически. Эти методы внутри себя проверяют наличие заголовка Content-Type: application/json. Если заголовка нет, метод считает, что данных нет, или они не в том формате, и возвращает пустоту или ошибку. То есть проблема не в структуре данных (сериализации), а в метаданных запроса (заголовках), позволяющих эти данные правильно прочитать.
Если при интеграции вы столкнулись с ситуацией, когда сервер не видит ваши данные или видит их искаженными:
Заголовки.Вставить("Content-Type", "application/json"); присутствует в коде.УстановитьТелоИзСтроки со значением ИспользованиеByteOrderMark.НеИспользовать.HTTPСоединение). Это позволит увидеть байт-в-байт, что именно уходит из 1С.