Перейти к содержимому

B2B API для партнёров

Назначение

Этот API предназначен для B2B‑клиентов (оптовиков, владельцев розничных интернет‑магазинов), которым нужно:

  • получать список доступных точек выдачи (pick_up_points);
  • получать список брендов по артикулу сразу по нескольким складам;
  • получать список предложений (остатков) по выбранным брендам и артикулу.

Все методы расположены по префиксу: /api/b2b/*.


Авторизация

Авторизация настраивается в админке:

  • Страница: Настройка сайта → вкладка 1С интеграция, блок B2B API.
  • Хранение настроек — App\Settings\GeneralSettings:
    • b2b_enabled — включение/выключение B2B‑API;
    • b2b_token — токен для авторизации.

При включении B2B‑API:

  • если токена ещё нет — он автоматически генерируется;
  • есть отдельная кнопка «Сгенерировать / перевыпустить токен B2B».

Каждый запрос к /api/b2b/* должен содержать заголовок:

http
Authorization: Bearer {B2B_TOKEN}

Ошибки авторизации:

  • 503 Service Unavailable — B2B‑API выключен (b2b_enabled = false);
  • 500 Internal Server Error — токен не настроен;
  • 401 Unauthorized — токен не передан или неверен.

1. Список офисов (точек выдачи)

POST /api/b2b/get-pick-up-points

Назначение: вернуть список точек выдачи, которые может использовать партнёр.

Запрос:

  • Тело может быть пустым.
  • Обязателен только заголовок Authorization.

Ответ:

json
{
  "result": true,
  "message": "OK",
  "pick_up_points": [
    {
      "id": 1,
      "caption": "Основной магазин",
      "country": null,
      "region": null,
      "city": null,
      "address": "г. Москва, ул. Примерная, д. 1",
      "phone": "+7 (900) 000-00-00",
      "email": "info@example.com",
      "description": "Основная точка выдачи",
      "timetable": "Пн‑Пт 9:00–18:00"
    }
  ]
}

Поля заполняются из модели PickUpPoint (name, description, address, phone, email, schedule).

Пример запроса (curl):

bash
curl -X POST "https://example.com/api/b2b/get-offices" \
  -H "Authorization: Bearer YOUR_B2B_TOKEN"

2. Получение брендов по артикулу

POST /api/b2b/get-brands

Назначение: найти все пары «бренд + артикул» по указанному артикулу на нескольких складах.

Тело запроса:

json
{
  "article": "OC247",
  "pick_up_points": [1, 2]
}
  • articleобязательный, строка (артикул).
  • pick_up_points — необязательный массив ID офисов:
    • если не указан, используются склады из GeneralSettings::storages_for_crosses;
    • если указан — берутся только склады, привязанные к заданным офисам.

Ответ:

json
{
  "result": true,
  "message": "OK",
  "brands": [
    {
      "brand": "KNECHT/MAHLE",
      "article": "OC247",
      "name": "Фильтр масляный",
      "storages": [
        { "storage_id": 10, "storage_name": "Склад 1" },
        { "storage_id": 11, "storage_name": "Склад 2" }
      ]
    }
  ]
}

Особенности реализации:

  • По каждому складу вызывается адаптер (AdapterManager::getAdapter) и его метод getBrands(article).
  • Результаты фильтруются:
    • по точному совпадению нормализованного артикула (функция normalizeArticle);
    • пары без названия (name пустое или "-") отбрасываются.
  • Названия брендов нормализуются через BrandNormalizer, чтобы синонимы объединялись.
  • Пары с одинаковыми brand + article агрегируются: в storages записываются все склады, где пара найдена.

Пример запроса (curl):

bash
curl -X POST "https://example.com/api/b2b/get-brands" \
  -H "Authorization: Bearer YOUR_B2B_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "article": "OC247",
    "pick_up_points": [1, 2]
  }'

3. Получение остатков по бренду и артикулу

POST /api/b2b/get-parts

Назначение: вернуть список предложений (остатков) по выбранным брендам и артикулу с разных складов.

Тело запроса:

json
{
  "article": "OC247",
  "brands": ["KNECHT/MAHLE", "MANN-FILTER"],
  "pick_up_points": [1, 2]
}
  • articleобязательный, строка.
  • brandsобязательный массив строк — названия брендов (как в ответе get-brands).
  • pick_up_points — необязательный массив ID офисов (логика такая же, как в get-brands).

Ответ:

json
{
  "result": true,
  "message": "OK",
  "parts": [
    {
      "brand": "KNECHT/MAHLE",
      "article": "OC247",
      "name": "Фильтр масляный",
      "quantity": 5,
      "price": 950.0,
      "delivery_days": 1,
      "storage_id": 10,
      "storage_name": "Склад 1"
    },
    {
      "brand": "KNECHT/MAHLE",
      "article": "OC247",
      "name": "Фильтр масляный",
      "quantity": 3,
      "price": 930.0,
      "delivery_days": 2,
      "storage_id": 11,
      "storage_name": "Склад 2"
    }
  ]
}

Особенности реализации:

  • Выбор складов — так же, как в get-brands (по storages_for_crosses и, опционально, по офисам).
  • Для каждого склада:
    • поднимается адаптер и вызывается его метод getParts(brands, article);
    • из списка позиций берутся только те, у которых quantity > 0;
    • для каждой позиции формируется минимальный набор полей:
      • brand, article, name,
      • quantity (int),
      • price (float, если доступна),
      • delivery_days (если вернул адаптер),
      • storage_id, storage_name.
  • Закупочные цены, наценки и внутренний payload адаптеров в B2B‑ответ не попадают.

Пример запроса (curl):

bash
curl -X POST "https://example.com/api/b2b/get-products" \
  -H "Authorization: Bearer YOUR_B2B_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "article": "OC247",
    "brands": ["KNECHT/MAHLE", "MANN-FILTER"],
    "pick_up_points": [1, 2]
  }'

Типичный сценарий работы для партнёра

  1. Забрать список офисов

    • Вызвать POST /api/b2b/get-pick-up-points.
    • Сохранить список точек выдачи и их ID.
  2. Поиск брендов по артикулу

    • Вызвать POST /api/b2b/get-brands с полями article и (опционально) pick_up_points.
    • Показать пользователю список брендов, полученный в поле brands.
  3. Получение остатков по выбранным брендам

    • Пользователь выбирает один или несколько брендов.
    • Вызывается POST /api/b2b/get-parts с article, brands и (опционально) pick_up_points.
    • Клиентский код отображает полученные предложения, может сортировать по цене/сроку/складу.

4. Загрузка прайс-листа (upload-price-list)

POST /api/b2b/upload-price-list

Назначение: обновить один из сконфигурированных прайс-листов на сайте, передав файл (CSV/Excel/архив) напрямую из внешней учётной системы.

Особенности метода:

  • авторизация выполняется по B2B-токену (Bearer);
  • формат ответа унифицирован с остальными B2B-методами.

Тело запроса (multipart/form-data)

Аргументы:

  • id (integer, required) — ID прайс-листа в системе сайта (из справочника price_lists).
    Это тот же ID, который вы настраиваете в админке при конфигурации прайса.
  • document (file, required) — файл прайс-листа:
    • поддерживаются те же форматы, что и при ручной загрузке в админке (CSV, TXT, XLS/XLSX, ZIP/RAR с одним файлом внутри и т.п.);
    • максимальный размер файла ограничен настройкой price-lists.import.max_file_size.
  • tech_key (string, optional) — зарезервировано под будущее; сейчас авторизация выполняется через заголовок Authorization.

Ответ

json
{
  "result": true,
  "message": "Price list upload scheduled for import.",
  "task_id": 123
}
  • result — булевый флаг успеха;
  • message — текстовое сообщение;
  • task_id — ID задачи импорта (price_list_import_tasks.id), по которому можно отслеживать статус.

Примеры ошибок:

json
{
  "result": false,
  "message": "Price list is not active."
}
json
{
  "result": false,
  "message": "Uploaded file is not valid."
}
json
{
  "result": false,
  "message": "Failed to store uploaded file."
}

HTTP-коды:

  • 200 — запрос принят, задача импорта создана;
  • 400 — проблема с данными (неактивный прайс-лист, невалидный файл и т.п.);
  • 500 — внутренняя ошибка при сохранении файла.

Пример запроса (curl)

bash
curl -X POST "https://example.com/api/b2b/upload-price-list" \
  -H "Authorization: Bearer YOUR_B2B_TOKEN" \
  -F "id=1" \
  -F "document=@/path/to/your/pricelist.csv"

5. Получение статуса импорта прайс-листа

POST /api/b2b/get-price-list-status

Назначение: по task_id узнать текущий статус задачи импорта прайс-листа, созданной методом upload-price-list.

Тело запроса

json
{
  "task_id": 123
}
  • task_idобязательный, целое число, идентификатор задачи импорта (price_list_import_tasks.id), который вернул метод upload-price-list.

Ответ (успешный)

json
{
  "result": true,
  "message": "OK",
  "task": {
    "id": 123,
    "price_list_id": 1,
    "status": "completed",
    "status_label": "Завершено",
    "source_type": "manual",
    "total_rows": 1500,
    "processed_rows": 1500,
    "imported_rows": 1450,
    "skipped_rows": 50,
    "error_message": null,
    "started_at": "2026-02-10T10:15:23+03:00",
    "completed_at": "2026-02-10T10:16:02+03:00"
  }
}

Поля:

  • status — машинное значение статуса:
    • pending — в очереди;
    • processing — в работе;
    • completed — завершено;
    • failed — ошибка.
  • status_label — человекочитаемый статус (по текущей локали админки).
  • source_type — способ загрузки:
    • manual, email, ftp, url.
  • total_rows, processed_rows, imported_rows, skipped_rows — счётчики строк.
  • error_message — текст ошибки, если статус failed.
  • started_at, completed_at — время старта/завершения задачи в формате ISO 8601 (или null, если ещё не установлены).

Примеры ошибок:

json
{
  "message": "The given data was invalid.",
  "errors": {
    "task_id": [
      "The selected task_id is invalid."
    ]
  }
}

HTTP-коды:

  • 200 — запрос успешен, информация о задаче возвращена;
  • 422 — ошибка валидации параметров (например, task_id не передан или неверного типа).

Пример запроса (curl)

bash
curl -X POST "https://example.com/api/b2b/get-price-list-status" \
  -H "Authorization: Bearer YOUR_B2B_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "task_id": 123
  }'

База знаний для EMS-платформы PlatParts.