Как отправить POST-запрос с JSON из 1С на сайт и правильно принять данные в PHP?

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

Интеграция 1С с внешними веб-сервисами и сайтами посредством HTTP-запросов — одна из базовых задач разработчика. Однако при отправке данных в формате JSON методом POST многие разработчики сталкиваются с неожиданной ситуацией: скрипт-обработчик возвращает пустой массив параметров, а переданные данные бесследно исчезают. Разберем по шагам, почему возникает эта ошибка, как работает транспорт HTTP и как правильно организовать обмен данными между 1С и веб-сервером.

В чем заключается проблема: анализируем исходную ситуацию

Рассмотрим классический пример кода 1С, формирующий структуру данных, сериализующий ее в JSON и отправляющий на веб-сервер с заголовком Content-Type: application/json:


тЗаписьJSON = Новый ЗаписьJSON;
тПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, " ", Истина);  
тЗаписьJSON.УстановитьСтроку(тПараметрыJSON);   

сЗаказы = Новый Структура;  
массивЧегото = Новый Массив; 

тДанные = Новый Структура;
тДанные.Вставить("ЧислоJSON", 100);
тДанные.Вставить("СтрокаJSON", "test");
массивЧегото.Добавить(тДанные); 

сЗаказы.Вставить("xxx", массивЧегото);
ЗаписатьJSON(тЗаписьJSON, сЗаказы);
strJSON = тЗаписьJSON.Закрыть();

Соединение = Новый HTTPСоединение(ИмяСайта);
HTTPЗапрос = Новый HTTPЗапрос(ИмяСкрипта); 
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(strJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);

На стороне PHP-скрипта разработчик пытается проверить переданные данные привычным способом через системные массивы:


var_dump($_POST);
var_dump($_GET);

Однако в результате выполнения сервер возвращает пустые массивы. Выясним причину такого поведения веб-сервера.

Почему массив $_POST пуст: особенности обработки протокола HTTP

Массив $_POST в PHP автоматически заполняется только в тех случаях, когда входящий запрос отправлен с определенными типами содержимого: application/x-www-form-urlencoded или multipart/form-data. Эти заголовки соответствуют отправке стандартных HTML-форм. Если клиент отправляет заголовок Content-Type: application/json, веб-сервер не производит синтаксический разбор тела запроса на отдельные переменные формы и оставляет массив $_POST пустым.

Строка JSON передается в виде необработанного (сырого) тела запроса (payload). Соответственно, ожидать наличия данных внутри $_POST при передаче чистого JSON некорректно.

Решение 1. Чтение потока ввода php://input на стороне сервера (рекомендуемый подход)

Для REST API и современной архитектуры веб-сервисов стандартным подходом является прямая передача JSON в теле запроса и его последующее чтение из входящего потока данных PHP. Рассмотрим правильный серверный код для приема данных:


// Считываем сырые данные из входного потока
$rawData = file_get_contents("php://input");

// Декодируем полученную JSON-строку в массив или объект PHP
$data = json_decode($rawData, true);

if ($data === null) {
    http_response_code(400);
    echo json_encode(["status" => "error", "message" => "Некорректный JSON"]);
    exit;
}

// Успешный ответ
http_response_code(200);
echo json_encode(["status" => "success", "received" => $data]);

Поток php://input позволяет получить необработанные байты тела запроса независимо от заголовка Content-Type, после чего функция json_decode преобразует строку в ассоциативный массив.

Решение 2. Передача данных в формате application/x-www-form-urlencoded

Если серверную часть изменить невозможно и принимающий скрипт жестко рассчитан на использование массива $_POST, данные из 1С необходимо сформировать как параметр формы. Однако здесь важно не допустить критическую ошибку с кодированием символов.

Проанализируем шаги правильного формирования запроса:

  1. Устанавливаем заголовок Content-Type: application/x-www-form-urlencoded; charset=utf-8.
  2. Обязательно кодируем JSON-строку в формат URL-encoded с помощью функции КодироватьСтроку, иначе спецсимволы (кавычки, двоеточия, фигурные скобки, амперсанды & и знаки =) сломают структуру POST-параметров.
  3. Помещаем закодированную строку в тело запроса в виде ИмяПараметра=Значение.

Посмотрим на пример реализации в 1С:


// Кодируем JSON для безопасной передачи в теле формы
ЗакодированныйJSON = КодироватьСтроку(strJSON, СпособКодированияСтроки.КодировкаURL);
ТелоЗапроса = "jsonData=" + ЗакодированныйJSON;

HTTPЗапрос = Новый HTTPЗапрос(ИмяСкрипта);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

Ответ = Соединение.ОтправитьДляОбработки(HTTPЗапрос);

В этом случае на стороне PHP данные будут доступны в переменной $_POST['jsonData'], и их можно будет декодировать с помощью json_decode($_POST['jsonData'], true).

Дополнительные технические нюансы и частые ошибки при отправке запросов из 1С

Если даже при использовании php://input входящий поток пуст, обратим внимание на следующие скрытые причины:

  1. HTTP-редиректы (коды 301 и 302): Если сервер перенаправляет запрос (например, с http:// на https:// или при отсутствии завершающего слэша в адресе скрипта), клиент платформы 1С может повторить запрос методом GET, полностью потеряв тело (payload). Всегда указывайте точный URL скрипта.
  2. Защищенное соединение (HTTPS): При работе с протоколом HTTPS в конструктор HTTPСоединение шестым параметром обязательно нужно передавать объект ЗащищенноеСоединениеOpenSSL. Без этого соединение не сможет защищенно передать заголовки и тело.
  3. Работа с ответом напрямую в памяти: Не создавайте лишние временные файлы на диске через ПолучитьИмяВременногоФайла. Метод ОтправитьДляОбработки(HTTPЗапрос) возвращает объект HTTPОтвет, у которого можно сразу вызвать Ответ.ПолучитьТелоКакСтроку().
  4. Потоковая отправка больших объемов: Если выгружаются тяжелые справочники или документы, не держите весь JSON в строковой переменной 1С. Используйте запись напрямую в файл через тЗаписьJSON.ОткрытьФайл(...) и передавайте его методу HTTPЗапрос.УстановитьИмяФайлаТела(...). Это исключит переполнение оперативной памяти.
← На главную