Files
please-pay-me/api/telegram_auth.py
2026-09-21 04:06:43 +03:00

66 lines
1.9 KiB
Python

from __future__ import annotations
import hashlib
import hmac
import time
from typing import Any
class TelegramAuthError(ValueError):
pass
def verify_telegram_login(
payload: dict[str, Any],
bot_token: str,
*,
max_age_seconds: int = 86400,
) -> dict[str, Any]:
"""Verify Telegram Login Widget data per Telegram docs."""
received_hash = payload.get("hash")
if not received_hash or not isinstance(received_hash, str):
raise TelegramAuthError("Missing hash")
check_pairs: list[str] = []
for key in sorted(payload.keys()):
if key == "hash":
continue
value = payload[key]
if value is None:
continue
check_pairs.append(f"{key}={value}")
data_check_string = "\n".join(check_pairs)
secret_key = hashlib.sha256(bot_token.encode("utf-8")).digest()
calculated = hmac.new(
secret_key,
data_check_string.encode("utf-8"),
hashlib.sha256,
).hexdigest()
if not hmac.compare_digest(calculated, received_hash):
raise TelegramAuthError("Invalid Telegram login signature")
auth_date_raw = payload.get("auth_date")
try:
auth_date = int(auth_date_raw)
except (TypeError, ValueError) as exc:
raise TelegramAuthError("Invalid auth_date") from exc
if max_age_seconds > 0 and time.time() - auth_date > max_age_seconds:
raise TelegramAuthError("Telegram login data expired")
try:
user_id = int(payload["id"])
except (KeyError, TypeError, ValueError) as exc:
raise TelegramAuthError("Missing Telegram user id") from exc
return {
"id": user_id,
"first_name": str(payload.get("first_name") or ""),
"last_name": str(payload.get("last_name") or "") or None,
"username": str(payload.get("username") or "") or None,
"photo_url": str(payload.get("photo_url") or "") or None,
"auth_date": auth_date,
}