Files

58 lines
2.5 KiB
Python
Raw Permalink Normal View History

2026-08-31 15:11:52 +03:30
# 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")