# apps/billing/providers/dynamic_discount.py """ تولید توکن «تخفیف پویا» کافه‌بازار (developers.cafebazaar.ir/fa/guidelines/in-app-billing/dynamic-discount). فقط یک تابع خام است، بدون endpoint/کمپین — چون فعلا کمپین تخفیف مشخصی در کار نیست؛ هر وقت لازم شد (مثلا یک ویو که برای یک GemPack با قیمت پایین‌تر توکن می‌سازد)، همین تابع را صدا بزن. کلید امضا (BazaarSettings. dynamic_discount_secret) عمدا فقط همین‌جا (سمت سرور) استفاده می‌شود و هیچ‌وقت نباید به کلاینت/اپ فلاتر فرستاده شود — طبق مستندات، ذخیره‌ی این کلید در اپ یعنی افشای آن، و کافه‌بازار مسئولیتی در قبال سوءاستفاده نمی‌پذیرد. خروجی این تابع مستقیم در فیلد dynamicPriceToken کلاس PurchaseRequest (سمت اپ، هنگام FlutterPoolakey.purchase) استفاده می‌شود. """ import time import uuid import jwt from apps.billing.models import BazaarSettings class DynamicDiscountNotConfigured(Exception): """کلید امضای تخفیف پویا در BazaarSettings تنظیم نشده.""" def generate_dynamic_discount_token( *, sku: str, price_rial: int, ttl_seconds: int = 300, account_id: str | None = None, ) -> str: """یک توکن یک‌بارمصرف طبق مشخصات مستندات کافه‌بازار می‌سازد. price_rial باید <= قیمت ثبت‌شده‌ی همین sku در پنل پیشخان باشد، وگرنه کافه‌بازار خودش موقع خرید خطای «قیمت بیش از حد مجاز» (کد ۱۰) برمی‌گرداند.""" settings_obj = BazaarSettings.get_solo() if not settings_obj.dynamic_discount_secret or not settings_obj.package_name: raise DynamicDiscountNotConfigured( "dynamic_discount_secret یا package_name در تنظیمات کافه‌بازار خالی است." ) now = int(time.time()) payload = { "price": price_rial, "package_name": settings_obj.package_name, "sku": sku, "exp": now + ttl_seconds, "nonce": uuid.uuid4().hex, } if account_id: payload["account_id"] = account_id return jwt.encode(payload, settings_obj.dynamic_discount_secret, algorithm="HS256")