PHP开发Viber API机器人无法保存用户消息问题求助
Viber机器人消息保存功能失效的问题排查与修复
你的Viber API机器人无法保存用户消息,核心问题出在会话存储方式错误、日志记录不全以及未处理Viber webhook的规范要求,以下是具体诊断和修复方案:
关键问题诊断
Session无法跨webhook请求保存数据
Viber的webhook请求来自官方服务器,不会携带用户端Cookie,每次请求都是全新的PHP会话,$_SESSION中的数据无法在不同请求间保留,自然无法持久化用户消息。日志记录缺失关键数据
当前代码仅记录$_POST内容,但Viber的webhook请求是通过JSON格式发送到php://input,而非传统表单POST数据,导致你无法看到Viber实际发送的消息内容,无法排查数据是否正确接收。未处理Viber webhook验证与响应要求
设置Viber webhook时,官方会发送验证请求;且所有webhook请求都要求服务器返回200 OK响应,否则Viber会重复发送请求,你的代码直接exit可能导致响应不符合规范。
修复方案
1. 替换Session为持久化存储
使用文件或数据库存储用户消息,通过Viber消息中的sender.id关联用户,确保不同请求能读取到对应用户的消息。
2. 完善日志记录
同时记录php://input的内容,完整捕获Viber发送的所有数据。
3. 处理webhook验证与规范响应
添加对Viber验证请求的处理,并确保所有POST请求返回200状态码。
修改后的代码示例
<?php error_reporting(E_ALL); ini_set('display_errors', 1); // 完善日志记录,捕获所有请求数据 $rawInput = file_get_contents('php://input'); file_put_contents('log.txt', "[" . date('Y-m-d H:i:s') . "] Incoming Request: " . $rawInput . "\n", FILE_APPEND); $authToken = '519567c55ba7dedd-bac773fe8df25c35-98130217c0617a4b'; $recipientId = '+ilW7lfATztDKWDskZSHjA=='; // 用文件存储替代Session,文件路径可自行调整 $storageFile = 'user_messages.json'; function sendKeyboardMessage($authToken, $recipientId) { $headers = [ 'Content-Type: application/json', 'X-Viber-Auth-Token: ' . $authToken ]; $data = [ 'receiver' => $recipientId, 'type' => 'text', 'text' => 'Please type your message in the chat box below and hit send.', 'keyboard' => [ 'Type' => 'keyboard', 'Buttons' => [ [ 'ActionType' => 'reply', 'ActionBody' => 'type_message', 'Text' => 'Type a message' ] ] ] ]; $ch = curl_init('https://chatapi.viber.com/pa/send_message'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); if (curl_errno($ch)) { file_put_contents('log.txt', "[" . date('Y-m-d H:i:s') . "] Curl Error: " . curl_error($ch) . "\n", FILE_APPEND); } curl_close($ch); return $response; } // 读取已存储的用户消息 function getSavedMessage($userId) { global $storageFile; if (!file_exists($storageFile)) { return ''; } $messages = json_decode(file_get_contents($storageFile), true) ?? []; return $messages[$userId] ?? ''; } // 保存用户消息 function saveMessage($userId, $message) { global $storageFile; $messages = json_decode(file_get_contents($storageFile), true) ?? []; $messages[$userId] = $message; file_put_contents($storageFile, json_encode($messages)); } if ($_SERVER['REQUEST_METHOD'] === 'POST') { $jsonData = json_decode($rawInput, true); // 处理Viber webhook验证请求 if (isset($jsonData['event']) && $jsonData['event'] === 'webhook') { echo $jsonData['event_token']; http_response_code(200); exit; } // 处理用户消息 if (isset($jsonData['message']['text'], $jsonData['sender']['id'])) { $incomingMessage = $jsonData['message']['text']; $userId = $jsonData['sender']['id']; if ($incomingMessage !== 'type_message') { saveMessage($userId, $incomingMessage); file_put_contents('log.txt', "[" . date('Y-m-d H:i:s') . "] Saved message for user $userId: $incomingMessage\n", FILE_APPEND); } } else { file_put_contents('log.txt', "[" . date('Y-m-d H:i:s') . "] No valid message or sender ID detected\n", FILE_APPEND); } // 返回规范的200响应 http_response_code(200); exit; } else { // GET请求时发送键盘消息(仅测试用,实际webhook应仅处理POST) echo "No POST detected. Sending keyboard message...<br>"; sendKeyboardMessage($authToken, $recipientId); $lastSaved = getSavedMessage($recipientId); echo "Last saved message: $lastSaved<br>"; } ?>
额外调试建议
- 查看
log.txt文件,确认Viber是否发送了包含message.text和sender.id的JSON数据 - 检查
user_messages.json文件的权限,确保PHP有读写权限 - 确认Viber后台设置的webhook URL正确,且能正常访问
内容的提问来源于stack exchange,提问作者Victor Kemp
相关产品推荐
相关产品推荐

