Для управления интеграцией Telegram Bot API требуются надежные административные инструменты. В то время как веб-перехватчики обрабатывают входящие пользовательские полезные нагрузки в режиме реального времени, настройка, проверка и обслуживание этих веб-перехватчиков должны выполняться вне жизненного цикла запросов веб-сервера HTTP. Использование инструмента CLI позволяет надежно выполнять этапы развертывания, проверки работоспособности и задачи обслуживания без тайм-аутов веб-сервера или публичного доступа.
В этом уроке мы построим специальный контроллер консоли Yii2 (commands/TelegramController.php), который напрямую взаимодействует с API Telegram Bot через cURL. Мы выполним четыре основных операции: тестирование учетных данных бота с getMe, регистрация URL-адреса общедоступного веб-перехватчика с помощью setWebhook (в том числе секретный токен инъекции), удаление веб-перехватчиков с помощью deleteWebhookи отсечение журналов архивных необработанных обновлений из локального дискового хранилища.
В этом руководстве основное внимание уделяется управлению жизненным циклом администратора и хранению журнала обновлений. Он не распространяется на написание полного диалогового механизма маршрутизации, обработку демонов с длительным поиском или создание пользовательского интерфейса сообщения.
---
Шаг 1. Настройка параметров API Telegram
Храните токены API в переменных среды или параметрах приложения Yii2. Избегайте жесткого кодирования маркеров внутри кода контроллера или файлов конфигурации, контролируемых версиями.
Добавьте конфигурацию в config/params.php:
<?php
return [
'telegram.botToken' => getenv('TELEGRAM_BOT_TOKEN') ?: '',
'telegram.secretToken' => getenv('TELEGRAM_SECRET_TOKEN') ?: '',
'telegram.webhookUrl' => getenv('TELEGRAM_WEBHOOK_URL') ?: '',
'telegram.logDir' => '@runtime/telegram-logs',
];
Убедитесь, что config/console.php включает пространство имен команд и правильно загружает params.php:
<?php
$params = require __DIR__ . '/params.php';
$config = [
'id' => 'basic-console',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'app\commands',
'components' => [
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
],
'params' => $params,
];
return $config;
---
Шаг 2. Внедрение контроллера консоли
Создать commands/TelegramController.php. Этот класс обрабатывает API-коммуникации с использованием стандартных функций PHP cURL. Он проверяет коды состояния http, декодирует структуры JSON, обрабатывает полезные нагрузки сбоя на уровне API (ok = false;) и регистрирует ошибку, выводимую непосредственно в Консоль::error.
<?php
namespace app\commands;
use Yii;
use yii\console\Controller;
use yii\console\ExitCode;
use yii\helpers\Console;
use yii\helpers\FileHelper;
class TelegramController extends Controller
{
/**
* @var string Output formatting verbosity level.
*/
public $defaultAction = 'health';
/**
* Executes getMe to verify bot token validity and connection health.
*/
public function actionHealth(): int
{
$this->stdout("Checking Telegram API connectivity...
", Console::FG_BLUE);
$response = $this->sendApiRequest('getMe');
if (!$response['ok']) {
$this->stderr("Health Check Failed: {$response['description']}
", Console::FG_RED);
return ExitCode::UNSPECIFIED_ERROR;
}
$bot = $response['result'];
$this->stdout("Bot ID: {$bot['id']}
", Console::FG_GREEN);
$this->stdout("Username: @{$bot['username']}
", Console::FG_GREEN);
$this->stdout("Can Join Groups: " . ($bot['can_join_groups'] ? 'Yes' : 'No') . "
");
$this->stdout("Can Read All Group Messages: " . ($bot['can_read_all_group_messages'] ? 'Yes' : 'No') . "
");
return ExitCode::OK;
}
/**
* Registers a webhook URL with Telegram.
*
* @param string|null $url Custom webhook URL. Defaults to params configuration.
*/
public function actionSetWebhook(?string $url = null): int
{
$targetUrl = $url ?? Yii::$app->params['telegram.webhookUrl'];
$secretToken = Yii::$app->params['telegram.secretToken'];
if (empty($targetUrl)) {
$this->stderr("Error: Webhook URL is not specified.
", Console::FG_RED);
return ExitCode::DATAERR;
}
$params = [
'url' => $targetUrl,
'max_connections' => 40,
'allowed_updates' => ['message', 'callback_query', 'my_chat_member'],
];
if (!empty($secretToken)) {
$params['secret_token'] = $secretToken;
}
$this->stdout("Setting webhook to: {$targetUrl}
");
$response = $this->sendApiRequest('setWebhook', $params);
if (!$response['ok']) {
$this->stderr("Failed to set webhook: {$response['description']}
", Console::FG_RED);
return ExitCode::UNSPECIFIED_ERROR;
}
$this->stdout("Success: {$response['result']}
", Console::FG_GREEN);
return ExitCode::OK;
}
/**
* Deletes the currently registered webhook.
*
* @param bool $dropPending Whether to drop pending updates stored on Telegram servers.
*/
public function actionDeleteWebhook(bool $dropPending = false): int
{
$this->stdout("Removing webhook configuration...
");
$params = [
'drop_pending_updates' => $dropPending,
];
$response = $this->sendApiRequest('deleteWebhook', $params);
if (!$response['ok']) {
$this->stderr("Failed to delete webhook: {$response['description']}
", Console::FG_RED);
return ExitCode::UNSPECIFIED_ERROR;
}
$this->stdout("Webhook successfully deleted.
", Console::FG_GREEN);
return ExitCode::OK;
}
/**
* Prunes update log files older than a specified number of days.
*
* @param int $days Number of days to keep logs.
*/
public function actionRotateLogs(int $days = 7): int
{
$logDir = Yii::getAlias(Yii::$app->params['telegram.logDir']);
if (!is_dir($logDir)) {
$this->stdout("Log directory does not exist: {$logDir}
", Console::FG_YELLOW);
return ExitCode::OK;
}
$cutoffTimestamp = time() - ($days * 86400);
$files = FileHelper::findFiles($logDir, ['only' => ['*.json', '*.log']]);
$deletedCount = 0;
foreach ($files as $file) {
if (filemtime($file) < $cutoffTimestamp) {
if (@unlink($file)) {
$deletedCount++;
} else {
$this->stderr("Could not delete file: {$file}
", Console::FG_RED);
}
}
}
$this->stdout("Log cleanup complete. Removed {$deletedCount} log files older than {$days} days.
", Console::FG_GREEN);
return ExitCode::OK;
}
/**
* Helper method to send HTTP Requests to Telegram Bot API via cURL.
*/
private function sendApiRequest(string $method, array $params = []): array
{
$token = Yii::$app->params['telegram.botToken'];
if (empty($token)) {
return [
'ok' => false,
'description' => 'TELEGRAM_BOT_TOKEN parameter is missing or empty.',
];
}
$url = "https://api.telegram.org/bot{$token}/{$method}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($params));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
$rawResponse = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
if ($rawResponse === false) {
return [
'ok' => false,
'description' => "cURL network error: {$curlError}",
];
}
$decoded = json_decode($rawResponse, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return [
'ok' => false,
'description' => "Failed to parse API response JSON. Raw output: " . substr($rawResponse, 0, 100),
];
}
if ($httpCode !== 200 && !isset($decoded['description'])) {
$decoded['description'] = "HTTP response status code {$httpCode}";
}
return $decoded;
}
}
---
Шаг 3: Использование команд и интеграция развертывания
С установленным контроллером проверьте свои команды, используя стандартные Yii Исполняемый файл CLI.
#### 1. Проверка учетных данных API Запустите Health ("Здоровье") команда для проверки того, что ваш TELEGRAM_BOT_TOKEN является правильным, и доступ к сети api.telegram.org беспрепятственно:
php yii telegram/health
Ожидаемые результаты
Checking Telegram API connectivity...
Bot ID: 123456789
Username: @MyProductionBot
Can Join Groups: Yes
Can Read All Group Messages: No
#### 2. Регистрация веб-перехватчиков для промежуточного или производственного развертывания может вызвать Установить веб-перехватчик автоматически в непрерывных интеграционных трубопроводах. Вы можете передать целевой URL-адрес веб-перехватчика в качестве явного параметра или позволить Yii2 забрать его из вашего Защита экологии Конфигурация:
php yii telegram/set-webhook "https://example.com/telegram/webhook"
Если запрос выполнен успешно, Telegram возвращается true, и ваш определенный секретный заголовок привязан ко всем входящим СООБЩЕНИЯМ, отправленным Telegram.
#### 3. Удаление веб-перехватчика в режиме обслуживания или обслуживания При переводе приложения в режим обслуживания или миграции серверных сред запустите Удалить вебхук. Чтобы отменить входящие обновления в очереди во время окон обслуживания, передайте --dropPending=1 flag:
php yii telegram/delete-webhook 1
#### 4. Автоматическая ротация журнала через System Cron Если ваш контроллер веб-перехватчика записывает необработанные полезные данные JSON в локальные файлы журнала (например, внутри @runtime/telegram-logs/YYYY-MM-DD.json), необходимо очистить старые журналы, чтобы контролировать использование диска. Настройте системное задание cron на вашем сервере для ежедневного выполнения ротации журналов:
# /etc/cron.d/telegram-maintenance
0 3 * * * www-data /usr/bin/php /var/www/my-app/yii telegram/rotate-logs 14 > /dev/null 2>&1
Это расписание выполняется каждую ночь в 3:00 утра, удаляя файлы обновлений старше 14 дней без ручного вмешательства.
---
Аспекты производства и безопасности
1. Применить секретный токен Валидация: Всегда проходите безопасную проверку секретный токен строка, содержащая от 1 до 256 буквенно-цифровых символов или подчеркиваний при вызове setWebhook. При обработке входящих HTTP-запросов POST в вашем веб-контроллере убедитесь, что заголовок X-Telegram-Bot-Api-Secret-Token соответствует этому секретному значению, используя hash_equals(). 2. Ограничить типы обновлений Используйте allowed_updates параметр массива в setWebhook указывать только полезные данные событий, которые явно обрабатывает ваше приложение (например, ['message', 'callback_query']). Ограничение типов не позволяет Telegram доставлять ненужные категории полезной нагрузки, снижая нагрузку на сеть и накладные расходы. 3. Таймауты и повторы: Установить строгие тайм-ауты (CURLOPT_TIMEOUT 10 секунд или меньше) в ваших административных вызовах API. Если Telegram испытывает частичную деградацию службы, задачи обслуживания CLI должны быстро завершаться, а не блокировать сценарии развертывания или очереди фоновых рабочих на неопределенный срок. 4. Разрешения: Убедитесь, что системный пользователь выполняет консольную команду (например, www-data или опубликовать) имеет разрешения на чтение и запись на @runtime/telegram-logs Выполнение rotate-logs учреждения.
Если вам нужна команда для работы с пользовательской архитектурой интеграции Telegram, веб-перехватчиками и инфраструктурой бэкенда Mini App, рассмотрите возможность работы с BotCreator.