Демо-режим! Все данные только для просмотра. Изменения не сохраняются.
🏗️ Архитектура системы DEXA
Информация
Slug:
architecture.html
Обновлено:
30.05.2026 15:03
30.05.2026 15:03
Размер:
57.75 KB
57.75 KB
Путь:
/resources/docs/developer/architecture.html
Ссылки
Публичная ссылка:
Ссылка в админке:
🏗️ Архитектура системы DEXA
👨💻 Целевая аудитория: Разработчики, DevOps инженеры, Технические руководители
📊 Уровень сложности: Средний
🎯 Цель документа: Полное описание архитектуры, компонентов, связей и бизнес-логики системы обмена валют DEXA
📊 Уровень сложности: Средний
🎯 Цель документа: Полное описание архитектуры, компонентов, связей и бизнес-логики системы обмена валют DEXA
🎯 Обзор системы
DEXA - это высоконагруженная система обмена криптовалют и фиатных денег с микросервисной архитектурой. Система предназначена для автоматизации процесса обмена между клиентами и партнерами (точками обмена).
Ключевые возможности:
- Обмен криптовалют - BTC, ETH, USDT, TRX и другие
- Обмен фиатных валют - RUB, USD, EUR
- Автоматическое обновление курсов из внешних API (Binance, Rapira.net)
- Гибкая система наценок для разных типов транзакций
- Партнерская программа с индивидуальными курсами для каждой точки обмена
- Административная панель с ролевой моделью и 2FA
- API для внешних интеграций
- Автоматические уведомления по Email и Telegram
⚙️ Технологический стек
Laravel 10
PHP 8.1+
MySQL 8.0+
MariaDB 10.4+
Redis 6.0+
Nginx/Apache
Bootstrap 5
jQuery 3.6
Font Awesome 6
CKEditor 5
Chart.js
Google2FA
🏗️ Высокоуровневая архитектура
┌─────────────────────────────────────────────────────────────────────────────┐
│ КЛИЕНТСКИЙ СЛОЙ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Web │ │ Mobile │ │ Admin │ │ API │ │
│ │ Client │ │ App │ │ Panel │ │ Client │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └───────────────┴───────────────┴───────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ API Gateway │ │
│ │ (Laravel) │ │
│ └────────┬────────┘ │
└───────────────────────────────────┼─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ СЕРВИСНЫЙ СЛОЙ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Auth │ │ Exchange │ │ Rate │ │ Notification│ │
│ │ Service │ │ Service │ │ Service │ │ Service │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Partner │ │ Currency │ │ API │ │ Analytics │ │
│ │ Service │ │ Service │ │ Service │ │ Service │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ СЛОЙ ДАННЫХ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Primary │ │ Redis │ │ External │ │ File │ │
│ │ DB │ │ Cache │ │ APIs │ │ Storage │ │
│ │ (MySQL) │ │ (Session) │ │ (Binance) │ │ (Logos) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
📂 Структура директорий проекта
dexa/
├── app/
│ ├── Console/
│ │ └── Commands/
│ │ ├── CheckRatesStale.php # Проверка устаревших курсов
│ │ ├── ForceUpdateRates.php # Принудительное обновление
│ │ ├── SyncCurrenciesCommand.php # Синхронизация валют
│ │ ├── TestSmtpConnection.php # Тест SMTP
│ │ ├── UpdateExchangeRates.php # Обновление курсов
│ │ └── UpdateRatesFromConfiguredApis.php # Обновление из API (крон)
│ │
│ ├── Exports/
│ │ └── OrdersExport.php # Экспорт заявок в Excel
│ │
│ ├── Helpers/
│ │ └── ColorHelper.php # Утилиты для работы с цветами
│ │
│ ├── Http/
│ │ ├── Controllers/
│ │ │ ├── Admin/
│ │ │ │ ├── AdminController.php # Управление администраторами
│ │ │ │ ├── ApiConfigController.php # API конфигурации
│ │ │ │ ├── AuthController.php # Аутентификация админов
│ │ │ │ ├── CityController.php # Управление городами
│ │ │ │ ├── CurrencyController.php # Управление валютами
│ │ │ │ ├── DashboardController.php # Дашборд и отчеты
│ │ │ │ ├── DocumentationController.php # Управление документацией
│ │ │ │ ├── ExchangeRateController.php # Управление курсами
│ │ │ │ ├── OrderController.php # Управление заявками
│ │ │ │ ├── PageController.php # Управление страницами
│ │ │ │ ├── PartnerController.php # Управление партнерами
│ │ │ │ ├── SettingController.php # Настройки системы
│ │ │ │ ├── TwoFactorController.php # 2FA для админов
│ │ │ │ └── UserController.php # Управление пользователями
│ │ │ │
│ │ │ ├── Api/
│ │ │ │ └── ApiController.php # Публичное API
│ │ │ │
│ │ │ ├── AuthController.php # Аутентификация пользователей
│ │ │ ├── ContactController.php # Контактная форма
│ │ │ ├── ExchangeController.php # Обмен валют
│ │ │ ├── HomeController.php # Главная страница
│ │ │ ├── PageController.php # Динамические страницы
│ │ │ ├── ProfileController.php # Личный кабинет
│ │ │ └── TwoFactorController.php # 2FA для пользователей
│ │ │
│ │ └── Middleware/
│ │ ├── AdminAuthMiddleware.php # Аутентификация админа
│ │ ├── AdminTwoFactorMiddleware.php # 2FA для админа
│ │ ├── CheckAdminPermission.php # Проверка прав админа
│ │ ├── CheckEmailVerified.php # Проверка email
│ │ ├── CheckProfileAccess.php # Доступ к профилю
│ │ ├── RateLimitMiddleware.php # Ограничение запросов
│ │ ├── SetAdminSessionCookie.php # Установка админ-сессии
│ │ ├── StartAdminSession.php # Запуск админ-сессии
│ │ └── TwoFactorMiddleware.php # 2FA для пользователей
│ │
│ ├── Mail/
│ │ ├── AdminOrderCreated.php # Уведомление админу о заявке
│ │ ├── ApiStaleRatesNotification.php # Уведомление о устаревших курсах
│ │ ├── BaseMailable.php # Базовый класс для писем
│ │ ├── ContactMessage.php # Контактная форма
│ │ ├── EmailVerification.php # Подтверждение email
│ │ ├── NewExchangeOrder.php # Новая заявка на обмен
│ │ ├── OrderConfirmation.php # Подтверждение заявки
│ │ ├── OrderStatusUpdated.php # Обновление статуса
│ │ ├── OrderVerification.php # Верификация заявки
│ │ └── PasswordReset.php # Сброс пароля
│ │
│ ├── Models/
│ │ ├── Admin.php # Администратор
│ │ ├── City.php # Город
│ │ ├── Currency.php # Валюта (с настройками 6 типов)
│ │ ├── Documentation.php # Управление документацией
│ │ ├── ExchangeApi.php # API конфигурация
│ │ ├── ExchangeOrder.php # Заявка на обмен
│ │ ├── ExchangeRate.php # Курс обмена
│ │ ├── ExternalRate.php # Внешний курс
│ │ ├── Page.php # Статическая страница
│ │ ├── Partner.php # Партнер
│ │ ├── Setting.php # Настройки системы
│ │ ├── User.php # Пользователь
│ │ └── UserWallet.php # Кошелек пользователя
│ │
│ ├── Providers/
│ │ ├── AppServiceProvider.php # Регистрация команд
│ │ ├── DynamicMailConfigProvider.php # Динамическая конфигурация почты
│ │ └── ExternalRateServiceProvider.php # Регистрация сервисов
│ │
│ └── Services/
│ ├── RateCalculation/ # КАЛЬКУЛЯТОРЫ КУРСОВ (новая архитектура)
│ │ ├── RateCalculatorInterface.php # Интерфейс калькулятора
│ │ ├── RateCalculatorManager.php # Менеджер калькуляторов
│ │ ├── PartnerManualRateCalculator.php # Ручной курс партнера
│ │ ├── PartnerExternalRateCalculator.php # Внешний курс партнера
│ │ ├── GeneralManualRateCalculator.php # Ручной общий курс
│ │ ├── GeneralExternalRateCalculator.php # Внешний общий курс
│ │ └── USDTCalculationCalculator.php # Расчет через USDT
│ │
│ ├── ExchangeCalculationService.php # Основная логика расчета
│ ├── ExternalRateService.php # Обновление внешних курсов
│ ├── MailLoggerService.php # Логирование почты
│ ├── RateUpdateService.php # Обновление курсов
│ ├── TelegramService.php # Telegram уведомления
│ └── UniversalApiService.php # Универсальный API клиент
│
├── bootstrap/
│ └── app.php # Конфигурация приложения
│
├── config/
│ ├── admin_session.php # Настройки админ-сессии
│ ├── app.php # Основные настройки
│ ├── auth.php # Аутентификация (guards)
│ ├── beget.php # Настройки для Beget хостинга
│ ├── cache.php # Кэширование
│ ├── database.php # База данных
│ ├── filesystems.php # Файловая система
│ ├── google2fa.php # 2FA настройки
│ ├── logging.php # Логирование
│ ├── mail.php # Почта
│ ├── queue.php # Очереди
│ └── services.php # Сторонние сервисы
│
├── database/
│ ├── migrations/
│ │ ├── 0001_01_01_000000_create_users_table.php
│ │ ├── 0001_01_01_000001_create_cache_table.php
│ │ ├── 0001_01_01_000002_create_jobs_table.php
│ │ ├── 2026_01_18_000000_create_dexa_database.php # Основная миграция
│ │ ├── 2026_02_21_000000_add_menu_settings_to_pages_table.php
│ │ ├── 2026_03_04_000000_add_2fa_fields_to_users_table.php
│ │ └── 2026_03_05_000000_add_2fa_fields_to_admins_table.php
│ │
│ └── seeders/
│ └── DatabaseSeeder.php # Начальные данные
│
├── public/
│ ├── css/
│ │ └── exchange-common.css # Общие стили
│ ├── js/
│ │ └── exchange-common.js # Общие JS функции
│ └── index.php
│
├── resources/
│ ├── docs/ # Файлы документации
│ │ ├── user/ # Документация для пользователей
│ │ └── developer/ # Документация для разработчиков
│ │
│ └── views/ # Blade шаблоны
│ ├── admin/ # Админ-панель
│ ├── auth/ # Аутентификация
│ ├── emails/ # Email шаблоны
│ ├── errors/ # Страницы ошибок
│ ├── layouts/ # Базовые шаблоны
│ ├── pages/ # Публичные страницы
│ ├── profile/ # Личный кабинет
│ └── tracking.blade.php # Отслеживание заявок
│
├── routes/
│ ├── api.php # API маршруты
│ ├── console.php # Cron задачи
│ └── web.php # Веб-маршруты
│
└── storage/ # Логи, кэш, сессии
🏗️ Компоненты системы
Сервис аутентификации (Auth Service)
Назначение: Управление пользователями, сессиями, ролями и правами доступа.
Основные функции:
- Раздельные гарды:
web(пользователи) иadmin(администраторы) - Раздельные сессии: через отдельные таблицы
sessionsиadmin_sessions - Двухфакторная аутентификация (2FA): для пользователей и админов через Google Authenticator
- Ролевая модель (RBAC): 4 уровня доступа (superadmin, admin, manager, moderator)
- Granular permissions: детальные права на каждый модуль (view, create, edit, delete)
- Управление сессиями: отдельные cookie для админ-панели (
dexaSuperUser) - Email верификация: обязательное подтверждение email для пользователей
- Сброс пароля: через email ссылку (действительна 24 часа)
Технологии:
Laravel Session
bcrypt
Google2FA
CSRF Tokens
Custom Middleware
API endpoints:
POST /login # Вход пользователя
POST /register # Регистрация
POST /logout # Выход
POST /forgot-password # Запрос сброса пароля
POST /reset-password # Сброс пароля
GET /verify-email/{token} # Подтверждение email
GET /2fa/verify # Форма 2FA
POST /2fa/verify # Проверка 2FA кода
POST /dexaSuperUser/login # Вход админа
POST /dexaSuperUser/logout # Выход админа
GET /dexaSuperUser/2fa/verify # Форма 2FA админа
POST /dexaSuperUser/2fa/verify # Проверка 2FA кода админа
POST /register # Регистрация
POST /logout # Выход
POST /forgot-password # Запрос сброса пароля
POST /reset-password # Сброс пароля
GET /verify-email/{token} # Подтверждение email
GET /2fa/verify # Форма 2FA
POST /2fa/verify # Проверка 2FA кода
POST /dexaSuperUser/login # Вход админа
POST /dexaSuperUser/logout # Выход админа
GET /dexaSuperUser/2fa/verify # Форма 2FA админа
POST /dexaSuperUser/2fa/verify # Проверка 2FA кода админа
Сервис обмена (Exchange Service)
Назначение: Обработка операций обмена валют, расчет курсов с учетом наценок, управление заявками.
Основные функции:
- Создание заявок: клиентские и административные
- Расчет курсов: по 6 типам транзакций с учетом наценок/скидок
- Стаканы (Order Book): использование bid/ask цен из внешних API
- Система приоритетов курсов:
- Ручной курс партнера
- Внешний курс партнера
- Ручной общий курс
- Общий внешний курс
- Расчет через USDT (резерв)
- Автоматическая верификация: по email ссылке или коду
- Управление статусами: pending, confirmed, processing, completed, cancelled, rejected
- Лимиты: минимальные и максимальные суммы для каждой пары
- Комиссии: процентная комиссия (может быть отрицательной для скидки)
Архитектура калькуляторов курсов (новое):
1
RateCalculatorManager - координатор, вызывает все калькуляторы по приоритету
2
PartnerManualRateCalculator - проверяет ручные курсы партнера
3
PartnerExternalRateCalculator - проверяет внешние курсы партнера
4
GeneralManualRateCalculator - проверяет общие ручные курсы
5
GeneralExternalRateCalculator - проверяет общие внешние курсы
6
USDTCalculationCalculator - резервный расчет через USDT
Основные методы ExchangeCalculationService:
array getBestRate(int $fromCurrencyId, int $toCurrencyId, int|null $partnerId = null)
array calculateExchange(int $fromCurrencyId, int $toCurrencyId, float $amount, int|null $partnerId = null)
bool isRateStale(int $fromCurrencyId, int|null $staleThresholdMinutes = null)
array prepareFormulaInfo(Currency $fromCurrency, Currency $toCurrency, float $baseRate, float $finalRate, float $margin, string $transactionType, float $bidPrice = 0, float $askPrice = 0, string $usedStakan = '', float $manualMargin = 0, bool $useExternal = true)
Сервис курсов (Rate Service)
Назначение: Получение, обработка и хранение курсов валют из внешних API.
Архитектура получения курсов:
1
ExternalRateService::updateRatesFromApi() - запускает обновление
2
Выбирает активные API из таблицы
exchange_apis3
Для каждого API вызывает
UniversalApiService::fetchFromApi()4
UniversalApiService отправляет HTTP запрос (GET/POST) с учетом аутентификации
5
Парсит ответ согласно
field_mapping (JSON/XML/CSV)6
Форматирует пары валют согласно
pair_format7
Сохраняет в таблицу
external_rates (или обновляет существующие)8
Создает обратные курсы (reverse_rates) для всех пар
Ключевые методы ExternalRateService:
int updateRatesFromApi()
array updateRatesFromSpecificApi(ExchangeApi $api)
int updatePartnerExternalRatesFromApi(int $partnerId, ExchangeApi|null $api = null)
array checkSpecificApi(ExchangeApi $api)
int createReverseRates()
UniversalApiService - универсальный клиент:
array fetchFromApi(ExchangeApi $api, bool $testMode = false)
array testApi(ExchangeApi $api, bool $useTestData = false, bool $showAllRates = false)
array|null fetchOrderBookData(string $symbol, array|null $mapping = null, ExchangeApi|null $api = null)
Сервис уведомлений (TelegramService)
Назначение: Отправка уведомлений о важных событиях в Telegram чат администраторов.
Основные функции:
- Новые заявки: уведомление администраторов о создании заявки
- Контактная форма: уведомление о новом сообщении
- Админские заявки: уведомление о заявках, созданных через админ-панель
- Тестовые уведомления: для проверки настроек
Ключевые методы:
bool sendExchangeOrderNotification(ExchangeOrder $order)
bool sendContactFormNotification(array $data)
bool sendAdminOrderNotification(array $orderData)
array checkBotStatus()
array sendTestNotification()
Настройки в .env:
TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here
🗄️ Структура базы данных
Основные таблицы и связи:
-- =====================================================
-- ЯДРО СИСТЕМЫ (АУТЕНТИФИКАЦИЯ)
-- =====================================================
users (
id, name, email, password, phone, telegram,
role, is_active,
email_verified_at, email_verification_token, verification_sent_at,
google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)
admins (
id, name, email, password, role, permissions, is_active,
google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)
sessions (id, user_id, ip_address, user_agent, payload, last_activity)
admin_sessions (id, admin_id, ip_address, user_agent, payload, last_activity)
password_reset_tokens (email, token, created_at)
-- =====================================================
-- ВАЛЮТЫ И КУРСЫ
-- =====================================================
currencies (
id, code, name, symbol, type, icon, is_active, sort_order,
our_wallet, wallet_for_other_currencies,
-- НАСТРОЙКИ ДЛЯ USDT
usdt_to_other_crypto_margin, usdt_to_other_crypto_min_amount,
usdt_to_rub_margin, usdt_to_rub_min_amount,
-- НАСТРОЙКИ ДЛЯ RUB
rub_to_usdt_margin, rub_to_usdt_min_amount,
rub_to_other_crypto_margin, rub_to_other_crypto_min_amount,
-- НАСТРОЙКИ ДЛЯ ДРУГИХ КРИПТО
other_crypto_to_rub_margin, other_crypto_to_rub_min_amount,
other_crypto_to_other_crypto_margin, other_crypto_to_other_crypto_min_amount
)
exchange_apis (
id, name, base_url, endpoint, method,
request_format, response_format,
field_mapping (JSON), pair_format (JSON),
authentication_type, api_key (encrypted), secret_key (encrypted),
is_active, priority, timeout, retry_count,
success_count, error_count, last_success_at, last_error_at
)
external_rates (
id, partner_id, from_currency_id, to_currency_id,
external_rate, source, last_updated,
order_book_buy (JSON), order_book_sell (JSON),
bid_price, ask_price, bid_volume, ask_volume, spread,
volume_24h, change_24h
)
exchange_rates (
id, partner_id, from_currency_id, to_currency_id,
rate, external_rate_id,
use_external_rate, use_partner_external,
manual_margin_percentage,
override_margin, override_min_amount,
min_amount, max_amount,
is_active, is_hidden, priority, last_updated
)
-- =====================================================
-- ГЕОГРАФИЯ И ПАРТНЕРЫ
-- =====================================================
cities (
id, name, country, latitude, longitude, is_active, sort_order
)
partners (
id, city_id, name, address, phone, email,
latitude, longitude, working_hours, description,
accepted_currencies (JSON), api_id,
rating, total_reviews, is_active
)
-- =====================================================
-- ОПЕРАЦИИ (ЗАЯВКИ)
-- =====================================================
exchange_orders (
id, order_number, user_id,
from_currency_id, to_currency_id,
partner_id, city_id,
amount, rate, fee_percentage, fee_amount, total_receive,
full_name, email, phone, wallet_address,
status, transaction_type,
admin_notes, user_notes,
verification_code, verification_token,
verified_at, expires_at,
ip_address, user_agent
)
-- =====================================================
-- КЛИЕНТСКИЕ ДАННЫЕ
-- =====================================================
user_wallets (
id, user_id, currency_id,
wallet_address, network, wallet_name,
is_default, is_active, notes
)
-- =====================================================
-- НАСТРОЙКИ
-- =====================================================
settings (
id, key, value, type, group, options,
default_cron_api_id, default_cron_api_name,
update_interval_minutes, auto_update_enabled,
primary_api_id, fallback_api_id,
order_expire_minutes, auto_confirm_orders, require_verification,
site_timezone, date_format,
recaptcha_site_key, recaptcha_secret_key
)
pages (
id, slug, title, content,
meta_title, meta_description, meta_keywords,
is_active, is_homepage, show_in_menu,
show_logistics_in_menu, show_home_in_menu,
page_type, sort_order
)
Связи между таблицами:
- currencies → exchange_rates: одна валюта может участвовать во многих курсах (как from или to)
- currencies → external_rates: одна валюта может участвовать во многих внешних курсах
- cities → partners: один город может иметь много партнеров
- partners → exchange_rates: один партнер может иметь много индивидуальных курсов
- partners → external_rates: один партнер может иметь много своих внешних курсов
- users → exchange_orders: один пользователь может иметь много заявок
- users → user_wallets: один пользователь может иметь много кошельков
- exchange_apis → external_rates: один API может быть источником для многих курсов
- exchange_apis → partners: один API может быть назначен многим партнерам
- external_rates → exchange_rates: внешний курс может использоваться во многих курсах обмена
🔌 Интеграции и API
| Интеграция | Тип | Назначение | Статус |
|---|---|---|---|
| Binance API | REST (GET) | Получение курсов криптовалют (USDT, BTC, ETH) | ✅ Активна |
| Rapira.net API | REST (GET/POST) | Получение курсов и стаканов заявок | ✅ Активна |
| Telegram Bot API | REST | Уведомления администраторов | ✅ Активна |
| SMTP сервер | SMTP | Отправка email уведомлений | ✅ Активна (настраивается) |
🛡️ Безопасность
Многоуровневая защита:
1. Сетевой уровень:
- HTTPS с HSTS
- Защита от DDoS (Cloudflare)
- Ограничение доступа к админ-панели через middleware
2. Уровень приложения:
- CSRF защита для всех форм (кроме API)
- XSS фильтрация входных данных
- SQL injection protection через Eloquent ORM и подготовленные запросы
- Rate limiting для API endpoints (60 запросов в минуту)
- Валидация всех входных данных через Form Requests
- Раздельные сессии для пользователей и админов
- Отдельная таблица сессий для админов (
admin_sessions)
3. Уровень данных:
- Шифрование API ключей в таблице
exchange_apis(AES-256) - Хеширование паролей (bcrypt, cost 12)
- Резервное копирование базы данных (настраивается через крон)
4. Аутентификация и авторизация:
- Двухфакторная аутентификация (2FA) для пользователей и админов
- Ролевая модель (RBAC) с 4 уровнями доступа
- Granular permissions для каждого модуля (view, create, edit, delete)
- Email верификация при регистрации
- Токены для сброса пароля (действительны 24 часа)
- Токены для подтверждения заявок (действительны 24 часа)
5. Middleware защита:
admin.auth # Проверка аутентификации админа
admin.permission # Проверка прав доступа
admin.2fa # Проверка 2FA для админа
profile.access # Доступ к личному кабинету
email.verified # Проверка подтверждения email
rate.limit # Ограничение запросов (60/мин)
2fa # Проверка 2FA для пользователей
admin.permission # Проверка прав доступа
admin.2fa # Проверка 2FA для админа
profile.access # Доступ к личному кабинету
email.verified # Проверка подтверждения email
rate.limit # Ограничение запросов (60/мин)
2fa # Проверка 2FA для пользователей
🚀 Deploy и DevOps
Требования к серверу:
- PHP: 8.1+ с расширениями (bcmath, ctype, fileinfo, json, mbstring, openssl, pdo, tokenizer, xml, zip, gd, redis)
- База данных: MySQL 8.0+ или MariaDB 10.4+
- Redis: 6.0+ (для кэширования и сессий)
- Веб-сервер: Nginx 1.18+ или Apache 2.4+
- Supervisor: для управления очередями (если используются)
Cron задачи (настроены в routes/console.php):
# Обновление курсов из API по умолчанию (каждый час)
* * * * * cd /path/to/dexa && php artisan schedule:run >> /dev/null 2>&1
# Фактические задачи внутри schedule:
$schedule->command('rates:update-from-apis')->hourly()
$schedule->command('rates:check-stale --threshold=30 --send-email')->everyFifteenMinutes()
$schedule->command('rates:force-update')->hourly()
$schedule->command('currencies:sync')->dailyAt('03:00')
Переменные окружения (.env):
APP_NAME="DEXA"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
APP_TIMEZONE=UTC
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dexa
DB_USERNAME=dexa_user
DB_PASSWORD=your_password
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379
SESSION_DRIVER=redis
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
MAIL_MAILER=smtp
MAIL_HOST=smtp.mail.ru
MAIL_PORT=465
MAIL_USERNAME=your-email@mail.ru
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=your-email@mail.ru
MAIL_FROM_NAME="DEXA Exchange"
TELEGRAM_BOT_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_id
📊 Система приоритетов курсов (подробно)
1
Ручной курс партнера - самый высокий приоритет
- Находится в таблице
exchange_ratesс заполненнымpartner_id - Поле
rateзаполнено,use_external_rate = false - Полностью игнорирует внешние API
2
Внешний курс партнера
- Находится в таблице
external_ratesс заполненнымpartner_id - ИЛИ
exchange_ratesсuse_partner_external = true - Использует API партнера (если настроен) или общий API
3
Ручной общий курс
- В таблице
exchange_ratesсpartner_id = NULL - Поле
rateзаполнено,use_external_rate = false - Применяется для всех партнеров, у которых нет своих курсов
4
Общий внешний курс
- В таблице
external_ratesсpartner_id = NULL - ИЛИ
exchange_ratesсuse_external_rate = true - Использует API по умолчанию
5
Расчет через USDT (резервный вариант)
- Вычисляется как
BTC → USDT → RUBесли нет прямого курса - Использует курсы USDT для расчета кросс-курса
- Работает для любых пар, где есть через USDT
🧪 Тестирование
В проекте используются следующие типы тестов:
- Unit тесты - для сервисов и моделей (PHPUnit)
- Feature тесты - для контроллеров и API
- Ручное тестирование через административную панель
Команды для тестирования:
# Тест SMTP подключения
php artisan smtp:test admin@example.com
# Проверка устаревших курсов
php artisan rates:check-stale --threshold=30 --send-email
# Принудительное обновление курсов
php artisan rates:force-update
# Синхронизация валют
php artisan currencies:sync
🔧 Устранение неисправностей
| Проблема | Причина | Решение |
|---|---|---|
| 502 Bad Gateway | PHP-FPM не запущен | sudo systemctl restart php8.1-fpm |
| Ошибки миграции | Нет прав на базу данных | Проверить пользователя MySQL, выполнить php artisan migrate:fresh |
| Медленная загрузка | Нет OPCache или Redis | Включить OPCache, настроить Redis для сессий и кэша |
| Не отправляются email | Неправильные SMTP настройки | Проверить в админ-панели Настройки → Email, выполнить php artisan smtp:test |
| Не обновляются курсы | Не настроен API по умолчанию или проблемы с API | В админ-панели Курсы обмена → Установить API по умолчанию → Обновить курсы |
| Курсы на сайте не отображаются | Нет записей в external_rates или exchange_rates |
Запустить php artisan rates:update-from-apis, проверить настройки валют |
📝 Примечание: Все логи хранятся в
storage/logs/laravel.log. Для мониторинга используйте tail -f storage/logs/laravel.log.
⚠️ Важно: Супер-администратор только один:
odeveloper@internet.ru. Его нельзя удалить или изменить роль.
Все остальные администраторы создаются с правами, которые задает супер-админ.
Последнее обновление: 30.05.2026 в 15:03
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Архитектура системы DEXA - Полная документация</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
line-height: 1.6;
color: #333;
padding: 20px;
max-width: 1400px;
margin: 0 auto;
background-color: #f8fafc;
}
h1 {
color: #2c3e50;
border-bottom: 3px solid #3498db;
padding-bottom: 15px;
margin-bottom: 30px;
}
h2 {
color: #34495e;
border-bottom: 2px solid #e0e6ed;
padding-bottom: 10px;
margin-top: 40px;
}
h3 {
color: #2c3e50;
margin-top: 25px;
}
h4 {
color: #4a5568;
margin-top: 20px;
}
.architecture-diagram {
background: white;
border: 2px solid #e2e8f0;
border-radius: 10px;
padding: 25px;
margin: 20px 0;
text-align: center;
overflow-x: auto;
}
.component {
background: white;
border: 1px solid #e2e8f0;
border-radius: 8px;
padding: 20px;
margin: 15px 0;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.component-header {
display: flex;
align-items: center;
margin-bottom: 15px;
}
.component-icon {
font-size: 24px;
margin-right: 10px;
}
.tech-stack {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 15px 0;
}
.tech-item {
background: #e3f2fd;
padding: 5px 12px;
border-radius: 20px;
font-size: 12px;
font-weight: 500;
}
.flow-diagram {
background: #f8f9fa;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
border-left: 4px solid #3498db;
}
.flow-step {
display: flex;
align-items: center;
margin: 10px 0;
}
.flow-number {
background: #3498db;
color: white;
width: 30px;
height: 30px;
border-radius: 50%;
text-align: center;
line-height: 30px;
margin-right: 15px;
flex-shrink: 0;
}
.note {
background: #e3f2fd;
border-left: 4px solid #2196f3;
padding: 15px;
margin: 20px 0;
border-radius: 4px;
}
.warning {
background: #fff3cd;
border-left: 4px solid #ffc107;
padding: 15px;
margin: 20px 0;
border-radius: 4px;
}
table {
border-collapse: collapse;
width: 100%;
margin: 20px 0;
background: white;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
border-radius: 8px;
overflow: hidden;
}
th, td {
padding: 12px 15px;
border: 1px solid #e2e8f0;
text-align: left;
}
th {
background-color: #f7fafc;
font-weight: 600;
color: #4a5568;
}
code {
background-color: #f1f3f4;
padding: 2px 6px;
border-radius: 4px;
font-family: 'Consolas', 'Monaco', monospace;
color: #e74c3c;
font-size: 0.9em;
}
pre {
background-color: #2d3436;
color: #dfe6e9;
padding: 20px;
border-radius: 8px;
overflow-x: auto;
margin: 15px 0;
border-left: 4px solid #3498db;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 14px;
}
.method-signature {
background: #2d3436;
color: #dfe6e9;
padding: 15px;
border-radius: 8px;
margin: 15px 0;
overflow-x: auto;
font-family: 'Consolas', 'Monaco', monospace;
}
.method-param {
color: #74b9ff;
}
.method-return {
color: #55efc4;
}
.mermaid {
background: white;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
}
.database-schema {
background: #2d3436;
color: white;
padding: 20px;
border-radius: 8px;
margin: 20px 0;
overflow-x: auto;
}
.rate-priority {
background: #e8f5e9;
border-left: 4px solid #4caf50;
padding: 15px;
margin: 20px 0;
border-radius: 4px;
}
.priority-item {
margin: 10px 0;
padding-left: 15px;
border-left: 3px solid #4caf50;
}
.priority-number {
display: inline-block;
background: #4caf50;
color: white;
width: 24px;
height: 24px;
border-radius: 50%;
text-align: center;
line-height: 24px;
font-size: 12px;
margin-right: 10px;
}
@media (max-width: 768px) {
body { padding: 10px; }
th, td { padding: 8px; font-size: 12px; }
pre { font-size: 11px; }
}
</style>
</head>
<body>
<h1>🏗️ Архитектура системы DEXA</h1>
<div class="note">
<strong>👨💻 Целевая аудитория:</strong> Разработчики, DevOps инженеры, Технические руководители<br>
<strong>📊 Уровень сложности:</strong> Средний<br>
<strong>🎯 Цель документа:</strong> Полное описание архитектуры, компонентов, связей и бизнес-логики системы обмена валют DEXA
</div>
<h2>🎯 Обзор системы</h2>
<p>DEXA - это высоконагруженная система обмена криптовалют и фиатных денег с микросервисной архитектурой.
Система предназначена для автоматизации процесса обмена между клиентами и партнерами (точками обмена).</p>
<h3>Ключевые возможности:</h3>
<ul>
<li><strong>Обмен криптовалют</strong> - BTC, ETH, USDT, TRX и другие</li>
<li><strong>Обмен фиатных валют</strong> - RUB, USD, EUR</li>
<li><strong>Автоматическое обновление курсов</strong> из внешних API (Binance, Rapira.net)</li>
<li><strong>Гибкая система наценок</strong> для разных типов транзакций</li>
<li><strong>Партнерская программа</strong> с индивидуальными курсами для каждой точки обмена</li>
<li><strong>Административная панель</strong> с ролевой моделью и 2FA</li>
<li><strong>API для внешних интеграций</strong></li>
<li><strong>Автоматические уведомления</strong> по Email и Telegram</li>
</ul>
<h2>⚙️ Технологический стек</h2>
<div class="tech-stack">
<span class="tech-item">Laravel 10</span>
<span class="tech-item">PHP 8.1+</span>
<span class="tech-item">MySQL 8.0+</span>
<span class="tech-item">MariaDB 10.4+</span>
<span class="tech-item">Redis 6.0+</span>
<span class="tech-item">Nginx/Apache</span>
<span class="tech-item">Bootstrap 5</span>
<span class="tech-item">jQuery 3.6</span>
<span class="tech-item">Font Awesome 6</span>
<span class="tech-item">CKEditor 5</span>
<span class="tech-item">Chart.js</span>
<span class="tech-item">Google2FA</span>
</div>
<h2>🏗️ Высокоуровневая архитектура</h2>
<div class="architecture-diagram">
<pre style="background: white; color: #333; text-align: left; border: none; padding: 0;">
┌─────────────────────────────────────────────────────────────────────────────┐
│ КЛИЕНТСКИЙ СЛОЙ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Web │ │ Mobile │ │ Admin │ │ API │ │
│ │ Client │ │ App │ │ Panel │ │ Client │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │ │
│ └───────────────┴───────────────┴───────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ API Gateway │ │
│ │ (Laravel) │ │
│ └────────┬────────┘ │
└───────────────────────────────────┼─────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ СЕРВИСНЫЙ СЛОЙ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Auth │ │ Exchange │ │ Rate │ │ Notification│ │
│ │ Service │ │ Service │ │ Service │ │ Service │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Partner │ │ Currency │ │ API │ │ Analytics │ │
│ │ Service │ │ Service │ │ Service │ │ Service │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ СЛОЙ ДАННЫХ │
├─────────────────────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Primary │ │ Redis │ │ External │ │ File │ │
│ │ DB │ │ Cache │ │ APIs │ │ Storage │ │
│ │ (MySQL) │ │ (Session) │ │ (Binance) │ │ (Logos) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
</pre>
</div>
<h2>📂 Структура директорий проекта</h2>
<pre><code>dexa/
├── app/
│ ├── Console/
│ │ └── Commands/
│ │ ├── CheckRatesStale.php # Проверка устаревших курсов
│ │ ├── ForceUpdateRates.php # Принудительное обновление
│ │ ├── SyncCurrenciesCommand.php # Синхронизация валют
│ │ ├── TestSmtpConnection.php # Тест SMTP
│ │ ├── UpdateExchangeRates.php # Обновление курсов
│ │ └── UpdateRatesFromConfiguredApis.php # Обновление из API (крон)
│ │
│ ├── Exports/
│ │ └── OrdersExport.php # Экспорт заявок в Excel
│ │
│ ├── Helpers/
│ │ └── ColorHelper.php # Утилиты для работы с цветами
│ │
│ ├── Http/
│ │ ├── Controllers/
│ │ │ ├── Admin/
│ │ │ │ ├── AdminController.php # Управление администраторами
│ │ │ │ ├── ApiConfigController.php # API конфигурации
│ │ │ │ ├── AuthController.php # Аутентификация админов
│ │ │ │ ├── CityController.php # Управление городами
│ │ │ │ ├── CurrencyController.php # Управление валютами
│ │ │ │ ├── DashboardController.php # Дашборд и отчеты
│ │ │ │ ├── DocumentationController.php # Управление документацией
│ │ │ │ ├── ExchangeRateController.php # Управление курсами
│ │ │ │ ├── OrderController.php # Управление заявками
│ │ │ │ ├── PageController.php # Управление страницами
│ │ │ │ ├── PartnerController.php # Управление партнерами
│ │ │ │ ├── SettingController.php # Настройки системы
│ │ │ │ ├── TwoFactorController.php # 2FA для админов
│ │ │ │ └── UserController.php # Управление пользователями
│ │ │ │
│ │ │ ├── Api/
│ │ │ │ └── ApiController.php # Публичное API
│ │ │ │
│ │ │ ├── AuthController.php # Аутентификация пользователей
│ │ │ ├── ContactController.php # Контактная форма
│ │ │ ├── ExchangeController.php # Обмен валют
│ │ │ ├── HomeController.php # Главная страница
│ │ │ ├── PageController.php # Динамические страницы
│ │ │ ├── ProfileController.php # Личный кабинет
│ │ │ └── TwoFactorController.php # 2FA для пользователей
│ │ │
│ │ └── Middleware/
│ │ ├── AdminAuthMiddleware.php # Аутентификация админа
│ │ ├── AdminTwoFactorMiddleware.php # 2FA для админа
│ │ ├── CheckAdminPermission.php # Проверка прав админа
│ │ ├── CheckEmailVerified.php # Проверка email
│ │ ├── CheckProfileAccess.php # Доступ к профилю
│ │ ├── RateLimitMiddleware.php # Ограничение запросов
│ │ ├── SetAdminSessionCookie.php # Установка админ-сессии
│ │ ├── StartAdminSession.php # Запуск админ-сессии
│ │ └── TwoFactorMiddleware.php # 2FA для пользователей
│ │
│ ├── Mail/
│ │ ├── AdminOrderCreated.php # Уведомление админу о заявке
│ │ ├── ApiStaleRatesNotification.php # Уведомление о устаревших курсах
│ │ ├── BaseMailable.php # Базовый класс для писем
│ │ ├── ContactMessage.php # Контактная форма
│ │ ├── EmailVerification.php # Подтверждение email
│ │ ├── NewExchangeOrder.php # Новая заявка на обмен
│ │ ├── OrderConfirmation.php # Подтверждение заявки
│ │ ├── OrderStatusUpdated.php # Обновление статуса
│ │ ├── OrderVerification.php # Верификация заявки
│ │ └── PasswordReset.php # Сброс пароля
│ │
│ ├── Models/
│ │ ├── Admin.php # Администратор
│ │ ├── City.php # Город
│ │ ├── Currency.php # Валюта (с настройками 6 типов)
│ │ ├── Documentation.php # Управление документацией
│ │ ├── ExchangeApi.php # API конфигурация
│ │ ├── ExchangeOrder.php # Заявка на обмен
│ │ ├── ExchangeRate.php # Курс обмена
│ │ ├── ExternalRate.php # Внешний курс
│ │ ├── Page.php # Статическая страница
│ │ ├── Partner.php # Партнер
│ │ ├── Setting.php # Настройки системы
│ │ ├── User.php # Пользователь
│ │ └── UserWallet.php # Кошелек пользователя
│ │
│ ├── Providers/
│ │ ├── AppServiceProvider.php # Регистрация команд
│ │ ├── DynamicMailConfigProvider.php # Динамическая конфигурация почты
│ │ └── ExternalRateServiceProvider.php # Регистрация сервисов
│ │
│ └── Services/
│ ├── RateCalculation/ # КАЛЬКУЛЯТОРЫ КУРСОВ (новая архитектура)
│ │ ├── RateCalculatorInterface.php # Интерфейс калькулятора
│ │ ├── RateCalculatorManager.php # Менеджер калькуляторов
│ │ ├── PartnerManualRateCalculator.php # Ручной курс партнера
│ │ ├── PartnerExternalRateCalculator.php # Внешний курс партнера
│ │ ├── GeneralManualRateCalculator.php # Ручной общий курс
│ │ ├── GeneralExternalRateCalculator.php # Внешний общий курс
│ │ └── USDTCalculationCalculator.php # Расчет через USDT
│ │
│ ├── ExchangeCalculationService.php # Основная логика расчета
│ ├── ExternalRateService.php # Обновление внешних курсов
│ ├── MailLoggerService.php # Логирование почты
│ ├── RateUpdateService.php # Обновление курсов
│ ├── TelegramService.php # Telegram уведомления
│ └── UniversalApiService.php # Универсальный API клиент
│
├── bootstrap/
│ └── app.php # Конфигурация приложения
│
├── config/
│ ├── admin_session.php # Настройки админ-сессии
│ ├── app.php # Основные настройки
│ ├── auth.php # Аутентификация (guards)
│ ├── beget.php # Настройки для Beget хостинга
│ ├── cache.php # Кэширование
│ ├── database.php # База данных
│ ├── filesystems.php # Файловая система
│ ├── google2fa.php # 2FA настройки
│ ├── logging.php # Логирование
│ ├── mail.php # Почта
│ ├── queue.php # Очереди
│ └── services.php # Сторонние сервисы
│
├── database/
│ ├── migrations/
│ │ ├── 0001_01_01_000000_create_users_table.php
│ │ ├── 0001_01_01_000001_create_cache_table.php
│ │ ├── 0001_01_01_000002_create_jobs_table.php
│ │ ├── 2026_01_18_000000_create_dexa_database.php # Основная миграция
│ │ ├── 2026_02_21_000000_add_menu_settings_to_pages_table.php
│ │ ├── 2026_03_04_000000_add_2fa_fields_to_users_table.php
│ │ └── 2026_03_05_000000_add_2fa_fields_to_admins_table.php
│ │
│ └── seeders/
│ └── DatabaseSeeder.php # Начальные данные
│
├── public/
│ ├── css/
│ │ └── exchange-common.css # Общие стили
│ ├── js/
│ │ └── exchange-common.js # Общие JS функции
│ └── index.php
│
├── resources/
│ ├── docs/ # Файлы документации
│ │ ├── user/ # Документация для пользователей
│ │ └── developer/ # Документация для разработчиков
│ │
│ └── views/ # Blade шаблоны
│ ├── admin/ # Админ-панель
│ ├── auth/ # Аутентификация
│ ├── emails/ # Email шаблоны
│ ├── errors/ # Страницы ошибок
│ ├── layouts/ # Базовые шаблоны
│ ├── pages/ # Публичные страницы
│ ├── profile/ # Личный кабинет
│ └── tracking.blade.php # Отслеживание заявок
│
├── routes/
│ ├── api.php # API маршруты
│ ├── console.php # Cron задачи
│ └── web.php # Веб-маршруты
│
└── storage/ # Логи, кэш, сессии
</code></pre>
<h2>🏗️ Компоненты системы</h2>
<div class="component">
<div class="component-header">
<div class="component-icon">🔐</div>
<h3>Сервис аутентификации (Auth Service)</h3>
</div>
<p><strong>Назначение:</strong> Управление пользователями, сессиями, ролями и правами доступа.</p>
<h4>Основные функции:</h4>
<ul>
<li><strong>Раздельные гарды:</strong> <code>web</code> (пользователи) и <code>admin</code> (администраторы)</li>
<li><strong>Раздельные сессии:</strong> через отдельные таблицы <code>sessions</code> и <code>admin_sessions</code></li>
<li><strong>Двухфакторная аутентификация (2FA):</strong> для пользователей и админов через Google Authenticator</li>
<li><strong>Ролевая модель (RBAC):</strong> 4 уровня доступа (superadmin, admin, manager, moderator)</li>
<li><strong>Granular permissions:</strong> детальные права на каждый модуль (view, create, edit, delete)</li>
<li><strong>Управление сессиями:</strong> отдельные cookie для админ-панели (<code>dexaSuperUser</code>)</li>
<li><strong>Email верификация:</strong> обязательное подтверждение email для пользователей</li>
<li><strong>Сброс пароля:</strong> через email ссылку (действительна 24 часа)</li>
</ul>
<h4>Технологии:</h4>
<div class="tech-stack">
<span class="tech-item">Laravel Session</span>
<span class="tech-item">bcrypt</span>
<span class="tech-item">Google2FA</span>
<span class="tech-item">CSRF Tokens</span>
<span class="tech-item">Custom Middleware</span>
</div>
<h4>API endpoints:</h4>
<div class="method-signature">
POST /login # Вход пользователя<br>
POST /register # Регистрация<br>
POST /logout # Выход<br>
POST /forgot-password # Запрос сброса пароля<br>
POST /reset-password # Сброс пароля<br>
GET /verify-email/{token} # Подтверждение email<br>
GET /2fa/verify # Форма 2FA<br>
POST /2fa/verify # Проверка 2FA кода<br>
<br>
POST /dexaSuperUser/login # Вход админа<br>
POST /dexaSuperUser/logout # Выход админа<br>
GET /dexaSuperUser/2fa/verify # Форма 2FA админа<br>
POST /dexaSuperUser/2fa/verify # Проверка 2FA кода админа
</div>
</div>
<div class="component">
<div class="component-header">
<div class="component-icon">💱</div>
<h3>Сервис обмена (Exchange Service)</h3>
</div>
<p><strong>Назначение:</strong> Обработка операций обмена валют, расчет курсов с учетом наценок, управление заявками.</p>
<h4>Основные функции:</h4>
<ul>
<li><strong>Создание заявок:</strong> клиентские и административные</li>
<li><strong>Расчет курсов:</strong> по 6 типам транзакций с учетом наценок/скидок</li>
<li><strong>Стаканы (Order Book):</strong> использование bid/ask цен из внешних API</li>
<li><strong>Система приоритетов курсов:</strong>
<ol>
<li>Ручной курс партнера</li>
<li>Внешний курс партнера</li>
<li>Ручной общий курс</li>
<li>Общий внешний курс</li>
<li>Расчет через USDT (резерв)</li>
</ol>
</li>
<li><strong>Автоматическая верификация:</strong> по email ссылке или коду</li>
<li><strong>Управление статусами:</strong> pending, confirmed, processing, completed, cancelled, rejected</li>
<li><strong>Лимиты:</strong> минимальные и максимальные суммы для каждой пары</li>
<li><strong>Комиссии:</strong> процентная комиссия (может быть отрицательной для скидки)</li>
</ul>
<h4>Архитектура калькуляторов курсов (новое):</h4>
<div class="flow-diagram">
<div class="flow-step">
<div class="flow-number">1</div>
<div><strong>RateCalculatorManager</strong> - координатор, вызывает все калькуляторы по приоритету</div>
</div>
<div class="flow-step">
<div class="flow-number">2</div>
<div><strong>PartnerManualRateCalculator</strong> - проверяет ручные курсы партнера</div>
</div>
<div class="flow-step">
<div class="flow-number">3</div>
<div><strong>PartnerExternalRateCalculator</strong> - проверяет внешние курсы партнера</div>
</div>
<div class="flow-step">
<div class="flow-number">4</div>
<div><strong>GeneralManualRateCalculator</strong> - проверяет общие ручные курсы</div>
</div>
<div class="flow-step">
<div class="flow-number">5</div>
<div><strong>GeneralExternalRateCalculator</strong> - проверяет общие внешние курсы</div>
</div>
<div class="flow-step">
<div class="flow-number">6</div>
<div><strong>USDTCalculationCalculator</strong> - резервный расчет через USDT</div>
</div>
</div>
<h4>Основные методы ExchangeCalculationService:</h4>
<div class="method-signature">
<span class="method-return">array</span> getBestRate(<span class="method-param">int $fromCurrencyId</span>, <span class="method-param">int $toCurrencyId</span>, <span class="method-param">int|null $partnerId = null</span>)
</div>
<div class="method-signature">
<span class="method-return">array</span> calculateExchange(<span class="method-param">int $fromCurrencyId</span>, <span class="method-param">int $toCurrencyId</span>, <span class="method-param">float $amount</span>, <span class="method-param">int|null $partnerId = null</span>)
</div>
<div class="method-signature">
<span class="method-return">bool</span> isRateStale(<span class="method-param">int $fromCurrencyId</span>, <span class="method-param">int|null $staleThresholdMinutes = null</span>)
</div>
<div class="method-signature">
<span class="method-return">array</span> prepareFormulaInfo(<span class="method-param">Currency $fromCurrency</span>, <span class="method-param">Currency $toCurrency</span>, <span class="method-param">float $baseRate</span>, <span class="method-param">float $finalRate</span>, <span class="method-param">float $margin</span>, <span class="method-param">string $transactionType</span>, <span class="method-param">float $bidPrice = 0</span>, <span class="method-param">float $askPrice = 0</span>, <span class="method-param">string $usedStakan = ''</span>, <span class="method-param">float $manualMargin = 0</span>, <span class="method-param">bool $useExternal = true</span>)
</div>
</div>
<div class="component">
<div class="component-header">
<div class="component-icon">📊</div>
<h3>Сервис курсов (Rate Service)</h3>
</div>
<p><strong>Назначение:</strong> Получение, обработка и хранение курсов валют из внешних API.</p>
<h4>Архитектура получения курсов:</h4>
<div class="flow-diagram">
<div class="flow-step">
<div class="flow-number">1</div>
<div><strong>ExternalRateService::updateRatesFromApi()</strong> - запускает обновление</div>
</div>
<div class="flow-step">
<div class="flow-number">2</div>
<div>Выбирает активные API из таблицы <code>exchange_apis</code></div>
</div>
<div class="flow-step">
<div class="flow-number">3</div>
<div>Для каждого API вызывает <code>UniversalApiService::fetchFromApi()</code></div>
</div>
<div class="flow-step">
<div class="flow-number">4</div>
<div>UniversalApiService отправляет HTTP запрос (GET/POST) с учетом аутентификации</div>
</div>
<div class="flow-step">
<div class="flow-number">5</div>
<div>Парсит ответ согласно <code>field_mapping</code> (JSON/XML/CSV)</div>
</div>
<div class="flow-step">
<div class="flow-number">6</div>
<div>Форматирует пары валют согласно <code>pair_format</code></div>
</div>
<div class="flow-step">
<div class="flow-number">7</div>
<div>Сохраняет в таблицу <code>external_rates</code> (или обновляет существующие)</div>
</div>
<div class="flow-step">
<div class="flow-number">8</div>
<div>Создает обратные курсы (reverse_rates) для всех пар</div>
</div>
</div>
<h4>Ключевые методы ExternalRateService:</h4>
<div class="method-signature">
<span class="method-return">int</span> updateRatesFromApi()
</div>
<div class="method-signature">
<span class="method-return">array</span> updateRatesFromSpecificApi(<span class="method-param">ExchangeApi $api</span>)
</div>
<div class="method-signature">
<span class="method-return">int</span> updatePartnerExternalRatesFromApi(<span class="method-param">int $partnerId</span>, <span class="method-param">ExchangeApi|null $api = null</span>)
</div>
<div class="method-signature">
<span class="method-return">array</span> checkSpecificApi(<span class="method-param">ExchangeApi $api</span>)
</div>
<div class="method-signature">
<span class="method-return">int</span> createReverseRates()
</div>
<h4>UniversalApiService - универсальный клиент:</h4>
<div class="method-signature">
<span class="method-return">array</span> fetchFromApi(<span class="method-param">ExchangeApi $api</span>, <span class="method-param">bool $testMode = false</span>)
</div>
<div class="method-signature">
<span class="method-return">array</span> testApi(<span class="method-param">ExchangeApi $api</span>, <span class="method-param">bool $useTestData = false</span>, <span class="method-param">bool $showAllRates = false</span>)
</div>
<div class="method-signature">
<span class="method-return">array|null</span> fetchOrderBookData(<span class="method-param">string $symbol</span>, <span class="method-param">array|null $mapping = null</span>, <span class="method-param">ExchangeApi|null $api = null</span>)
</div>
</div>
<div class="component">
<div class="component-header">
<div class="component-icon">🤖</div>
<h3>Сервис уведомлений (TelegramService)</h3>
</div>
<p><strong>Назначение:</strong> Отправка уведомлений о важных событиях в Telegram чат администраторов.</p>
<h4>Основные функции:</h4>
<ul>
<li><strong>Новые заявки:</strong> уведомление администраторов о создании заявки</li>
<li><strong>Контактная форма:</strong> уведомление о новом сообщении</li>
<li><strong>Админские заявки:</strong> уведомление о заявках, созданных через админ-панель</li>
<li><strong>Тестовые уведомления:</strong> для проверки настроек</li>
</ul>
<h4>Ключевые методы:</h4>
<div class="method-signature">
<span class="method-return">bool</span> sendExchangeOrderNotification(<span class="method-param">ExchangeOrder $order</span>)
</div>
<div class="method-signature">
<span class="method-return">bool</span> sendContactFormNotification(<span class="method-param">array $data</span>)
</div>
<div class="method-signature">
<span class="method-return">bool</span> sendAdminOrderNotification(<span class="method-param">array $orderData</span>)
</div>
<div class="method-signature">
<span class="method-return">array</span> checkBotStatus()
</div>
<div class="method-signature">
<span class="method-return">array</span> sendTestNotification()
</div>
<h4>Настройки в .env:</h4>
<pre><code>TELEGRAM_BOT_TOKEN=your_bot_token_here
TELEGRAM_CHAT_ID=your_chat_id_here</code></pre>
</div>
<h2>🗄️ Структура базы данных</h2>
<div class="database-schema">
<h3 style="color: white;">Основные таблицы и связи:</h3>
<pre><code style="color: #dfe6e9; font-size: 12px;">
-- =====================================================
-- ЯДРО СИСТЕМЫ (АУТЕНТИФИКАЦИЯ)
-- =====================================================
users (
id, name, email, password, phone, telegram,
role, is_active,
email_verified_at, email_verification_token, verification_sent_at,
google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)
admins (
id, name, email, password, role, permissions, is_active,
google2fa_secret, google2fa_enabled, backup_codes, last_2fa_at
)
sessions (id, user_id, ip_address, user_agent, payload, last_activity)
admin_sessions (id, admin_id, ip_address, user_agent, payload, last_activity)
password_reset_tokens (email, token, created_at)
-- =====================================================
-- ВАЛЮТЫ И КУРСЫ
-- =====================================================
currencies (
id, code, name, symbol, type, icon, is_active, sort_order,
our_wallet, wallet_for_other_currencies,
-- НАСТРОЙКИ ДЛЯ USDT
usdt_to_other_crypto_margin, usdt_to_other_crypto_min_amount,
usdt_to_rub_margin, usdt_to_rub_min_amount,
-- НАСТРОЙКИ ДЛЯ RUB
rub_to_usdt_margin, rub_to_usdt_min_amount,
rub_to_other_crypto_margin, rub_to_other_crypto_min_amount,
-- НАСТРОЙКИ ДЛЯ ДРУГИХ КРИПТО
other_crypto_to_rub_margin, other_crypto_to_rub_min_amount,
other_crypto_to_other_crypto_margin, other_crypto_to_other_crypto_min_amount
)
exchange_apis (
id, name, base_url, endpoint, method,
request_format, response_format,
field_mapping (JSON), pair_format (JSON),
authentication_type, api_key (encrypted), secret_key (encrypted),
is_active, priority, timeout, retry_count,
success_count, error_count, last_success_at, last_error_at
)
external_rates (
id, partner_id, from_currency_id, to_currency_id,
external_rate, source, last_updated,
order_book_buy (JSON), order_book_sell (JSON),
bid_price, ask_price, bid_volume, ask_volume, spread,
volume_24h, change_24h
)
exchange_rates (
id, partner_id, from_currency_id, to_currency_id,
rate, external_rate_id,
use_external_rate, use_partner_external,
manual_margin_percentage,
override_margin, override_min_amount,
min_amount, max_amount,
is_active, is_hidden, priority, last_updated
)
-- =====================================================
-- ГЕОГРАФИЯ И ПАРТНЕРЫ
-- =====================================================
cities (
id, name, country, latitude, longitude, is_active, sort_order
)
partners (
id, city_id, name, address, phone, email,
latitude, longitude, working_hours, description,
accepted_currencies (JSON), api_id,
rating, total_reviews, is_active
)
-- =====================================================
-- ОПЕРАЦИИ (ЗАЯВКИ)
-- =====================================================
exchange_orders (
id, order_number, user_id,
from_currency_id, to_currency_id,
partner_id, city_id,
amount, rate, fee_percentage, fee_amount, total_receive,
full_name, email, phone, wallet_address,
status, transaction_type,
admin_notes, user_notes,
verification_code, verification_token,
verified_at, expires_at,
ip_address, user_agent
)
-- =====================================================
-- КЛИЕНТСКИЕ ДАННЫЕ
-- =====================================================
user_wallets (
id, user_id, currency_id,
wallet_address, network, wallet_name,
is_default, is_active, notes
)
-- =====================================================
-- НАСТРОЙКИ
-- =====================================================
settings (
id, key, value, type, group, options,
default_cron_api_id, default_cron_api_name,
update_interval_minutes, auto_update_enabled,
primary_api_id, fallback_api_id,
order_expire_minutes, auto_confirm_orders, require_verification,
site_timezone, date_format,
recaptcha_site_key, recaptcha_secret_key
)
pages (
id, slug, title, content,
meta_title, meta_description, meta_keywords,
is_active, is_homepage, show_in_menu,
show_logistics_in_menu, show_home_in_menu,
page_type, sort_order
)
</code></pre>
</div>
<h3>Связи между таблицами:</h3>
<ul>
<li><strong>currencies → exchange_rates:</strong> одна валюта может участвовать во многих курсах (как from или to)</li>
<li><strong>currencies → external_rates:</strong> одна валюта может участвовать во многих внешних курсах</li>
<li><strong>cities → partners:</strong> один город может иметь много партнеров</li>
<li><strong>partners → exchange_rates:</strong> один партнер может иметь много индивидуальных курсов</li>
<li><strong>partners → external_rates:</strong> один партнер может иметь много своих внешних курсов</li>
<li><strong>users → exchange_orders:</strong> один пользователь может иметь много заявок</li>
<li><strong>users → user_wallets:</strong> один пользователь может иметь много кошельков</li>
<li><strong>exchange_apis → external_rates:</strong> один API может быть источником для многих курсов</li>
<li><strong>exchange_apis → partners:</strong> один API может быть назначен многим партнерам</li>
<li><strong>external_rates → exchange_rates:</strong> внешний курс может использоваться во многих курсах обмена</li>
</ul>
<h2>🔌 Интеграции и API</h2>
<table>
<thead>
<tr>
<th>Интеграция</th>
<th>Тип</th>
<th>Назначение</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
<tr>
<td>Binance API</td>
<td>REST (GET)</td>
<td>Получение курсов криптовалют (USDT, BTC, ETH)</td>
<td>✅ Активна</td>
</tr>
<tr>
<td>Rapira.net API</td>
<td>REST (GET/POST)</td>
<td>Получение курсов и стаканов заявок</td>
<td>✅ Активна</td>
</tr>
<table>
<td>Telegram Bot API</td>
<td>REST</td>
<td>Уведомления администраторов</td>
<td>✅ Активна</td>
</tr>
<tr>
<td>SMTP сервер</td>
<td>SMTP</td>
<td>Отправка email уведомлений</td>
<td>✅ Активна (настраивается)</td>
</tr>
</tbody>
</table>
<h2>🛡️ Безопасность</h2>
<h3>Многоуровневая защита:</h3>
<h4>1. Сетевой уровень:</h4>
<ul>
<li>HTTPS с HSTS</li>
<li>Защита от DDoS (Cloudflare)</li>
<li>Ограничение доступа к админ-панели через middleware</li>
</ul>
<h4>2. Уровень приложения:</h4>
<ul>
<li><strong>CSRF защита</strong> для всех форм (кроме API)</li>
<li><strong>XSS фильтрация</strong> входных данных</li>
<li><strong>SQL injection protection</strong> через Eloquent ORM и подготовленные запросы</li>
<li><strong>Rate limiting</strong> для API endpoints (60 запросов в минуту)</li>
<li><strong>Валидация</strong> всех входных данных через Form Requests</li>
<li><strong>Раздельные сессии</strong> для пользователей и админов</li>
<li><strong>Отдельная таблица сессий</strong> для админов (<code>admin_sessions</code>)</li>
</ul>
<h4>3. Уровень данных:</h4>
<ul>
<li><strong>Шифрование</strong> API ключей в таблице <code>exchange_apis</code> (AES-256)</li>
<li><strong>Хеширование паролей</strong> (bcrypt, cost 12)</li>
<li><strong>Резервное копирование</strong> базы данных (настраивается через крон)</li>
</ul>
<h4>4. Аутентификация и авторизация:</h4>
<ul>
<li><strong>Двухфакторная аутентификация (2FA)</strong> для пользователей и админов</li>
<li><strong>Ролевая модель (RBAC)</strong> с 4 уровнями доступа</li>
<li><strong>Granular permissions</strong> для каждого модуля (view, create, edit, delete)</li>
<li><strong>Email верификация</strong> при регистрации</li>
<li><strong>Токены для сброса пароля</strong> (действительны 24 часа)</li>
<li><strong>Токены для подтверждения заявок</strong> (действительны 24 часа)</li>
</ul>
<h4>5. Middleware защита:</h4>
<div class="method-signature">
<span class="method-return">admin.auth</span> # Проверка аутентификации админа<br>
<span class="method-return">admin.permission</span> # Проверка прав доступа<br>
<span class="method-return">admin.2fa</span> # Проверка 2FA для админа<br>
<span class="method-return">profile.access</span> # Доступ к личному кабинету<br>
<span class="method-return">email.verified</span> # Проверка подтверждения email<br>
<span class="method-return">rate.limit</span> # Ограничение запросов (60/мин)<br>
<span class="method-return">2fa</span> # Проверка 2FA для пользователей
</div>
<h2>🚀 Deploy и DevOps</h2>
<h3>Требования к серверу:</h3>
<ul>
<li><strong>PHP:</strong> 8.1+ с расширениями (bcmath, ctype, fileinfo, json, mbstring, openssl, pdo, tokenizer, xml, zip, gd, redis)</li>
<li><strong>База данных:</strong> MySQL 8.0+ или MariaDB 10.4+</li>
<li><strong>Redis:</strong> 6.0+ (для кэширования и сессий)</li>
<li><strong>Веб-сервер:</strong> Nginx 1.18+ или Apache 2.4+</li>
<li><strong>Supervisor:</strong> для управления очередями (если используются)</li>
</ul>
<h3>Cron задачи (настроены в routes/console.php):</h3>
<pre><code># Обновление курсов из API по умолчанию (каждый час)
* * * * * cd /path/to/dexa && php artisan schedule:run >> /dev/null 2>&1
# Фактические задачи внутри schedule:
$schedule->command('rates:update-from-apis')->hourly()
$schedule->command('rates:check-stale --threshold=30 --send-email')->everyFifteenMinutes()
$schedule->command('rates:force-update')->hourly()
$schedule->command('currencies:sync')->dailyAt('03:00')</code></pre>
<h3>Переменные окружения (.env):</h3>
<pre><code>APP_NAME="DEXA"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.com
APP_TIMEZONE=UTC
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=dexa
DB_USERNAME=dexa_user
DB_PASSWORD=your_password
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=your_redis_password
REDIS_PORT=6379
SESSION_DRIVER=redis
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
MAIL_MAILER=smtp
MAIL_HOST=smtp.mail.ru
MAIL_PORT=465
MAIL_USERNAME=your-email@mail.ru
MAIL_PASSWORD=your-password
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=your-email@mail.ru
MAIL_FROM_NAME="DEXA Exchange"
TELEGRAM_BOT_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_id
</code></pre>
<h2>📊 Система приоритетов курсов (подробно)</h2>
<div class="rate-priority">
<div class="priority-item">
<span class="priority-number">1</span>
<strong>Ручной курс партнера</strong> - самый высокий приоритет
<ul>
<li>Находится в таблице <code>exchange_rates</code> с заполненным <code>partner_id</code></li>
<li>Поле <code>rate</code> заполнено, <code>use_external_rate = false</code></li>
<li>Полностью игнорирует внешние API</li>
</ul>
</div>
<div class="priority-item">
<span class="priority-number">2</span>
<strong>Внешний курс партнера</strong>
<ul>
<li>Находится в таблице <code>external_rates</code> с заполненным <code>partner_id</code></li>
<li>ИЛИ <code>exchange_rates</code> с <code>use_partner_external = true</code></li>
<li>Использует API партнера (если настроен) или общий API</li>
</ul>
</div>
<div class="priority-item">
<span class="priority-number">3</span>
<strong>Ручной общий курс</strong>
<ul>
<li>В таблице <code>exchange_rates</code> с <code>partner_id = NULL</code></li>
<li>Поле <code>rate</code> заполнено, <code>use_external_rate = false</code></li>
<li>Применяется для всех партнеров, у которых нет своих курсов</li>
</ul>
</div>
<div class="priority-item">
<span class="priority-number">4</span>
<strong>Общий внешний курс</strong>
<ul>
<li>В таблице <code>external_rates</code> с <code>partner_id = NULL</code></li>
<li>ИЛИ <code>exchange_rates</code> с <code>use_external_rate = true</code></li>
<li>Использует API по умолчанию</li>
</ul>
</div>
<div class="priority-item">
<span class="priority-number">5</span>
<strong>Расчет через USDT</strong> (резервный вариант)
<ul>
<li>Вычисляется как <code>BTC → USDT → RUB</code> если нет прямого курса</li>
<li>Использует курсы USDT для расчета кросс-курса</li>
<li>Работает для любых пар, где есть через USDT</li>
</ul>
</div>
</div>
<h2>🧪 Тестирование</h2>
<p>В проекте используются следующие типы тестов:</p>
<ul>
<li><strong>Unit тесты</strong> - для сервисов и моделей (PHPUnit)</li>
<li><strong>Feature тесты</strong> - для контроллеров и API</li>
<li><strong>Ручное тестирование</strong> через административную панель</li>
</ul>
<h3>Команды для тестирования:</h3>
<pre><code># Тест SMTP подключения
php artisan smtp:test admin@example.com
# Проверка устаревших курсов
php artisan rates:check-stale --threshold=30 --send-email
# Принудительное обновление курсов
php artisan rates:force-update
# Синхронизация валют
php artisan currencies:sync
</code></pre>
<h2>🔧 Устранение неисправностей</h2>
<table>
<thead>
<tr>
<th>Проблема</th>
<th>Причина</th>
<th>Решение</th>
</tr>
</thead>
<tbody>
<tr>
<td>502 Bad Gateway</td>
<td>PHP-FPM не запущен</td>
<td><code>sudo systemctl restart php8.1-fpm</code></td>
</tr>
<tr>
<td>Ошибки миграции</td>
<td>Нет прав на базу данных</td>
<td>Проверить пользователя MySQL, выполнить <code>php artisan migrate:fresh</code></td>
</tr>
<tr>
<td>Медленная загрузка</td>
<td>Нет OPCache или Redis</td>
<td>Включить OPCache, настроить Redis для сессий и кэша</td>
</tr>
<tr>
<td>Не отправляются email</td>
<td>Неправильные SMTP настройки</td>
<td>Проверить в админ-панели Настройки → Email, выполнить <code>php artisan smtp:test</code></td>
</tr>
<tr>
<td>Не обновляются курсы</td>
<td>Не настроен API по умолчанию или проблемы с API</td>
<td>В админ-панели Курсы обмена → Установить API по умолчанию → Обновить курсы</td>
</tr>
<tr>
<td>Курсы на сайте не отображаются</td>
<td>Нет записей в <code>external_rates</code> или <code>exchange_rates</code></td>
<td>Запустить <code>php artisan rates:update-from-apis</code>, проверить настройки валют</td>
</tr>
</tbody>
</table>
<div class="note">
<strong>📝 Примечание:</strong> Все логи хранятся в <code>storage/logs/laravel.log</code>. Для мониторинга используйте <code>tail -f storage/logs/laravel.log</code>.
</div>
<div class="warning">
<strong>⚠️ Важно:</strong> Супер-администратор только один: <code>odeveloper@internet.ru</code>. Его нельзя удалить или изменить роль.
Все остальные администраторы создаются с правами, которые задает супер-админ.
</div>
</body>
</html>