В нашей компании принято устраивать звонки-знакомства — на них клиенты могут напрямую пообщаться с командами, которые будут им помогать или сопровождать. Во время таких встреч поднимается множество вопросов, в том числе связанных с интеграцией. Чаще всего вопросы одни и те же, поэтому я даже имею заготовленный спич, который позволяет на пальцах объяснить принцип работы нашей интеграции и быстро оценить сложность её реализации на своей стороне. Спич долго был только в моей голове, но для Хабра я решил изложить его в письменном виде и поделиться с вами.
? Сначала материал не разрешили публиковать — сочли его рекламным. Но когда узнали все детали — что через наш API можно формировать до 500 запросов в сутки бесплатно (а этого по опыту хватает в среднем на обработку 50 заказов), — «дали зеленый свет» и попросили указать все это в начале материала. Что я и делаю ? Заявку на подключение доступа можно оформить на сайте компании через форму обратной связи.
Шаг 1. Обновление цен и стоков
Первый поток данных, который нужно запустить. Информация о ценах и остатках должна транслироваться из системы клиента во все маркетплейсы. Инициатором обмена выступает система клиента — именно в ней происходит изменение цен и стоков.
Алгоритм работы сильно зависит от возможностей системы клиента, обычно реализуются следующие варианты:
Мгновенное обновление при событии
В учётной системе клиента произошло изменение цены или стока.
Учётная система клиента отслеживает это событие и в тот же момент вызывает методы передачи цены или стока (в зависимости от того, что изменилось) и отправляет новые значения в XWAY API.
XWAY API доставляет данные до маркетплейсов.
Таким образом, время, прошедшее с момента изменения данных в учётной системе клиента до обновления данных на маркетплейсе, составляет сотни миллисекунд, максимум 1-2 секунды. Это самый правильный сценарий, к которому стоит стремиться. Так сказать, идеальный мир интеграции ?
Запуск рекуррентного обновления по времени
У многих наших клиентов учётная система не может отследить изменение цены или стока, а значит, не может мгновенно запустить обмен и передать новые данные на маркетплейс. Поэтому они реализуют следующую логику:
Раз в N минут (параметр целиком и полностью зависит от конкретной системы) запускается сборщик, который пробегает по всей базе и выделяет массив товаров, где изменилась цена или сток за последние N минут.
Для найденных массивов товаров формируются соответствующие запросы на обновление цен или стоков и передаются в XWAY API.
XWAY API доставляет данные до маркетплейсов.
Очевидным минусом такого подхода является его дискретность. По опыту, наши клиенты, использующие данную схему, осуществляют отправку данных раз в 5 минут и реже. Если сделать чаще, то появляется высокая нагрузка на учётную систему клиента. Если сделать реже — увеличится вероятность продажи большего количества товаров, чем есть на складе.
Запуск полного обновления по времени
Самый печальный случай. Учётная система клиента по тем или иным причинам не может выделить товары, в которых произошли изменения цены или стока, поэтому производится отправка всего массива информации о товарах, ценах и остатках.
Раз в N минут (параметр целиком и полностью зависит от конкретной системы) запускается обмен по всем товарам, которые есть у клиента.
Для всех товаров формируются соответствующие запросы на обновление цен или стоков и передаются в XWAY API.
XWAY API доставляет данные до маркетплейсов.
Конечно же, дикие объемы передаваемых данных. Естественно, такой обмен невозможно сделать быстрым, хотя бы потому, что тут же начинаем упираться в лимиты по запросам маркетплейсов. Но если по другому нельзя, то можно и так сделать ?
Примеры методов
Обновление цен
Возможны 2 модели асинхронного взаимодействия, с использованием Webhook и без него.
Если используется Webhook:
В запросе продавец передаёт URL своего эндпоинта в параметре request_url.
{
"request_url": "https://seller.com/webhook/",
"shop_id": 2145,
"items": [
{
"external_id": "204245576795",
"price": 99987,
"discount_price": 95000,
"available": true,
"batch_count": 1
},
{
"external_id": "204245576797",
"price": 39342,
"discount_price": 30999,
"available": false,
"batch_count": 1
}
]
}
После обработки запроса на указанный эндпоинт продавца придёт request_id.
Используя метод https://seller-api.xway.ru/api/v2/requests/{request_id} продавец получает результат выполнения запроса.
Если не используется Webhook:
В запросе продавец не передаёт параметр request_url.
{
"shop_id": 2145,
"items": [
{
"external_id": "204245576795",
"price": 99987,
"discount_price": 95000,
"available": true,
"batch_count": 1
},
{
"external_id": "204245576797",
"price": 39342,
"discount_price": 30999,
"available": false,
"batch_count": 1
}
]
}
В ответе на запрос продавец сразу получает request_id
Используя метод https://seller-api.xway.ru/api/v2/requests/{request_id} продавец получает результат выполнения запроса.
? В одном запросе нельзя передавать цену на один и тот же товар более одного раза.
? В одном запросе нельзя передавать массив более чем из 500 элементов.
Шаг 2. Получение заказов
Следующий поток данных, который нам нужно организовать для полноценной работы с маркетплейсами по схеме FBS — обмен информацией о заказах. Чем быстрее продавец получит заказ с маркетплейса и его обработает (зарезервирует товар под этот заказ), тем быстрее он сможет протранслировать новые значения остатков для товаров, которые были в заказе. И тем меньше вероятность оверсейла (продажи большего числа товара, чем есть на складе).
Однако зачастую маркетплейсы не выступают инициатором обмена и ждут, когда учётная система продавца обратится к ним за новыми заказами. Мы поддерживаем несколько схем получения заказа.
Продавец запрашивает новые заказы по расписанию
Продавец при разработке интеграции реализует в своей учётной системе метод, который с определённой периодичностью обращается к XWAY API и получает список новых заказов. То есть в качестве инициатора обмена выступает система продавца.
Понятно, что такая схема приводит к задержкам, напрямую зависящим от частоты запросов.
Если сделать частоту запросов слишком большой, то задержка уменьшится, но при этом увеличится нагрузка как на учётную систему продавца, так и на сервер XWAY API.
Если сделать частоту запросов слишком низкой, то задержка увеличится, что приведёт к оверсейлам.
Запрос на получение списка заказов достаточно простой. Это GET запрос, в котором можно с помощью параметров добавить дополнительную фильтрацию, например, по дате создания, дате изменения, статусу заказа и так далее.
Пример запроса на получение списка заказов для магазина с id 6414 и статусом delivered:
curl --request GET \
--url 'https://seller-api.xway.ru/api/v2/orders/?shop_id=6414&status=delivered' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGci587IUzI1NiJ9.eyJ1c2VyX2lkIjo2MDQ1LCJ1c2VyX2d1aWQiOiI2ZWQzNDE2Yy03YmQzLTQyNTctYmQzYi1hZjRlNTYzNzE2OGEiLCJleHAiOjE2OTI4MDQyNTgsImF1dGhfbWV0aG9kX3R5cGUiOiJFTUFJTCIsImFjY291bnRzIjp7IlBBU1NQT1JUIjo2MDQ1LCJVTklDT1JOIjo1NTY2fSwicGVybWlzc2lvbnMiOnt9LCJpc194d2F5X2VtcGxveWVlIjpmYWxzZX0.Qf63EQ_kF-ZwIzJYIdC_izro1uTsh6q1zJslxsGcpuc' \
--header 'content-type: application/json
В ответ на подобный запрос XWAY API выдаст список заказов для данного магазина:
{
"meta": {
"request_id": "a4a17610-9ee9-48f5-a33d-e888eb1846d2",
"message": null
},
"result": {
"orders": [
{
"id": 34511146,
"shop_id": 6414,
"order_id": "107586281",
"marketplace_code": "beru",
"created_at": "2022-04-27T03:00:00.000000Z",
"modified_at": "2022-05-01T13:24:01.165000Z",
"status": "delivered"
},
{
"id": 34511144,
"shop_id": 6414,
"order_id": "107857757",
"marketplace_code": "beru",
"created_at": "2022-04-29T03:00:00.000000Z",
"modified_at": "2022-05-01T13:10:49.838000Z",
"status": "delivered"
}
]
},
"pagination": {
"limit": 100,
"offset": 0,
"total": 482
}
}
Продавец получает информацию о новых заказах на webhook
Продавец при разработке интеграции реализует в своей учётной системе дополнительный эндпойнт (урл, webhook), адрес которого прописывается в XWAY API. Как только в XWAY API появляется информация о том, что у продавца на любом из маркетплейсов появился новый заказ, в тот же момент XWAY API отправляет уведомления на webhook продавца и селлер тут же вызывает метод получения нового заказа.
Такая схема работы чуть более сложна в реализации для продавца (ему нужно делать отдельный webhook и писать дополнительный обработчик), но обладает рядом важных преимуществ:
Оптимизация трафика между двумя системами. Обмен начинается только в том случае, если поступил заказ.
Ускорение обмена между двумя системами. Как только пришёл новый заказ, в тот же момент XWAY API отправляет соответствующее уведомление учётной системе продавца и запускается обмен информацией по заказу. Задержка между появлением заказа в XWAY API и в системе продавца уменьшается до 1 секунды.
Получения полной информации о заказе
Независимо от того, каким образом продавец получает информацию о новом заказе, в ней не содержится полная информация. XWAY API отдаёт только базовую информацию о том, что появился заказ или произошло изменение в существующем. Для получения полной информации продавец должен вызвать метод получения полной информации о заказе:
curl --request GET \
--url 'https://seller-api.xway.ru/api/v2/orders/34511146?shop_id=6414' \
--header 'authorization: Bearer eyJ0eXAiOiJKV1QiLCJ589GciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjo2MDQ1LCJ1c2VyX2d1aWQiOiI2ZWQzNDE2Yy03YmQzLTQyNTctYmQzYi1hZjRlNTYzNzE2OGEiLCJleHAiOjE2OTI4MDQyNTgsImF1dGhfbWV0aG9kX3R5cGUiOiJFTUFJTCIsImFjY291bnRzIjp7IlBBU1NQT1JUIjo2MDQ1LCJVTklDT1JOIjo1NTY2fSwicGVybWlzc2lvbnMiOnt9LCJpc194d2F5X2VtcGxveWVlIjpmYWxzZX0.Qf63EQ_kF-ZwIzJYIdC_izro1uTsh6q1zJslxsGcpuc' \
--header 'content-type: application/json'
В ответ XWAY API отдаст подробную информацию о заказе:
{
"meta": {
"request_id": "d1268645-be96-4634-b814-07933c2dc819"
},
"result": {
"id": "42486407",
"shop_id": 2848,
"marketplace_code": "SMM",
"order_id": "747378127",
"created_at": "2022-08-01T11:56:45.000000Z",
"modified_at": "2022-08-01T11:59:10.670598Z",
"status": "delivered",
"antifraud_status": null,
"total_amount": 95.0,
"memo": null,
"order_items": [
{
"id": 43273407,
"xway_offer_id": 22763052,
"external_id": "84.140",
"sku_code": "22763052",
"seller_price": 718.0,
"buyer_price": 95.0,
"subsidy": 623.0,
"currency_code": "RUB",
"name": "Антимоскитная сетка \"Герберы\" для дверного проема 2,1х1,0м",
"quantity": 1,
"is_cancel": false,
"memo": null,
"properties": []
}
],
"buyer_info": {
"name": null,
"phone": null
},
"delivery": {
"delivery_status": null,
"service_type": "fbs",
"shipment_date": "2022-08-04T15:00:00+00:00",
"warehouse_id": null,
"delivery_price": 0.0,
"delivery_type": null,
"delivery_service": "delivery_by_goods",
"customer": {
"name": "Мина Мария",
"phone": null,
"address_full": "г Киров, ул Пушкина, д 15А",
"address_detail": null
},
"delivery_interval": {
"from_date": "2022-08-07",
"to_date": "2022-08-07",
"from_time": "21:00",
"to_time": "21:00",
"timezone": "UTC+0"
},
"shipments": []
},
"requirements": {
"gtd": [],
"country": [],
"mandatory_mark": [],
"rnpt": []
}
}
}
Шаг 3. Обработка заказа
Ну что же, заказ получили — теперь его нужно обработать :) Если бы вы делали интеграцию с каждым маркетплейсом отдельно, то тут бы было множество алгоритмов обработки заказа, каждый из которых бы зависел от конкретного маркетплейса.
Забудьте как страшный сон!
Мы всё уже сделали: свели все методы к единому набору, а все статусы — к единой статусной модели.
Вам без разницы, заказ с какого маркетплейса вы хотите обрабатывать. Просто всегда делайте одну и ту же последовательность шагов на складе и одну и ту же последовательность вызовов XWAY API:
Подтверждаем или отменяем товары в заказе.
Собираем заказ.
Получаем наклейку на упакованное отправление.
Создаём поставку.
Получаем документы на поставку.
ВСЁ! ?
Всего пять шагов, всегда стандартные пять шагов ?
Конечно, я мог бы далее расписать каждый из шагов, привести примеры кода…но мне кажется, это уже лишнее. Если вам действительно интересны технические детали, вы можете ознакомиться с ними в нашей документации https://seller-api.xway.ru/redoc
В заключении хочется выразить простую мысль, которую я хотел донести в этой статье:
Интеграция может быть простой и понятной.
Забудьте об особенностях каждого маркетплейса, о куче методов, механизмов авторизации, множестве ключей и кредов для каждого маркетплейса, о разных айди, каждый из которых называется по-своему и каждый из которых надо передавать в свои методы и в свои параметры. Просто сделайте одну интеграцию — и работайте спокойно, а всю эту головную боль можно делегировать экспертам :) Если у вас есть вопросы, буду рад ответить на них в комментариях или в Телеграм @anton_batashov