Payment providers as classes (Strategy + factory); 10342 = monthly; health logs a failed Bazaar check

- payment/providers.py: ZarinpalProvider / BazaarProvider with one interface (check_plan, sku_for, payment_url,
  purchase_extras, discount_blocker, reconcile_user); provider_for / provider_for_method pick one; unknown fails.
  create_order, purchase view, discount redeem and reconcile_user_orders use it instead of scattered ifs.
- subscription.0015: Bazaar SKU 10342 on the one-month plan (owner: "probably the monthly one").
- config/health: the Bazaar check no longer swallows its exception without a log.
982 tests green.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-12 18:21:45 +03:30
parent 76b0ef976e
commit c0fa46be44
11 changed files with 246 additions and 66 deletions

View File

@@ -12,6 +12,7 @@ GET /api/health — «آیا این سرور واقعاً سالم است؟»
عمداً هیچ سکرتی برنمی‌گرداند: فقط بله/خیرِ «تنظیم شده» و شمارشِ محتوا.
"""
import logging
import os
from datetime import timedelta
@@ -25,6 +26,8 @@ from rest_framework.response import Response
from rest_framework.throttling import ScopedRateThrottle
from rest_framework.views import APIView
logger = logging.getLogger(__name__)
def _check_database() -> dict:
try:
@@ -129,7 +132,8 @@ def _bazaar_configured() -> bool:
try:
from payment.bazaar import is_configured
return is_configured()
except Exception:
except Exception: # noqa: BLE001 — سلامت نباید با خطای خواندنِ اعتبارِ بازار ۵۰۰ بدهد؛ ولی دیده شود
logger.exception('health: بررسیِ تنظیمِ بازار شکست خورد')
return False