fix(payments): enforce idempotent and verified webhook processing

This commit is contained in:
kavore
2026-02-08 21:30:39 +03:00
parent 4853a49112
commit 9a32cab718
6 changed files with 280 additions and 24 deletions
+60 -2
View File
@@ -204,12 +204,70 @@ class CryptoPayService:
logging.error(f"CryptoPay: Payment record {payment_db_id} not found")
return
await payment_dal.update_provider_payment_and_status(
if payment_record.user_id != user_id:
logging.error(
"CryptoPay webhook: user mismatch for payment %s (db=%s, payload=%s)",
payment_db_id,
payment_record.user_id,
user_id,
)
return
provider_currency = None
for candidate in (
getattr(invoice, "fiat", None),
getattr(invoice, "asset", None),
getattr(invoice, "paid_asset", None),
settings.CRYPTOPAY_ASSET,
):
if candidate:
provider_currency = str(candidate).upper()
break
expected_currency = str(payment_record.currency or "").upper()
if expected_currency and provider_currency and expected_currency != provider_currency:
logging.error(
"CryptoPay webhook: currency mismatch for payment %s (expected %s, got %s)",
payment_db_id,
expected_currency,
provider_currency,
)
return
if payment_record.status == "succeeded":
logging.info("CryptoPay webhook: payment %s already succeeded", payment_db_id)
return
try:
expected_amount = float(payment_record.amount)
incoming_amount = float(invoice.amount)
if round(incoming_amount, 2) != round(expected_amount, 2):
logging.error(
"CryptoPay webhook: amount mismatch for payment %s (expected %.2f, got %.2f)",
payment_db_id,
expected_amount,
incoming_amount,
)
return
except Exception as amount_exc:
logging.error(
"CryptoPay webhook: failed to compare amount for payment %s: %s",
payment_db_id,
amount_exc,
)
return
marked = await payment_dal.mark_provider_payment_succeeded_once(
session,
payment_db_id,
str(invoice.invoice_id),
"succeeded",
)
if not marked:
logging.info(
"CryptoPay webhook: payment %s already processed atomically",
payment_db_id,
)
return
activation = await subscription_service.activate_subscription(
session,
user_id,