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 и переопределение продавца в строке запрещены.

ПолеОбязательное значение или предел
channelmanual
external_order_id1–200
source_platformjd / pinduoduo / poizon
seller_name1–200
currency / monetary_unitCNY / CNY_minor
domestic_shipping_fee / items[].unit_priceinteger ≥ 0
items / items[].quantity1–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

Email support