Клавиатуры

Reply Keyboard

Полное руководство по Reply Keyboard в Telegram Bot API на PHP. Разбираем параметры ReplyKeyboardMarkup, отправку кнопок, обработку контактов и геопозиции, а также удаление клавиатуры.

Reply Keyboard (обычная, или «шаблонная» клавиатура) — это элемент интерфейса Telegram, который заменяет стандартную системную клавиатуру устройства пользователя набором заранее подготовленных кнопок. В отличие от Inline Keyboard, эти кнопки не прикрепляются к конкретным сообщениям, а располагаются в нижней части экрана, прямо под полем ввода текста.

Принцип работы и отличие от Inline Keyboard

Главное архитектурное отличие Reply Keyboard заключается в способе передачи данных на ваш сервер:

  • При нажатии на кнопку Reply Keyboard клиент Telegram автоматически отправляет в чат обычное текстовое сообщение от имени пользователя. Текст этого сообщения в точности совпадает с надписью на кнопке.
  • Ваш бот получает стандартный объект Update с типом message. Никаких событий callback_query в данном случае не генерируется.
  • Пользователь может в любой момент скрыть клавиатуру и написать тот же текст руками — для вашего обработчика на сервере результат будет абсолютно одинаковым.

Reply Keyboard идеально подходит для построения главного меню бота («Каталог», «Профиль», «Корзина»), быстрого выбора ответов в опросах или безопасного запроса конфиденциальных данных (номер телефона, геолокация).

Параметры ReplyKeyboardMarkup

Клавиатура передаётся в параметре reply_markup метода sendMessage (или любого другого метода отправки медиа) в виде JSON-строки. Объект клавиатуры поддерживает следующие настройки:

  • keyboard (массив массивов объектов KeyboardButton) — двумерная сетка кнопок. Каждый вложенный массив представляет собой один горизонтальный ряд.
  • resize_keyboard (boolean) — по умолчанию false. Если оставить его выключенным, кнопки будут огромными (высотой со стандартную клавиатуру телефона). Всегда устанавливайте true, чтобы кнопки аккуратно сжимались под размер текста.
  • one_time_keyboard (boolean) — если true, клавиатура автоматически скроется сразу после нажатия на любую кнопку. Её можно будет вернуть, нажав на специальную иконку в поле ввода.
  • input_field_placeholder (string) — текст-подсказка, который отображается в поле ввода, когда клавиатура активна (например, «Выберите пункт меню...»). Максимум 64 символа.
  • is_persistent (boolean) — если true, клавиатура будет отображаться всегда, даже когда открыта стандартная системная клавиатура для ввода текста.
  • selective (boolean) — позволяет показывать клавиатуру только конкретным пользователям. Полезно в групповых чатах, чтобы не спамить интерфейс всем участникам.

Отправка Reply Keyboard на PHP

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

<?php
// send_keyboard.php

// ID чата, куда отправляем клавиатуру.
// Значение chat_id мы научились получать в главе https://api.telegram.org/ или в разделе про webhook.
$chatId = 123456789;

// Описываем структуру клавиатуры
$keyboardMarkup = [
'keyboard' => [
[
['text' => '🛍️ Каталог'],
['text' => '🛒 Корзина']
],
[
['text' => '📱 Поделиться контактом', 'request_contact' => true],
['text' => '📍 Отправить локацию', 'request_location' => true]
],
[
['text' => '❓ Помощь']
]
],
'resize_keyboard' => true,
'one_time_keyboard' => false,
'input_field_placeholder' => 'Выберите действие...'
];

try {
$response = telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Добро пожаловать в наше меню! Используйте кнопки ниже для навигации.',
'reply_markup' => json_encode($keyboardMarkup)
]);

echo "Запрос успешно выполнен. Результат:\n";
print_r($response);
} catch (Exception $e) {
echo "Произошла ошибка: " . $e->getMessage() . "\n";
}

Анализ успешного ответа API

При успешной отправке сообщения с клавиатурой Telegram возвращает стандартный объект Message. Обратите внимание, что сама структура клавиатуры в ответе не дублируется — API лишь подтверждает факт отправки текстового сообщения:

{
"ok": true,
"result": {
"message_id": 1024,
"from": {
"id": 987654321,
"is_bot": true,
"first_name": "My Helper Bot",
"username": "my_helper_bot"
},
"chat": {
"id": 123456789,
"first_name": "Ivan",
"type": "private"
},
"date": 1672531199,
"text": "Добро пожаловать в наше меню! Используйте кнопки ниже для навигации."
}
}

Если в ответе поле ok равно false, обязательно проверяйте description. Самая частая ошибка при отправке клавиатур — невалидный JSON в параметре reply_markup (например, забыли вызвать json_encode или передали некорректную структуру массивов).

Обработка нажатий на сервере

Когда пользователь нажимает кнопку, ваш скрипт-обработчик получает обычное сообщение. Для разбора входящих обновлений мы используем логику, описанную в главе Webhook.

Чтобы увидеть структуру входящего запроса «изнутри», вы можете записать сырой поток в файл с помощью file_put_contents('update.json', file_get_contents('php://input')). Ниже представлен пример обработки текстовых кнопок, а также специальных кнопок отправки контакта и геолокации.

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

<?php
// webhook_handler.php

$rawInput = file_get_contents('php://input');
$update = json_decode($rawInput, true);

if (isset($update['message'])) {
$message = $update['message'];
$chatId = $message['chat']['id'];

// 1. Обработка текстовых кнопок
if (isset($message['text'])) {
$text = $message['text'];

switch ($text) {
case '🛍️ Каталог':
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Загружаю актуальный список товаров...'
]);
break;

case '🛒 Корзина':
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Ваша корзина пуста. Добавьте товары из каталога.'
]);
break;

case '❓ Помощь':
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Вы можете управлять ботом с помощью кнопок меню.'
]);
break;
}
}

// 2. Обработка кнопки отправки контакта
if (isset($message['contact'])) {
$contact = $message['contact'];
$phoneNumber = $contact['phone_number'];
$firstName = $contact['first_name'];

// Безопасность: проверяем, совпадает ли user_id контакта с id отправителя,
// чтобы пользователь не прислал чужой контакт из телефонной книги.
if (isset($contact['user_id']) && $contact['user_id'] === $message['from']['id']) {
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => "Спасибо, {$firstName}! Ваш номер {$phoneNumber} успешно верифицирован."
]);
} else {
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Пожалуйста, отправьте именно свой контакт через кнопку.'
]);
}
}

// 3. Обработка кнопки отправки геолокации
if (isset($message['location'])) {
$location = $message['location'];
$latitude = $location['latitude'];
$longitude = $location['longitude'];

telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => "Координаты приняты! Широта: {$latitude}, Долгота: {$longitude}"
]);
}
}

Как удалить клавиатуру

Reply Keyboard не исчезает сама по себе (даже если включен параметр one_time_keyboard, она лишь сворачивается в иконку). Чтобы полностью убрать её с экрана пользователя, необходимо отправить специальный объект ReplyKeyboardRemove в параметре reply_markup очередного сообщения.

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

<?php
// remove_keyboard.php

$chatId = 123456789;

$removeMarkup = [
'remove_keyboard' => true,
'selective' => false
];

try {
telegramApi('sendMessage', [
'chat_id' => $chatId,
'text' => 'Переходим в стандартный режим ввода. Клавиатура скрыта.',
'reply_markup' => json_encode($removeMarkup)
]);
echo "Клавиатура успешно удалена из интерфейса чата.\n";
} catch (Exception $e) {
echo "Ошибка: " . $e->getMessage() . "\n";
}

Важные ограничения и особенности

  • Отсутствие скрытых данных: В отличие от Inline-кнопок, где есть скрытый параметр callback_data, обычные кнопки отправляют только видимый текст. Если вы измените название кнопки (например, исправите опечатку), старый обработчик на PHP перестанет на неё реагировать. Придётся менять условия в switch.
  • Проблема локализации: Если ваш бот мультиязычный, вам придётся проверять текст кнопок на всех поддерживаемых языках либо использовать FSM (конечные автоматы) для отслеживания текущего контекста пользователя.
  • Перекрытие интерфейса в группах: В групповых чатах Reply Keyboard может мешать общению. Используйте параметр selective => true, чтобы клавиатура появлялась только у того пользователя, который вызвал команду.

Дальше: Команды /start, /help