From 3cb22a5c7d749e43b3d44769119ea16cf84142e5 Mon Sep 17 00:00:00 2001 From: Boris Kovalskii <36034823+JustYay@users.noreply.github.com> Date: Fri, 17 Oct 2025 09:41:17 +1000 Subject: [PATCH] Delete web/heleket_payment.py --- web/heleket_payment.py | 203 ----------------------------------------- 1 file changed, 203 deletions(-) delete mode 100644 web/heleket_payment.py diff --git a/web/heleket_payment.py b/web/heleket_payment.py deleted file mode 100644 index d421a0f4..00000000 --- a/web/heleket_payment.py +++ /dev/null @@ -1,203 +0,0 @@ -import base64 -import hashlib -import json - -from decimal import ROUND_HALF_UP, Decimal - -import aiohttp - -from aiohttp import web -from sqlalchemy import select - -from config import HELEKET_API_KEY -from database import Payment, async_session_maker, update_balance, update_payment_status -from handlers.payments.currency_rates import to_rub -from handlers.payments.utils import send_payment_success_notification -from logger import logger - - -processed_payments = set() - - -async def heleket_payment_webhook(request: web.Request): - try: - data = await request.json() - logger.info(f"Heleket webhook received from {request.remote}") - logger.info(f"Heleket webhook data: {data}") - - signature = data.get("sign", "") - if not verify_heleket_webhook_signature(data, signature): - logger.error("Heleket: Invalid signature") - return web.Response(status=400, text="Invalid signature") - - uuid = data.get("uuid") - order_id = data.get("order_id") - payment_status = data.get("status") - amount_raw = data.get("amount") - currency = str(data.get("currency") or "").upper() or None - payment_amount_raw = data.get("payment_amount") - to_currency = str(data.get("to_currency") or "").upper() or None - additional_data = data.get("additional_data", "") - - logger.info( - f"Heleket payment: uuid={uuid}, order_id={order_id}, status={payment_status}, " - f"amount={amount_raw}, payment_amount={payment_amount_raw}, currency={currency}, to_currency={to_currency}" - ) - - if payment_status != "paid": - logger.info(f"Heleket: Payment not completed, status={payment_status}") - return web.Response(status=200, text="OK") - - if not uuid: - logger.error("Heleket: Missing uuid") - return web.Response(status=400, text="Missing required fields") - - if uuid in processed_payments: - logger.warning(f"Heleket: Duplicate payment uuid={uuid}") - return web.Response(status=200, text="OK") - if order_id and order_id in processed_payments: - logger.warning(f"Heleket: Duplicate payment order_id={order_id}") - return web.Response(status=200, text="OK") - - tg_id = None - rub_amount: Decimal | None = None - - try: - if additional_data and "tg_id:" in additional_data: - parts = [p.strip() for p in additional_data.split(",")] - for part in parts: - if part.startswith("tg_id:"): - tg_id = int(part.split("tg_id:")[1]) - elif part.startswith("rub_amount:"): - val = part.split("rub_amount:")[1] - rub_amount = Decimal(str(val)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP) - - if tg_id is None and order_id and "_" in order_id: - tg_id = int(order_id.split("_")[1]) - except (ValueError, IndexError) as e: - logger.error(f"Heleket: Error extracting tg_id or rub_amount: {e}") - return web.Response(status=400, text="Invalid user ID or amount format") - - paid_ccy = None - original_amount_dec: Decimal | None = None - - if currency and amount_raw is not None: - try: - original_amount_dec = Decimal(str(amount_raw)) - paid_ccy = currency - except Exception: - original_amount_dec = None - - if original_amount_dec is None and to_currency and payment_amount_raw is not None: - try: - original_amount_dec = Decimal(str(payment_amount_raw)) - paid_ccy = to_currency - except Exception: - original_amount_dec = None - - if rub_amount is None: - amt_str = str(amount_raw or "").strip() - if amt_str and currency: - try: - amt_dec = Decimal(amt_str) - async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10)) as s: - rub_amount = await to_rub(amt_dec, currency, session=s) - except Exception as e: - logger.error(f"Heleket: RUB conversion failed ({currency}→RUB) for amount={amt_str}: {e}") - rub_amount = None - - if rub_amount is None and payment_amount_raw and to_currency: - try: - amt_dec = Decimal(str(payment_amount_raw)) - async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10)) as s: - rub_amount = await to_rub(amt_dec, to_currency, session=s) - except Exception as e: - logger.error( - f"Heleket: RUB conversion failed ({to_currency}→RUB) for payment_amount={payment_amount_raw}: {e}" - ) - rub_amount = None - - if rub_amount is None: - logger.error("Heleket: Could not determine rub_amount") - return web.Response(status=400, text="Cannot determine amount") - - if tg_id is None: - logger.error("Heleket: Cannot extract tg_id from data") - return web.Response(status=400, text="Cannot extract user ID") - - meta_patch = { - "provider": "HELEKET", - "heleket_raw": data, - "provider_uuid": uuid, - "provider_order_id": order_id, - } - if paid_ccy and original_amount_dec is not None: - meta_patch["paid_invoice_amount"] = float(original_amount_dec) - meta_patch["paid_invoice_currency"] = paid_ccy - meta_patch["fx"] = {"base": paid_ccy, "rub_equivalent": str(rub_amount)} - - async with async_session_maker() as session: - internal_payment = None - if order_id: - res = await session.execute(select(Payment).where(Payment.payment_id == str(order_id)).limit(1)) - internal_payment = res.scalar_one_or_none() - - if internal_payment: - internal_payment.status = "success" - if order_id: - internal_payment.payment_id = str(order_id) - if paid_ccy: - internal_payment.currency = paid_ccy - if original_amount_dec is not None: - internal_payment.original_amount = float(original_amount_dec) - current_md = getattr(internal_payment, "metadata_", None) - if isinstance(current_md, dict): - current_md.update(meta_patch) - internal_payment.metadata_ = current_md - else: - internal_payment.metadata_ = meta_patch - await session.commit() - else: - ok = await update_payment_status( - session=session, - internal_id=0, - new_status="success", - payment_id=str(order_id) if order_id else None, - metadata_patch=meta_patch, - ) - if not ok: - logger.error("Heleket: Failed to update payment status for unknown internal payment") - - await update_balance(session, tg_id, float(rub_amount)) - await send_payment_success_notification(tg_id, float(rub_amount), session) - - processed_payments.add(uuid) - if order_id: - processed_payments.add(order_id) - - logger.info(f"Heleket: Payment processed for user {tg_id}, amount {rub_amount} RUB, uuid={uuid}") - return web.Response(status=200, text="OK") - - except Exception as e: - logger.error(f"Heleket webhook error: {e}") - return web.Response(status=500, text="Internal server error") - - -def verify_heleket_webhook_signature(data: dict, signature: str) -> bool: - try: - data_without_sign = {k: v for k, v in data.items() if k != "sign"} - json_data = json.dumps(data_without_sign, separators=(",", ":"), ensure_ascii=False) - base64_data = base64.b64encode(json_data.encode("utf-8")).decode("utf-8") - sign_string = base64_data + HELEKET_API_KEY - expected_signature = hashlib.md5(sign_string.encode("utf-8")).hexdigest() - - result = signature.upper() == expected_signature.upper() - if not result: - logger.error("Heleket webhook signature mismatch") - logger.error(f"Expected: {expected_signature}, Got: {signature}") - logger.error(f"Base64 data: {base64_data}") - logger.error(f"Sign string: {sign_string}") - return result - except Exception as e: - logger.error(f"Heleket signature verification error: {e}") - return False