Выполнение запросов sendMessage в Telegram на Raw PHP: таймауты, JSON-парсинг и санация HTML

Для выполнения стандартных HTTP-запросов к API Telegram Bot с использованием необработанного PHP требуется больше, чем просто file_get_contents() вызов. Производственные среды требуют явных элементов управления тайм-аутом, проверки сетевых ошибок, допустимого синтаксического анализа JSON, обработки полезных нагрузок ошибок на уровне API Telegram и строгого экранирования вывода для отформатированного текста.

В этом руководстве мы создадим готовую к работе PHP-функцию для выполнения SendMessage запросы через cURL. Мы рассмотрим сетевые таймауты, проверку HTTP-статуса, безопасность декодирования JSON, обработку ошибок на уровне Telegram и экранирование динамических строк при отправке сообщений в формате HTML. Мы не будем настраивать обработчики веб-перехватчиков, обрабатывать входящие обновления или создавать фоновые процессоры очереди.

Дезинфекция динамических входных данных для Telegram HTML

Использование parse_mode=HTML, Telegram поддерживает подмножество HTML-тегов (<b>, <i>, <a>, <code>, <pre>). Если динамические данные, вставленные в ваш шаблон, содержат такие символы, как <, >или &, API Telegram не сможет проанализировать дерево сущностей и вернуть 400 Плохой запрос ошибка с описанием Bad Request: не удается проанализировать сущности.

Использование htmlspecialchars где ENT_QUOTES | ENT_REPLACE для кодирования необработанных пользовательских входов перед их интерполяцией в отформатированные строки сообщений:

function sanitizeTelegramHtml(string $text): string
{
return htmlspecialchars($text, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}

// Usage example:
$userInput = 'User <script>alert(1)</script> & "special"';
$safeUser = sanitizeTelegramHtml($userInput);

$formattedMessage = "New lead received:\n<b>Name:</b> {$safeUser}";

Сборка мессенджера cURL

Чтобы сделать надежные HTTP-запросы POST, настройте собственный cURL с тайм-аутами соединения и общего времени выполнения. Скрипт должен явно проверять три уровня отказа:

1. Транспортный уровень: ошибки cURL (например, сбой разрешения DNS, превышение времени ожидания сети). 2. HTTP-слой: HTTP-коды ответов, отличные от 200. 3. Прикладной уровень: стандартная структура JSON API Telegram, где OK является ложный.

Вот полная реализация:

<?php

declare(strict_types=1);

/**
* Sends a message to a Telegram chat using cURL.
*
* @param int|string $chatId Unique identifier for the target chat or username
* @param string $text Text of the message to be sent
* @param string $parseMode Optional formatting (e.g., 'HTML')
* @return array<string, mixed>
* @throws RuntimeException On transport, HTTP, or Telegram API failures
*/
function sendTelegramMessage(int|string $chatId, string $text, string $parseMode = 'HTML'): array
{
$botToken = getenv('TELEGRAM_BOT_TOKEN');
if (!$botToken) {
throw new RuntimeException('TELEGRAM_BOT_TOKEN environment variable is missing.');
}

$url = sprintf('https://api.telegram.org/bot%s/sendMessage', $botToken);

$payload = [
'chat_id' => $chatId,
'text' => $text,
];

if ($parseMode !== '') {
$payload['parse_mode'] = $parseMode;
}

$ch = curl_init();

curl_setopt_array($ch, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 5, // Max time allowed to establish connection
CURLOPT_TIMEOUT => 10, // Max total time allowed for request execution
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
],
]);

$response = curl_exec($ch);
$curlErrno = curl_errno($ch);
$curlError = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// 1. Check cURL network transport errors
if ($curlErrno !== 0) {
throw new RuntimeException(sprintf('cURL error [%d]: %s', $curlErrno, $curlError));
}

if (!is_string($response) || $response === '') {
throw new RuntimeException('Received empty response from Telegram API server.');
}

// 2. Decode and validate JSON format
$data = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException(sprintf(
'Failed to parse Telegram JSON response. Error: %s. Raw response: %s',
json_last_error_msg(),
$response
));
}

// 3. Check Telegram Application level status
if (!isset($data['ok']) || $data['ok'] !== true) {
$errorCode = $data['error_code'] ?? $httpCode;
$description = $data['description'] ?? 'Unknown API error occurred.';
throw new RuntimeException(sprintf(
'Telegram API Error [%d]: %s',
$errorCode,
$description
));
}

return $data;
}

Исполнение Кодекса

Вы можете запустить эту функцию в обработчике запросов или скрипте CLI, установив переменную окружения:

export TELEGRAM_BOT_TOKEN="123456789:ABCdefGHIjklMNOpqrsTUVwxyZ"
php send_message.php
try {
$chatId = 123456789;
$rawMessage = "Order update: Status changed to <b>Processing</b>.";

$result = sendTelegramMessage($chatId, $rawMessage, 'HTML');
echo "Message sent successfully. Message ID: " . $result['result']['message_id'];
} catch (RuntimeException $e) {
error_log("Telegram delivery failed: " . $e->getMessage());
}

V. СООБРАЖЕНИЯ, СВЯЗАННЫЕ С ПОДГОТОВКОЙ МАТЕРИАЛОВ

- Ограничения скорости (HTTP 429): Если Telegram отвечает HTTP-статусом 429 (Слишком много запросов), проверьте parameters.retry_after поле полезной нагрузки. Если это происходит регулярно, делегируйте исходящие сообщения базе данных или очереди Redis, а не выполняйте cURL внутри синхронных веб- HTTP-запросов. - Пользовательские блоки (HTTP 403): Если пользователь заблокировал вашего бота или удалил чат, Telegram возвращается 403 Forbidden Описание Запрещено: бот был заблокирован пользователем. Ловите эту ошибку специально, чтобы пометить записи пользователей как неактивные в вашей базе данных. - Альтернатива полезной нагрузки JSON: в приведенном выше примере используется application/x-www-form-urlencoded. Если ваша полезная нагрузка включает сложные вложенные массивы (например, reply_markup inline keybaords), закодируйте всю полезную нагрузку с помощью json_encode() и отправьте его вместе с Использовать Content-Type = application/json вместо заголовка.

Нужно масштабировать пользовательскую автоматизацию, веб-перехватчики или бессерверную инфраструктуру для систем обмена сообщениями? Свяжитесь с BotCreator — студией, которая поставляет Telegram-ботов /мини-приложения.

Новые статьи — в Telegram

Разбираем, что автоматизировать в бизнесе и как это работает на практике. Без спама.