Webhook bilan joylashtirish
Production uchun: Zamin yangilanishlarni HTTPS orqali serveringizga yuboradi, Flask ilovasi ularni qabul qiladi. Maxfiy sarlavha tekshiriladi, javob darhol qaytariladi.
Talablar
- Domen va ishonchli TLS sertifikat (masalan, Let's Encrypt). O'z-o'zidan imzolangan sertifikat ishlamaydi.
- Port 443, 80, 88 yoki 8443. Server ommaviy IP manzilda bo'lishi kerak (SSRF qoidalari).
- Python 3.8+,
flask,requests,gunicorn.
1. Maxfiy kalit
Terminal
python3 -c "import secrets; print(secrets.token_urlsafe(32))"Natija faqat A-Z a-z 0-9 _ - belgilaridan iborat — secret_token uchun mos.
2. Flask ilovasi
app.py
import hmac
import logging
import os
import requests
from flask import Flask, abort, request
TOKEN = os.environ["ZAMIN_BOT_TOKEN"]
SECRET = os.environ["ZAMIN_WEBHOOK_SECRET"]
API = f"https://api.zamin.app/bot{TOKEN}"
app = Flask(__name__)
log = logging.getLogger("bot")
def call(method, params):
r = requests.post(f"{API}/{method}", json=params, timeout=5)
body = r.json()
if not body.get("ok"):
log.warning("%s: %s %s", method, body.get("error_code"), body.get("description"))
return body.get("result")
def handle(update):
message = update.get("message")
if message and "text" in message:
chat_id = message["chat"]["id"]
if message["text"].startswith("/start"):
call("sendMessage", {"chat_id": chat_id, "text": "Salom! Men webhook orqali ishlayman 🚀"})
else:
call("sendMessage", {"chat_id": chat_id, "text": message["text"]})
@app.route("/zamin/webhook", methods=["POST"])
def webhook():
# 1) Maxfiy sarlavhani doimiy vaqtli solishtirish bilan tekshiramiz
got = request.headers.get("X-Zamin-Bot-Api-Secret-Token", "")
if not hmac.compare_digest(got.encode(), SECRET.encode()):
abort(403)
update = request.get_json(silent=True)
if not isinstance(update, dict):
abort(400)
# 2) Ichki xato bo'lsa ham 200 qaytaramiz: aks holda Zamin shu yangilanishni
# qayta-qayta yuboradi va keyingilari navbatda kutib qoladi.
try:
handle(update)
except Exception:
log.exception("update %s", update.get("update_id"))
return "", 200
@app.route("/healthz")
def healthz():
return "ok"3. Ishga tushirish (gunicorn)
Terminal
pip3 install flask requests gunicorn
export ZAMIN_BOT_TOKEN="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
export ZAMIN_WEBHOOK_SECRET="…1-qadamdagi qiymat…"
gunicorn -w 2 -b 127.0.0.1:8000 app:appOldiga TLS'ni hal qiladigan reverse proxy qo'ying (nginx, Caddy …) va /zamin/webhook'ni 127.0.0.1:8000'ga yo'naltiring. Masalan, nginx:
nginx
location /zamin/webhook {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
client_max_body_size 1m;
}4. Webhookni o'rnatish
set_webhook.py
import os
import requests
TOKEN = os.environ["ZAMIN_BOT_TOKEN"]
API = f"https://api.zamin.app/bot{TOKEN}"
r = requests.post(
f"{API}/setWebhook",
json={
"url": os.environ["WEBHOOK_URL"], # https://bot.example.com/zamin/webhook
"secret_token": os.environ["ZAMIN_WEBHOOK_SECRET"],
"allowed_updates": ["message", "callback_query", "my_chat_member"],
"drop_pending_updates": False,
},
timeout=15,
)
print(r.json())
print(requests.get(f"{API}/getWebhookInfo", timeout=15).json())Terminal
export WEBHOOK_URL="https://bot.example.com/zamin/webhook"
python3 set_webhook.py5. systemd xizmati
/etc/systemd/system/zamin-bot.service
[Unit]
Description=Zamin bot (webhook)
After=network-online.target
[Service]
WorkingDirectory=/opt/zamin-bot
EnvironmentFile=/opt/zamin-bot/.env
ExecStart=/opt/zamin-bot/.venv/bin/gunicorn -w 2 -b 127.0.0.1:8000 app:app
Restart=always
User=zaminbot
[Install]
WantedBy=multi-user.target.env faylida ZAMIN_BOT_TOKEN=… va ZAMIN_WEBHOOK_SECRET=… bo'ladi; unga faqat xizmat foydalanuvchisi kira olsin (chmod 600).
Tekshirish va nosozliklar
- getWebhookInfo:
pending_update_counto'sib borsa valast_error_messagebo'lsa, yetkazishda muammo bor. Wrong response from the webhook: 403— sarlavha mos kelmayapti (secret noto'g'ri).Connection timed out— javob 10 soniyadan uzoq: ishni fonga o'tkazing.Connection failed— port yopiq, sertifikat noto'g'ri yoki server ishlamayapti.- Yetkazish ketma-ket: bitta yangilanishga xato qaytarsangiz, keyingilari ham kutadi. Shuning uchun
app.pyichki xatoda ham 200 qaytaradi. - Tokenni
/revokeqilsangiz, webhook o'chadi —set_webhook.py'ni yangi token bilan qayta ishga tushiring.