diff --git a/bot/handlers/user/payment.py b/bot/handlers/user/payment.py index ef25452..b577596 100644 --- a/bot/handlers/user/payment.py +++ b/bot/handlers/user/payment.py @@ -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(