Практика: проектируем API для интернет-магазина
Собираем всё что изучили в курсе в одном реальном примере. Спроектируем REST API для интернет-магазина с нуля, от списка ресурсов до полной таблицы эндпоинтов.
Шаг 1: Определяем ресурсы
Интернет-магазин работает с:
| Ресурс | Описание |
|---|---|
users |
Покупатели и администраторы |
products |
Товары |
categories |
Категории товаров |
cart |
Корзина пользователя |
cart_items |
Позиции в корзине |
orders |
Заказы |
order_items |
Позиции заказа |
addresses |
Адреса доставки |
reviews |
Отзывы на товары |
Шаг 2: Полная таблица эндпоинтов
Аутентификация
| Метод | URL | Описание | Доступ |
|---|---|---|---|
| POST | /v1/auth/register | Регистрация | Публичный |
| POST | /v1/auth/login | Вход | Публичный |
| POST | /v1/auth/logout | Выход | Авторизован |
| POST | /v1/auth/refresh | Обновить токен | Авторизован |
Пользователи
| Метод | URL | Описание | Доступ |
|---|---|---|---|
| GET | /v1/users/me | Мой профиль | Авторизован |
| PATCH | /v1/users/me | Обновить профиль | Авторизован |
| GET | /v1/users | Список пользователей | Admin |
| GET | /v1/users/:id | Пользователь по ID | Admin |
| DELETE | /v1/users/:id | Удалить пользователя | Admin |
Товары
| Метод | URL | Описание | Доступ |
|---|---|---|---|
| GET | /v1/products | Список товаров | Публичный |
| GET | /v1/products/:id | Товар по ID | Публичный |
| POST | /v1/products | Создать товар | Admin |
| PATCH | /v1/products/:id | Обновить товар | Admin |
| DELETE | /v1/products/:id | Удалить товар | Admin |
| GET | /v1/categories/:id/products | Товары категории | Публичный |
Корзина
| Метод | URL | Описание | Доступ |
|---|---|---|---|
| GET | /v1/cart | Моя корзина | Авторизован |
| POST | /v1/cart/items | Добавить в корзину | Авторизован |
| PATCH | /v1/cart/items/:id | Изменить количество | Авторизован |
| DELETE | /v1/cart/items/:id | Удалить из корзины | Авторизован |
| DELETE | /v1/cart | Очистить корзину | Авторизован |
Заказы
| Метод | URL | Описание | Доступ |
|---|---|---|---|
| POST | /v1/orders | Оформить заказ | Авторизован |
| GET | /v1/orders | Мои заказы | Авторизован |
| GET | /v1/orders/:id | Заказ по ID | Авторизован |
| POST | /v1/orders/:id/cancel | Отменить заказ | Авторизован |
| GET | /v1/admin/orders | Все заказы | Admin |
| PATCH | /v1/admin/orders/:id/status | Изменить статус | Admin |
Шаг 3: Структуры данных
Товар
GET /v1/products/42
{
"id": 42,
"name": "Ноутбук Dell XPS 15",
"slug": "dell-xps-15",
"description": "15-дюймовый ноутбук с OLED дисплеем...",
"price": 149999,
"currency": "RUB",
"category": {
"id": 5,
"name": "Ноутбуки",
"slug": "laptops"
},
"images": [
{ "url": "https://cdn.example.com/products/42/main.jpg", "is_main": true },
{ "url": "https://cdn.example.com/products/42/side.jpg", "is_main": false }
],
"attributes": {
"brand": "Dell",
"processor": "Intel Core i7-12700H",
"ram_gb": 32,
"storage_gb": 1000
},
"stock": {
"quantity": 15,
"in_stock": true
},
"rating": {
"average": 4.7,
"count": 89
},
"created_at": "2024-01-15T09:00:00Z",
"updated_at": "2024-03-10T14:30:00Z"
}
Список товаров с пагинацией и фильтрами
GET /v1/products?category_id=5&min_price=50000&max_price=200000&in_stock=true&sort=-price&page=1&per_page=24
{
"data": [
{ "id": 42, "name": "Dell XPS 15", "price": 149999, "image_url": "...", "in_stock": true },
{ "id": 38, "name": "MacBook Pro 14", "price": 199999, "image_url": "...", "in_stock": true }
],
"pagination": {
"current_page": 1,
"per_page": 24,
"total": 47,
"total_pages": 2,
"has_next": true,
"has_prev": false
},
"filters_applied": {
"category_id": 5,
"min_price": 50000,
"max_price": 200000,
"in_stock": true
}
}
Корзина
GET /v1/cart
{
"id": "cart_user_123",
"items": [
{
"id": 1,
"product": {
"id": 42,
"name": "Ноутбук Dell XPS 15",
"price": 149999,
"image_url": "https://cdn.example.com/products/42/main.jpg"
},
"quantity": 1,
"subtotal": 149999
},
{
"id": 2,
"product": {
"id": 17,
"name": "Мышь Logitech MX Master",
"price": 8999,
"image_url": "..."
},
"quantity": 2,
"subtotal": 17998
}
],
"total": 167997,
"currency": "RUB",
"items_count": 3
}
Оформление заказа
POST /v1/orders
{
"address_id": 5,
"delivery_method": "courier",
"payment_method": "card",
"promo_code": "SAVE10",
"comment": "Оставьте у двери"
}
Ответ:
HTTP/1.1 201 Created
{
"id": 1047,
"number": "ORD-2024-001047",
"status": "pending",
"items": [
{
"product_id": 42,
"name": "Ноутбук Dell XPS 15",
"quantity": 1,
"price": 149999
}
],
"delivery": {
"method": "courier",
"address": {
"city": "Москва",
"street": "ул. Ленина",
"building": "42",
"apartment": "15",
"postal_code": "123456"
},
"estimated_date": "2024-03-20"
},
"payment": {
"method": "card",
"status": "pending",
"amount": 152997
},
"pricing": {
"subtotal": 167997,
"discount": 15000,
"discount_reason": "Промокод SAVE10 (-10%)",
"delivery_cost": 0,
"total": 152997
},
"created_at": "2024-03-15T10:23:00Z"
}
Шаг 4: Аутентификация и права доступа
Используем JWT с access + refresh токенами:
POST /v1/auth/login
{ "email": "user@example.com", "password": "password123" }
→ 200 OK
{
"access_token": "eyJhbGci...",
"refresh_token": "eyJhbGci...",
"expires_in": 900,
"user": {
"id": 123,
"name": "Иван Петров",
"role": "customer"
}
}
Роли: customer (покупатель) и admin.
Шаг 5: Обработка ошибок
// Товар не найден
HTTP/1.1 404 Not Found
{
"error": {
"code": "PRODUCT_NOT_FOUND",
"message": "Товар с id=999 не найден"
}
}
// Товара нет в наличии
HTTP/1.1 409 Conflict
{
"error": {
"code": "OUT_OF_STOCK",
"message": "Товар недоступен в запрошенном количестве",
"context": {
"requested": 5,
"available": 2
}
}
}
// Промокод не работает
HTTP/1.1 422 Unprocessable Entity
{
"error": {
"code": "PROMO_CODE_EXPIRED",
"message": "Срок действия промокода истёк",
"context": {
"expired_at": "2024-03-01T00:00:00Z"
}
}
}
Итоговый чеклист проекта
- ✅ Ресурсы в множественном числе, существительные
- ✅ Версия в URL
/v1/ - ✅ Правильные HTTP методы для каждой операции
- ✅ Правильные статус-коды (201 при создании, 204 при удалении)
- ✅ Пагинация для списков
- ✅ Фильтрация и сортировка через query params
- ✅ JWT аутентификация с ролями
- ✅ Понятные коды ошибок с
details - ✅ Вложенность не глубже 2 уровней
- ✅ Действия через POST (cancel, activate)
Это полноценный REST API для интернет-магазина который соответствует всем принципам изученным в курсе.