package paymentconfig import ( "testing" "time" "hfb_sys/backend/internal/model" "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) func TestImportCreateRequestKeepsOneActiveConfigPerPayWay(t *testing.T) { configs := []ConfigDTO{ {Provider: "lakala", MerchantID: "M1", PayWay: "ZFBZF", Status: "active", IsDefault: true}, {Provider: "leshua", MerchantID: "M2", PayWay: "ZFBZF", Status: "active", IsDefault: false}, {Provider: "leshua", MerchantID: "M3", PayWay: "WXZF", Status: "active", IsDefault: true}, } activeKeys := backupActiveKeys(configs) first := importCreateRequest(configs[0], activeKeys) second := importCreateRequest(configs[1], activeKeys) third := importCreateRequest(configs[2], activeKeys) if first.Status != "active" || !first.IsDefault { t.Fatalf("first config status/default = %s/%v, want active/true", first.Status, first.IsDefault) } if second.Status != "disabled" || second.IsDefault { t.Fatalf("second config status/default = %s/%v, want disabled/false", second.Status, second.IsDefault) } if third.Status != "active" || !third.IsDefault { t.Fatalf("third config status/default = %s/%v, want active/true", third.Status, third.IsDefault) } } func TestImportCreateRequestPreservesTestingConfig(t *testing.T) { cfg := ConfigDTO{ Provider: "lakala", MerchantID: "M1", Status: "testing", } req := importCreateRequest(cfg, nil) if req.Status != "testing" || req.IsDefault { t.Fatalf("status/default = %s/%v, want testing/false", req.Status, req.IsDefault) } } func TestValidateCreateRequestRequiresShunchengSecretID(t *testing.T) { repo := &Repository{} req := CreateRequest{ Name: "顺成生产商户", Provider: "shuncheng", MerchantID: "0000000038", GatewayURL: "http://jyzxapi.ydxnhb.com", SignKey: "secret-key", NotifyKey: "notify-key", NotifyURL: "https://example.com/api/payments/shuncheng/notify", PayWay: "ZFBZF", } if err := repo.validateCreateRequest(req); err != ErrSecretIDRequired { t.Fatalf("validateCreateRequest() error = %v, want ErrSecretIDRequired", err) } req.ExtraConfig = map[string]any{"secret_id": "SEC-1"} if err := repo.validateCreateRequest(req); err != nil { t.Fatalf("validateCreateRequest() error = %v, want nil", err) } } // TestListUsesSuccessfulPaymentStats 验证配置页只统计成功支付,不把打开二维码或取消订单算作成交。 func TestListUsesSuccessfulPaymentStats(t *testing.T) { db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{Logger: logger.Default.LogMode(logger.Silent)}) if err != nil { t.Fatalf("open db failed: %v", err) } if err := db.AutoMigrate(&model.PaymentMerchantConfig{}, &model.PaymentOrder{}); err != nil { t.Fatalf("migrate failed: %v", err) } config := model.PaymentMerchantConfig{ Name: "拉卡拉微信", Provider: "lakala", MerchantID: "M1", PayWay: "WXZF", Status: "active", Environment: "production", TotalTransactions: 99, TotalAmountCent: 999999, } if err := db.Create(&config).Error; err != nil { t.Fatalf("create config failed: %v", err) } paidAt := time.Date(2026, 6, 14, 23, 36, 7, 0, time.UTC) payments := []model.PaymentOrder{ { PaymentNo: "PAY-SUCCESS", OrderID: 1, OrderNo: "ORD-SUCCESS", UserID: 2, PaymentConfigID: config.ID, Provider: "lakala", MerchantID: "M1", ThirdOrderID: "PAY-SUCCESS", AmountCent: 10130, BizType: "order_pay", Status: "paid", PaidAt: &paidAt, }, { PaymentNo: "PAY-CANCELLED", OrderID: 2, OrderNo: "ORD-CANCELLED", UserID: 2, PaymentConfigID: config.ID, Provider: "lakala", MerchantID: "M1", ThirdOrderID: "PAY-CANCELLED", AmountCent: 10130, BizType: "order_pay", Status: "closed", }, { PaymentNo: "PAY-LEGACY", OrderID: 3, OrderNo: "ORD-LEGACY", UserID: 2, PaymentConfigID: 0, Provider: "lakala", MerchantID: "M1", ThirdOrderID: "PAY-LEGACY", PayWay: "WXZF", AmountCent: 10130, BizType: "order_pay", Status: "failed", }, } if err := db.Create(&payments).Error; err != nil { t.Fatalf("create payments failed: %v", err) } repo := NewRepository(db, nil) items, total, err := repo.List(t.Context(), ListQuery{Page: 1, PageSize: 20}) if err != nil { t.Fatalf("List() error = %v", err) } if total != 1 || len(items) != 1 { t.Fatalf("items/total = %d/%d, want 1/1", len(items), total) } if items[0].TotalTransactions != 1 || items[0].TotalAmountCent != 10130 { t.Fatalf("success stats = %d/%d, want 1/10130", items[0].TotalTransactions, items[0].TotalAmountCent) } if items[0].ReferenceCount != 3 { t.Fatalf("reference_count = %d, want 3", items[0].ReferenceCount) } if items[0].LastUsedAt == nil { t.Fatal("last success pay time should not be nil") } }