Cannot receive incoming JSON from Telegram webHook

2019-09-08 13:17发布

问题:

So the problem is that I have set a webHook address for my Telegram bot like this: https://api.telegram.org/bot<TOKEN>/setWebHook?url=https://evolhookah.com/Home/ReceiveWebhook

Afterwards, I received confirmation in JSON format stating that from now Telegram will send messages to that URL.

Then I created a method ReceiveWebhook(), which is responsible for handling incoming requests, which used to look like these methods (none of them worked):

    public ActionResult ReceiveJSON(int? id)
    {
        Stream req = Request.InputStream;
        req.Seek(0, System.IO.SeekOrigin.Begin);
        string receivedJson = new StreamReader(req).ReadToEnd();
        var bs = new TgDesserialize(); //Class containing JSON desserializing function
        PeopleAttributes people = bs.desserializer(receivedJson); //desserializer manages with desserializing received JSON and returns an object people filled up with necessary values
        return Content(people.firstName);
    }

Unfortunately idea with a stream did NOT work, then I decided to receive incoming JSON as a string, and this is how it looked like:

    public ActionResult JSONString(String receivedJSON)
    {
        var bs = new TgDesserialize(); 
        PeopleAttributes people = bs.desserializer(receivedJSON); 
        return Content(people.firstName);
    }

Problem: Everytime I receive a webhook, I either get null JSON or cannot receive it properly in the controller.

Questions:

  1. Is there any possible way I can check that Telegram is sending JSON with data inside while sending a webHook?
  2. Why do I always get NULLs, while https://api.telegram.org/bot<TOKEN>/getUpdates shows that I have data inside JSON?
  3. Am I receiving my JSON in a wrong way in a controller? If yes, what is the best practice of handling incoming JSON?

回答1:

First of all, I suggest you to using telegram.bot library and looking this example for Webhook. But in general:

  1. install the Postman and post a manual message like the telegram webhook message to your controller. Then make sure there are no bugs in your controller.

A Postman sample:

{
    "update_id":10000,
    "message":{
      "date":1441645532,
      "chat":{
         "last_name":"Test Lastname",
         "id":1111111,
         "first_name":"Test",
         "username":"Test"
      },
      "message_id":1365,
      "from":{
         "last_name":"Test Lastname",
         "id":1111111,
         "first_name":"Test",
         "username":"Test"
      },
      "text":"/start"
    }

  1. if your controller is true you must make sure that the Webhook message is sent by Telegram. You can download ngrok and create a https proxy to your localhost.

Use this command in ngrok:

ngrok http 20201

20201 is your localhost port (localhost:20201). Now ngrok give you a https link, and you must set that link as your telegram webhook (just like the way you said). At this moment if telegram sends a webhook message for your bot then you can debug it in the localhost.

  1. Finally, if you do not find the problem you must read the Marvin's Patent Pending Guide to All Things Webhook to check all the requirements again.
  1. Supports IPv4, IPv6 is currently not supported for Webhooks.
  2. Accepts incoming POSTs from 149.154.167.197-233 on port 443,80,88 or 8443.
  3. Is able to handle TLS1.0+ HTTPS-traffic.
  4. Provides a supported,non-wildcard, verified or self-signed certificate.
  5. Uses a CN or SAN.that matches the domain you’ve supplied on setup.
  6. Supplies all intermediate certificates to complete a verification chain.


回答2:

You need to create a class based on the JSON from telegram.

Example:

Telegram JSON:

{ 
    "update_id": 1
    "message": { ... fill in message json here},
    .... other properties here
}

You then create a class:

public class TelegramUpdate
{
    public int update_id {get; set;}
    public Message message {get; set;}
    // other properties here
}

public class Message
{
    // message properties here
}
// ... More nested classes go here

Pro tip: If you have an example JSON-file, you can copy it, got Visual Studio=>Edit=> Paste Special=> Paste JSON as class. This will generate the classes for you

You can then add this class as a parameter to your webhook:

public ActionResult JSONString(TelegramUpdate update)
{
    return Content(update.message.from.first_name);
}


回答3:

[HttpPost]
public async Task<ActionResult> Index()
    {
        try
        {

            var req = Request.InputStream; //get Request from telegram 
            var responsString = new StreamReader(req).ReadToEnd(); //read request
            RootObject ro = JsonConvert.DeserializeObject<RootObject>(responsString);

        }
        catch (Exception ex)
        {
            return Content("Error");
        }


        // This code hint to telegram Ttat , I Get Message And dont need to send this message again
        return Content("{\"ok\":true}");

    }

You then create a class:

 public class From
{
    public int id { get; set; }
    public bool is_bot { get; set; }
    public string first_name { get; set; }
    public string username { get; set; }
    public string language_code { get; set; }
}

public class Chat
{
    public long id { get; set; }
    public string title { get; set; }
    public string type { get; set; }
    public string username { get; set; }
}

public class ForwardFromChat
{
    public long id { get; set; }
    public string title { get; set; }
    public string type { get; set; }
}

public class Document
{
    public string file_name { get; set; }
    public string mime_type { get; set; }
    public string file_id { get; set; }
    public int file_size { get; set; }
}
public class Audio
{
    public int duration { get; set; }
    public string mime_type { get; set; }
    public string title { get; set; }
    public string performer { get; set; }
    public string file_id { get; set; }
    public int file_size { get; set; }
}
public class Photo
{
    public string file_id { get; set; }
    public int file_size { get; set; }
    public int width { get; set; }
    public int height { get; set; }
}
public class Video
{
    public int duration { get; set; }
    public int width { get; set; }
    public int height { get; set; }
    public string mime_type { get; set; }
    public Thumb thumb { get; set; }
    public string file_id { get; set; }
    public int file_size { get; set; }
}
public class Thumb
{
    public string file_id { get; set; }
    public int file_size { get; set; }
    public int width { get; set; }
    public int height { get; set; }
}
public class Message
{
    public int message_id { get; set; }
    public From from { get; set; }
    public Chat chat { get; set; }
    public int date { get; set; }
    public string text { get; set; }
}

public class CaptionEntity
{
    public int offset { get; set; }
    public int length { get; set; }
    public string type { get; set; }
}

public class EditedChannelPost
{
    public int message_id { get; set; }
    public Chat chat { get; set; }
    public int date { get; set; }
    public int edit_date { get; set; }
    public string caption { get; set; }
    public List<CaptionEntity> caption_entities { get; set; }
    public string text { get; set; }
    public Document document { get; set; }
    public Video video { get; set; }
    public Audio audio { get; set; }
    public List<Photo> photo { get; set; }
}
public class ChannelPost
{
    public int message_id { get; set; }
    public Chat chat { get; set; }
    public int date { get; set; }
    public ForwardFromChat forward_from_chat { get; set; }
    public int forward_from_message_id { get; set; }
    public string forward_signature { get; set; }
    public int forward_date { get; set; }
    public string caption { get; set; }
    public string text { get; set; }
    public List<CaptionEntity> caption_entities { get; set; }
    public Document document { get; set; }
    public Video video { get; set; }
    public Audio audio { get; set; }
    public List<Photo> photo { get; set; }
}

public class RootObject
{
    public long update_id { get; set; }
    public ChannelPost channel_post { get; set; }
    public EditedChannelPost edited_channel_post { get; set; }
    public Message message { get; set; }
}

Enjoy it!