fix(payments): improve YooKassa webhook processing for terminal failures

Refactor the YooKassa webhook handling to better manage terminal payment failures. Introduce checks for payment status based on metadata, ensuring that only terminal failures are committed to the database. Enhance error handling and logging for non-terminal failures, providing clearer responses for retry scenarios. This improves the robustness of payment processing and reduces unnecessary retries.
This commit is contained in:
kavore
2026-02-12 15:23:12 +03:00
parent d39e781203
commit e546ba3515
+37 -13
View File
@@ -690,20 +690,44 @@ async def yookassa_webhook_route(request: web.Request):
yookassa_service,
lknpd_service)
if not processed:
# process_successful_payment uses False for permanent business failures
# (e.g. user not found / metadata issues) and may have already updated
# the payment status. Commit the status and ACK the webhook to stop
# indefinite provider retries.
try:
await session.commit()
except Exception:
await session.rollback()
logging.exception(
"Failed to commit failure status for YooKassa payment %s",
payment_dict_for_processing.get("id"),
metadata_for_result = payment_dict_for_processing.get("metadata") or {}
payment_db_id_raw = metadata_for_result.get("payment_db_id")
payment_db_id_for_check = None
if isinstance(payment_db_id_raw, int):
payment_db_id_for_check = payment_db_id_raw
elif isinstance(payment_db_id_raw, str) and payment_db_id_raw.isdigit():
payment_db_id_for_check = int(payment_db_id_raw)
terminal_failure_recorded = False
if payment_db_id_for_check is not None:
payment_after_processing = await payment_dal.get_payment_by_db_id(
session,
payment_db_id_for_check,
)
return web.Response(status=503, text="yookassa_processing_failed_retry")
return web.Response(status=200, text="ok")
terminal_failure_recorded = bool(
payment_after_processing
and isinstance(payment_after_processing.status, str)
and payment_after_processing.status.startswith("failed")
)
if terminal_failure_recorded:
try:
await session.commit()
except Exception:
await session.rollback()
logging.exception(
"Failed to commit failure status for YooKassa payment %s",
payment_dict_for_processing.get("id"),
)
return web.Response(status=503, text="yookassa_processing_failed_retry")
return web.Response(status=200, text="ok")
await session.rollback()
logging.warning(
"YooKassa payment %s processing returned non-terminal failure; responding 503 for retry",
payment_dict_for_processing.get("id"),
)
return web.Response(status=503, text="yookassa_processing_failed_retry")
await session.commit()
else:
logging.warning(