Недавно сдал проект интеграции с ozon seller. Думал небольшая такая задачка, но оказалась — целый квест. И в первую очередь из-за нехватки нормальной документации и нормальной поддержки. Плюс система так устроена, что жуть.
В интернете хватает боли по этой части (например, эта или эта , а вот теперь еще от Леонида Каганова и эта (!)), а я решил добавить свою. Это лонгрид, держитесь.
Задача ставилась так. Сделать загрузку товаров, цен, остатков в ozon из файла Excel, который формировали из какой-то отраслевой старой 1С 8.2. Система не обновлялась и принципиально на старых движках 8.2. Поэтому от нее мы получаем что-то простое, типа выгрузки в Excel или xml
Пример записи ниже
После некоторого размышления я решил, что необходимо разработать простую конфигурацию на 1С 8.3, на БСП.
Общая схема
- На входе есть файл xml с полями как в Excel (все данные текстовые), который появляется в определенной папке с определенным именем.
- Система загружает файл xml как строки таблицы, создавая или обновляя карточки номенклатуры/характеристики.
- В карточке характеристики устанавливаем флаг «Обновить карточку»
- Далее вызывается процедура выгрузки в Ozon через из их API вызовом REST-сервисов
- выгрузить/обновить карточку характеристики;
- выгрузить/обновить цену;
- выгрузить/обновить складской остаток;
- выгрузить все.
- На каждом этапе есть логи в виде регистров сведений
Передача данных в Озон
Коммуникация с Озон строится посредством REST-сервисов Озона, которые приведены в документации, которую я местами перечитывал бесконечно https://api-seller.ozon.ru и новая ее версия https://docs.ozon.ru/api/seller. В ответ тоже получаем данные, которые затем обрабатываем.
Теперь по структуре выгрузки в Озон, так как в этом основная сложность.
Структура карточки в Озон
Для идентификации карточки товара Озон использует offer_id (код поставщика), который поставщик передает в систему. Если карточка успешно загружена, то Озон присваивает карточке product_id (это может занять 3-5 дней пока идет модерация!). В дальнейшем, для идентификации товара можно использовать offer_id или product_id равноправно.
Также, обязательно у товара присутствует Категория товара — category_id, которая не может меняться у карточки (жестко привязывается при первой загрузке). Категория товара в терминах 1С — это Вид номенклатуры. Категория определяет набор Атрибутов товара (Набор свойств в терминах 1С). Атрибуты — могут быть примитивного типа или же это справочник со своим набором значений.
Термин Озон | Термин 1С (БСП, ERP) | Сущность 1С |
Товар (item) | Характеристика номенклатуры | Справочник «Характеристики номенклатуры» |
Артикул | Номенклатура | Справочник «Номенклатура» |
Категория товара (Category) | Вид номенклатуры | Справочник «Виды номенклатуры» |
Характеристики товара (attributes) | Набор свойств | План видов характеристик «Наборы дополнительных реквизитов и сведений» |
Значения (values) | Дополнительные значения | Примитивные типы (Строка, число), Справочник «Дополнительные значения» |
У номенклатуры есть набор свойств и у вида номенклатуры есть свой набор свойств. Вид номенклатуры в терминах Ozon — это категория товаров.
Вот реальный пример отправки одного товара на сайт. Возможно отправлять до 1000 товаров в массиве, но для отладки — рекомендуется по одному товару.
{«items»:
[{
«complex_attributes»: [],
«attributes»: [{
«complex_id»: 0,»id»: 85,»values»: [{«dictionary_value_id»: 5592388,»value»: «Brandname»}]},
{«complex_id»: 0,»id»: 4194,»values»: [{
«dictionary_value_id»: 0,»value»: «https://Brandname.ru/components/com_jshopping/files/img_products/051az_kb.jpg»}]},
{«complex_id»: 0,»id»: 5309,»values»: [{«dictionary_value_id»: 527117518,»value»: «Золото красное»}]},
{«complex_id»: 0,»id»: 5315,»values»: [{«dictionary_value_id»: 25661,»value»: «585»}]},
{«complex_id»: 0,»id»: 5326,»values»: [{«dictionary_value_id»: 39261,»value»: «18.5»}]},
{«complex_id»: 0,»id»: 5352,»values»: [{«dictionary_value_id»: 0,»value»: «4,41»}},
{«complex_id»: 0,»id»: 8229,»values»: [{
«dictionary_value_id»: 92590,»value»: «Кольцо»}]},
{«complex_id»: 0,»id»: 9048,»values»: [{
«dictionary_value_id»: 0,»value»: «Кольцо 010051 Аз»}]},
{«complex_id»: 0,»id»: 10289,»values»: [{
«dictionary_value_id»: 0,»value»: «010051 Аз»}]},
{«complex_id»: 0,»id»: 4180,»values»: [{
«dictionary_value_id»: 0,»value»: «Кольцо 010051 Аз»}]},
{«complex_id»: 0,»id»: 4191,»values»: [{
«dictionary_value_id»: 0,»value»: «Кольцо 051Аз выполнено из золота 585 пробы и украшено натуральными вставками: 1 Аметист зеленый триллион 12 мм на 12 мм, вес 5.71 карат Средний вес украшения — 4,41 грамм.»}]},
{«complex_id»: 0,»id»: 4195,»values»: [{
«dictionary_value_id»: 0,»value»: «https://Brandname.ru/components/com_jshopping/files/img_products/051/051az_kb1.jpg»}]},
{«complex_id»: 0,»id»: 4383,»values»: [{
«dictionary_value_id»: 0,»value»: «4,41»}]},
{«complex_id»: 0,»id»: 4384,»values»: [{
«dictionary_value_id»: 0,»value»: «украшение, бирка, коробочка»}]},
{«complex_id»: 0,»id»: 4389,»values»: [{
«dictionary_value_id»: 90295,»value»: «Россия»}]},
{«complex_id»: 0,»id»: 5289,»values»: [{
«dictionary_value_id»: 0,»value»: «Аметист зеленый»}]},
{«complex_id»: 0,»id»: 9024,»values»: [{
«dictionary_value_id»: 0,»value»: «Кольцо 051Аз»}]},
{«complex_id»: 0,»id»: 9163,»values»: [{
«dictionary_value_id»: 22881,»value»: «Женский»}]},
{«complex_id»: 0,»id»: 9233,»values»: [{
«dictionary_value_id»: 0,»value»: «true»}]},
{«complex_id»: 0,»id»: 9461,»values»: [{
«dictionary_value_id»: 970685248,»value»: «Золото кольцо со вставками женское»}]}],
«barcode»: «2200002013000»,
«category_id»: 78910355,»name»: «Золотое кольцо c Аметистом зеленым Brandname 585 пробы»,
«offer_id»: «Кольцо 051Аз 18.5»,
«height»: 10,»depth»: 40,»width»: 50,»dimension_unit»: «mm»,
«weight»: 4,»weight_unit»: «g»,
«images»: [«https://Brandname.ru/components/com_jshopping/files/img_products/051/051az_kb1.jpg»],
«file_name»: «https://Brandname.ru/components/com_jshopping/files/img_products/051az_kb.jpg»,
«vat»: «0»,
«price»: «53560»
}]}
В начале идет раздел с атрибутами. Возможны комплексные атрибуты (complex_attributes), но у нас их не было, передаю пустой массив. В разделе атрибутов — указывается complex_id — 0 (если нет), id — код справочника со значениями самого озона (их надо будет предварительно загрузить, я это опишу далее), далее — массив самих значений, у нас — только одно, не могу представить, почему тут может быть массив. Массив значений — тоже в виде кода значения справочника и представления его значения.
Например, для некого бренда- его код — 5592388, и определенное значение (это тоже надо будет предварительно загрузить, я это опишу далее). И так по каждой характеристике (Набору свойств). Если значение характеристики примитивного типа — только код справочника и значения. Например «Средний вес изделия, гр» — код справочника id = 5352, dictionary_value_id =0, значение ставим текстовое «4,41». После раздела с массивом характеристик — данные собственно карточки — категория, код поставщика, штрихкод, и проч.
Важно учесть, что некоторые характеристики обязательные, а некоторые — можно не заполнять.
Важно! Невероятно, но факт! В терминах 1С номенклатура является в Озоне как самостоятельная сущность отсутствует, является виртуальной сущностью, объединяемых общим Артикулом. То есть, чтобы связать товары в Озон необходимо, чтобы у товаров был одинаковый Артикул, а это специальная характеристика.
{«complex_id»: 0,»id»: 10289,»values»: [{
«dictionary_value_id»: 0,»value»: «010051 Аз»}]},
.
В данном примере мы выгружаем две характеристики с одинаковым Артикулом, а озон их сам объединяет в некую общность на карточке.
В 1С карточки характеристики и номенклатуры выглядят так:
Категория товара и его характеристики (атрибуты)
У каждой товара есть набор обязательных атрибутов
Помимо этого, есть категория товаров, которая определяет еще некий набор характеристик (у каждой категории — свой набор) со своими значениями. Например, для ювелирных изделий — проба (с фиксированным списком значений — «585», «925» и т.д.), обязательное поле, для других категорий, вообще не применимое.
Для загрузки использовался метод /v2/category/attribute, который возвращает необходимые нам атрибуты и их тип. После чего, если тип — справочник — нам необходимо загрузить их значения методом /v2/category/attribute/values. Это очень важная разовая процедура, причем разработчики озона предупреждают, что значения и даже состав характеристик может меняться без предупреждения. Так что держите ухо востро.
Загрузка в 1С из внешней системы
Теперь, когда мы научились формировать json для товаров, опишем как работает система в целом.
- Сначала обработка загружает карточки номенклатуры (и характеристик), используя файл xml, который лежит по определенному пути (на ftp). В файле присутствует вся информация о товаре, ценах и складских остатках. Реализована как внешняя обработка, запускается по расписанию, определяемым администратором.
- Затем обработка формирует запросы в ozon. Обработка загрузки была создана одна, но с 4 разными командами:
- выгрузить карточки в ozon;
- выгрузить цены в ozon;
- выгрузить остатки в ozon.
- Все команды работают по своему расписанию
- Все пишется в журнал импорта. Важно хранить текст запроса и ответ озона. Для разбора проблем это очень важно
Изображения
Во-первых, есть требования по изображениям. А вот по формату передачи ссылок на изображения — в документации все нечетко написано, неоднозначно и без примеров. Вот фрагмент из документаци:
Но основной нюанс с изображениями с точки зрения формирования данных: это то в массиве изображений должно присутствовать «основное изображение», иначе выйдет ошибка при загрузке. Сразу даю живой пример, как должно быть в основном разделе:
И еще в разделе атрибутов- основное изображение (id 4194 «Изображение»)
И еще массив в разделе атрибутов — id 4195 «Изображения»
Короче, с картинками пришлось долго мучиться
Еще нюансы
Модерация проходит долго, несколько дней или дольше. Например, при отправке товара вы получаете в ответ номер задачи на создание. После чего через некоторое время получаете статус pending — товар на модерации. Через некоторое время (3 рабочих дня, иногда быстрее или дольше) получаете статус imported или ошибку и список ошибок. С ними еще придется научиться их понимать.
Техподдержка сильно перегружена и не всегда сама хорошо знает api ozon. Некоторые кейсы разбирали вместе долго и упорно. Готовьтесь и вы, запасайтесь терпением. Админ сайта до сих пор (уже 3 месяца!) пытается разобраться с отдельными ошибками (я подглядываю в их общий чат)
Выгрузка цен
Тут все просто, выгружаем массив по 1000 значений (ограничение Озона) с кодами поставщика и ценой со скидкой и без. Метод /v1/product/import/prices
Выгрузка остатков
Тут тоже все просто, выгружаем массив по 100 значений (ограничение Озона) с кодами поставщика и остатками. Метод /v1/product/import/stocks
Выводы
Система работает, запущена в эксплуатацию уже пару месяцев на момент написания статьи. Заказы идут, в плане торговой площадки — озон достоин этих усилий! Но с точки зрения удобства для поставщика — все тяжко.
Однако, дошедшие до финиша — получат долю с не дошедших и не пошедших! Для бизнеса — это хорошо!
Если есть желание получить данное решение для экономии времени — пишите pavel.pche@gmail.com — о цене договоримся
UPD 05/09/2021
Появилось расширение от Озона, которое решает поставленные задачи для УТ11/КА2/ERP.
Вот описание (с загрузкой внутри) https://seller-edu.ozon.ru/docs/work-with-goods/zagruzka-1c.html
Я уже изучаю и настраиваю людям — напишу как будет материал
UPD 14/09/2021
Вот человек написал примерно то, что и я думал. Почитайте, не пожалеете
http://lleo.me/dnevnik/2021/09/11_1
Пару цитат для затравочки:
«Простите, вы там вообще наркоманы упоротые?
Мало того, что вы отключили старый API и нарушили работу систем всех своих партнеров.
Мало того, что ваш новый API чудовищно непрофессионально спроектирован и заставляет делать сотни тысяч обращений к серверам чтобы локально вытянуть кучу гигантских словарей и узнать, каким сраным временным индексом в своих грёбаных внутренних базах вы сегодня обозначили нужное value. Так у вас еще и эти базы битые, содержат взаимно противоречащие дубли?!!»
….
«Вы вообще что ли ничего не умеете, даже индексы строить?! Вас по итогам районной олимпиады трудоустроили в корпорацию? Может вам всем отделом уже пойти на курсы какие-нибудь по программированию и базам данных? Господи Кришна, на что я бл@ть, простой писатель-фантаст, трачу своё сука время, помогая другу с автоматизацией его неведомого склада, который я ему наладил год назад и забыл нах!й, а теперь вы бл@ть всё поломали. Да будьте вы прокляты, е4анаты хтонические!»