68 lines
2.8 KiB
Python
68 lines
2.8 KiB
Python
# ruff: noqa: F401,F403,F405,I001
|
|
from ._runtime import * # noqa: F403,F405
|
|
|
|
|
|
class RenewalMixin:
|
|
async def charge_subscription_renewal(
|
|
self,
|
|
session: AsyncSession,
|
|
sub: Subscription,
|
|
) -> bool:
|
|
"""Attempt to charge user using saved payment method. Return True on initiated/handled, False on failure.""" # noqa: E501
|
|
if getattr(self.settings, "traffic_sale_mode", False):
|
|
logging.info("Auto-renew skipped: traffic sale mode enabled")
|
|
return True
|
|
if not sub.auto_renew_enabled:
|
|
return True
|
|
# If autopayments are disabled globally, skip charging attempts
|
|
if not self.settings.yookassa_autopayments_active:
|
|
return True
|
|
if sub.provider != "yookassa":
|
|
logging.info(
|
|
"Auto-renew skipped: provider %s does not support auto-renew", sub.provider
|
|
)
|
|
return True
|
|
|
|
from db.dal.user_billing_dal import get_user_default_payment_method
|
|
|
|
default_pm = await get_user_default_payment_method(session, sub.user_id)
|
|
if not default_pm:
|
|
logging.info(f"Auto-renew skipped: no saved payment method for user {sub.user_id}")
|
|
return False
|
|
|
|
# ``yookassa_service`` is wired onto the subscription service via
|
|
# ``build_core_services`` (setattr). Read it directly — the previous
|
|
# ``from .yookassa_service import …`` pointed at a non-existent module
|
|
# inside this package, the ImportError got swallowed, and every
|
|
# auto-renew silently returned False.
|
|
yk = getattr(self, "yookassa_service", None)
|
|
if not yk or not getattr(yk, "configured", False):
|
|
logging.warning("YooKassa unavailable for auto-renew")
|
|
return False
|
|
|
|
months = sub.duration_months or 1
|
|
amount = self.settings.subscription_options.get(months)
|
|
if not amount:
|
|
logging.error(f"Auto-renew price missing for {months} months")
|
|
return False
|
|
|
|
metadata = {
|
|
"user_id": str(sub.user_id),
|
|
"auto_renew_for_subscription_id": str(sub.subscription_id),
|
|
"subscription_months": str(months),
|
|
}
|
|
resp = await yk.create_payment(
|
|
amount=float(amount),
|
|
currency="RUB",
|
|
description=f"Auto-renewal for {months} months",
|
|
metadata=metadata,
|
|
payment_method_id=default_pm.provider_payment_method_id,
|
|
save_payment_method=False,
|
|
capture=True,
|
|
)
|
|
if not resp or resp.get("status") not in {"pending", "waiting_for_capture", "succeeded"}:
|
|
logging.error(f"Auto-renew create_payment failed: {resp}")
|
|
return False
|
|
logging.info(f"Auto-renew initiated for user {sub.user_id} payment_id={resp.get('id')}")
|
|
return True
|