Got problems with webhook to Telegram Bot API

37,900

Solution 1

I was with this problem. I was trying to look everywhere and couldn't find the solution for my problem, because people were all the time saying that the problem was the SSL certificate. But I found the problem, and that were a lot of things missing on the code to interact with the telegram API webhook envolving curl and this kind of stuff. After I looked in an example at the telegram bot documentation, I solved my problem. Look this example 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"]);
}
?>

Solution 2

Just another one moment, why your webhooks not work.

In my case the reason was in allowed_updates webhook parameter.

By calling :

https://api.telegram.org/bot<your_bot_token>/getWebhookInfo

You can see

{
  "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"
    ]
  }
}

It means, that your bot can't react to your text messages, and you will not receive any webhooks!

You can note, that "allowed_updates" contains array. So, currently it will react only to inline button events (passed as keyboard layout!). According to the setWebhook documentation, allowed_updates is an "optional" parameter.

To start receieve text messages, you need to add "message" to your "allowed_updates" prop. To do it, just again set your webhooks and add it to query. Like here :

https://api.telegram.org/bot<your_token>/setWebHook?url=<your_url>&allowed_updates=["callback_query","message"]

You will receive something like "url already added", but don't worry, allowed_updates will be updated even in this case. Just try type your message to bot and test your webhooks.

That's all, now, telegram will send webhooks to each direct message from you to your bot. Hope, it helps someone.

Solution 3

I had similar problem. Now solved. The problem is possibly in a wrong public certificate. Please follow with attention instructions I propose in my project:

https://github.com/solyaris/BOTServer/blob/master/wiki/usage.md#step-4-create-self-signed-certificate

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"

Telegram setWebhooks API do not check data inside your self-signed digital certificate, returning "ok" even if by example you do not specify a valid /CN! So be carefull to generate a public .pem certificate containing /CN=your_domain corresponding to your REAL HOST domain name!

Solution 4

It may be the SSL cert. I had the same problem: Webhook confirmed but actually SSL cert borked.

This reddit thread was helpful: https://www.reddit.com/r/Telegram/comments/3b4z1k/bot_api_recieving_nothing_on_a_correctly/

Solution 5

This may help who works with Laravel Telegram SDK. I had a problem with self-signed webhook in Laravel 5.3. After setup and getting OK result from Telegram with "Webhook was set" message, it didn't work.
The problem was related to CSRF verification. So I added the webhook url to CSRF exceptions and now everything works like a charm.

Share:
37,900
Admin
Author by

Admin

Updated on January 26, 2021

Comments

  • Admin
    Admin over 3 years

    Why is my webhook not working? I do not get any data from telegram bot API. Here is the detailed explanation of my problem:

    I got SSL cert from StartSSL, it works fine on my website (according to GeoCerts SSL checker), but still seems like my webhook to Telegram Bot API doesn't work (despite it says that webhook was set I do not get any data).

    I am making a webhook to my script on my website in this form:

    https://api.telegram.org/bot<token>/setWebhook?url=https://mywebsite.com/path/to/giveawaysbot.php
    

    I get this text in response:

    {"ok":true,"result":true,"description":"Webhook was set"}
    

    So it must be working, but it actually doesn't.

    Here is my script code:

    <?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);
    }
    
    ?>
    

    I don't actually receive any data to $update. So webhook is not working. Why?