skip to Main Content

I don’t want to use getUpdates method to retrieve updates from Telegram, but a webhook instead.

Error from getWebhookInfo is:

has_custom_certificate: false,
pending_update_count: 20,
last_error_date: 1591888018,
last_error_message: "SSL error {error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed}"

My code is:

from flask import Flask
from flask import request
from flask import Response

app = Flask(__name__)

@app.route('/', methods=['POST', 'GET']) 
def bot():
    if request.method == 'POST':
        return Response('Ok', status=200)
    else:
        return f'--- GET request ----'

if __name__ == "__main__":
    app.run(host='0.0.0.0', port='8443', debug=True, ssl_context=('./contract.crt', '.private.key'))

When I hit https://www.mydomain.ext:8443/ I can see GET requests coming but not POST ones when I write something on my telegram-bot chat
Also that’s how I set a webhook for telegram as follow:

https://api.telegram.org/botNUMBER:TELEGRAM_KEY/setWebhook?url=https://www.mydomain.ext:8443

result:

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

Any suggestion or something wrong I’ve done?

https://core.telegram.org/bots/api#setwebhook

I’m wondering if the problem it’s caused because I’m using 0.0.0.0, the reason it’s that if I use 127.0.0.0 the url/www.mydomain.ext cannot be reached

Update

ca_certitificate = {'certificate': open('./folder/ca.ca-bundle', 'rb')}
r = requests.post(url, files=ca_certitificate)
print(r.text)

that print gives me:

{
  "ok": false,
  "error_code": 400,
  "description": "Bad Request: bad webhook: Failed to set custom certificate file"
 }

3

Answers


  1. I deployed a Telegram chatbot without Flask a while ago.
    I remember that the POST and GET requests required /getUpdates and /sendMessage added to the bot url. Maybe it will help.

    Login or Signup to reply.
  2. Telegram bots only works with full chained certificates. And the error in your getWebHookInfo:

    "last_error_message":"SSL error {337047686, error:1416F086:SSL routines:tls_process_server_certificate:certificate verify failed}"
    

    Is Telegram saying that it needs the whole certificate chain (it’s also called CA Bundle or full chained certificate). as answered on the question.

    If you validate your certificate using the SSLlabs you will see that your domain have chain issues:

    https://www.ssllabs.com/ssltest/analyze.html?d=www.vallotta-party-bot.com&hideResults=on

    To solve this need you need to set the CA Certificate. In this way, you need to find the CA certificate file with your CA provider.

    Also, the best option in production sites is to use gunicorn instead of Flask.

    If you are using gunicorn, you can do this with command line arguments:

    $ gunicorn --certfile cert.pem --keyfile key.pem --ca_certs cert.ca-bundle -b 0.0.0.0:443 hello:app
    

    Or create a gunicorn.py with the following content:

    import multiprocessing
    
    bind = "0.0.0.0:443"
    
    workers = multiprocessing.cpu_count() * 2 + 1
    
    timeout = 120
    
    certfile = "cert/certfile.crt"
    
    keyfile = "cert/service-key.pem"
    
    ca_certs = "cert/cert.ca-bundle"
    
    loglevel = 'info'
    

    and run as follows:

    gunicorn --config=gunicorn.py hello:app
    

    If you use Nginx as a reverse proxy, then you can configure the certificate with Nginx, and then Nginx can "terminate" the encrypted connection, meaning that it will accept encrypted connections from the outside, but then use regular unencrypted connections to talk to your Flask backend. This is a very useful setup, as it frees your application from having to deal with certificates and encryption. The configuration items for Nginx are as follows:

    server {
        listen 443 ssl;
        server_name example.com;
        ssl_certificate /path/to/cert.pem;
        ssl_certificate_key /path/to/key.pem;
        # ...
    }
    

    Another important item you need to consider is how are clients that connect through regular HTTP going to be handled. The best solution, in my opinion, is to respond to unencrypted requests with a redirect to the same URL but on HTTPS. For a Flask application, you can achieve that using the Flask-SSLify extension. With Nginx, you can include another server block in your configuration:

    server {
        listen 80;
        server_name example.com;
        location / {
            return 301 https://$host$request_uri;
        }
    }
    

    A good tutorial of how setup your application with https can be found here: Running Your Flask Application Over HTTPS

    Login or Signup to reply.
  3. I had similar case. I was developing bot on localhost (yet without SSL) and tunneled it to web through ngrok. In beginning all was OK, but once I found no POST-requests are coming. It turned out time of tunneling expired. I laughed and restarted tunneling. But requests weren’t coming. It turned out, I forgot to change address of webhook (it switches every ngrok session). Don’t repeat my errors.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search