Разработка JSON API для 1С-Битрикс
JSON API — это не просто «эндпоинты, которые возвращают JSON». Это спецификация (jsonapi.org), определяющая структуру запросов и ответов: формат данных, пагинация, фильтрация, сортировка, включение связанных ресурсов, обработка ошибок. Строгий контракт означает, что клиент, знающий спецификацию, работает с любым совместимым API без дополнительной документации. Но даже если вы не следуете спецификации дословно — принципы JSON API применимы к любому REST API на Битрикс.
Архитектура JSON API на Битрикс
Чистая PHP-реализация поверх ядра Битрикс. Точка входа — контроллер, расположенный вне компонентной системы:
/local/
api/
v1/
router.php — маршрутизация запросов
middleware/
AuthMiddleware.php
RateLimitMiddleware.php
resources/
ProductResource.php — трансформер данных
OrderResource.php
controllers/
ProductController.php
OrderController.php
В router.php определяются маршруты:
$router->get('/v1/products', [ProductController::class, 'index']);
$router->get('/v1/products/{id}', [ProductController::class, 'show']);
$router->post('/v1/orders', [OrderController::class, 'create']);
$router->patch('/v1/orders/{id}', [OrderController::class, 'update']);
Ресурсы и трансформация данных
Resource-класс преобразует сырые данные Битрикс в JSON-структуру. Это изолирует клиентов от внутренних изменений модели данных:
class ProductResource
{
public static function make(array $product, array $include = []): array
{
$data = [
'id' => (int)$product['ID'],
'type' => 'products',
'attributes' => [
'name' => $product['NAME'],
'code' => $product['CODE'],
'description' => $product['DETAIL_TEXT'],
'active' => $product['ACTIVE'] === 'Y',
'created_at' => $product['DATE_CREATE'],
],
'relationships' => [],
];
if (in_array('prices', $include)) {
$data['relationships']['prices'] = PriceResource::collection(
PriceRepository::getForProduct((int)$product['ID'])
);
}
if (in_array('sku', $include)) {
$data['relationships']['sku'] = SkuResource::collection(
SkuRepository::getForProduct((int)$product['ID'])
);
}
return $data;
}
}
Параметр ?include=prices,sku в запросе управляет включением связанных данных — клиент получает ровно то, что ему нужно.
Список товаров: фильтрация, сортировка, пагинация
Все три механизма реализуются через query-параметры:
Фильтрация: ?filter[active]=true&filter[section_id]=45
$filter = ['IBLOCK_ID' => CATALOG_IBLOCK_ID, 'ACTIVE' => 'Y'];
if (isset($_GET['filter']['section_id'])) {
$filter['SECTION_ID'] = (int)$_GET['filter']['section_id'];
}
Сортировка: ?sort=-price,name (минус = DESC)
$sort = [];
foreach (explode(',', $_GET['sort'] ?? 'id') as $field) {
$direction = str_starts_with($field, '-') ? 'DESC' : 'ASC';
$sort[ltrim($field, '-')] = $direction;
}
Пагинация (offset-based): ?page[number]=2&page[size]=20
$limit = (int)($_GET['page']['size'] ?? 20);
$offset = ((int)($_GET['page']['number'] ?? 1) - 1) * $limit;
Ответ включает метаданные:
{
"data": [...],
"meta": {
"total": 1543,
"page": 2,
"per_page": 20,
"last_page": 78
},
"links": {
"self": "/v1/products?page[number]=2",
"next": "/v1/products?page[number]=3",
"prev": "/v1/products?page[number]=1"
}
}
Создание заказа
POST /v1/orders с телом запроса:
{
"data": {
"type": "orders",
"attributes": {
"delivery_address": "Москва, ул. Пушкина, 1",
"payment_method": "card"
},
"relationships": {
"items": {
"data": [
{ "type": "order-items", "product_id": 123, "quantity": 2 },
{ "type": "order-items", "product_id": 456, "quantity": 1 }
]
}
}
}
}
Контроллер валидирует данные и вызывает \Bitrix\Sale\Order::create() через D7-API модуля sale. При ошибке валидации — ответ 422 Unprocessable Entity со структурированным списком ошибок.
Авторизация
Сессия Битрикс. Для запросов из браузерных приложений, где пользователь залогинен на сайте. Проверяем \CUser::IsAuthorized().
Bearer-токен (JWT). Для мобильных клиентов и server-to-server. Middleware декодирует JWT, получает user_id, инициализирует сессию Битрикс:
$userId = $jwt->getClaim('sub');
\CUser::SetCurrent($userId); // Устанавливаем текущего пользователя Битрикс
После этого все штатные проверки прав Битрикс работают корректно.
API Key. Для интеграций B2B-партнёров. Ключ передаётся в заголовке X-API-Key, ключ привязан к пользователю или группе пользователей в Битрикс.
Валидация входных данных
Перед передачей данных в модули Битрикс — строгая валидация. Каждый эндпоинт имеет Request-класс с правилами:
class CreateOrderRequest
{
public function validate(array $data): array
{
$errors = [];
if (empty($data['delivery_address'])) {
$errors[] = ['pointer' => '/data/attributes/delivery_address', 'detail' => 'Обязательное поле'];
}
if (!in_array($data['payment_method'] ?? '', ['card', 'cash', 'invoice'])) {
$errors[] = ['pointer' => '/data/attributes/payment_method', 'detail' => 'Недопустимое значение'];
}
return $errors;
}
}
Ошибки возвращаются в формате JSON API Errors:
{
"errors": [
{
"status": "422",
"source": { "pointer": "/data/attributes/delivery_address" },
"title": "Ошибка валидации",
"detail": "Обязательное поле"
}
]
}
Кеширование ответов
Для GET-запросов настраиваем HTTP-кеш через заголовки:
// Для каталога — 10 минут в браузере, 1 час на CDN
header('Cache-Control: public, max-age=600, s-maxage=3600');
header('ETag: "' . md5($cacheKey . $dataHash) . '"');
На стороне Битрикс — тегированный кеш для агрегированных данных. При обновлении товара из 1С-обмена тег инвалидируется и следующий запрос вытягивает актуальные данные из БД.
Этапы разработки
| Этап | Содержание | Срок |
|---|---|---|
| Проектирование | Ресурсы, эндпоинты, формат данных | 1 неделя |
| Инфраструктура | Роутер, middleware, авторизация | 1 неделя |
| Ресурсы каталога | Products, SKU, цены, остатки, секции | 1–2 недели |
| Коммерческие операции | Корзина, заказы, оплата | 1–2 недели |
| Пользовательские эндпоинты | Авторизация, профиль, история заказов | 1 неделя |
| Кеширование | HTTP-заголовки, Redis, тегированный кеш | 1 неделя |
| Документация | OpenAPI, Postman-коллекция | 3–5 дней |
| Тестирование | Интеграционные тесты, нагрузка | 1 неделя |
JSON API на Битрикс — это строгий, предсказуемый контракт, который живёт независимо от версий компонентов и шаблонов. При правильной реализации фронтенд-команда работает с API как с независимым сервисом и не зависит от особенностей Битрикс.







