统一月付价格为 10 USDC 并清理所有 trial 文案

- 默认月付 fallback 从 5U 改为 10U(contract_checkout.py、AccountCenter.tsx)
- 移除 LoginClient / HeaderBar / AccountCenter / UnlockProOverlay 中的试用推广文案
- VPS 同步: PLAN_CATALOG_JSON、GROUP_MEMBER_PRICE_USDC 更新为 10
- SIGNUP_TRIAL_ENABLED=false 保持关闭
@
This commit is contained in:
2569718930@qq.com
2026-05-20 11:12:29 +08:00
parent 6e3b7f60a2
commit 60093d3162
5 changed files with 24 additions and 59 deletions
+9 -28
View File
@@ -819,14 +819,6 @@ export function AccountCenter() {
freeTier: "FREE TIER",
proPendingSync: isEn ? "Activated (pending sync)" : "已开通(待同步)",
noProSubscription: isEn ? "No Pro subscription" : "暂无 Pro 订阅",
trialEndsSoonTitle: isEn ? "Trial ending soon" : "试用即将结束",
trialEndsSoonBody: isEn
? "Your 3-day trial is almost over. Upgrade to Pro to keep full intraday analysis and decision cards."
: "你的 3 天试用即将结束。升级 Pro 后可继续使用完整日内分析和城市决策卡。",
trialExpiredTitle: isEn ? "Trial ended" : "试用已结束",
trialExpiredBody: isEn
? "Your trial access has ended. Renew with Pro to restore full access."
: "试用权限已结束。开通 Pro 后可恢复完整权限。",
proEndsSoonTitle: isEn ? "Pro renewal due soon" : "Pro 即将到期",
proEndsSoonBody: isEn
? "Your Pro membership will expire soon. Renew now to avoid interruption."
@@ -836,7 +828,6 @@ export function AccountCenter() {
? "Your Pro membership has expired. Renew now to restore premium access."
: "你的 Pro 会员已到期。立即续费可恢复高级权限。",
renewNow: isEn ? "Renew Now" : "立即续费",
trialBadge: isEn ? "TRIAL" : "试用中",
daysLeft: isEn ? "{days} days left" : "剩余 {days} 天",
queuedExtensionSummary: isEn
? "Current plan until {current}. Queued extension: +{days} days. Total access until {total}."
@@ -1513,7 +1504,7 @@ export function AccountCenter() {
telegram_pricing?: TelegramPricing | null;
};
if (data.telegram_pricing?.is_group_member) {
const amount = data.telegram_pricing.amount_usdc || "5";
const amount = data.telegram_pricing.amount_usdc || "10";
setPaymentInfo(`Telegram 群成员验证成功,当前会员价 ${amount}U。`);
}
await loadSnapshot();
@@ -1576,25 +1567,17 @@ export function AccountCenter() {
const paymentFeatureReady = paymentReadyForRecovery;
const canOpenCheckoutOverlay = Boolean(
paymentFeatureReady &&
(!isSubscribed || isTrialPlan || showExpiringSoon || showExpiredReminder),
(!isSubscribed || showExpiringSoon || showExpiredReminder),
);
const subscriptionStatusTitle = showExpiredReminder
? isTrialPlan
? copy.trialExpiredTitle
: copy.proExpiredTitle
? copy.proExpiredTitle
: showExpiringSoon
? isTrialPlan
? copy.trialEndsSoonTitle
: copy.proEndsSoonTitle
? copy.proEndsSoonTitle
: "";
const subscriptionStatusBody = showExpiredReminder
? isTrialPlan
? copy.trialExpiredBody
: copy.proExpiredBody
? copy.proExpiredBody
: showExpiringSoon
? isTrialPlan
? copy.trialEndsSoonBody
: copy.proEndsSoonBody
? copy.proEndsSoonBody
: "";
const subscriptionStatusMeta =
expiryInfo && (showExpiringSoon || showExpiredReminder)
@@ -1738,7 +1721,7 @@ export function AccountCenter() {
const billing = useMemo(() => {
const parsedPlanAmount = Number(
backend?.telegram_pricing?.amount_usdc ?? selectedPlan?.amount_usdc ?? 5,
backend?.telegram_pricing?.amount_usdc ?? selectedPlan?.amount_usdc ?? 10,
);
const planAmount =
Number.isFinite(parsedPlanAmount) && parsedPlanAmount > 0
@@ -2778,9 +2761,7 @@ export function AccountCenter() {
className={`px-2 py-0.5 rounded-full text-[10px] font-black uppercase tracking-tighter border ${isSubscribed ? "bg-blue-500/20 border-blue-500/40 text-blue-400" : "bg-slate-700/50 border-white/10 text-slate-500"}`}
>
{isSubscribed
? isTrialPlan
? copy.trialBadge
: copy.proMember
? copy.proMember
: copy.freeTier}
</span>
</div>
@@ -2861,7 +2842,7 @@ export function AccountCenter() {
Top 2-3
</span>
<span className="text-xs font-bold text-slate-300">
+100 & 3Pro
+100
</span>
</div>
<div className="flex items-center justify-between p-3 bg-white/5 rounded-xl border border-white/5">
-6
View File
@@ -72,9 +72,6 @@ export function LoginClient({ nextPath }: LoginClientProps) {
signupCheckEmail: isEn
? "Sign-up successful. Please verify your email before signing in."
: "注册成功,请检查邮箱并完成验证后登录。",
trialPromo: isEn
? "New users unlock a free 3-day Pro trial after sign-up."
: "新用户注册后可免费体验 3 天 Pro。",
reset: isEn ? "Forgot password?" : "忘记密码?",
resetSent: isEn
? "Reset link sent. Check your inbox."
@@ -231,9 +228,6 @@ export function LoginClient({ nextPath }: LoginClientProps) {
</div>
<h1 className="text-3xl font-bold tracking-tight text-white">PolyWeather</h1>
<p className="mt-2 text-sm text-slate-400">{copy.subtitle}</p>
<div className="mt-4 inline-flex items-center rounded-full border border-cyan-400/30 bg-cyan-400/10 px-4 py-1.5 text-xs font-semibold text-cyan-200 shadow-[0_0_20px_rgba(34,211,238,0.08)]">
{copy.trialPromo}
</div>
</div>
<button
+6 -17
View File
@@ -76,9 +76,6 @@ export function HeaderBar({
proAccess.subscriptionActive &&
proAccess.subscriptionQueuedDays > 0,
);
const isTrialPlan = /trial/i.test(
String(proAccess.subscriptionPlanCode || ""),
);
const showRenewReminder =
isAuthenticated &&
!proAccess.loading &&
@@ -90,20 +87,12 @@ export function HeaderBar({
const renewReminderLabel = !showRenewReminder
? ""
: !proAccess.subscriptionActive
? isTrialPlan
? locale === "en-US"
? "Trial ended"
: "试用已结束"
: locale === "en-US"
? "Pro expired"
: "Pro 已到期"
: isTrialPlan
? locale === "en-US"
? `Trial ${Math.max(expiryInfo?.daysLeft || 0, 0)}d left`
: `试用剩余 ${Math.max(expiryInfo?.daysLeft || 0, 0)}`
: locale === "en-US"
? `Pro ${Math.max(expiryInfo?.daysLeft || 0, 0)}d left`
: `Pro 还剩 ${Math.max(expiryInfo?.daysLeft || 0, 0)}`;
? locale === "en-US"
? "Pro expired"
: "Pro 已到期"
: locale === "en-US"
? `Pro ${Math.max(expiryInfo?.daysLeft || 0, 0)}d left`
: `Pro 还剩 ${Math.max(expiryInfo?.daysLeft || 0, 0)}`;
useEffect(() => {
const savedTheme =
@@ -147,11 +147,6 @@ export function UnlockProOverlay({
? "High-precision weather intelligence, delivered everywhere."
: "全球最精准的高精度气象推送,全平台覆盖"}
</p>
<div className={s.trialPromo}>
{isEn
? "New users get a free 3-day Pro trial before billing."
: "新用户可先免费体验 3 天 Pro,再决定是否付费。"}
</div>
</div>
{/* ── Cards ── */}
+9 -3
View File
@@ -21,6 +21,8 @@ from src.database.db_manager import DBManager
DEFAULT_POLYGON_CHAIN_ID = 137
DEFAULT_USDC_E_ADDRESS = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174"
DEFAULT_NATIVE_USDC_ADDRESS = "0x3c499c542cef5e3811e1192ce70d8cc03d5c3359"
DEFAULT_USDT_ADDRESS = "0xc2132d05d31c914a87c6611c10748aeb04b58e8f"
DEFAULT_PUSD_ADDRESS = "0xc011a7e12a19f7b1f670d46f03b03f3342e82dfb"
PAYMENT_CONTRACT_ABI = [
{
@@ -86,7 +88,7 @@ ERC20_TRANSFER_EVENT_ABI = {
}
DEFAULT_PLAN_CATALOG: Dict[str, Dict[str, Any]] = {
"pro_monthly": {"plan_id": 101, "amount_usdc": "5", "duration_days": 30},
"pro_monthly": {"plan_id": 101, "amount_usdc": "10", "duration_days": 30},
"pro_quarterly": {"plan_id": 102, "amount_usdc": "79", "duration_days": 90},
"pro_yearly": {"plan_id": 103, "amount_usdc": "279", "duration_days": 365},
}
@@ -266,8 +268,8 @@ class PaymentContractCheckoutService:
legacy_receiver_contract = _normalize_address(
os.getenv("POLYWEATHER_PAYMENT_RECEIVER_CONTRACT") or ""
)
legacy_token_address = _normalize_address(
os.getenv("POLYWEATHER_PAYMENT_TOKEN_ADDRESS") or DEFAULT_USDC_E_ADDRESS
legacy_token_address = (
os.getenv("POLYWEATHER_PAYMENT_TOKEN_ADDRESS") or DEFAULT_NATIVE_USDC_ADDRESS
)
self.supported_tokens = self._load_supported_tokens(
os.getenv("POLYWEATHER_PAYMENT_ACCEPTED_TOKENS_JSON") or "",
@@ -381,6 +383,10 @@ class PaymentContractCheckoutService:
normalized = _normalize_address(address)
if normalized == _normalize_address(DEFAULT_NATIVE_USDC_ADDRESS):
return {"code": "usdc", "symbol": "USDC", "name": "Native USDC"}
if normalized == _normalize_address(DEFAULT_USDT_ADDRESS):
return {"code": "usdt", "symbol": "USDT", "name": "USDT"}
if normalized == _normalize_address(DEFAULT_PUSD_ADDRESS):
return {"code": "pusd", "symbol": "pUSD", "name": "Polymarket pUSD"}
if normalized == _normalize_address(DEFAULT_USDC_E_ADDRESS):
return {"code": "usdc_e", "symbol": "USDC.e", "name": "USDC.e (PoS)"}
return {"code": "usdc_token", "symbol": "USDC", "name": "USDC"}