fix: 测试包年商品改用 USD,避免 CNY 不被支持

Waffo 测试侧 Yearly Product 仅支持 USD;按 Product ID 自动选币种。
This commit is contained in:
Logan.Li committed 2026-08-13 00:13:07 +08:00
1 parent 2b44e8dcb3
commit 37d9e8ca56
3 files changed
+51 -23

No files matched your search

+17 -3
View File
@@ -456,22 +456,36 @@ func productIDForPlan(cfg WaffoConfig, planType string) string {
} }
func currencyForPlan(cfg WaffoConfig, planType string) string { func currencyForPlan(cfg WaffoConfig, planType string) string {
// 已知商品 ID 优先(测试包年不支持 CNY) // Logan.Li
if pid := productIDForPlan(cfg, planType); pid != "" {
switch pid {
case "PROD_1BIezCi932IbgCzRIV8hcJ", // test yearly
"PROD_0pcnzzT4nalEkkcdyIUoD5", // test perpetual
"PROD_3BSJqDRkVBoYNgO78NsTAU": // live perpetual
return "USD"
case "PROD_5PqVJyEiCM4nDgVoA0RKjN": // live yearly
return "CNY"
}
}
switch strings.TrimSpace(strings.ToLower(planType)) { switch strings.TrimSpace(strings.ToLower(planType)) {
case "yearly", "monthly": case "yearly", "monthly":
if cfg.CurrencyYearly != "" { if cfg.CurrencyYearly != "" {
return cfg.CurrencyYearly return cfg.CurrencyYearly
} }
return "CNY" // OpsXshell 包年默认人民币 // Logan.Li if NormalizeWaffoEnvironment(cfg.Environment) == "live" {
return "CNY"
}
return "USD"
case "perpetual", "lifetime": case "perpetual", "lifetime":
if cfg.CurrencyPerpetual != "" { if cfg.CurrencyPerpetual != "" {
return cfg.CurrencyPerpetual return cfg.CurrencyPerpetual
} }
return "USD" // OpsXshell 永久默认美元 // Logan.Li return "USD"
} }
if cfg.Currency != "" { if cfg.Currency != "" {
return cfg.Currency return cfg.Currency
} }
return "CNY" return "USD"
} }
func checkoutTypeForPlan(planType string) string { func checkoutTypeForPlan(planType string) string {
@@ -6,13 +6,13 @@ import (
"testing" "testing"
) )
func TestResolveBaseCheckoutURL_YearlyOnetimeCNY(t *testing.T) { func TestResolveBaseCheckoutURL_YearlyOnetimeUSD(t *testing.T) {
cfg := WaffoConfig{ cfg := WaffoConfig{
StoreSlug: "opsxshell-pwsi6m4n", StoreSlug: "opsxshell-pwsi6m4n",
ProductIDYearly: "PROD_1BIezCi932IbgCzRIV8hcJ", ProductIDYearly: "PROD_1BIezCi932IbgCzRIV8hcJ",
ProductIDPerpetual: "PROD_0pcnzzT4nalEkkcdyIUoD5", ProductIDPerpetual: "PROD_0pcnzzT4nalEkkcdyIUoD5",
Currency: "CNY", Currency: "CNY",
CurrencyYearly: "CNY", CurrencyYearly: "CNY", // 即使配置写 CNY,已知测试商品仍强制 USD // Logan.Li
CurrencyPerpetual: "USD", CurrencyPerpetual: "USD",
Environment: "test", Environment: "test",
SuccessURL: "opsxshell://pro/activated", SuccessURL: "opsxshell://pro/activated",
@@ -28,12 +28,12 @@ func TestResolveBaseCheckoutURL_YearlyOnetimeCNY(t *testing.T) {
if q.Get("type") != "onetime" { if q.Get("type") != "onetime" {
t.Fatalf("type=%s want onetime", q.Get("type")) t.Fatalf("type=%s want onetime", q.Get("type"))
} }
if q.Get("currency") != "CNY" { if q.Get("currency") != "USD" {
t.Fatalf("currency=%s want CNY", q.Get("currency")) t.Fatalf("currency=%s want USD", q.Get("currency"))
} }
} }
func TestResolveBaseCheckoutURL_PerpetualOnetimeCNY(t *testing.T) { func TestResolveBaseCheckoutURL_PerpetualOnetimeUSD(t *testing.T) {
cfg := WaffoConfig{ cfg := WaffoConfig{
StoreSlug: "opsxshell-pwsi6m4n", StoreSlug: "opsxshell-pwsi6m4n",
ProductIDYearly: "PROD_1BIezCi932IbgCzRIV8hcJ", ProductIDYearly: "PROD_1BIezCi932IbgCzRIV8hcJ",
@@ -55,8 +55,8 @@ func TestResolveBaseCheckoutURL_PerpetualOnetimeCNY(t *testing.T) {
if q.Get("type") != "onetime" { if q.Get("type") != "onetime" {
t.Fatalf("type=%s want onetime", q.Get("type")) t.Fatalf("type=%s want onetime", q.Get("type"))
} }
if q.Get("currency") != "CNY" { if q.Get("currency") != "USD" {
t.Fatalf("currency=%s want CNY", q.Get("currency")) t.Fatalf("currency=%s want USD", q.Get("currency"))
} }
} }
+27 -13
View File
@@ -107,7 +107,7 @@
type="warning" type="warning"
:closable="false" :closable="false"
show-icon show-icon
title="下单时按计划选用对应 PROD_xxx:包年→yearly,永久→perpetual。货币由后端按计划自动带(包年 CNY / 永久 USD),无需手填。" title="下单时按计划选用对应 PROD_xxx。币种按商品自动选择(测试包年 USD;生产包年 CNY;永久 USD)。"
style="margin-bottom: 12px" style="margin-bottom: 12px"
/> />
<el-table :data="productMappings" border stripe> <el-table :data="productMappings" border stripe>
@@ -157,16 +157,24 @@ import { getWaffoSettings, updateWaffoSettings, testWaffoConnection } from '@/ap
const planKeyOptions = ['trial', 'yearly', 'perpetual', 'monthly', 'lifetime'] const planKeyOptions = ['trial', 'yearly', 'perpetual', 'monthly', 'lifetime']
// OpsXshell 商品:测试 / 生产各一套 // Logan.Li // OpsXshell 商品:测试 / 生产各一套(币种跟 Waffo 商品实际支持走) // Logan.Li
const OPSXSHELL_PRODUCTS_LIVE = [ const OPSXSHELL_PRODUCTS_LIVE = [
{ plan_key: 'yearly', label: 'OpsXshell Yearly', product_id: 'PROD_5PqVJyEiCM4nDgVoA0RKjN' }, { plan_key: 'yearly', label: 'OpsXshell Yearly', product_id: 'PROD_5PqVJyEiCM4nDgVoA0RKjN', currency: 'CNY' },
{ plan_key: 'perpetual', label: 'OpsXshell Perpetual', product_id: 'PROD_3BSJqDRkVBoYNgO78NsTAU' }, { plan_key: 'perpetual', label: 'OpsXshell Perpetual', product_id: 'PROD_3BSJqDRkVBoYNgO78NsTAU', currency: 'USD' },
] ]
const OPSXSHELL_PRODUCTS_TEST = [ const OPSXSHELL_PRODUCTS_TEST = [
{ plan_key: 'yearly', label: 'OpsXshell Yearly', product_id: 'PROD_1BIezCi932IbgCzRIV8hcJ' }, // 测试包年商品不支持 CNY,须用 USD // Logan.Li
{ plan_key: 'perpetual', label: 'OpsXshell Perpetual', product_id: 'PROD_0pcnzzT4nalEkkcdyIUoD5' }, { plan_key: 'yearly', label: 'OpsXshell Yearly', product_id: 'PROD_1BIezCi932IbgCzRIV8hcJ', currency: 'USD' },
{ plan_key: 'perpetual', label: 'OpsXshell Perpetual', product_id: 'PROD_0pcnzzT4nalEkkcdyIUoD5', currency: 'USD' },
] ]
const PRODUCT_CURRENCY = {
PROD_5PqVJyEiCM4nDgVoA0RKjN: 'CNY',
PROD_3BSJqDRkVBoYNgO78NsTAU: 'USD',
PROD_1BIezCi932IbgCzRIV8hcJ: 'USD',
PROD_0pcnzzT4nalEkkcdyIUoD5: 'USD',
}
const loading = ref(false) const loading = ref(false)
const saving = ref(false) const saving = ref(false)
const debugging = ref(false) const debugging = ref(false)
@@ -226,19 +234,24 @@ function normalizeMappings(data = {}) {
return rows.length ? rows : defaultMappings() return rows.length ? rows : defaultMappings()
} }
// 按计划自动带货币,不再展示币种列 // Logan.Li // 按 Product ID / 计划推断币种(测试包年是 USD,生产包年才是 CNY) // Logan.Li
function currencyForKey(planKey) { function currencyForRow(row = {}) {
const k = (planKey || '').toLowerCase() const pid = (row.product_id || '').trim()
if (pid && PRODUCT_CURRENCY[pid]) return PRODUCT_CURRENCY[pid]
if ((row.currency || '').trim()) return row.currency.trim().toUpperCase()
const k = (row.plan_key || '').toLowerCase()
if (k === 'perpetual' || k === 'lifetime') return 'USD' if (k === 'perpetual' || k === 'lifetime') return 'USD'
return 'CNY' return isLive.value ? 'CNY' : 'USD'
} }
function mappingsToCompatFields(rows) { function mappingsToCompatFields(rows) {
const map = {} const map = {}
const currencyMap = {}
for (const row of rows) { for (const row of rows) {
const key = (row.plan_key || '').trim() const key = (row.plan_key || '').trim()
if (!key) continue if (!key) continue
map[key] = (row.product_id || '').trim() map[key] = (row.product_id || '').trim()
currencyMap[key] = currencyForRow(row)
} }
return { return {
product_mappings: rows product_mappings: rows
@@ -247,13 +260,13 @@ function mappingsToCompatFields(rows) {
plan_key: r.plan_key.trim(), plan_key: r.plan_key.trim(),
label: r.label || '', label: r.label || '',
product_id: (r.product_id || '').trim(), product_id: (r.product_id || '').trim(),
currency: currencyForKey(r.plan_key), currency: currencyForRow(r),
})), })),
product_id_yearly: map.yearly || '', product_id_yearly: map.yearly || '',
product_id_perpetual: map.perpetual || map.lifetime || '', product_id_perpetual: map.perpetual || map.lifetime || '',
product_id: map.perpetual || map.lifetime || map.yearly || '', product_id: map.perpetual || map.lifetime || map.yearly || '',
currency_yearly: 'CNY', currency_yearly: currencyMap.yearly || (isLive.value ? 'CNY' : 'USD'),
currency_perpetual: 'USD', currency_perpetual: currencyMap.perpetual || currencyMap.lifetime || 'USD',
} }
} }
@@ -302,6 +315,7 @@ function fillOpsxshellProducts() {
if (byKey[item.plan_key]) { if (byKey[item.plan_key]) {
byKey[item.plan_key].product_id = item.product_id byKey[item.plan_key].product_id = item.product_id
byKey[item.plan_key].label = item.label byKey[item.plan_key].label = item.label
byKey[item.plan_key].currency = item.currency
} else { } else {
productMappings.value.push({ ...item }) productMappings.value.push({ ...item })
} }