Telegram bot webhook implementation with Spring Boot Webflux
You can either import the project into the Spring Tool Suite (https://spring.io/tools/sts/all) by using the Buildship (https://github.com/eclipse/buildship/blob/master/docs/user/Installation.md) import wizard and start it from the IDE or simply start the application by running the bootRun
Gradle task.
./gradlew bRun
Usually you’d want to use a webhook, if you’re providing a rest endpoint like this app does.
The webhook should point the /telegram/webhook endpoint, e.g., https://{your-domain}/telegram/webhook.
curl -H "Content-Type: application/json" -X POST -d '{"update_id":463166687, "message":{"message_id":256,"from":{"id":{your-user-id},"is_bot":false,"first_name":"Simon","last_name":"Scholz","language_code":"en-US"},"chat":{"id":{your-chat-id},"first_name":"Simon","last_name":"Scholz","type":"private"},"date":1519229850,"text":"/now Hamburg","entities":[{"offset":0,"length":4,"type":"bot_command"}]}}' https://localhost:8080/telegram/webhook
A nice way to set the webhook is by using curl:
curl -F "url=https://{your-domain}/telegram/webhook" https://api.telegram.org/bot{your-bots-api-token}/setWebhook
For a custom ssl certificate(telegram required pem) the following command can be used:
curl -F "url=https://{your-domain}/webhook" -F "certificate=@/home/simon/ssl/keystore.pem" https://api.telegram.org/bot{your api token}/setWebhook
Tip
|
See https://core.telegram.org/bots/api#setwebhook for further information about setting a webhook. |
To use a webhook for telegram you need to use port 443 or 8443 with ssl. See Let’s Encrypt for further information about ssl security for your domain.
This is also a nice introduction how to achieve that: https://dzone.com/articles/spring-boot-secured-by-lets-encrypt
To run this Spring Boot application with your own bot you usually have to adjust the application.yml file.
server:
port: 443
ssl:
key-store: /{path-to-file}/keystore.p12 (1)
key-store-password: *** your password ***
key-store-type: PKCS12
key-alias: {your-key-alias}
-
See Let’s Encrypt for *.p12 key store generation
You can install Nginx on your server and add the following config files.
http.conf.j2
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri; (1)
}
-
Redirect port 80 (http) to port 443 (https)
Then add the following https.conf.j2 Nginx config:
upstream app-upstream {
server localhost:{port}; (1)
}
server {
listen 443 default ssl;
server_name {{ service_host }};
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
ssl_certificate /etc/letsencrypt/live/{{ service_host }}/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/{{ service_host }}/privkey.pem;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_ecdh_curve secp384r1;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_pass https://app-upstream;
}
}
-
Substitute {port} with your server apps port
Feedback is highly appreciated. You may open issues, send pull requests or simply contact me.
Add ssl certificate to your domain.
AVM is currently working on a setting for Let’s Encrypt and their routers.
cd {your home directory}
mkdir certbot
cd certbot
wget https://dl.eff.org/certbot-auto
chmod +x certbot-auto
./certbot-auto certonly -a standalone -d {your domain name -> example.ddns.net}
cd /etc/letsencrypt/live/{your domain name -> example.ddns.net}/
openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out keystore.p12 -name telegram-bot -CAfile chain.pem -caname root
The keystore.p12 file has to be moved to a location, which can be accessed by the user, which starts the spring boot app service. The chown -R {username} and chgrp -R {username}
command are helpful here.
The conversion to a keystore.p12 file with openssl is necessary, because spring boot does not work with *.pem files, but with *.p12 files. See server.ssl.key-store property in application.properties file of the spring boot application.