Интеграция систем 1С с внешними веб-сервисами — одна из самых частых задач современного разработчика. В процессе настройки обмена данными часто приходится сталкиваться с отправкой HTTP-запросов методом POST, тело которых должно содержать сложную иерархическую структуру данных в формате JSON. Отличным примером такого взаимодействия является интеграция с API системы лояльности UDS (United Digital Solutions) Partner API V2.
В этой статье мы подробно разберем, как правильно сформировать и отправить POST-запрос из 1С 8.3, проанализируем типичные ошибки разработчиков при обходе табличных частей документов, а также научимся конструировать сложные древовидные JSON-структуры для выгрузки товаров с несколькими ценовыми вариантами. Для автоматизации подобных действий в системах, не имеющих открытого API, может применяться платформа One RPA для роботизации действий пользователя.
Прежде чем отправить запрос, нам необходимо разобрать строку 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.Вставить("Пароль", Пароль);
Результат.Вставить("ИмяСервера", ИмяСервера);
Результат.Вставить("Хост", Хост);
Результат.Вставить("Порт", ?(Порт <> "", Число(Порт), Неопределено));
Результат.Вставить("ПутьНаСервере", ПутьНаСервере);
Возврат Результат;
КонецФункции
Для создания простой категории товаров 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);
Иначе
Сообщить("Ошибка при создании категории. Код: " + РезультатЗапроса.КодСостояния);
Сообщить("Ответ сервера: " + ТекстОтвета);
КонецЕсли;
Исключение
Сообщить("Ошибка сетевого соединения: " + ОписаниеОшибки());
КонецПопытки;
Рассмотрим две критические ошибки, которые часто совершают начинающие разработчики при переносе кода выгрузки в обработку табличной части (ТЧ).
В оригинальном обсуждении на форуме разработчик столкнулся с тем, что выгружался только последний элемент ТЧ. Проанализируем ошибочный код:
Для Каждого СтрокаТабличнойЧасти из Объект.Запасы Цикл
Товар = СтрокаТабличнойЧасти.Номенклатура.Родитель;
КонецЦикла;
// Формирование JSON и отправка происходят ВНЕ цикла!
СтруктураДляJSON = Новый Структура("name,nodeId,externalId", СокрЛП(Товар), , СокрЛП(Товар));
// ... отправка запроса ...
Причина ошибки: Переменная Товар в цикле постоянно перезаписывается, и к моменту завершения обхода табличной части она хранит значение только из самой последней строки. Код формирования JSON и вызова HTTP-запроса находится ниже цикла, поэтому отрабатывает всего один раз. Чтобы исправить это, весь процесс сборки JSON и отправки HTTP-запроса должен быть перенесен внутрь цикла.
Другой ошибочной стратегией является попытка сложить все подготовленные JSON-структуры товаров в один Массив и отправить его единым запросом:
ТаблицаТоваров = Новый Массив;
Для Каждого СтрокаТабличнойЧасти из Объект.Запасы Цикл
// ... заполнение структуры ...
ТаблицаТоваров.Добавить(СтруктураДляJSON);
КонецЦикла;
// ... отправка массива в теле запроса ...
Причина ошибки: Спецификация UDS Partner API V2 не поддерживает групповую выгрузку товаров через один запрос. Конечная точка POST /partner/v2/goods строго ожидает на вход **один объект** (а не массив объектов). Отправка массива данных приводит к ошибке разбора схемы на стороне сервера (обычно возвращается код 400 Bad Request).
Правильное решение: Мы должны организовать итерационную отправку. В цикле обходим ТЧ, формируем JSON-структуру для одной позиции и сразу отправляем ее через HTTP-соединение. Для пользователей 1С:УНФ аналогичный механизм обмена реализован в готовой интеграции маркетплейсов для 1С:УНФ 3.0/1.6.
Перейдем к наиболее сложной задаче — выгрузке товара, который имеет несколько вариантов (например, кофе разного объема: 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.Закрыть();
Чтобы ваша интеграция работала стабильно и сервер не возвращал ошибки авторизации или валидации схем, необходимо учесть несколько важных технических регламентов UDS:
X-Origin-Request-Id — уникальный идентификатор транзакции в формате UUID (v4). В 1С мы можем сгенерировать его вызовом: Строка(Новый УникальныйИдентификатор).X-Timestamp — метка времени формирования запроса в международном формате ISO 8601 (например, 2026-03-31T15:30:00Z).Окр(Цена, 2, РежимОкругления.Окр15Через10) перед записью в JSON.
nodeId должно иметь значение Null.
Null. Если учет остатков включен, в структуру варианта необходимо добавить вложенный объект inventory со свойством inStock, содержащим числовой остаток.
Применяя данные подходы, вы сможете построить отказоустойчивый и гибкий механизм синхронизации каталога товаров 1С с бонусным пространством UDS. Для получения актуальной информации о стоимости товаров конкурентов на торговых площадках удобно использовать сервис парсинга цен на маркетплейсах.