package payment import ( "context" "encoding/json" "testing" "kra/internal/biz" ) func TestMigrateSeedsPaymentProviders(t *testing.T) { db, err := openWithDriver("sqlite", "file:"+t.Name()+"?mode=memory&cache=shared") if err != nil { t.Fatal(err) } if err = migrateAll(db); err != nil { t.Fatal(err) } var count int64 if err = db.Model(&integrationConfigPO{}).Where("kind = ?", integrationKindPayment).Count(&count).Error; err != nil { t.Fatal(err) } if count != int64(len(biz.SupportedPaymentProviders)) { t.Fatalf("payment providers = %d", count) } if !db.Migrator().HasTable("pay_orders") { t.Fatal("payment migration must create pay_orders") } if db.Migrator().HasTable("pay_callback_events") { t.Fatal("payment migration must not create pay_callback_events") } } func TestPaymentSecretMaskAndMerge(t *testing.T) { values := map[string]any{"app_id": "a", "private_key": "private", "nested": map[string]any{"api_v3_key": "key"}} maskPaymentSecrets(values) if values["private_key"] != "******" || values["nested"].(map[string]any)["api_v3_key"] != "******" { t.Fatalf("not masked: %#v", values) } mergePaymentSecrets(values, map[string]any{"private_key": "private", "nested": map[string]any{"api_v3_key": "key"}}) if values["private_key"] != "private" || values["nested"].(map[string]any)["api_v3_key"] != "key" { t.Fatalf("not merged: %#v", values) } } func TestPaymentConfigListMasksAndSavePreservesSecretAliases(t *testing.T) { db := openIntegrationConfigTestDB(t) repo := &paymentRepo{data: &Data{gormDB: newReloadableDB(db, nil)}} secrets := map[string]string{ "app_key": "app-key-secret", "token": "signing-token", "key_content": "private-key-content", "pkcs12_content": "pkcs12-content", "op_user_passwd": "operator-password", "api_v3key": "api-v3-key-alias", "apiv3_key": "api-v3-key-compact-alias", "key_pem": "key-pem-content", "apiclient_key": "api-client-key-content", } storedValues := map[string]any{"app_id": "public-app-id"} for key, value := range secrets { storedValues[key] = value } storedValues["nested"] = map[string]any{"token": "nested-token"} raw, err := json.Marshal(storedValues) if err != nil { t.Fatal(err) } if err = db.Create(&integrationConfigPO{ Kind: integrationKindPayment, Provider: biz.PaymentQQ, Config: string(raw), }).Error; err != nil { t.Fatal(err) } configs, err := repo.ListConfigs(context.Background()) if err != nil { t.Fatal(err) } if len(configs) != 1 { t.Fatalf("payment configs = %d, want 1", len(configs)) } masked := map[string]any{} if err = json.Unmarshal(configs[0].Values, &masked); err != nil { t.Fatal(err) } if masked["app_id"] != "public-app-id" { t.Fatalf("non-secret app_id = %#v, want public-app-id", masked["app_id"]) } for key := range secrets { if masked[key] != "******" { t.Errorf("secret %s = %#v, want masked value", key, masked[key]) } } if nested, ok := masked["nested"].(map[string]any); !ok || nested["token"] != "******" { t.Errorf("nested token was not masked: %#v", masked["nested"]) } if err = repo.SaveConfig(context.Background(), &biz.PaymentConfig{ Provider: biz.PaymentQQ, Values: configs[0].Values, }); err != nil { t.Fatal(err) } var row integrationConfigPO if err = db.Where("kind = ? AND provider = ?", integrationKindPayment, biz.PaymentQQ).First(&row).Error; err != nil { t.Fatal(err) } preserved := map[string]any{} if err = json.Unmarshal([]byte(row.Config), &preserved); err != nil { t.Fatal(err) } for key, want := range secrets { if preserved[key] != want { t.Errorf("preserved secret %s = %#v, want %q", key, preserved[key], want) } } if nested, ok := preserved["nested"].(map[string]any); !ok || nested["token"] != "nested-token" { t.Errorf("nested token was not preserved: %#v", preserved["nested"]) } }