Как отправить POST-запрос с JSON из 1С 8.3: выгрузка категорий и сложных товаров на примере интеграции с UDS API

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

Интеграция систем 1С с внешними веб-сервисами — одна из самых частых задач современного разработчика. В процессе настройки обмена данными часто приходится сталкиваться с отправкой HTTP-запросов методом POST, тело которых должно содержать сложную иерархическую структуру данных в формате JSON. Отличным примером такого взаимодействия является интеграция с API системы лояльности UDS (United Digital Solutions) Partner API V2.

В этой статье мы подробно разберем, как правильно сформировать и отправить POST-запрос из 1С 8.3, проанализируем типичные ошибки разработчиков при обходе табличных частей документов, а также научимся конструировать сложные древовидные JSON-структуры для выгрузки товаров с несколькими ценовыми вариантами. Для автоматизации подобных действий в системах, не имеющих открытого API, может применяться платформа One RPA для роботизации действий пользователя.

Шаг 1. Разбор и подготовка URI-адреса для HTTP-соединения

Прежде чем отправить запрос, нам необходимо разобрать строку URL-адреса на составляющие: схему протокола, имя сервера (хост), порт и непосредственно путь к ресурсу на сервере. Для этого мы будем использовать вспомогательную функцию СтруктураURI. Она парсит переданную строку и возвращает структуру, готовую для инициализации объектов платформы 1С.

Рассмотрим код этой функции подробнее:


Функция СтруктураURI(Знач СтрокаURI) Экспорт
    СтрокаURI = СокрЛП(СтрокаURI);
    
    // Выделяем схему (http или https)
    Схема = "";
    Позиция = Найти(СтрокаURI, "://");
    Если Позиция > 0 Тогда
        Схема = НРег(Лев(СтрокаURI, Позиция - 1));
        СтрокаURI = Сред(СтрокаURI, Позиция + 3);
    КонецЕсли;
    
    // Разделяем хост и путь на сервере
    СтрокаСоединения = СтрокаURI;
    ПутьНаСервере = "";
    Позиция = Найти(СтрокаСоединения, "/");
    Если Позиция > 0 Тогда
        ПутьНаСервере = Сред(СтрокаСоединения, Позиция + 1);
        СтрокаСоединения = Лев(СтрокаСоединения, Позиция - 1);
    КонецЕсли;
    
    // Извлекаем информацию об авторизации, если она указана в URL
    СтрокаАвторизации = "";
    ИмяСервера = СтрокаСоединения;
    Позиция = Найти(СтрокаСоединения, "@");
    Если Позиция > 0 Тогда
        СтрокаАвторизации = Лев(СтрокаСоединения, Позиция - 1);
        ИмяСервера = Сред(СтрокаСоединения, Позиция + 1);
    КонецЕсли;
    
    // Выделяем логин и пароль
    Логин = СтрокаАвторизации;
    Пароль = "";
    Позиция = Найти(СтрокаАвторизации, ":");
    Если Позиция > 0 Тогда
        Логин = Лев(СтрокаАвторизации, Позиция - 1);
        Пароль = Сред(СтрокаАвторизации, Позиция + 1);
    КонецЕсли;
    
    // Отделяем хост от порта
    Хост = ИмяСервера;
    Порт = "";
    Позиция = Найти(ИмяСервера, ":");
    Если Позиция > 0 Тогда
        Хост = Лев(ИмяСервера, Позиция - 1);
        Порт = Сред(ИмяСервера, Позиция + 1);
    КонецЕсли;
    
    Результат = Новый Структура;
    Результат.Вставить("Схема", Схема);
    Результат.Вставить("Логин", Логин);
    Result.Вставить("Пароль", Пароль);
    Результат.Вставить("ИмяСервера", ИмяСервера);
    Результат.Вставить("Хост", Хост);
    Результат.Вставить("Порт", ?(Порт <> "", Число(Порт), Неопределено));
    Результат.Вставить("ПутьНаСервере", ПутьНаСервере);
    
    Возврат Результат;
КонецФункции

Шаг 2. Отправка базового POST-запроса (создание категории)

Для создания простой категории товаров API UDS требует передать JSON-объект следующего вида:


{
  "name": "Кофе",
  "nodeId": null,
  "externalId": "category_coffee",
  "data": {
    "type": "CATEGORY"
  }
}

Выясним причину, как правильно реализовать это в коде 1С. Мы будем использовать объект HTTPСоединение для установки связи и ЗаписьJSON для автоматической и корректной сериализации структуры 1С в текстовую строку формата JSON.


// Задаем адрес ресурса и авторизационные данные API UDS
СтрокаURI = "https://api.uds.app/partner/v2/goods";
СтруктураURI = СтруктураURI(СтрокаURI);

ИдентификаторКомпании = "Ваш_ID_Компании";
КлючAPI = "Ваш_API_Key";

// Инициализируем защищенное SSL-соединение
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL();
HTTPСоединение = Новый HTTPСоединение(
    СтруктураURI.Хост, 
    СтруктураURI.Порт, 
    ИдентификаторКомпании, 
    КлючAPI, 
    , 
    , 
    ЗащищенноеСоединение
);

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

// Конструируем структуру данных для категории
СтруктураJSON = Новый Структура;
СтруктураJSON.Вставить("name", "Кофе");
СтруктураJSON.Вставить("nodeId", Null); // Родителем является корень каталога
СтруктураJSON.Вставить("externalId", "category_coffee");

ДанныеКатегории = Новый Структура;
ДанныеКатегории.Вставить("type", "CATEGORY");
СтруктураJSON.Вставить("data", ДанныеКатегории);

// Сериализуем структуру в строку JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку;
ЗаписатьJSON(ЗаписьJSON, СтруктураJSON);
ТелоЗапроса = ЗаписьJSON.Закрыть();

// Создаем и отправляем запрос
HTTPЗапрос = Новый HTTPЗапрос(СтруктураURI.ПутьНаСервере, Заголовки);
HTTPЗапрос.УстановитьТелоИзСтроки(ТелоЗапроса, КодировкаТекста.UTF8);

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

Шаг 3. Анализ и исправление типичных ошибок работы с циклами

Рассмотрим две критические ошибки, которые часто совершают начинающие разработчики при переносе кода выгрузки в обработку табличной части (ТЧ).

Ошибка 1: Выгрузка только последней строки (ошибка области видимости цикла)

В оригинальном обсуждении на форуме разработчик столкнулся с тем, что выгружался только последний элемент ТЧ. Проанализируем ошибочный код:


Для Каждого СтрокаТабличнойЧасти из Объект.Запасы Цикл
    Товар = СтрокаТабличнойЧасти.Номенклатура.Родитель;
КонецЦикла;

// Формирование JSON и отправка происходят ВНЕ цикла!
СтруктураДляJSON = Новый Структура("name,nodeId,externalId", СокрЛП(Товар), , СокрЛП(Товар));
// ... отправка запроса ...

Причина ошибки: Переменная Товар в цикле постоянно перезаписывается, и к моменту завершения обхода табличной части она хранит значение только из самой последней строки. Код формирования JSON и вызова HTTP-запроса находится ниже цикла, поэтому отрабатывает всего один раз. Чтобы исправить это, весь процесс сборки JSON и отправки HTTP-запроса должен быть перенесен внутрь цикла.

Ошибка 2: Попытка пакетной отправки (Bulk Upload)

Другой ошибочной стратегией является попытка сложить все подготовленные JSON-структуры товаров в один Массив и отправить его единым запросом:


ТаблицаТоваров = Новый Массив;
Для Каждого СтрокаТабличнойЧасти из Объект.Запасы Цикл
    // ... заполнение структуры ...
    ТаблицаТоваров.Добавить(СтруктураДляJSON);
КонецЦикла;
// ... отправка массива в теле запроса ...

Причина ошибки: Спецификация UDS Partner API V2 не поддерживает групповую выгрузку товаров через один запрос. Конечная точка POST /partner/v2/goods строго ожидает на вход **один объект** (а не массив объектов). Отправка массива данных приводит к ошибке разбора схемы на стороне сервера (обычно возвращается код 400 Bad Request).

Правильное решение: Мы должны организовать итерационную отправку. В цикле обходим ТЧ, формируем JSON-структуру для одной позиции и сразу отправляем ее через HTTP-соединение. Для пользователей 1С:УНФ аналогичный механизм обмена реализован в готовой интеграции маркетплейсов для 1С:УНФ 3.0/1.6.

Шаг 4. Сборка сложной JSON-структуры для товара с вариантами цен

Перейдем к наиболее сложной задаче — выгрузке товара, который имеет несколько вариантов (например, кофе разного объема: 100 мл, 200 мл и 300 мл, каждый из которых имеет свою цену и артикул). В терминах UDS такой товар классифицируется типом VARYING_ITEM.

Для создания такой позиции нам необходимо построить многоуровневое дерево объектов: корневая структура содержит описание товара, вложенная структура data содержит массив структур variants.

Проанализируем пример схемы данных:


{
  "name": "Капучино",
  "nodeId": 641108,
  "externalId": "coffee_cappuccino",
  "data": {
    "type": "VARYING_ITEM",
    "description": "Классический капучино на основе эспрессо",
    "variants": [
      {
        "name": "Маленький 100 мл",
        "price": 100.00,
        "sku": "1"
      },
      {
        "name": "Средний 200 мл",
        "price": 150.00,
        "sku": "2"
      }
    ]
  }
}

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


// 1. Инициализируем корневую структуру товара
ТоварСтруктура = Новый Структура;
ТоварСтруктура.Вставить("name", "Капучино");
ТоварСтруктура.Вставить("nodeId", 641108); // Числовой ID родительской категории в UDS
ТоварСтруктура.Вставить("externalId", "coffee_cappuccino"); // Наш ID из 1С

// 2. Создаем структуру специфичных данных товара (data)
ДанныеТовара = Новый Структура;
ДанныеТовара.Вставить("type", "VARYING_ITEM");
ДанныеТовара.Вставить("description", "Классический капучино на основе эспрессо");

// 3. Создаем массив для хранения вариантов цен (variants)
МассивВариантов = Новый Массив;

// Вариант №1: Маленький объем
Вариант1 = Новый Структура;
Вариант1.Вставить("name", "Маленький 100 мл");
// Важно! Цена должна передаваться числом с округлением до 2 знаков после запятой
Вариант1.Вставить("price", Окр(100.00, 2, РежимОкругления.Окр15Через10));
Вариант1.Вставить("sku", "1");
МассивВариантов.Добавить(Вариант1);

// Вариант №2: Средний объем
Вариант2 = Новый Структура;
Вариант2.Вставить("name", "Средний 200 мл");
Вариант2.Вставить("price", Окр(150.00, 2, РежимОкругления.Окр15Через10));
Вариант2.Вставить("sku", "2");
МассивВариантов.Добавить(Вариант2);

// 4. Связываем все элементы воедино
ДанныеТовара.Вставить("variants", МассивВариантов);
ТоварСтруктура.Вставить("data", ДанныеТовара);

// 5. Сериализация в JSON
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку;
ЗаписатьJSON(ЗаписьJSON, ТоварСтруктура);
ИтоговыйJSON = ЗаписьJSON.Закрыть();

Шаг 5. Тонкие нюансы и обязательные требования UDS API

Чтобы ваша интеграция работала стабильно и сервер не возвращал ошибки авторизации или валидации схем, необходимо учесть несколько важных технических регламентов UDS:

  1. Уникальные HTTP-заголовки запроса: UDS API V2 требует передавать для каждого запроса дополнительные параметры отслеживания:
    • X-Origin-Request-Id — уникальный идентификатор транзакции в формате UUID (v4). В 1С мы можем сгенерировать его вызовом: Строка(Новый УникальныйИдентификатор).
    • X-Timestamp — метка времени формирования запроса в международном формате ISO 8601 (например, 2026-03-31T15:30:00Z).
  2. Строгое округление цен: Передаваемые числовые значения цен должны быть округлены строго до двух знаков после запятой с использованием математического метода. Всегда используйте конструкцию Окр(Цена, 2, РежимОкругления.Окр15Через10) перед записью в JSON.
  3. Ограничения вложенности категорий: Система UDS поддерживает иерархию категорий максимум в 3 уровня вложенности. Попытка загрузить товар в подкатегорию более глубокого уровня вернет ошибку API. При создании корневой (базовой) категории поле nodeId должно иметь значение Null.
  4. Управление складскими остатками: Если товар поставляется без ограничений по количеству, передавайте значение остатка как Null. Если учет остатков включен, в структуру варианта необходимо добавить вложенный объект inventory со свойством inStock, содержащим числовой остаток.

Применяя данные подходы, вы сможете построить отказоустойчивый и гибкий механизм синхронизации каталога товаров 1С с бонусным пространством UDS. Для получения актуальной информации о стоимости товаров конкурентов на торговых площадках удобно использовать сервис парсинга цен на маркетплейсах.

← На главную