Telegram API中点击内联键盘按钮后如何处理用户后续输入?
问题描述
我现在用以下代码实现Telegram机器人的内联键盘:
$arr1 = array('text' => "weather forecast", 'callback_data' => "weatherscript"); $arr2 = array('text' => "some other script", 'callback_data' => "script2"); $keyboard = array(array($arr1, $arr2)); sendInlineKeyboard($bot_id,$json_out->message->chat->id,"Wähle aus",$keyboard);
我想要实现的流程是:
- 询问用户要执行的脚本(比如天气脚本);
- 用户点击按钮后,机器人请求用户输入具体城市名称;
- 用户输入完成后,机器人返回对应城市的天气信息。
现在的困惑是:点击按钮后怎么处理用户后续的输入内容?
解决方案
核心思路是给用户维护一个交互状态,因为Telegram机器人是无状态的HTTP请求模型,每次用户操作(点击按钮/发消息)都是独立请求,必须靠外部存储(数据库、Redis甚至文件)记录用户当前处于哪个交互步骤。
步骤1:处理按钮回调,设置用户状态
当用户点击内联按钮时,Telegram会推送callback_query类型的更新。你需要捕获这个回调,根据callback_data判断用户选择的脚本,给用户设置对应状态,并发送输入提示。
示例代码(以MySQL数据库存储状态为例):
// 处理按钮回调请求 if (isset($update['callback_query'])) { $chat_id = $update['callback_query']['message']['chat']['id']; $callback_data = $update['callback_query']['data']; // 根据回调内容设置用户状态 if ($callback_data === 'weatherscript') { // 标记用户当前需要输入城市名 saveUserState($chat_id, 'waiting_for_city'); sendMessage($bot_id, $chat_id, "请输入你要查询天气的城市名称:"); } elseif ($callback_data === 'script2') { saveUserState($chat_id, 'waiting_for_script2_input'); sendMessage($bot_id, $chat_id, "请输入所需参数:"); } // 必须回复回调,否则按钮会一直显示加载状态 answerCallbackQuery($bot_id, $update['callback_query']['id']); } // 保存用户状态的函数 function saveUserState($chat_id, $state) { $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'db_user', 'db_pass'); // 用REPLACE实现存在则更新,不存在则插入 $stmt = $pdo->prepare("REPLACE INTO user_states (chat_id, current_state) VALUES (?, ?)"); $stmt->execute([$chat_id, $state]); }
步骤2:根据用户状态处理后续输入
当用户发送文本消息时,先读取该用户的当前状态,再根据状态处理输入内容:
// 处理用户文本消息 if (isset($update['message']['text'])) { $chat_id = $update['message']['chat']['id']; $user_input = $update['message']['text']; $current_state = getUserState($chat_id); // 按状态分支处理输入 if ($current_state === 'waiting_for_city') { // 调用天气接口获取数据 $weather_info = fetchWeatherData($user_input); sendMessage($bot_id, $chat_id, $weather_info); // 处理完成后重置状态 saveUserState($chat_id, 'idle'); } elseif ($current_state === 'waiting_for_script2_input') { $script_result = handleScript2($user_input); sendMessage($bot_id, $chat_id, $script_result); saveUserState($chat_id, 'idle'); } else { // 用户无状态时,显示初始内联键盘 $arr1 = array('text' => "weather forecast", 'callback_data' => "weatherscript"); $arr2 = array('text' => "some other script", 'callback_data' => "script2"); $keyboard = array(array($arr1, $arr2)); sendInlineKeyboard($bot_id, $chat_id, "Wähle aus", $keyboard); } } // 获取用户当前状态的函数 function getUserState($chat_id) { $pdo = new PDO('mysql:host=localhost;dbname=your_db', 'db_user', 'db_pass'); $stmt = $pdo->prepare("SELECT current_state FROM user_states WHERE chat_id = ?"); $stmt->execute([$chat_id]); $state = $stmt->fetchColumn(); // 默认返回idle表示无待处理状态 return $state ?: 'idle'; } // 模拟天气数据获取函数 function fetchWeatherData($city) { // 替换为实际天气API调用逻辑 return "{$city}今日天气:晴,气温26℃,风力2级"; }
关键注意事项
- 必须回复
callback_query:用户点击按钮后,Telegram会等待机器人调用answerCallbackQuery,否则按钮会一直处于加载状态。 - 状态存储选择:小体量机器人可以用文件或轻量数据库;用户量大时推荐用Redis这类内存存储,提升读写效率。
- 状态重置:处理完用户输入后,一定要将状态重置为
idle或清除,避免后续消息误触发旧逻辑。
内容的提问来源于stack exchange,提问作者user3594295
相关产品推荐
相关产品推荐

