Интеграция учетной системы 1С с маркетплейсом Ozon — это стандартная задача для современной торговли. Синхронизация остатков в реальном времени позволяет избежать штрафов за отмену заказов и поддерживать актуальность данных на витрине. Однако при разработке механизма обмена программисты часто сталкиваются с ошибкой HTTP 400 (Bad Request). В этой статье мы подробно разберем правильный алгоритм синхронизации остатков, напишем работающий код на языке 1С и выясним основные причины возникновения ошибок валидации запросов. Чтобы не разрабатывать решение самостоятельно, можно применить готовое расширение для интеграции 1С с Ozon по схеме FBS.
Прежде чем приступать к написанию кода, давайте проанализируем базовую схему взаимодействия систем. Процесс обновления остатков на стороне маркетплейса состоит из следующих последовательных шагов:
offer_id).Код состояния 400 означает, что сервер Ozon отклонил наш запрос из-за некорректного формата данных. Выделим ключевые технические нюансы, которые чаще всего приводят к этой ошибке при отправке запросов из 1С:
/v1/product/import/stocks. Если у вас в кабинете Ozon настроено несколько складов (например, для схемы rFBS), этот метод вернет ошибку 400. Необходимо использовать актуальный метод /v2/products/stocks.warehouse_id должен передаваться строго как число (целое число int64), а не как строка. Если в 1С этот реквизит записан как строка (например, "1234567"), Ozon вернет ошибку валидации схемы. Аналогично, остаток stock должен быть числом, а артикул offer_id — строкой.Warehouse_id вместо warehouse_id) гарантированно приведет к сбою.Рассмотрим детальный пример функции на языке 1С, которая формирует JSON-пакет по требованиям Ozon API v2 и отправляет его на сервер. Обратите внимание на правильную сериализацию типов данных и установку кодировки. В качестве готовой альтернативы программированию вручную можно использовать внешнюю обработку для обновления цен и остатков на Ozon.
// Функция отправляет актуальные остатки товаров на Ozon API v2
Функция ОбновитьОстаткиНаOzon(МассивТоваров, НастройкиПодключения) Экспорт
// Параметры НастройкиПодключения должны содержать:
// - ClientId (строка)
// - ApiKey (строка)
// - WarehouseId (число или строка, содержащая только цифры)
// Проверим, что массив содержит элементы и не превышает лимит в 100 позиций
Если МассивТоваров.Количество() = 0 Тогда
ЗаписьЖурналаРегистрации("Ozon API", УровеньЖурналаРегистрации.Предупреждение,, "Массив товаров пуст.");
Возврат Ложь;
ИначеЕсли МассивТоваров.Количество() > 100 Тогда
ЗаписьЖурналаРегистрации("Ozon API", УровеньЖурналаРегистрации.Ошибка,, "Превышен лимит позиций в одном запросе (макс. 100).");
Возврат Ложь;
КонецЕсли;
// Шаг 1. Формируем структуру JSON-запроса
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписьJSON.ЗаписатьНачалоОбъекта();
ЗаписьJSON.ЗаписатьИмяСвойства("stocks");
ЗаписьJSON.ЗаписатьНачалоМассива();
Для Каждого СтрокаТовара Из МассивТоваров Цикл
ЗаписьJSON.ЗаписатьНачалоОбъекта();
// Артикул товара (обязательно строка)
ЗаписьJSON.ЗаписатьИмяСвойства("offer_id");
ЗаписьJSON.ЗаписатьЗначение(Строка(СтрокаТовара.Артикул));
// Идентификатор склада (обязательно целое число)
ЗаписьJSON.ЗаписатьИмяСвойства("warehouse_id");
ЗаписьJSON.ЗаписатьЗначение(Число(НастройкиПодключения.WarehouseId));
// Количество товара на складе (обязательно число)
ЗаписьJSON.ЗаписатьИмяСвойства("stock");
ЗаписьJSON.ЗаписатьЗначение(Число(СтрокаТовара.Количество));
ЗаписьJSON.ЗаписатьКонецОбъекта();
КонецЦикла;
ЗаписьJSON.ЗаписатьКонецМассива();
ЗаписьJSON.ЗаписатьКонецОбъекта();
СтрокаJSON = ЗаписьJSON.Закрыть();
// Шаг 2. Настраиваем HTTP-соединение с защитой SSL
Сервер = "api-seller.ozon.ru";
Защита = Новый ЗащищенноеСоединениеOpenSSL();
HTTPСоединение = Новый HTTPСоединение(Сервер,,,,,, Защита);
// Шаг 3. Подготавливаем POST-запрос
Ресурс = "/v2/products/stocks";
HTTPЗапрос = Новый HTTPЗапрос(Ресурс);
// Устанавливаем обязательные заголовки авторизации и типа контента
HTTPЗапрос.Заголовки.Вставить("Client-Id", НастройкиПодключения.ClientId);
HTTPЗапрос.Заголовки.Вставить("Api-Key", НастройкиПодключения.ApiKey);
HTTPЗапрос.Заголовки.Вставить("Content-Type", "application/json");
// Преобразуем JSON в двоичные данные, явно указав кодировку UTF-8 без BOM
HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Шаг 4. Отправляем запрос и анализируем ответ
Попытка
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
КодCостояния = HTTPОтвет.КодСостояния;
ТекстОтвета = HTTPОтвет.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
Если КодCостояния = 200 Тогда
ЗаписьЖурналаРегистрации("Ozon API", УровеньЖурналаРегистрации.Информация,, "Остатки успешно обновлены: " + ТекстОтвета);
Возврат Истина;
Иначе
ЗаписьЖурналаРегистрации("Ozon API", УровеньЖурналаРегистрации.Ошибка,, "Ошибка обновления остатков. Код ответа: " + КодCостояния + ". Ответ: " + ТекстОтвета);
Возврат Ложь;
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("Ozon API", УровеньЖурналаРегистрации.Ошибка,, "Ошибка сетевого соединения: " + ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
КонецФункции
Если в процессе разработки вы продолжаете получать ошибку 400, воспользуйтесь следующими проверенными методами отладки:
HTTPСоединение.ОтправитьДляОбработки() сохраняйте сформированную строку JSON во временный текстовый файл или записывайте ее в Журнал регистрации. Это позволит вам увидеть реальную структуру пакета, отправляемого из 1С.Client-Id, Api-Key, Content-Type) и выполните POST-запрос. Postman возвращает детализированный ответ от Ozon, где будет указано конкретное поле, не прошедшее валидацию.Для создания отказоустойчивой системы интеграции рекомендуем внедрить следующие архитектурные решения:
Применяя данные подходы и контролируя типы передаваемых полей в JSON, вы сможете построить надежную и быструю интеграцию вашей системы 1С с Ozon API без досадных ошибок валидации. Чтобы не разрабатывать механизм с нуля в УТ 11, КА 2 или ERP 2, можно настроить интеграцию 1С с Ozon, Wildberries и Яндекс.Маркетом.