Initial commit
This commit is contained in:
@@ -0,0 +1,298 @@
|
||||
# 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)]]
|
||||
Reference in New Issue
Block a user