From b30f472d904162665572d143063b14a18b2a98f6 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Sun, 12 Jul 2026 06:54:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(server/pay):=20=E8=AE=A2=E5=8D=95=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E9=87=91=E9=A2=9D=E5=85=9C=E5=BA=95=20=E2=80=94=20?= =?UTF-8?q?=E8=80=81=E5=8D=95=20amount=5Fminor=3D0=20=E5=9B=9E=E9=80=80?= =?UTF-8?q?=E6=A1=A3=E4=BD=8D=E5=B1=95=E7=A4=BA=E4=BB=B7(=E6=8C=89?= =?UTF-8?q?=E6=96=B9=E5=BC=8F=E7=BB=93=E7=AE=97=E5=B8=81=E7=A7=8D)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.8 (1M context) Claude-Session: https://claude.ai/code/session_013nMthbVEmQquxBRKb9Fj8u --- server/internal/pay/handler.go | 8 ++++++++ server/internal/pay/handler_test.go | 32 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/server/internal/pay/handler.go b/server/internal/pay/handler.go index 839c3b9..6499f34 100644 --- a/server/internal/pay/handler.go +++ b/server/internal/pay/handler.go @@ -165,6 +165,14 @@ func orderViewFromRow(row *PurchaseRow) orderView { } if it, ok := CatalogBySKU(row.SKU); ok { v.Plan, v.Days = it.Plan, it.Days + // 展示金额兜底:老单/webhook 前 amount_minor=0(旧下单不落金额)→ 按档位+ + // 支付方式的结算币种回退到展示价,列表/详情不再显 0。webhook 到账后为实际金额,不触发。 + if v.AmountMinor == 0 { + v.AmountMinor = DisplayAmountMinor(it, row.Method) + if v.Currency == "" { + v.Currency = SettlementCurrency(row.Method) + } + } } if row.PaidAt.Valid { s := row.PaidAt.Time.UTC().Format(time.RFC3339) diff --git a/server/internal/pay/handler_test.go b/server/internal/pay/handler_test.go index e983643..805fd84 100644 --- a/server/internal/pay/handler_test.go +++ b/server/internal/pay/handler_test.go @@ -211,6 +211,38 @@ func TestList_OwnershipAndFields(t *testing.T) { } } +// 展示金额兜底:老单 amount_minor=0 → 列表按档位+方式回退到展示价(不显 0)。 +func TestList_ZeroAmountFallback(t *testing.T) { + router, st := newHandlerRig(t, nil) + ctx := context.Background() + // 模拟老单:amount=0、currency 空(旧下单不落金额) + if err := st.Insert(ctx, 1, "uuid-1", "pro_month", "old-alipay", "alipay", 0, ""); err != nil { + t.Fatal(err) + } + if err := st.Insert(ctx, 1, "uuid-1", "pro_year", "old-crypto", "crypto", 0, ""); err != nil { + t.Fatal(err) + } + w := httptest.NewRecorder() + router.ServeHTTP(w, authed(httptest.NewRequest(http.MethodGet, "/v1/pay/orders", nil), 1)) + var resp struct { + Orders []orderView `json:"orders"` + } + if err := json.Unmarshal(w.Body.Bytes(), &resp); err != nil { + t.Fatal(err) + } + got := map[string]orderView{} + for _, o := range resp.Orders { + got[o.OrderNo] = o + } + // alipay → CNY 展示价 2999;crypto → USDT 展示价 34990000 + if a := got["old-alipay"]; a.AmountMinor != 2999 || a.Currency != "CNY" { + t.Fatalf("alipay 兜底不符: amount=%d curr=%q, want 2999/CNY", a.AmountMinor, a.Currency) + } + if cr := got["old-crypto"]; cr.AmountMinor != 34990000 || cr.Currency != "USDT" { + t.Fatalf("crypto 兜底不符: amount=%d curr=%q, want 34990000/USDT", cr.AmountMinor, cr.Currency) + } +} + // 订单详情:回带台账富字段 + pay_status/activated。 func TestGetOrder_EnrichedFields(t *testing.T) { router, st := newHandlerRig(t, func(w http.ResponseWriter, r *http.Request) {