PHP и фреймворки

Laravel

Интеграция Telegram Bot API в Laravel: сервис-класс на Http::client, контроллер для webhook, artisan-команда для setWebhook и работа через очереди.

Laravel предлагает несколько способов интеграции с Telegram Bot API: от простого использования HTTP-клиента до полноценных пакетов вроде irazasyed/telegram-bot-sdk или laravel-telegram-bot. Ниже — минимальный нативный вариант без лишних зависимостей, максимально близкий к подходу из страницы HTTP-клиент на PHP.

Сервис-класс для отправки запросов

Выносим логику в отдельный класс app/Services/TelegramBot.php. Используем встроенный HTTP-клиент Laravel (обёртка над Guzzle), который автоматически обрабатывает ретраи, таймауты и исключения.

<?php

namespace App\Services;

use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\RequestException;

class TelegramBot
{
    protected string $token;
    protected string $baseUrl;

    public function __construct(?string $token = null)
    {
        $this->token = $token ?? config('services.telegram.token');
        $this->baseUrl = "https://api.telegram.org/bot{$this->token}";
    }

    /**
     * Универсальный вызов метода Bot API.
     * @throws \RuntimeException
     */
    public function call(string $method, array $params = []): array
    {
        try {
            $response = Http::timeout(15)
                ->retry(3, 100)
                ->post("{$this->baseUrl}/{$method}", $params)
                ->throw()
                ->json();
        } catch (ConnectionException $e) {
            throw new \RuntimeException("Telegram API connection failed: " . $e->getMessage());
        } catch (RequestException $e) {
            $body = $e->response?->json();
            $desc = $body['description'] ?? $e->getMessage();
            throw new \RuntimeException("Telegram API error: {$desc}");
        }

        if (empty($response['ok'])) {
            throw new \RuntimeException("Telegram API returned ok=false: " . ($response['description'] ?? 'unknown'));
        }

        return $response['result'];
    }

    public function sendMessage(int|string $chatId, string $text, array $options = []): array
    {
        return $this->call('sendMessage', array_merge([
            'chat_id' => $chatId,
            'text' => $text,
            'parse_mode' => 'HTML',
        ], $options));
    }

    public function answerCallbackQuery(string $callbackQueryId, ?string $text = null, bool $showAlert = false): array
    {
        return $this->call('answerCallbackQuery', [
            'callback_query_id' => $callbackQueryId,
            'text' => $text,
            'show_alert' => $showAlert,
        ]);
    }
}

Конфигурация

Добавьте токен в config/services.php и переменную окружения:

// config/services.php
'telegram' => [
    'token' => env('TELEGRAM_BOT_TOKEN'),
],

// .env
TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11

Контроллер для Webhook

Создайте контроллер app/Http/Controllers/TelegramWebhookController.php. Laravel автоматически валидирует JSON и конвертирует его в массив.

<?php

namespace App\Http\Controllers;

use App\Services\TelegramBot;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

class TelegramWebhookController extends Controller
{
    public function __invoke(Request $request, TelegramBot $bot): JsonResponse
    {
        $update = $request->all();

        if (!isset($update['update_id'])) {
            return response()->json(['ok' => true]);
        }

        // Обработка сообщений
        if (isset($update['message'])) {
            $msg = $update['message'];
            $chatId = $msg['chat']['id'];
            $text = $msg['text'] ?? '';

            if (str_starts_with($text, '/start')) {
                $bot->sendMessage($chatId, "Привет! Я бот на Laravel.");
            } elseif ($text === '/help') {
                $bot->sendMessage($chatId, "Доступные команды: /start, /help");
            }
        }

        // Обработка callback_query
        if (isset($update['callback_query'])) {
            $cq = $update['callback_query'];
            $bot->answerCallbackQuery($cq['id'], "Нажата кнопка: {$cq['data']}");
        }

        return response()->json(['ok' => true]);
    }
}

Маршрут и регистрация Webhook

В routes/web.php (или api.php) добавьте маршрут. URL должен быть доступен извне (HTTPS, валидный сертификат).

use App\Http\Controllers\TelegramWebhookController;

Route::post('/telegram/webhook/{token}', TelegramWebhookController::class)
    ->where('token', '.*');

Установите webhook разово (например, в php artisan app:setup-telegram-webhook или через Tinker):

<?php

namespace App\Console\Commands;

use App\Services\TelegramBot;
use Illuminate\Console\Command;

class SetupTelegramWebhook extends Command
{
    protected $signature = 'app:setup-telegram-webhook';
    protected $description = 'Set Telegram webhook URL';

    public function handle(TelegramBot $bot): int
    {
        $url = config('app.url') . '/telegram/webhook/' . config('services.telegram.token');
        $result = $bot->call('setWebhook', ['url' => $url, 'drop_pending_updates' => true]);
        $this->info("Webhook set: " . ($result ? 'ok' : 'failed'));
        return self::SUCCESS;
    }
}

Использование в коде приложения

Сервис доступен через контейнер или фасад. Пример в Job/Listener/Controller:

use App\Services\TelegramBot;

class NotifyUser
{
    public function __construct(protected TelegramBot $bot) {}

    public function handle(int $chatId, string $message): void
    {
        $this->bot->sendMessage($chatId, $message);
    }
}

Очереди и повторные попытки

Для продакшена отправку сообщений лучше выносить в очереди (implements ShouldQueue). Laravel автоматически сделает ретраи при исключениях из TelegramBot::call(). Настройте retry_after в конфиге очереди и --tries у воркера.

Дальше: БД и состояния (FSM)