本文详解如何在 ajax 表单提交中准确捕获并响应 php 后端(如 telegram bot api 调用)的真实错误状态,避免 `fopen()` 静默失败问题,通过 curl + http 状态码 + json 响应体实现可靠错误处理。
在前端使用 jQuery.ajax() 提交表单时,仅依赖 success 回调无法真实反映后端逻辑是否成功——因为 success 触发条件是 HTTP 请求“已发出且收到响应”(即使响应状态码为 500 或 401),而非业务逻辑成功。典型反例就是原代码中直接用 fopen() 请求 Telegram API:它不校验 HTTP 状态码,也不解析返回的 JSON,导致 Token 错误、Chat ID 无效等场景仍触发 success,掩盖了实际错误。
要真正实现错误可感知,需从前端和后端两方面协同改进:
? 后端(js/send_to_telegram.php)必须:
优化后的 PHP 示例:
|
header('Content-Type: application/json; charset=utf-8');
$token = "5306003979:AAEPK2NhlxW"; $chat_id = "497358"; $txt = !empty($_POST["text"]) ? htmlspecialchars(trim($_POST["text"])) : "";
// 简单校验输入 if (empty($txt)) { http_response_code(400); echo json_encode(["message" => "Text is required"]); exit; }
function telegramPost($url, $data) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 生产环境请启用证书验证
$response = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch);
return [ 'code' => $httpCode, 'body' => json_decode($response, true) ]; }
$result = telegramPost("https://api.telegram.org/bot{$token}/sendMessage", [ 'chat_id' => $chat_id, 'text' => $txt, 'parse_mode' => 'html' ]);
// 检查 Telegram API 是否返回 ok=true 且 HTTP 状态码正常(2xx) if ($result['code'] >= 200 && $result['code'] < 300 && !empty($result['body']['ok']) && $result['body']['ok'] === true) { http_response_code(200); echo json_encode(["message" => "ok", "sent_at" => date('c')]); } else { http_response_code(500); $errorDesc = $result['body']['description'] ?? 'Unknown Telegram API error'; echo json_encode(["message" => "Telegram failed: {$errorDesc}", "http_code" => $result['code']]); } |
? 前端(JavaScript)需增强错误处理逻辑:
增强版前端代码:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
jQuery("form").submit(function (e) { e.preventDefault(); // 阻止默认提交 var form_data = jQuery(this).serialize();
jQuery.ajax({ type: "POST", url: "js/send_to_telegram.php", data: form_data, dataType: "json", success: function (result) { donemodal.style.display = "block"; console.log("Success:", result); }, error: function (jqXHR, textStatus, errorThrown) { let errorMsg = "Submission failed."; if (jqXHR.responseJSON && jqXHR.responseJSON.message) { errorMsg = jqXHR.responseJSON.message; } else if (textStatus === "timeout") { errorMsg = "Request timed out. Please check your connection."; } else if (textStatus === "error") { errorMsg = "Server returned an error response."; } console.error("AJAX Error:", textStatus, errorThrown, jqXHR.responseJSON); document.getElementById("error-message").textContent = errorMsg; errormodal.style.display = "block"; } }); }); |
?? 重要注意事项:
通过以上改造,当 Token 错误时,Telegram API 将返回 {"ok":false,"error_code":401,"description":"Unauthorized"},PHP 正确识别并返回 500 状态码,前端 error 回调被触发,用户即可获得明确反馈——这才是健壮 Web 表单错误处理的标准实践。