mirror of
https://github.com/wasrusgen/zov-tech.git
synced 2026-06-03 19:04:49 +00:00
53 lines
1.9 KiB
Python
53 lines
1.9 KiB
Python
"""Telegram WebApp initData verification (HMAC-SHA-256)."""
|
||
from __future__ import annotations
|
||
import hmac
|
||
import hashlib
|
||
import json
|
||
import time
|
||
from typing import Any
|
||
from urllib.parse import parse_qsl
|
||
|
||
|
||
def verify_init_data(init_data: str, bot_token: str, max_age_sec: int = 86400) -> dict[str, Any] | None:
|
||
"""
|
||
Проверяет подпись initData от Telegram WebApp.
|
||
Возвращает распарсенные данные с ключом 'user' (dict) или None при невалидной/просроченной подписи.
|
||
|
||
Спецификация: https://core.telegram.org/bots/webapps#validating-data-received-via-the-mini-app
|
||
"""
|
||
if not init_data:
|
||
return None
|
||
parsed = dict(parse_qsl(init_data, keep_blank_values=True))
|
||
received_hash = parsed.pop("hash", None)
|
||
if not received_hash:
|
||
return None
|
||
|
||
# data_check_string: ключ=значение, отсортированы алфавитно, разделитель \n
|
||
data_check_string = "\n".join(f"{k}={parsed[k]}" for k in sorted(parsed))
|
||
|
||
# secret_key = HMAC-SHA-256(key="WebAppData", data=BOT_TOKEN)
|
||
secret_key = hmac.new(b"WebAppData", bot_token.strip().encode(), hashlib.sha256).digest()
|
||
expected_hash = hmac.new(secret_key, data_check_string.encode(), hashlib.sha256).hexdigest()
|
||
|
||
if not hmac.compare_digest(expected_hash, received_hash):
|
||
return None
|
||
|
||
# Свежесть подписи (24 часа по умолчанию)
|
||
auth_date = int(parsed.get("auth_date", "0"))
|
||
if time.time() - auth_date > max_age_sec:
|
||
return None
|
||
|
||
user = None
|
||
if "user" in parsed:
|
||
try:
|
||
user = json.loads(parsed["user"])
|
||
except json.JSONDecodeError:
|
||
user = None
|
||
|
||
return {
|
||
"user": user,
|
||
"auth_date": auth_date,
|
||
"start_param": parsed.get("start_param"),
|
||
"chat_instance": parsed.get("chat_instance"),
|
||
}
|