Skip to content
MiniShop3
MiniShop3
Современный компонент интернет-магазина для MODX 3
  1. Компоненты
  2. MiniShop3
  3. Разработка
  4. API Router

API Router

MiniShop3 использует библиотеку FastRoute для маршрутизации API запросов. Компонент предоставляет два отдельных API с различными механизмами авторизации.

Архитектура

Два типа API

ПараметрManager APIWeb API
Префикс/api/mgr/*/api/v1/*
НазначениеАдминистративная панель MODXФронтенд магазина
Entry pointconnector.phpassets/.../api.php
АвторизацияMODX сессии + HTTP_MODAUTHТокены MS3TOKEN
MiddlewareAuthMiddleware, PermissionMiddlewareTokenMiddleware, CorsMiddleware, RateLimitMiddleware
Файл роутовconfig/routes/manager.phpconfig/routes/web.php

Структура файлов

core/components/minishop3/
├── config/
│   ├── routes/
│   │   ├── manager.php                    # Системные роуты Manager API
│   │   └── web.php                        # Системные роуты Web API
│   └── routes_manager.custom.example.php  # Пример кастомных роутов

core/config/
├── ms3_routes_manager.custom.php          # Кастомные Manager роуты
└── ms3_routes_web.custom.php              # Кастомные Web роуты

Базовое использование

Определение роутов

php
use MiniShop3\Router\Response;

// Простой GET роут
$router->get('/api/mgr/my-endpoint', function($params) use ($modx) {
    return Response::success(['data' => 'value']);
});

// POST роут
$router->post('/api/mgr/items', function($params) use ($modx) {
    $data = json_decode(file_get_contents('php://input'), true);
    return Response::success(['created' => true]);
});

// PUT роут
$router->put('/api/mgr/items/{id}', function($params) use ($modx) {
    $id = $params['id'];
    return Response::success(['updated' => $id]);
});

// DELETE роут
$router->delete('/api/mgr/items/{id}', function($params) use ($modx) {
    return Response::success(['deleted' => true]);
});

Параметры URL

php
// Один параметр
$router->get('/api/mgr/products/{id}', function($params) use ($modx) {
    $id = $params['id'];  // Значение из URL
    return Response::success(['product_id' => $id]);
});

// Несколько параметров
$router->get('/api/mgr/orders/{order_id}/products/{product_id}', function($params) use ($modx) {
    $orderId = $params['order_id'];
    $productId = $params['product_id'];
    return Response::success([
        'order_id' => $orderId,
        'product_id' => $productId
    ]);
});

Группировка роутов

php
use MiniShop3\Router\Middleware\AuthMiddleware;
use MiniShop3\Router\Middleware\PermissionMiddleware;

$router->group('/api/mgr/catalog', function($router) use ($modx) {

    // GET /api/mgr/catalog/products
    $router->get('/products', function($params) use ($modx) {
        return Response::success(['products' => []]);
    });

    // GET /api/mgr/catalog/categories
    $router->get('/categories', function($params) use ($modx) {
        return Response::success(['categories' => []]);
    });

    // POST /api/mgr/catalog/products
    $router->post('/products', function($params) use ($modx) {
        return Response::success(['created' => true]);
    });

}, [
    // Middleware для всей группы
    new AuthMiddleware($modx, 'mgr'),
    new PermissionMiddleware($modx, 'msproduct_save')
]);

Контроллеры

Для сложной логики рекомендуется использовать контроллеры:

php
$router->group('/api/mgr/orders', function($router) use ($modx) {

    $router->get('', function($params) use ($modx) {
        $controller = new \MiniShop3\Controllers\Api\Manager\OrdersController($modx);
        return $controller->getList($params);
    });

    $router->get('/{id}', function($params) use ($modx) {
        $controller = new \MiniShop3\Controllers\Api\Manager\OrdersController($modx);
        return $controller->get($params);
    });

    $router->put('/{id}', function($params) use ($modx) {
        $body = json_decode(file_get_contents('php://input'), true) ?: [];
        $allParams = array_merge($params, $body);

        $controller = new \MiniShop3\Controllers\Api\Manager\OrdersController($modx);
        return $controller->update($allParams);
    });

});

Response

Все API endpoints возвращают JSON ответы через класс MiniShop3\Router\Response:

php
use MiniShop3\Router\Response;

// Успешный ответ
Response::success($data, $message, $statusCode);

// Ответ с ошибкой
Response::error($message, $statusCode, $errors);

Формат ответа

Успешный ответ:

json
{
  "success": true,
  "message": "Operation completed",
  "data": {
    "id": 123,
    "name": "Product"
  }
}

Ответ с ошибкой:

json
{
  "success": false,
  "message": "Validation failed",
  "errors": {
    "name": "Field is required"
  }
}

HTTP коды ответов

КодОписаниеИспользование
200OKУспешный запрос
400Bad RequestОшибка валидации
401UnauthorizedНе авторизован
403ForbiddenНет прав доступа
404Not FoundРоут или ресурс не найден
405Method Not AllowedМетод не разрешён
429Too Many RequestsПревышен лимит запросов
500Internal Server ErrorВнутренняя ошибка

Middleware

Middleware выполняются последовательно перед обработчиком роута. Если middleware возвращает Response, выполнение прерывается.

Интерфейс

php
namespace MiniShop3\Router\Middleware;

interface MiddlewareInterface
{
    /**
     * @param array $params URL параметры
     * @return Response|null Response для прерывания, null для продолжения
     */
    public function handle(array $params);
}

Встроенные middleware

AuthMiddleware

Проверяет авторизацию пользователя MODX. Для контекста mgr дополнительно проверяет токен HTTP_MODAUTH.

php
use MiniShop3\Router\Middleware\AuthMiddleware;

// Проверка авторизации в админке
$router->get('/api/mgr/secure', function($params) use ($modx) {
    return Response::success(['user' => $modx->user->get('username')]);
}, [
    new AuthMiddleware($modx, 'mgr')  // 'mgr' или 'web'
]);

Проверки:

  • Наличие авторизованного пользователя $modx->user
  • Для mgr: валидность токена HTTP_MODAUTH

PermissionMiddleware

Проверяет права доступа пользователя через $modx->hasPermission().

php
use MiniShop3\Router\Middleware\PermissionMiddleware;

$router->post('/api/mgr/products', function($params) use ($modx) {
    // Создание товара
}, [
    new PermissionMiddleware($modx, 'msproduct_save')
]);

Основные права MiniShop3:

  • msproduct_save — создание/редактирование товаров
  • mssetting_save — управление настройками
  • msorder_list — просмотр заказов
  • msorder_save — редактирование заказов

TokenMiddleware

Проверяет токен авторизации для Web API. Токен передаётся в заголовке MS3TOKEN.

php
use MiniShop3\Middleware\TokenMiddleware;

$tokenMiddleware = new TokenMiddleware($modx);

$router->group('/api/v1/cart', function($router) use ($modx) {
    // Роуты корзины
}, [$tokenMiddleware]);

Публичные роуты (не требуют токен):

  • /api/v1/cart/get
  • /api/v1/product/get
  • /api/v1/product/list
  • /api/v1/customer/token/get
  • /api/v1/health

CorsMiddleware

Настраивает CORS заголовки для кросс-доменных запросов.

php
use MiniShop3\Middleware\CorsMiddleware;

$corsMiddleware = new CorsMiddleware([
    'allowed_origins' => ['https://shop.example.com', 'https://admin.example.com'],
    'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],
    'allowed_headers' => ['Content-Type', 'Authorization', 'MS3TOKEN'],
    'allow_credentials' => true,
    'max_age' => 86400  // Кеш preflight запросов (24 часа)
]);

Системная настройка: ms3_cors_allowed_origins — список разрешённых доменов.

RateLimitMiddleware

Ограничивает количество запросов для защиты от злоупотреблений.

php
use MiniShop3\Middleware\RateLimitMiddleware;

$rateLimitMiddleware = new RateLimitMiddleware(
    60,   // Максимум 60 запросов
    60    // За 60 секунд
);

Системные настройки:

  • ms3_rate_limit_max_attempts — максимум запросов (по умолчанию: 60)
  • ms3_rate_limit_decay_seconds — период в секундах (по умолчанию: 60)

Заголовки ответа:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1703001234

Создание своего middleware

php
<?php
namespace MyComponent\Middleware;

use MiniShop3\Router\Middleware\MiddlewareInterface;
use MiniShop3\Router\Response;
use MODX\Revolution\modX;

class LoggingMiddleware implements MiddlewareInterface
{
    private modX $modx;

    public function __construct(modX $modx)
    {
        $this->modx = $modx;
    }

    public function handle(array $params)
    {
        // Логирование запроса
        $this->modx->log(
            modX::LOG_LEVEL_INFO,
            sprintf(
                '[API] %s %s from %s',
                $_SERVER['REQUEST_METHOD'],
                $_SERVER['REQUEST_URI'],
                $_SERVER['REMOTE_ADDR']
            )
        );

        // null = продолжить выполнение
        return null;
    }
}

Использование:

php
use MyComponent\Middleware\LoggingMiddleware;

$router->get('/api/mgr/logged-endpoint', function($params) use ($modx) {
    return Response::success(['logged' => true]);
}, [
    new LoggingMiddleware($modx),
    new AuthMiddleware($modx, 'mgr')
]);

Порядок выполнения middleware

Middleware выполняются в порядке указания:

php
$router->get('/api/mgr/endpoint', $handler, [
    new CorsMiddleware(),        // 1. Сначала CORS
    new RateLimitMiddleware(),   // 2. Проверка лимита
    new AuthMiddleware($modx),   // 3. Авторизация
    new PermissionMiddleware(),  // 4. Права доступа
]);

При возврате Response из middleware, остальные middleware и обработчик не выполняются.

Карта роутов

Manager API (/api/mgr/*)

Общие

МетодРоутОписание
GET/healthПроверка работоспособности API
GET/user/infoИнформация о текущем пользователе

Конфигурация (/config)

МетодРоутОписание
GET/page-fields/{page_key}Получить поля страницы
GET/page-fields/{page_key}/allВсе поля страницы
PUT/page-fields/{page_key}Обновить поля
DELETE/page-fields/{page_key}/{field_name}Удалить переопределение поля
GET/sections/{page_key}Получить секции
PUT/sections/{page_key}Обновить секции

Заказы (/orders)

МетодРоутОписаниеПраво
GET``Список заказовmsorder_list
POST``Создать заказmsorder_list
GET/filtersКонфигурация фильтровmsorder_list
GET/{id}Получить заказmsorder_list
PUT/{id}Обновить заказmsorder_list
DELETE/{id}Удалить заказmsorder_list
GET/{id}/productsТовары заказаmsorder_list
POST/{id}/productsДобавить товарmsorder_list
PUT/{id}/products/{product_id}Обновить товарmsorder_list
DELETE/{id}/products/{product_id}Удалить товарmsorder_list
GET/{id}/logsИстория измененийmsorder_list
DELETE/bulkМассовое удалениеmsorder_list

Покупатели (/customers)

МетодРоутОписаниеПраво
GET``Список покупателейview_document
GET/{id}Получить покупателяview_document
PUT/{id}Обновить покупателяview_document
DELETE/{id}Удалить покупателяview_document
GET/{id}/addressesАдреса покупателяview_document
POST/{id}/addressesДобавить адресview_document
PUT/{id}/addresses/{address_id}Обновить адресview_document
DELETE/{id}/addresses/{address_id}Удалить адресview_document

Настройки магазина

Доставки (/deliveries), Оплаты (/payments), Производители (/vendors), Статусы (/statuses), Связи (/links) — CRUD операции с правом mssetting_save.

Уведомления (/notifications)

МетодРоутОписаниеПраво
GET/referencesСправочники для формmssetting_save
GET``Список уведомленийmssetting_save
GET/{id}Получить уведомлениеmssetting_save
POST``Создать уведомлениеmssetting_save
PUT/{id}Обновитьmssetting_save
DELETE/{id}Удалитьmssetting_save

Импорт (/import)

МетодРоутОписаниеПраво
GET/fieldsПоля для маппингаmsproduct_save
POST/uploadЗагрузка CSVmsproduct_save
POST/previewПредпросмотрmsproduct_save
POST/startЗапуск импортаmsproduct_save
GET/progress/{import_id}Прогресс импортаmsproduct_save

Web API (/api/v1/*)

Корзина (/cart)

МетодРоутОписаниеТокен
GET/getПолучить корзинуОпционально
POST/addДобавить товарОбязательно
POST/changeИзменить количествоОбязательно
POST/removeУдалить товарОбязательно
POST/cleanОчистить корзинуОбязательно

Заказ (/order)

МетодРоутОписаниеТокен
GET/getПолучить заказОбязательно
POST/addДобавить данныеОбязательно
POST/setУстановить поляОбязательно
POST/submitОформить заказОбязательно
GET/costПолная стоимостьОбязательно
GET/cost/cartСтоимость товаровОбязательно
GET/cost/deliveryСтоимость доставкиОбязательно
POST/address/setУстановить адресОбязательно

Покупатель (/customer)

МетодРоутОписаниеТокен
POST/loginАвторизацияНет
POST/registerРегистрацияНет
GET/token/getПолучить токенНет
PUT/profileОбновить профильОбязательно
GET/addressesСписок адресовОбязательно
POST/addressesДобавить адресОбязательно
PUT/addresses/{id}Обновить адресОбязательно
DELETE/addresses/{id}Удалить адресОбязательно

Общие

МетодРоутОписание
GET/healthПроверка работоспособности

Кастомизация роутов

Добавление своих роутов

Создайте файл core/config/ms3_routes_manager.custom.php:

php
<?php
use MiniShop3\Router\Middleware\AuthMiddleware;
use MiniShop3\Router\Middleware\PermissionMiddleware;
use MiniShop3\Router\Response;

// Простой роут
$router->get('/api/mgr/my-custom-endpoint', function() use ($modx) {
    return Response::success(['custom' => true]);
}, [
    new AuthMiddleware($modx, 'mgr')
]);

// Группа роутов
$router->group('/api/mgr/my-module', function($router) use ($modx) {

    $router->get('/dashboard', function() use ($modx) {
        return Response::success([
            'stats' => ['orders' => 100, 'revenue' => 50000]
        ]);
    });

    $router->post('/action', function($params) use ($modx) {
        $data = json_decode(file_get_contents('php://input'), true);
        // Обработка...
        return Response::success(['processed' => true]);
    });

}, [
    new AuthMiddleware($modx, 'mgr'),
    new PermissionMiddleware($modx, 'my_module_permission')
]);

Для Web API создайте core/config/ms3_routes_web.custom.php.

Переопределение системных роутов

Кастомные роуты загружаются после системных и переопределяют их:

php
<?php
// core/config/ms3_routes_manager.custom.php

use MiniShop3\Router\Response;

// Переопределение системного роута /api/mgr/health
$router->get('/api/mgr/health', function() use ($modx) {
    return Response::success([
        'status' => 'custom_ok',
        'version' => '1.0.0-custom',
        'timestamp' => time()
    ]);
});

Интеграция со сторонними компонентами

Сторонний компонент может добавлять свои роуты через файл конфигурации:

php
<?php
// core/config/ms3_routes_manager.custom.php

use MiniShop3\Router\Response;
use MiniShop3\Router\Middleware\AuthMiddleware;

// Роуты для компонента msPromoCode
$router->group('/api/mgr/promocodes', function($router) use ($modx) {

    $router->get('', function($params) use ($modx) {
        $codes = $modx->getCollection('msPromoCode');
        $result = [];
        foreach ($codes as $code) {
            $result[] = $code->toArray();
        }
        return Response::success(['codes' => $result]);
    });

    $router->post('', function($params) use ($modx) {
        $data = json_decode(file_get_contents('php://input'), true);

        $code = $modx->newObject('msPromoCode');
        $code->fromArray($data);

        if ($code->save()) {
            return Response::success(['id' => $code->get('id')]);
        }
        return Response::error('Failed to create promo code', 400);
    });

    $router->delete('/{id}', function($params) use ($modx) {
        $code = $modx->getObject('msPromoCode', $params['id']);
        if ($code && $code->remove()) {
            return Response::success(['deleted' => true]);
        }
        return Response::error('Not found', 404);
    });

}, [
    new AuthMiddleware($modx, 'mgr')
]);

Системные настройки

НастройкаПо умолчаниюОписание
ms3_cors_allowed_origins["*"]Разрешённые домены для CORS
ms3_rate_limit_max_attempts60Лимит запросов
ms3_rate_limit_decay_seconds60Период сброса лимита (сек)

Отладка

Логирование запросов

php
$router->get('/api/mgr/debug', function($params) use ($modx) {
    $modx->log(
        \MODX\Revolution\modX::LOG_LEVEL_INFO,
        '[API Debug] ' . json_encode([
            'method' => $_SERVER['REQUEST_METHOD'],
            'uri' => $_SERVER['REQUEST_URI'],
            'params' => $params,
            'body' => file_get_contents('php://input')
        ])
    );

    return Response::success(['debug' => true]);
});

Типичные ошибки

401 Unauthorized:

  • Не авторизован в MODX
  • Отсутствует или невалидный HTTP_MODAUTH токен
  • Для Web API: отсутствует или истёк MS3TOKEN

403 Forbidden:

  • Нет права доступа (проверьте ACL пользователя)

404 Not Found:

  • Роут не зарегистрирован
  • Опечатка в URL

405 Method Not Allowed:

  • Используется неправильный HTTP метод (GET вместо POST и т.д.)

429 Too Many Requests:

  • Превышен лимит запросов, подождите Retry-After секунд