Переклад цього гайду зʼявиться незабаром. Поки що текст доступний російською — перемкніться на RU або читайте нижче. Відкрити російську версію

Повідомлення

sendMessage

sendMessage — основной метод Bot API для отправки текстового сообщения. В этой главе разберём обязательные параметры, безопасную работу с HTML-разметкой, типичные ошибки и то, как проверить ответ API в PHP.

Сигнатура метода и обязательные поля

Метод принимает chat_id (цель доставки) и text (содержимое до 4096 символов). Все остальные параметры опциональны: parse_mode, disable_web_page_preview, reply_markup и др.

Используем функцию telegramApi(), которую мы сделали в главе Первый запрос: getMe. Здесь только вызываем её — реализацию не копируем.

<?php
// reminder: telegramApi() из главы first-request
// function telegramApi(string $token, string $method, array $params = []): array { ... }

$token = getenv('TELEGRAM_BOT_TOKEN') ?: exit('TELEGRAM_BOT_TOKEN not set');
$chatId = 123456789; // замените на реальный chat_id

$result = telegramApi($token, 'sendMessage', [
'chat_id' => $chatId,
'text' => 'Привет! Это тестовое сообщение.',
]);

// Как посмотреть результат в терминале:
print_r($result);
// или для красивого JSON:
echo json_encode($result, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);

Пример успешного ответа API

{
"message_id": 42,
"date": 1725000000,
"chat": {
"id": 123456789,
"type": "private",
"first_name": "Ivan",
"username": "ivan_test"
},
"text": "Привет! Это тестовое сообщение."
}

Что смотреть: message_id — уникальный идентификатор отправленного сообщения (нужен для editMessageText, deleteMessage); date — Unix-время отправки; chat — объект чата, подтверждающий доставку. Если поле ok в обёртке равно true — сообщение ушло в очередь Telegram.

HTML parse_mode и экранирование

Telegram не экранирует текст автоматически. Передача пользовательского ввода без экранирования в режиме HTML ломает разметку и открывает вектор для инъекций ссылок/тегов. Всегда используйте htmlspecialchars с флагами ENT_QUOTES | ENT_SUBSTITUTE и кодировкой UTF-8.

Используем функцию telegramApi() из главы Первый запрос: getMe.

<?php
$safe = static fn(string $s): string =
htmlspecialchars($s, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');

$name = $_POST['name'] ?? 'Аноним';
$email = $_POST['email'] ?? 'не указан';

$result = telegramApi($token, 'sendMessage', [
'chat_id' => $chatId,
'parse_mode' => 'HTML',
'text' => "<b>Новая заявка</b>\n"
. "Имя: {$safe($name)}\n"
. "Email: {$safe($email)}",
]);

echo "OK, message_id: {$result['message_id']}\n";

Поддерживаемые HTML-теги: <b>, <i>, <u>, <s>, <code>, <pre>, <a href="...">, <tg-spoiler>. Перенос строки — обычный \n. Подробнее о разметке и MarkdownV2 — в следующей главе.

Параметр chat_id: откуда брать и ограничения

  • Личный чат: user_id (число), который приходит в message.chat.id апдейта. Бот не может написать пользователю первым, если тот не нажал /start или не писал боту.
  • Группа/супергруппа: отрицательный chat_id (например, -1001234567890). Бот должен быть участником.
  • Канал: @channelusername (публичный) или числовой chat_id (приватный). Бот должен быть администратором канала.

Получить chat_id можно, выведя $update['message']['chat']['id'] в обработчике апдейтов (см. главу getUpdates и update_id).

Типичные ошибки и как их обрабатывать

  • chat not found — неверный chat_id или бот не в чате. Проверить ID, добавить бота в группу/канал.
  • bot was blocked by the user — пользователь заблокировал бота. Удалить chat_id из рассылки, не спамить.
  • Too Many Requests: retry later (HTTP 429) — превышен лимит (30 msg/sec на чат, 20 msg/min в группу). Прочитать заголовок Retry-After, поставить в очередь, повторить через указанное время.
  • Message is too long — текст > 4096 символов. Разбить на части или отправить как документ (sendDocument).
  • Bad Request: can't parse entities — невалидный HTML/Markdown. Экранировать ввод, проверять закрывающие теги.

Используем функцию telegramApi() из главы Первый запрос: getMe.

<?php
try {
$result = telegramApi($token, 'sendMessage', [
'chat_id' => $chatId,
'text' => $longText,
]);
echo "OK, message_id: {$result['message_id']}\n";
} catch (RuntimeException $e) {
// Логируем для отладки
error_log('sendMessage failed: ' . $e->getMessage());
// Если 429 — можно извлечь Retry-After из заголовков (нужно расширить telegramApi)
// Если chat not found — пометить чат как неактивный в БД
}

Полезные опциональные параметры

  • disable_web_page_preview (bool) — отключает превью ссылок в сообщении.
  • disable_notification (bool) — отправляет без звука (silent message).
  • reply_to_message_id (int) — делает сообщение ответом на конкретное.
  • reply_markup — клавиатуры (inline/reply/force_reply), разбираются в следующих главах.

Дальше: HTML и Markdown — полное руководство по разметке.