API ручной закупки
Один канал, один продавец, один заказ на закупку
Заказ на закупку может содержать несколько товаров или SKU, но все позиции должны относиться к одному каналу и одному продавцу.
Если покупатель выбирает товары разных продавцов или каналов, приложение должно разделить их на отдельные заказы на закупку до вызова API заказов HIOBuy.
HIOBuy не разделяет заказы автоматически и не предоставляет API пакетного оформления для этого процесса.
Как определить канал и продавца
- Используйте
channelна уровне заказа. Канал сокращённого пути, тела запроса и товарных позиций должен совпадать. Не смешивайте каналы вlines[]илиitems[]. - Для группировки на стороне клиента используйте настоящий
seller.idиз API товаров, если он доступен: у 1688 он определяется черезsellerOpenId, у деталей Taobao — черезshop_id. Сгенерированные подстановкиseller_1688_*/seller_taobao_*, отсутствие ID, название товара или магазина не подтверждают личность продавца. ID магазина Taobao и ID продавца из ответа рендеринга относятся к разным системам идентификаторов; сравнивать их нельзя. - Новое обязательное поле продавца в стандартный запрос не добавляется. В режиме self шлюз до официального создания проверяет принадлежность товаров 1688 по исходным деталям, а Taobao — по
render_item_list[].seller_idс проверкой всех запрошенных товаров и SKU. При отсутствии или неоднозначности подтверждений создание отклоняется. - В режиме закупки Warehouse, включая ручные заказы, склад проверяет продавца до создания заказа, запуска закупки, списания с кошелька или частичного успеха. Шлюз проверяет конфликты каналов исходного запроса и передаёт ошибки склада без повторных запросов к площадкам. Складу нужна отдельная приёмка; публикация шлюза не подтверждает реализацию этой проверки внешним складом.
- Ручные заказы используют
channel=manual; у всех позиций также должна совпадатьsource_platform. Полеseller_nameпредназначено только для отображения. Склад должен установить настоящего продавца каждого товара на площадке либо вернутьSELLER_ID_UNAVAILABLE. Указанное клиентом имя или ID не заменяет проверку. Не включайте ручное создание до приёмки контракта склада.
Ошибки и способы исправления
Все три ошибки используют HTTP 400 и категорию VALIDATION_ERROR:
| Код | Что делать |
|---|---|
MULTIPLE_CHANNELS_NOT_ALLOWED | Разделите товары по каналам и согласуйте каналы пути, тела запроса и позиций. |
MULTIPLE_SELLERS_NOT_ALLOWED | Внутри каждого канала разделите товары по настоящим продавцам и создайте заказы отдельно. |
SELLER_ID_UNAVAILABLE | Получите действительные ID товаров/SKU или надёжный механизм определения продавца складом. Не повторяйте неизменённый запрос и не определяйте продавца по имени. |
Оригинальный английский текст API при смешанном заказе:
A purchase order must contain products from the same channel and seller. Please split the items into separate orders by channel and seller.
Отказ при проверке продавца не должен создавать заказ или задачу закупки, списывать средства либо приводить к частичному успеху. Существующие правила идемпотентности сохраняются. Каждой намеренно выделенной закупке нужен собственный бизнес-номер/ключ; при повторе неизменённой закупки используйте исходный ключ.
Закупка и объединённая отправка
Заказы на закупку — это внутренние покупки у отдельных продавцов. Товары разных заказов могут поступить на склад отдельными посылками, а затем объединиться в международное отправление при соблюдении правил склада и перевозки. Объединение не сливает исходные номера закупок, внутреннюю доставку и состояния оплаты, отмены или возврата средств.
Верный запрос: несколько SKU проверенного продавца
Склад обязан самостоятельно установить, что обе товарные ссылки принадлежат одному устойчиво идентифицированному продавцу площадки. Примерные URL не являются доказательством личности продавца или результатом production-приёмки.
{
"channel": "manual",
"external_order_id": "MANUAL-SELLER-A-001",
"source_platform": "jd",
"seller_name": "Seller A",
"domestic_shipping_fee": 800,
"currency": "CNY",
"monetary_unit": "CNY_minor",
"items": [
{
"product_url": "https://example.com/seller-A/shoe",
"product_name": "Shoes",
"specification": "Size 40",
"unit_price": 5000,
"quantity": 1
},
{
"product_url": "https://example.com/seller-A/shoe",
"product_name": "Shoes",
"specification": "Size 41",
"unit_price": 5000,
"quantity": 1
}
]
}Ошибочный пример: настоящие продавцы различаются
Если items[0].product_url принадлежит продавцу A, а items[1].product_url — продавцу B, склад обязан вернуть MULTIPLE_SELLERS_NOT_ALLOWED, даже при seller_name: "Seller A". Если принадлежность проверить нельзя, верните SELLER_ID_UNAVAILABLE, а не принимайте заявленное имя.
{
"channel": "manual",
"external_order_id": "INVALID-MIXED-001",
"source_platform": "jd",
"seller_name": "Seller A",
"domestic_shipping_fee": 800,
"currency": "CNY",
"monetary_unit": "CNY_minor",
"items": [
{
"product_url": "https://example.com/seller-A/shoe",
"product_name": "Shoes",
"specification": "Size 40",
"unit_price": 5000,
"quantity": 1
},
{
"product_url": "https://example.com/seller-B/shirt",
"product_name": "Shirt",
"specification": "M",
"unit_price": 3000,
"quantity": 1
}
]
}Отказ склада по продавцу должен воспроизводиться по существующему контракту бизнес-номера/идемпотентности без создания заказа и списаний. Для уже созданных заказов сохраняется поведение повторного запроса, просмотра, оплаты и отмены.
POST /v1/orders/manual
Один запрос создаёт заказ для одной площадки и одного продавца с несколькими товарами этого продавца. Доступны только jd, pinduoduo, poizon; seller_name обязателен. Разные площадки или продавцы требуют отдельных запросов и номеров закупки.
Нужны Production API Key, право order:create, режим warehouse и действующая привязка склада. OAuth площадки не требуется. Sandbox не поддерживается. Перед использованием склад должен реализовать и проверить ручной API.
Запрос
Authorization: Bearer <PRODUCTION_API_KEY>
Content-Type: application/json
Idempotency-Key: 6c14ce20-cf29-4c25-a9ee-3d36aac94c16{
"channel": "manual",
"external_order_id": "EXT-10001",
"source_platform": "jd",
"seller_name": "Seller A",
"domestic_shipping_fee": 800,
"currency": "CNY",
"monetary_unit": "CNY_minor",
"language": "ru",
"remark": "Please ship together",
"items": [
{
"item_ref": "I001",
"product_url": "https://example.com/item1",
"product_name": "Wireless Mouse",
"specification": "Black",
"unit_price": 3500,
"quantity": 2,
"product_image": null,
"remark": ""
}
]
}external_order_id обязателен и уникален среди ручных заказов приложения. Тот же номер и данные возвращают прежний заказ; изменение данных даёт HTTP 409 IDEMPOTENCY_CONFLICT. Новая закупка требует нового номера. Idempotency-Key обязателен для создания, оплаты и отмены. order_sn создаёт HIOBuy; item_ref можно опустить. Массив sellers и переопределение продавца в строке запрещены.
| Поле | Обязательное значение или предел |
|---|---|
channel | manual |
external_order_id | 1–200 |
source_platform | jd / pinduoduo / poizon |
seller_name | 1–200 |
currency / monetary_unit | CNY / CNY_minor |
domestic_shipping_fee / items[].unit_price | integer ≥ 0 |
items / items[].quantity | 1–100 / 1–9999 |
Суммы склада
Суммы задаются целыми фэнями CNY: 3500 = CNY 35.00. Склад рассчитывает товары, внутреннюю доставку, действующий сбор 5% и итог. Пример не задаёт базу, минимум или округление. HIOBuy сохраняет суммы и не добавляет ещё 5%. При неполных суммах или связях товаров оплата запрещена.
{
"channel": "manual",
"success": true,
"order_id": "WH10001",
"order_sn": "HB202610160001",
"external_order_id": "EXT-10001",
"source_platform": "jd",
"seller_name": "Seller A",
"status": "wait_payment",
"currency": "CNY",
"monetary_unit": "CNY_minor",
"total": {
"merchandise": {
"amount": 7000,
"currency": "CNY"
},
"shipping": {
"amount": 800,
"currency": "CNY"
},
"procurement_fee": {
"amount": 390,
"currency": "CNY"
},
"payment": {
"amount": 8190,
"currency": "CNY"
}
},
"order_list": [
{
"order_id": "WH10001",
"shipping": {
"amount": 800,
"currency": "CNY"
},
"lines": [
{
"item_ref": "I001",
"sub_order_id": "WI10001",
"title": "Wireless Mouse",
"spec_title": "Black",
"quantity": 2,
"unit_price": {
"amount": 3500,
"currency": "CNY"
},
"line_total": {
"amount": 7000,
"currency": "CNY"
}
}
]
}
],
"failed_offers": [],
"request_id": "req_example"
}Существующие операции
Создание не списывает деньги и не начинает закупку. Используйте order_id и channel=manual с прежними API оплаты, отмены, деталей и внутреннего трекинга. Не передавайте pay_amount. После сверки сохранённой суммы склад выполняет существующую оплату кошельком. Закупка начинается только после подтверждения оплаты. Отмена не означает завершённый возврат денег.
{
"channel": "manual",
"order_id": "WH10001"
}{
"channel": "manual",
"order_id": "WH10001",
"cancel_reason": "buyer_request"
}Повторы и ограничения
При тайм-ауте или неизвестном результате сохраняйте номер и ключ и проверяйте детали. Не меняйте ключ для автоматической повторной оплаты. Детали содержат payment_status, ссылки строк и сборы. Список заказов площадок и API возвратов площадок не поддерживают manual. Допустимо 1–100 строк, количество 1–9999, имя продавца 200 символов, название и спецификация 500, примечания 1000, HTTP/HTTPS URL 2048. Строковые и дробные суммы запрещены.
400 VALIDATION_ERROR · 403 FULFILLMENT_MODE_NOT_SUPPORTED / WAREHOUSE_AUTH_INVALID · 409 IDEMPOTENCY_CONFLICT / ORDER_AMOUNT_CHANGED / ORDER_OPERATION_UNRESOLVED · 502 WAREHOUSE_INVALID_RESPONSE · 503 WAREHOUSE_UNAVAILABLE
Webhooks
procurement.failed / procurement.out_of_stock
{
"type": "procurement.failed",
"data": {
"channel": "manual",
"order_id": "WH10001",
"order_sn": "HB202610160001",
"external_order_id": "EXT-10001",
"source_platform": "jd",
"seller_name": "Seller A",
"status": "partial_failure",
"reason_code": "OUT_OF_STOCK",
"items": [
{
"item_ref": "I001",
"sub_order_id": "WI10001",
"quantity": 1,
"reason_code": "OUT_OF_STOCK"
}
]
}
}Get Support
Need integration help? Contact Developer Support at support@hiobuy.com · Response within 1–2 business days