feat(payment): 实现动态国家货币配置加载功能

- 移除硬编码国家货币映射,改为从API动态加载
- 添加 /api/payment/countries 接口获取支持的国家/货币列表
- 实现国家列表缓存机制(1小时有效期)
- 在支付页面添加国家选择下拉框动态渲染
- 添加网络请求失败时的备用数据方案
- 保留批量模式状态不被重置的注释说明
This commit is contained in:
cnlimiter
2026-03-27 17:00:55 +08:00
parent 2e47834152
commit f3268ec0a6
4 changed files with 91 additions and 20 deletions

View File

@@ -178,4 +178,52 @@ def mark_subscription(account_id: int, request: MarkSubscriptionRequest):
return {"success": True, "subscription_type": request.subscription_type}
# ============== 国家/货币配置 ==============
_countries_cache: dict = {} # {"data": [...], "expires_at": float}
@router.get("/countries")
def get_checkout_countries():
"""从 ChatGPT checkout 接口获取支持的国家/货币列表(缓存 1 小时)"""
import time
import curl_cffi.requests as cffi_requests
now = time.time()
if _countries_cache.get("expires_at", 0) > now:
return {"success": True, "countries": _countries_cache["data"]}
with get_db() as db:
proxy = get_settings().get_proxy_url(db=db)
try:
resp = cffi_requests.get(
"https://chatgpt.com/backend-api/checkout_pricing_config/countries",
proxies={"http": proxy, "https": proxy} if proxy else None,
timeout=15,
impersonate="chrome110",
)
resp.raise_for_status()
data = resp.json()
countries = data if isinstance(data, list) else data.get("countries", [])
_countries_cache["data"] = countries
_countries_cache["expires_at"] = now + 3600
return {"success": True, "countries": countries}
except Exception as e:
logger.warning(f"获取国家列表失败: {e}")
fallback = [
{"country_code": "SG", "currency": "SGD", "country_name": "Singapore"},
{"country_code": "US", "currency": "USD", "country_name": "United States"},
{"country_code": "TR", "currency": "TRY", "country_name": "Turkey"},
{"country_code": "JP", "currency": "JPY", "country_name": "Japan"},
{"country_code": "HK", "currency": "HKD", "country_name": "Hong Kong"},
{"country_code": "GB", "currency": "GBP", "country_name": "United Kingdom"},
{"country_code": "AU", "currency": "AUD", "country_name": "Australia"},
{"country_code": "CA", "currency": "CAD", "country_name": "Canada"},
{"country_code": "IN", "currency": "INR", "country_name": "India"},
{"country_code": "BR", "currency": "BRL", "country_name": "Brazil"},
{"country_code": "MX", "currency": "MXN", "country_name": "Mexico"},
]
return {"success": False, "countries": fallback, "error": str(e)}