feat: Implement subscription-based premium features, payment processing, and enhanced dashboard components.

This commit is contained in:
2569718930@qq.com
2026-03-13 06:41:33 +08:00
parent f7b649bb0a
commit 54c4a26162
19 changed files with 427 additions and 90 deletions
+11 -7
View File
@@ -134,15 +134,11 @@ class SupabaseEntitlementService:
logger.warning(f"supabase auth user check failed: {exc}")
return None
def has_active_subscription(self, user_id: str) -> bool:
if not self.require_subscription:
return True
def _query_active_subscription(self, user_id: str) -> bool:
if not user_id:
return False
if not self.service_role_key:
logger.warning(
"POLYWEATHER_AUTH_REQUIRE_SUBSCRIPTION=true but SUPABASE_SERVICE_ROLE_KEY is missing",
)
logger.warning("SUPABASE_SERVICE_ROLE_KEY is missing")
return False
now_ts = time.time()
@@ -188,6 +184,14 @@ class SupabaseEntitlementService:
logger.warning(f"supabase subscription query error user_id={user_id}: {exc}")
return False
def has_active_subscription(
self,
user_id: str,
respect_requirement: bool = True,
) -> bool:
if respect_requirement and not self.require_subscription:
return True
return self._query_active_subscription(user_id)
SUPABASE_ENTITLEMENT = SupabaseEntitlementService()
+27
View File
@@ -159,6 +159,18 @@ def _parse_plan_catalog(raw: str) -> Dict[str, Dict[str, Any]]:
return out or dict(DEFAULT_PLAN_CATALOG)
def _parse_allowed_plan_codes(raw: str) -> List[str]:
text = str(raw or "").strip()
if not text:
return ["pro_monthly"]
out: List[str] = []
for part in text.split(","):
code = str(part or "").strip().lower()
if code and code not in out:
out.append(code)
return out or ["pro_monthly"]
@dataclass
class WalletBindingRecord:
chain_id: int
@@ -224,6 +236,21 @@ class PaymentContractCheckoutService:
self.plan_catalog = _parse_plan_catalog(
os.getenv("POLYWEATHER_PAYMENT_PLAN_CATALOG_JSON") or ""
)
self.allowed_plan_codes = _parse_allowed_plan_codes(
os.getenv("POLYWEATHER_PAYMENT_ALLOWED_PLAN_CODES") or ""
)
filtered_catalog = {
code: row
for code, row in self.plan_catalog.items()
if code in self.allowed_plan_codes
}
if filtered_catalog:
self.plan_catalog = filtered_catalog
elif "pro_monthly" in self.plan_catalog:
self.plan_catalog = {"pro_monthly": self.plan_catalog["pro_monthly"]}
elif self.plan_catalog:
first_code = sorted(self.plan_catalog.keys())[0]
self.plan_catalog = {first_code: self.plan_catalog[first_code]}
self.notify_telegram = _env_bool(
"POLYWEATHER_PAYMENT_TELEGRAM_NOTIFY_ENABLED", True
)