为什么我的webhook无法正常工作?我没有从电报bot API获得任何数据。以下是我的问题的详细解释:
我从StartSSL获得了 SSL证书,它在我的网站上工作正常(根据GeoCerts SSL checker),但似乎我对Telegram Bot API的webhook不起作用(尽管它说webhook已设置我没有得到任何数据。)
我正在以这种形式在我的网站上发布我的脚本:
https://api.telegram.org/bot<token>/setWebhook?url=https://mywebsite.com/path/to/giveawaysbot.php
我在回复中得到了这个文字:
{"ok":true,"result":true,"description":"Webhook was set"}
所以它必须有效,但事实上并非如此。
这是我的脚本代码:
<?php
ini_set('error_reporting', E_ALL);
$botToken = "<token>";
$website = "https://api.telegram.org/bot".$botToken;
$update = file_get_contents('php://input');
$update = json_decode($update);
print_r($update); // this is made to check if i get any data or not
$chatId = $update["message"]["chat"]["id"];
$message = $update["message"]["text"];
switch ($message) {
case "/test":
sendMessage($chatId,"test complete");
break;
case "/hi":
sendMessage($chatId,"hey there");
break;
default:
sendMessage($chatId,"nono i dont understand you");
}
function sendMessage ($chatId, $message) {
$url = $GLOBALS[website]."/sendMessage?chat_id=".$chatId."&text=".urlencode($message);
file_get_contents($url);
}
?>
我实际上并没有收到$ update的任何数据。所以webhook无效。为什么呢?
答案 0 :(得分:7)
我遇到了这个问题。我试图到处寻找并找不到我的问题的解决方案,因为人们总是说问题是SSL证书。但是我发现了这个问题,而且代码中缺少很多与电报API webhook相互作用的东西,包括卷曲和这种东西。在我查看电报机器人文档的示例后,我解决了我的问题。看一下这个例子https://core.telegram.org/bots/samples/hellobot
<?php
//telegram example
define('BOT_TOKEN', '12345678:replace-me-with-real-token');
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');
function apiRequestWebhook($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
$parameters["method"] = $method;
header("Content-Type: application/json");
echo json_encode($parameters);
return true;
}
function exec_curl_request($handle) {
$response = curl_exec($handle);
if ($response === false) {
$errno = curl_errno($handle);
$error = curl_error($handle);
error_log("Curl returned error $errno: $error\n");
curl_close($handle);
return false;
}
$http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE));
curl_close($handle);
if ($http_code >= 500) {
// do not wat to DDOS server if something goes wrong
sleep(10);
return false;
} else if ($http_code != 200) {
$response = json_decode($response, true);
error_log("Request has failed with error {$response['error_code']}: {$response['description']}\n");
if ($http_code == 401) {
throw new Exception('Invalid access token provided');
}
return false;
} else {
$response = json_decode($response, true);
if (isset($response['description'])) {
error_log("Request was successfull: {$response['description']}\n");
}
$response = $response['result'];
}
return $response;
}
function apiRequest($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
foreach ($parameters as $key => &$val) {
// encoding to JSON array parameters, for example reply_markup
if (!is_numeric($val) && !is_string($val)) {
$val = json_encode($val);
}
}
$url = API_URL.$method.'?'.http_build_query($parameters);
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
return exec_curl_request($handle);
}
function apiRequestJson($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
$parameters["method"] = $method;
$handle = curl_init(API_URL);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
return exec_curl_request($handle);
}
function processMessage($message) {
// process incoming message
$message_id = $message['message_id'];
$chat_id = $message['chat']['id'];
if (isset($message['text'])) {
// incoming text message
$text = $message['text'];
if (strpos($text, "/start") === 0) {
apiRequestJson("sendMessage", array('chat_id' => $chat_id, "text" => 'Hello', 'reply_markup' => array(
'keyboard' => array(array('Hello', 'Hi')),
'one_time_keyboard' => true,
'resize_keyboard' => true)));
} else if ($text === "Hello" || $text === "Hi") {
apiRequest("sendMessage", array('chat_id' => $chat_id, "text" => 'Nice to meet you'));
} else if (strpos($text, "/stop") === 0) {
// stop now
} else {
apiRequestWebhook("sendMessage", array('chat_id' => $chat_id, "reply_to_message_id" => $message_id, "text" => 'Cool'));
}
} else {
apiRequest("sendMessage", array('chat_id' => $chat_id, "text" => 'I understand only text messages'));
}
}
define('WEBHOOK_URL', 'https://my-site.example.com/secret-path-for-webhooks/');
if (php_sapi_name() == 'cli') {
// if run from console, set or delete webhook
apiRequest('setWebhook', array('url' => isset($argv[1]) && $argv[1] == 'delete' ? '' : WEBHOOK_URL));
exit;
}
$content = file_get_contents("php://input");
$update = json_decode($content, true);
if (!$update) {
// receive wrong update, must not happen
exit;
}
if (isset($update["message"])) {
processMessage($update["message"]);
}
?>
答案 1 :(得分:3)
我有类似的问题。现在解决了。 问题可能在于错误的公共证书。请按照我在项目中提出的注意说明进行操作:
openssl req -newkey rsa:2048 -sha256 -nodes -keyout /your_home/BOTServer/ssl/PRIVATE.key -x509 -days 365 -out /your_home/BOTServer/ssl/PUBLIC.pem -subj "/C=IT/ST=state/L=location/O=description/CN=your_domain.com"
电报setWebhooks API不会检查自签名数字证书中的数据,返回&#34; ok&#34;即使您举例说明您没有指定有效/ CN!因此,请小心生成包含与您的REAL HOST域名对应的 / CN = your_domain的公开.pem证书!
答案 2 :(得分:2)
可能是SSL证书。我遇到了同样的问题:Webhook确认但实际上SSL证书已被证实。
这个reddit主题很有帮助:https://www.reddit.com/r/Telegram/comments/3b4z1k/bot_api_recieving_nothing_on_a_correctly/
答案 3 :(得分:1)
我也有这个问题,不知怎么电报没有运行我的机器人,所以我试图更新证书并再次设置网络挂钩,但它再次没有用,所以我更新了我的VPS(yum更新)然后续订我的证书并再次设置Web挂钩。之后它再次开始工作。
答案 4 :(得分:0)
这是因为您没有像这样设置证书
curl -F "url=https://bot.sapamatech.com/tg" -F "certificate=@/etc/apache2/ssl/bot.pem" https://api.telegram.org/bot265033849:AAHAs6vKVlY7UyqWFUHoE7Toe2TsGvu0sf4/setWebhook
检查link如何设置电报自签名证书
答案 5 :(得分:0)
这可能有助于使用Laravel Telegram SDK。
我在Laravel 5.3中遇到了自签名webhook的问题。
设置并从Telegram获得OK结果并显示“Webhook已设置”消息后,它无法正常工作。
问题与CSRF验证有关。所以我将webhook网址添加到CSRF例外中,现在一切都像魅力一样。
答案 6 :(得分:0)
试试这段代码。如果您的Web主机上有一个有效的SSL并且您已正确运行setWebhook,它应该可以工作(对我而言)。确保创建一个名为“log.txt”的文件并为其提供写入权限:
<?php
define('BOT_TOKEN', '????');
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');
// read incoming info and grab the chatID
$content = file_get_contents("php://input");
$update = json_decode($content, true);
$chatID = $update["message"]["chat"]["id"];
$message = $update["message"]["text"];
// compose reply
$reply ="";
switch ($message) {
case "/start":
$reply = "Welcome to Siamaks's bot. Type /help to see commands";
break;
case "/test":
$reply = "test complete";
break;
case "/hi":
$reply = "hey there";
break;
case "/help":
$reply = "commands: /start , /test , /hi , /help ";
break;
default:
$reply = "NoNo, I don't understand you";
}
// send reply
$sendto =API_URL."sendmessage?chat_id=".$chatID."&text=".$reply;
file_get_contents($sendto);
// Create a debug log.txt to check the response/repy from Telegram in JSON format.
// You can disable it by commenting checkJSON.
checkJSON($chatID,$update);
function checkJSON($chatID,$update){
$myFile = "log.txt";
$updateArray = print_r($update,TRUE);
$fh = fopen($myFile, 'a') or die("can't open file");
fwrite($fh, $chatID ."nn");
fwrite($fh, $updateArray."nn");
fclose($fh);
}
答案 7 :(得分:0)
我也有这个问题。就我而言,在声明我的API方法时出错。我首先创建了GET方法而不是POST。
@api.route('/my-webhook-url')
class TelegramWebhook(Resource):
def post(self): # POST, Carl!
# ...
return response
答案 8 :(得分:0)
再等一会,您的网络钩子为什么不起作用。
就我而言,原因是在 allowed_updates webhook参数中。
通过致电:
https://api.telegram.org/bot<your_bot_token>/getWebhookInfo
您可以看到
{
"ok": true,
"result": {
"url": "<your webhook url should be here>",
"has_custom_certificate": false,
"pending_update_count": 0,
"max_connections": 40,
"allowed_updates": [
"callback_query"
]
}
}
这意味着您的漫游器无法对您的短信做出反应,并且您不会收到任何网络响声!
您可以注意到,“ allowed_updates”包含数组。因此,当前它将仅对嵌入式按钮事件做出反应(作为键盘布局传递!)。
要开始接收文本消息,您需要在“ allowed_updates”道具中添加“消息”。为此,只需再次设置您的webhook并将其添加到查询中即可。就像这里:
https://api.telegram.org/<your_token>/setWebHook?url=<your_url>&allowed_updates=["callback_query","message"]
您将收到类似“已添加URL”的信息,但是请放心,即使在这种情况下,allowed_updates也会被更新。只需尝试键入您要发送给机器人的消息并测试您的网络钩子即可。
仅此而已,电报将向您发送给机器人的每条直接消息发送Webhooks。希望对别人有所帮助。
答案 9 :(得分:0)
就我而言,错误是由于 PHP 配置(使用 cPanel)造成的
[26-Jan-2021 09:38:17 UTC] PHP Warning: file_get_contents(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /home/myUsername/public_html/mydomain.com/my_bot_file.php on line 40
和
[26-Jan-2021 09:38:17 UTC] PHP Warning: file_get_contents(https://api.telegram.org/bot<my-bot-id>/sendmessage?chat_id=647778451&text=hello charlie ! k99 ): failed to open stream: no suitable wrapper could be found in /home/myUsername/public_html/myDomain.com/my_bot_file.php on line 40
所以 - 这是不言自明的。
php 配置中的 allow_url_fopen=0
变量实际上禁用了所需的操作。
但无论如何,您最好的办法是查看服务器上的 error log
并查看脚本或服务器配置中是否存在任何其他错误。