geekcodev / laravel-max-client
Laravel adapter for the MAX Messenger Bot API client (geekcodev/max-php-client)
Requires
- php: ^8.4
- geekcodev/max-php-client: ^1.0
- guzzlehttp/guzzle: ^7.15
- laravel/framework: ^12.0|^13.0
- psr/http-client: ^1.0
- psr/http-factory: ^1.0
- psr/http-message: ^1.1|^2.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.0
- orchestra/testbench: ^10.0|^11.0
- phpstan/phpstan: ^2.0
- phpunit/phpunit: ^11.5
README
Тонкий Laravel-адаптер для MAX Messenger Bot API поверх framework-agnostic ядра
geekcodev/max-php-client.
Пакет отвечает только за «Laravel-клей»: конфиг, DI, фасад, вебхук-роутинг, очередь. Вся бизнес-логика API (DTO,
эндпоинты, ретраи, rate limit, безопасность, загрузка медиа) живёт в ядре — см. его документацию и OpenAPI-спецификацию
max-openapi.
Требования
- PHP ^8.4
- Laravel ^12.0|^13.0
geekcodev/max-php-client^1.0
Установка
composer require geekcodev/laravel-max-client
Сервис-провайдер GeekCo\LaravelMaxClient\MaxServiceProvider и alias Max
подхватываются автоматически (package discovery). Затем опубликуйте конфиг:
php artisan vendor:publish --tag=laravel-max-client-config
Конфигурация
Минимально необходима одна переменная — токен бота:
MAX_API_TOKEN=your-bot-access-token
Все доступные переменные (имена см. в .env.example):
| Переменная | По умолчанию | Описание |
|---|---|---|
MAX_API_TOKEN |
— | Токен бота (заголовок Authorization) |
MAX_BASE_URI |
https://platform-api2.max.ru |
Базовый URI API (домен platform-api2) |
MAX_WEBHOOK_ENABLED |
false |
Регистрировать вебхук-роут |
MAX_WEBHOOK_SECRET |
— | Секрет вебхука (без него роут не включается) |
MAX_WEBHOOK_QUEUE |
default |
Очередь для джобов обработки Update |
MAX_WEBHOOK_PATH |
/max/webhook |
Путь вебхук-роута |
MAX_RETRY_* |
3 / 1 / 30 / 2 / false | Ретраи (попытки/базовая/макс. задержка/фактор/не-идемпотентные) |
MAX_RATE_LIMIT_* |
2.0 / 2.0 | Token bucket: токенов в секунду / максимум |
Токен и секрет никогда не должны попадать в код, логи или коммиты — только env.
Использование
Фасад Max резолвит единый экземпляр ApiClient из контейнера:
use GeekCo\LaravelMaxClient\Facades\Max; use GeekCo\MaxPhpClient\Dto\Recipient; use GeekCo\MaxPhpClient\Dto\NewMessageBody; $me = Max::getMe(); Max::sendMessage( new Recipient(chatId: $chatId), new NewMessageBody(text: 'Привет!'), );
Список доступных методов — в ядре GeekCo\MaxPhpClient\ApiClient.
Полные рабочие примеры — в каталоге examples/:
basic-usage.php (фасад), webhook-listener.php (обработка апдейтов),
custom-http-client.php (подмена PSR-18 клиента),
long-polling-local-dev.md (настройка и запуск Long Polling локально и в Docker).
Свой PSR-18 клиент
По умолчанию используется Guzzle с опциями http.options. Чтобы подменить транспорт, зарегистрируйте свою реализацию
Psr\Http\Client\ClientInterface в контейнере:
// AppServiceProvider $this->app->instance(\Psr\Http\Client\ClientInterface::class, $yourClient);
Вебхук
-
Включите вебхук и задайте секрет:
MAX_WEBHOOK_ENABLED=true MAX_WEBHOOK_SECRET=some-secret
Роут
POST /max/webhook(имяmax.webhook) регистрируется только при включённом флаге и заданном секрете (fail-closed). Роут вне CSRF, сthrottle:60,1(настраивается вwebhook.middlewareконфига). Приёмка проверяетX-Max-Bot-Api-Secretчерезhash_equals(иначе 401). -
Подпишитесь на событие доставки
MaxUpdateReceived:// app/Providers/EventServiceProvider.php protected $listen = [ \GeekCo\LaravelMaxClient\Webhook\MaxUpdateReceived::class => [ YourUpdateListener::class, ], ];
Обработчик:
use GeekCo\LaravelMaxClient\Webhook\MaxUpdateReceived; class YourUpdateListener { public function handle(MaxUpdateReceived $event): void { $update = $event->update; // GeekCo\MaxPhpClient\Dto\Update // бизнес-обработка апдейта } }
-
Пакет ставит
HandleMaxUpdateJobв очередьwebhook.queueна каждыйUpdateи сразу отвечает200(API требует ответ в течение 30 секунд). Если на событие нет слушателей — работа в очередь не ставится.
Long Polling (локальная разработка)
Вебхук требует публичного домена с HTTPS и доверенным CA, поэтому для локальной разработки используйте Long Polling:
php artisan max:listen
Команда опрашивает GET /updates через ядро (LongPollingRunner) и ставит
HandleMaxUpdateJob в ту же очередь (webhook.queue) — апдейты обрабатывает тот же слушатель MaxUpdateReceived.
Остановка — Ctrl+C.
Опции:
--marker=42— начать с указанного marker (последний обработанный timestamp);--once— обработать одну партию апдейтов и завершиться (для cron/смоука).
Поведение по умолчанию — в секции long_polling конфига (env MAX_POLLING_*):
limit (100), timeout (30 сек), break_on_failure (true — завершаться при ошибке API; для долгой работы в dev
задайте MAX_POLLING_BREAK_ON_FAILURE=false).
Активная webhook-подписка отключает Long Polling — не используйте оба механизма одновременно.
Тестирование
# unit-тесты (Testbench), lint, статика, покрытие, аудит
composer run lint
composer run format
composer run analyse
vendor/bin/phpunit
composer run coverage
composer audit
Интеграционные смоук-тесты против реального API (read-only, нужен MAX_API_TOKEN, TLS из Docker-сети блокируется —
только --network host):
source .env && docker run --rm --network host \ -v "$(pwd)":/var/www/html -w /var/www/html \ -e MAX_API_TOKEN="$MAX_API_TOKEN" \ ghcr.io/geekcodev/php:8.4-bookworm vendor/bin/phpunit --group integration
Лицензия
MIT (c) 2026 Evgeny Semenov. См. LICENSE.