Looking to hire Laravel developers? Try LaraJobs

laravel-telegram maintained by labrodev

Description
Stateless Telegram Bot API client for Laravel with webhook update parsing and secret-token verification.
Author
Last update
2026/07/20 21:08 (dev-main)
License
Downloads
0

Comments
comments powered by Disqus

Laravel Telegram

Stateless Telegram Bot API client for Laravel with webhook update parsing and secret-token verification. Every client call reads the bot token from config and hits the Telegram Bot API directly — the package stores nothing about chats, updates, or webhooks itself.

Installation

composer require labrodev/laravel-telegram

Publish the config file:

php artisan vendor:publish --tag=telegram-config

Set the environment variables:

TELEGRAM_BOT_TOKEN=123456:your-bot-token-from-botfather
TELEGRAM_BOT_USERNAME=YourBotUsername
TELEGRAM_WEBHOOK_SECRET=a-high-entropy-string-you-generate

Sending messages

use Labrodev\Telegram\Services\TelegramClient;

$telegramClient = new TelegramClient();

$telegramClient->sendMessage(
    chatId: $chatId,
    text: 'Hello from Laravel!',
    options: ['parse_mode' => 'Markdown'],
);

Registering the webhook

Call setWebhook() once (from a console command or a one-off route) with your public webhook URL and the same secret configured as TELEGRAM_WEBHOOK_SECRET. Telegram echoes that secret back on every update it delivers:

use Labrodev\Telegram\Services\TelegramClient;

$telegramClient = new TelegramClient();

$telegramClient->setWebhook(
    url: 'https://my-app.test/telegram/webhook',
    secretToken: config('telegram.webhook_secret'),
    allowedUpdates: ['message'],
);

Handling incoming updates

TelegramWebhookSecretVerifier and TelegramUpdateParser are both single-purpose services — invoke them directly rather than calling a named method. Verify the X-Telegram-Bot-Api-Secret-Token header before trusting the payload, then parse it into a TelegramCommand:

use Illuminate\Http\Request;
use Labrodev\Telegram\Services\TelegramUpdateParser;
use Labrodev\Telegram\Services\TelegramWebhookSecretVerifier;

class TelegramWebhookController
{
    public function __invoke(
        Request $request,
        TelegramWebhookSecretVerifier $telegramWebhookSecretVerifier,
        TelegramUpdateParser $telegramUpdateParser,
    ) {
        if (! $telegramWebhookSecretVerifier($request->header('X-Telegram-Bot-Api-Secret-Token'))) {
            abort(403);
        }

        $telegramCommand = $telegramUpdateParser($request->all());

        if ($telegramCommand === null) {
            return response()->noContent();
        }

        match ($telegramCommand->command) {
            'start' => // handle /start, $telegramCommand->argument, $telegramCommand->chatId
            default => null,
        };

        return response()->noContent();
    }
}

TelegramWebhookSecretVerifier throws TelegramWebhookSecretMissing rather than returning false when telegram.webhook_secret isn't configured — that's a deployment mistake on your side, not an untrusted request, and should surface loudly (let it bubble into a 500) instead of being swallowed as an ordinary 403.

Exceptions

  • Labrodev\Telegram\Exceptions\TelegramAuthFailed — Telegram returned 401/403, or no bot token is configured.
  • Labrodev\Telegram\Exceptions\TelegramRequestFailed — any other failed request.
  • Labrodev\Telegram\Exceptions\TelegramWebhookSecretMissingtelegram.webhook_secret is not configured. Thrown by TelegramWebhookSecretVerifier instead of failing closed, since this is a misconfiguration that needs fixing, not a rejected caller.

The first two carry fixed messages only. The bot token rides in the request URL path itself (https://api.telegram.org/bot{token}/...), so no URL, response body, or request detail is ever interpolated into an exception message.

Testing

composer test      # pest
composer phpstan   # larastan, level 7
composer pint      # laravel preset
composer check     # all of the above

License

MIT. See LICENSE.md.