cb8453f415
fix notifications for notifications module
73 lines
3.3 KiB
Python
73 lines
3.3 KiB
Python
import base64
|
|
import json
|
|
|
|
import aiohttp
|
|
|
|
from aiohttp import web
|
|
from cryptography.hazmat.backends import default_backend
|
|
from cryptography.hazmat.primitives import hashes, serialization
|
|
from cryptography.hazmat.primitives.asymmetric import padding
|
|
|
|
from database import add_payment, async_session_maker, update_balance
|
|
from handlers.payments.utils import send_payment_success_notification
|
|
from logger import logger
|
|
|
|
|
|
PUBLIC_KEY_URL = "https://api.wata.pro/api/h2h/public-key"
|
|
|
|
|
|
async def get_wata_public_key():
|
|
async with aiohttp.ClientSession() as session:
|
|
async with session.get(PUBLIC_KEY_URL) as resp:
|
|
data = await resp.json()
|
|
return data["value"].encode()
|
|
|
|
|
|
async def verify_signature(raw_json: bytes, signature: str, public_key_pem: bytes) -> bool:
|
|
try:
|
|
public_key = serialization.load_pem_public_key(public_key_pem, backend=default_backend())
|
|
signature_bytes = base64.b64decode(signature)
|
|
public_key.verify(signature_bytes, raw_json, padding.PKCS1v15(), hashes.SHA512())
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"Ошибка проверки подписи WATA: {e}")
|
|
return False
|
|
|
|
|
|
async def wata_payment_webhook(request: web.Request):
|
|
try:
|
|
raw_json = await request.read()
|
|
data = json.loads(raw_json)
|
|
signature = request.headers.get("X-Signature")
|
|
if not signature:
|
|
logger.error("Нет подписи X-Signature в заголовке!")
|
|
return web.Response(status=400)
|
|
public_key_pem = await get_wata_public_key()
|
|
if not await verify_signature(raw_json, signature, public_key_pem):
|
|
logger.error("Подпись WATA не прошла проверку!")
|
|
return web.Response(status=400)
|
|
|
|
logger.info(f"WATA webhook: {json.dumps(data, ensure_ascii=False)}")
|
|
logger.info(
|
|
f"transactionId={data.get('transactionId')}, status={data.get('transactionStatus')}, orderId={data.get('orderId')}, amount={data.get('amount')}, currency={data.get('currency')}, errorCode={data.get('errorCode')}, errorDescription={data.get('errorDescription')}"
|
|
)
|
|
if data.get("transactionStatus") == "Paid":
|
|
tg_id = data.get("orderId")
|
|
amount = data.get("amount")
|
|
if not tg_id or not amount:
|
|
logger.error(f"WATA: отсутствует orderId или amount: {data}")
|
|
return web.Response(status=400)
|
|
async with async_session_maker() as session:
|
|
await update_balance(session, int(tg_id), float(amount))
|
|
await add_payment(session, int(tg_id), float(amount), "wata")
|
|
await send_payment_success_notification(tg_id, float(amount), session)
|
|
logger.info(f"✅ WATA: баланс пополнен для пользователя {tg_id} на {amount}")
|
|
elif data.get("transactionStatus") == "Declined":
|
|
logger.warning(f"WATA: транзакция отклонена: {data}")
|
|
else:
|
|
logger.warning(f"WATA: неизвестный статус транзакции: {data.get('transactionStatus')}")
|
|
return web.Response(status=200)
|
|
except Exception as e:
|
|
logger.error(f"Ошибка в webhook WATA: {e}")
|
|
return web.Response(status=500)
|