Files
obsidian/Магазин обуви (apelsincom)/REST API — методы и примеры (richcode.api).md
T
2026-07-06 13:05:56 +03:00

299 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# REST API — методы и примеры (richcode.api)
Полный справочник действий модуля `richcode.api` и примеры запросов. Составлено по исходникам контроллеров (`bitrix/modules/richcode.api/lib/*/controllers/*.php`) и ядра модуля (`lib/core/`). Обзор и настройки — в [[REST API (richcode.api)]].
## Содержание
- URL-схема
- Авторизация и фильтры
- Формат ответа
- Справочник действий (по контроллерам)
- Примеры запросов
- Точные схемы (проверено по моделям)
## URL-схема
```
/{apiPath}/{module}/{token}/{controller}/{action}
```
- `apiPath` — базовый путь, по умолчанию `api` (модуль срабатывает, если первый сегмент URL равен ему — из `Init::checkPathApi`).
- `module` / `controller` — из карты в `lib/core/Init.php`: `iblock/element`, `sale/product|order|store|discount|measure`, `main/user`, `crm/deal`.
- `token` — сегмент URL с токеном (если включена авторизация).
- `action`**оставшиеся сегменты пути после контроллера, склеенные точкой**. Поэтому `.../element/section/add` → действие `section.add`, `.../order/status/set``status.set`.
- Параметры: для GET — query-строка; для POST/PUT/DELETE — тело JSON (`Content-Type: application/json`) или form-data.
## Авторизация и фильтры
Проверки идут по порядку (`Init::checkFilters`): **токен → только HTTPS → IP-список → группа пользователя**. Любая непройденная — ответ `403`.
- Токен берётся из **сегмента URL** и ищется в поле пользователя **`UF_API_TOKEN`** (`Tokens::checkToken`). Запрос выполняется **от имени этого пользователя** — его правами и ограничен.
- Пользователь-владелец токена должен состоять в группе, заданной в настройках модуля (`Config::getGroupId()`).
- Формат токена: `xxxxxxxx-xxxxxxxx-xxxxxxxx-xxxxxxxx` (например `b2b23c2b-8df82f85-256913d3-ff261962`), генерируется в настройках модуля.
> [!warning] Расхождения, которые собьют с толку
> - В подсказке настроек модуля поле названо `UF_RESTFUL_API_TOKEN`, но в коде используется **`UF_API_TOKEN`**. Верно то, что в коде.
> - Та же подсказка предлагает передавать токен заголовком `Authorization-Token`, но рабочий код (`Route`+`Init`) читает токен **из сегмента URL**, а не из заголовка. Заголовок лишь разрешён в CORS. Используйте токен в URL.
> - Токен в URL попадёт в логи веб-сервера и в собственный лог модуля (HL-блок). Это чувствительно — см. [[Информационная безопасность (apelsincom)]].
## Формат ответа
Всегда JSON `{"status", "result"}` (из `lib/core/Response.php`):
- Успех — HTTP 200: `{"status":200,"result": <данные>}`.
- Бизнес-ошибка — HTTP 400: `{"status":400,"result":{"type":"error","message":"..."}}`.
- Отказ фильтра (нет токена / не HTTPS / чужой IP / не та группа) — HTTP 403: `{"status":403,"result":{"type":"error","message":"Forgbiden"}}` (опечатка в исходнике сохранена как есть).
## Справочник действий
### iblock / element (и sale / product — те же действия, но по товарам каталога)
| Действие (URL) | Параметры | Что делает |
|---|---|---|
| `add` | поля элемента | создать элемент, вернуть ID |
| `update` | `ID` + поля | обновить элемент |
| `delete` | `ID` | удалить |
| `get` | `ID` | элемент по ID |
| `list` | фильтр/выборка | список элементов |
| `fields` | — | доступные поля элемента |
| `property.list` | (`IBLOCK_ID`) | список свойств инфоблока |
| `property.get` | `ID` | свойство по ID |
| `property.enumeration.fields` | параметры свойства | значения списочного свойства |
| `property.add` / `property.update` | поля свойства | создать/изменить свойство |
| `property.enumeration.add` / `.update` | поля | значения списочного свойства |
| `property.add.group` / `property.update.group` / `property.enumeration.add.group` / `property.enumeration.update.group` | `fields[]` | групповые операции |
| `section.add` / `section.update` | поля раздела | создать/изменить раздел |
| `section.update.group` | `fields[]` | групповое изменение разделов |
| `section.list` | фильтр | список разделов |
| `section.get` | `ID` | раздел по ID |
| `section.property.list` | `IBLOCK_ID` | свойства раздела |
| `section.property.enumeration.fields` | — | значения свойств раздела |
| `update.group` | `fields[]` | групповое обновление элементов |
| `file.add` | файл | добавить файл |
| `measure.ratio.update` | параметры | коэффициент единицы измерения |
| `store.amount.get` / `store.amount.set` | параметры остатков | остатки товара по складам |
### sale / order
| Действие | Параметры | Что делает |
|---|---|---|
| `create` | поля заказа | создать заказ, вернуть ID |
| `get` | `ORDER_ID` | заказ по ID |
| `list` | фильтр | список заказов |
| `fields` | — | поля заказа |
| `basket` | `ORDER_ID` | состав корзины заказа |
| `status.list` | — | список статусов заказа |
| `status.set` | `ORDER_ID`, `STATUS_ID` | сменить статус |
| `cancel` / `uncancel` | `ORDER_ID` | отмена / снятие отмены |
| `payed` / `unpayed` | `ORDER_ID` | отметить оплаченным / нет |
| `delivery.status.list` | — | статусы доставки |
| `delivery.status.set` | `ORDER_ID`, `STATUS_ID` | статус доставки |
| `delivery.accept` / `delivery.decline` | `ORDER_ID` | принять / отклонить доставку |
| `shipment.accept` / `shipment.decline` | `ORDER_ID` | отгрузка |
| `payer.list` | — | типы плательщиков |
| `property.list` / `property.enum` | — | свойства заказа |
| `payment.list` / `delivery.list` | — | доступные оплаты / доставки |
### sale / store
| Действие | Параметры | Что делает |
|---|---|---|
| `add` | `fields` | создать склад |
| `update` | `fields` | изменить склад |
| `set.amount` | `PRODUCT_ID`, `STORE_ID`, кол-во | задать остаток |
| `set.amount.group` | `fields[]` | групповые остатки |
| `list` | — | список складов |
### sale / measure, sale / discount, main / user, crm / deal
| Контроллер | Действия |
|---|---|
| `sale/measure` | `add`, `update` (`fields.ID`), `delete` (`ID`), `list` |
| `sale/discount` | `add`, `update`, `delete` (`ID`), `list` |
| `main/user` | `list`, `add`, `update`, `delete` (`ID`), `fields` |
| `crm/deal` | `productrows.set` (задать товарные позиции сделки) |
## Примеры запросов
Ниже `https://<домен>` = адрес сайта, `<TOKEN>` = токен из `UF_API_TOKEN`, `apiPath` = `api`. Reads — через GET, writes — через POST (роутер разбирает параметры и там, и там; метод влияет только на способ передачи данных).
> [!warning] Каталог vs обычный инфоблок — разные контроллеры
> Проверено по моделям: **`iblock/element` работает только с НЕ-каталожными инфоблоками**, а для товаров и разделов **каталога (инфоблок 2) нужен `sale/product`** (те же действия). Перепутаете — получите ошибку «Инфоблок с указанным ID не найден». Поэтому примеры для каталога ниже — на `sale/product`. И у `add`/`update`/`section.*` тело обёрнуто в ключ **`fields`** (у `order/create` — нет). Полные схемы — в разделе «Точные схемы».
**Доступные поля элемента:**
```bash
curl "https://<домен>/api/iblock/<TOKEN>/element/fields"
```
**Получить товар каталога по ID:**
```bash
curl "https://<домен>/api/sale/<TOKEN>/product/get?ID=123"
# → {"status":200,"result":{ ...поля товара... }}
```
**Список товаров каталога:**
```bash
curl "https://<домен>/api/sale/<TOKEN>/product/list?filter[IBLOCK_ID]=2"
```
**Создать товар каталога (инфоблок 2):**
```bash
curl -X POST "https://<домен>/api/sale/<TOKEN>/product/add" \
-H "Content-Type: application/json" \
-d '{"fields":{
"IBLOCK_ID": 2,
"NAME": "Кроссовки Модель X",
"CODE": "krossovki-model-x",
"ACTIVE": "Y",
"PRICE": 4990,
"CURRENCY": "RUB",
"QUANTITY": 10,
"PROPERTY_ARTNUMBER": "ART-001"
}}'
# → {"status":200,"result": <новый ID>}
```
**Создать элемент обычного (не каталог) инфоблока:**
```bash
curl -X POST "https://<домен>/api/iblock/<TOKEN>/element/add" \
-H "Content-Type: application/json" \
-d '{"fields":{"IBLOCK_ID":5,"NAME":"Новость","CODE":"novost","ACTIVE":"Y","PROPERTY_AUTHOR":"Редакция"}}'
```
**Обновить товар:**
```bash
curl -X POST "https://<домен>/api/sale/<TOKEN>/product/update" \
-H "Content-Type: application/json" \
-d '{"fields":{"ID": 123, "NAME": "Новое название", "PRICE": 5490}}'
```
**Удалить товар:**
```bash
curl -X POST "https://<домен>/api/sale/<TOKEN>/product/delete" \
-H "Content-Type: application/json" -d '{"ID": 123}'
```
**Разделы каталога:**
```bash
# список разделов
curl "https://<домен>/api/sale/<TOKEN>/product/section/list?filter[IBLOCK_ID]=2"
# создать раздел
curl -X POST "https://<домен>/api/sale/<TOKEN>/product/section/add" \
-H "Content-Type: application/json" \
-d '{"fields":{"IBLOCK_ID":2,"NAME":"Мужская обувь","CODE":"muzhskaya-obuv","ACTIVE":"Y"}}'
```
**Остатки на складе:**
```bash
curl -X POST "https://<домен>/api/sale/<TOKEN>/store/set/amount" \
-H "Content-Type: application/json" \
-d '{"PRODUCT_ID":123,"STORE_ID":1,"AMOUNT":10}'
```
**Заказы:**
```bash
# получить заказ
curl "https://<домен>/api/sale/<TOKEN>/order/get?ORDER_ID=1001"
# список заказов
curl "https://<домен>/api/sale/<TOKEN>/order/list"
# создать заказ (полная схема — в разделе «Точные схемы»)
curl -X POST "https://<домен>/api/sale/<TOKEN>/order/create" \
-H "Content-Type: application/json" \
-d '{"PERSON_TYPE_ID":1,"DELIVERY_ID":1,"PAYSYSTEM_ID":1,
"ITEMS":[{"PRODUCT_ID":412,"QUANTITY":1}],
"PROPERTIES":[{"ID":1,"VALUE":"Иван"}]}'
# сменить статус
curl -X POST "https://<домен>/api/sale/<TOKEN>/order/status/set" \
-H "Content-Type: application/json" -d '{"ORDER_ID":1001,"STATUS_ID":"F"}'
# отметить оплаченным
curl -X POST "https://<домен>/api/sale/<TOKEN>/order/payed" \
-H "Content-Type: application/json" -d '{"ORDER_ID":1001}'
```
**Пользователь:**
```bash
curl -X POST "https://<домен>/api/main/<TOKEN>/user/add" \
-H "Content-Type: application/json" -d '{ ...поля пользователя... }'
```
## Точные схемы (проверено по моделям)
Схемы ниже сверены по коду моделей (`lib/…/models/…`), а не по догадкам.
### Правило: каталог vs обычный инфоблок
- `iblock/element/*` — только **не-каталожные** инфоблоки (`add`, `list`, `get`, `section.*` внутренне исключают каталоги).
- `sale/product/*` — только **каталог** (инфоблок 2); те же действия, но модель работает с ценой, остатком и товарными полями.
- У `add` / `update` / `section.add` / `section.update` тело обёрнуто в ключ **`fields`** (плоская карта). Свойства элемента — с префиксом `PROPERTY_<КОД>`, поля раздела — `UF_<КОД>`.
### element/add — элемент обычного инфоблока
`POST /api/iblock/<TOKEN>/element/add`
```json
{ "fields": {
"IBLOCK_ID": 5,
"NAME": "Заголовок",
"CODE": "zagolovok",
"ACTIVE": "Y",
"SORT": 100,
"PREVIEW_TEXT": "…",
"DETAIL_TEXT": "…",
"IBLOCK_SECTION_ID": 12,
"PROPERTY_AUTHOR": "Редакция"
} }
```
Стандартные поля (`getAvailableElementFields`): `ID, IBLOCK_ID, IBLOCK_SECTION_ID, ACTIVE, XML_ID, DATE_ACTIVE_FROM, DATE_ACTIVE_TO, SORT, NAME, PREVIEW_PICTURE, PREVIEW_TEXT, DETAIL_PICTURE, DETAIL_TEXT, CODE`. Если `CODE` пуст, а в инфоблоке включён транслит — сгенерируется из `NAME`. Возвращает ID нового элемента. Каталог (ИБ 2) метод отклонит.
### sale/product/add — товар каталога (инфоблок 2)
`POST /api/sale/<TOKEN>/product/add`
```json
{ "fields": {
"IBLOCK_ID": 2,
"NAME": "Кроссовки Модель X",
"CODE": "krossovki-model-x",
"ACTIVE": "Y",
"IBLOCK_SECTION_ID": 15,
"PRICE": 4990,
"CURRENCY": "RUB",
"QUANTITY": 10,
"VAT_ID": 1,
"VAT_INCLUDED": "Y",
"MEASURE": 5,
"WEIGHT": 800,
"PROPERTY_ARTNUMBER": "ART-001",
"PROPERTY_MANUFACTURER": "Производитель"
} }
```
Помимо полей элемента поддерживаются товарные (`Product::getAvailableElementFields`): `PRICE, CURRENCY, QUANTITY, QUANTITY_RESERVED, VAT_ID, VAT_INCLUDED, MEASURE, EXTERNAL_ID, PURCHASING_PRICE, PURCHASING_CURRENCY, WIDTH, HEIGHT, LENGTH, WEIGHT`. Метод сам заводит товар в торговом каталоге и ставит базовую цену. Требует именно каталог.
### section.add — раздел
`POST /api/sale/<TOKEN>/product/section/add` (каталог) или `/api/iblock/<TOKEN>/element/section/add` (обычный ИБ)
```json
{ "fields": {
"IBLOCK_ID": 2,
"NAME": "Мужская обувь",
"CODE": "muzhskaya-obuv",
"SORT": 100,
"ACTIVE": "Y",
"IBLOCK_SECTION_ID": 0,
"UF_SHOW_IN_MENU": 1
} }
```
Поля раздела: `ID, IBLOCK_SECTION_ID, IBLOCK_ID, NAME, CODE, SORT, ACTIVE` + пользовательские `UF_*` (например `UF_SHOW_IN_MENU`, см. [[Инфоблоки и каталог (apelsincom)]]).
### order/create — заказ
`POST /api/sale/<TOKEN>/order/create` (**без** обёртки `fields`). Заказ создаётся на пользователя токена.
```json
{
"PERSON_TYPE_ID": 1,
"DELIVERY_ID": 1,
"PAYSYSTEM_ID": 1,
"ITEMS": [
{ "PRODUCT_ID": 412, "QUANTITY": 1 },
{ "PRODUCT_ID": 413, "QUANTITY": 4 }
],
"PROPERTIES": [
{ "ID": 1, "VALUE": "Иван" },
{ "ID": 5, "VALUE": ["Опция А", "Опция Б"] }
]
}
```
- `ITEMS[].PRODUCT_ID` — ID товара/предложения каталога, `QUANTITY` — количество. Корзина строится через провайдер `catalog`, валюта — базовая.
- `PROPERTIES[].ID` — ID свойства заказа (значения списков — из `order/property.list`), `VALUE` может быть массивом для множественных.
- `DELIVERY_ID` / `PAYSYSTEM_ID` — из `order/delivery.list` и `order/payment.list`; `PERSON_TYPE_ID` — из `order/payer.list`.
- Возвращает ID созданного заказа; при ошибке — 400 с текстом от `sale`.
### Остальные схемы — сверять в моделях
Для `store/set.amount`, `user/add`, `measure/*`, `discount/*` и свойств (`property.*`) точный формат — в `lib/sale/models/Store.php`, `Product/DmlStore.php`, `lib/main/models/User.php`, `lib/iblock/models/Element/DmlProperty.php`. Быстро узнать поля вживую: `…/product/fields`, `…/order/fields`, `…/user/fields`, `…/product/property/list?filter[IBLOCK_ID]=2`.
## См. также
- [[REST API (richcode.api)]]
- [[Сценарии. Товары и разделы]]
- [[Информационная безопасность (apelsincom)]]