Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,556 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
dbent "github.com/Wei-Shaw/sub2api/ent"
|
||||
"github.com/Wei-Shaw/sub2api/ent/enttest"
|
||||
"github.com/Wei-Shaw/sub2api/internal/payment"
|
||||
|
||||
"entgo.io/ent/dialect"
|
||||
entsql "entgo.io/ent/dialect/sql"
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
|
||||
func TestPcParseFloat(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
defaultVal float64
|
||||
expected float64
|
||||
}{
|
||||
{"empty string returns default", "", 1.0, 1.0},
|
||||
{"valid float", "3.14", 0, 3.14},
|
||||
{"valid integer as float", "42", 0, 42.0},
|
||||
{"invalid string returns default", "notanumber", 9.99, 9.99},
|
||||
{"zero value", "0", 5.0, 0},
|
||||
{"negative value", "-10.5", 0, -10.5},
|
||||
{"very large value", "99999999.99", 0, 99999999.99},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := pcParseFloat(tt.input, tt.defaultVal)
|
||||
if got != tt.expected {
|
||||
t.Fatalf("pcParseFloat(%q, %v) = %v, want %v", tt.input, tt.defaultVal, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPcParseInt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
defaultVal int
|
||||
expected int
|
||||
}{
|
||||
{"empty string returns default", "", 30, 30},
|
||||
{"valid int", "10", 0, 10},
|
||||
{"invalid string returns default", "abc", 5, 5},
|
||||
{"float string returns default", "3.14", 0, 0},
|
||||
{"zero value", "0", 99, 0},
|
||||
{"negative value", "-1", 0, -1},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := pcParseInt(tt.input, tt.defaultVal)
|
||||
if got != tt.expected {
|
||||
t.Fatalf("pcParseInt(%q, %v) = %v, want %v", tt.input, tt.defaultVal, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlipayMobilePrecreateEnvironmentOverride(t *testing.T) {
|
||||
svc := &PaymentConfigService{}
|
||||
|
||||
t.Setenv(SettingAlipayMobilePrecreateDeepLink, "true")
|
||||
if !svc.parsePaymentConfig(map[string]string{SettingAlipayMobilePrecreateDeepLink: "false"}).AlipayMobilePrecreateDeepLink {
|
||||
t.Fatal("expected environment variable to enable mobile Alipay precreate")
|
||||
}
|
||||
|
||||
t.Setenv(SettingAlipayMobilePrecreateDeepLink, "false")
|
||||
if svc.parsePaymentConfig(map[string]string{SettingAlipayMobilePrecreateDeepLink: "true"}).AlipayMobilePrecreateDeepLink {
|
||||
t.Fatal("expected environment variable to disable mobile Alipay precreate")
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePaymentConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
svc := &PaymentConfigService{}
|
||||
|
||||
t.Run("empty vals uses defaults", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := svc.parsePaymentConfig(map[string]string{})
|
||||
if cfg.Enabled {
|
||||
t.Fatal("expected Enabled=false by default")
|
||||
}
|
||||
if cfg.MinAmount != 1 {
|
||||
t.Fatalf("expected MinAmount=1, got %v", cfg.MinAmount)
|
||||
}
|
||||
if cfg.MaxAmount != 0 {
|
||||
t.Fatalf("expected MaxAmount=0 (no limit), got %v", cfg.MaxAmount)
|
||||
}
|
||||
if cfg.OrderTimeoutMin != 30 {
|
||||
t.Fatalf("expected OrderTimeoutMin=30, got %v", cfg.OrderTimeoutMin)
|
||||
}
|
||||
if cfg.MaxPendingOrders != 3 {
|
||||
t.Fatalf("expected MaxPendingOrders=3, got %v", cfg.MaxPendingOrders)
|
||||
}
|
||||
if cfg.LoadBalanceStrategy != payment.DefaultLoadBalanceStrategy {
|
||||
t.Fatalf("expected LoadBalanceStrategy=%s, got %q", payment.DefaultLoadBalanceStrategy, cfg.LoadBalanceStrategy)
|
||||
}
|
||||
if len(cfg.EnabledTypes) != 0 {
|
||||
t.Fatalf("expected empty EnabledTypes, got %v", cfg.EnabledTypes)
|
||||
}
|
||||
if cfg.AlipayMobilePrecreateDeepLink {
|
||||
t.Fatal("expected AlipayMobilePrecreateDeepLink=false by default")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("all values populated", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
vals := map[string]string{
|
||||
SettingPaymentEnabled: "true",
|
||||
SettingMinRechargeAmount: "5.00",
|
||||
SettingMaxRechargeAmount: "1000.00",
|
||||
SettingDailyRechargeLimit: "5000.00",
|
||||
SettingOrderTimeoutMinutes: "15",
|
||||
SettingMaxPendingOrders: "5",
|
||||
SettingEnabledPaymentTypes: "alipay,wxpay,stripe",
|
||||
SettingBalancePayDisabled: "true",
|
||||
SettingLoadBalanceStrategy: "least_amount",
|
||||
SettingProductNamePrefix: "PRE",
|
||||
SettingProductNameSuffix: "SUF",
|
||||
SettingAlipayMobilePrecreateDeepLink: "true",
|
||||
}
|
||||
cfg := svc.parsePaymentConfig(vals)
|
||||
|
||||
if !cfg.Enabled {
|
||||
t.Fatal("expected Enabled=true")
|
||||
}
|
||||
if cfg.MinAmount != 5 {
|
||||
t.Fatalf("MinAmount = %v, want 5", cfg.MinAmount)
|
||||
}
|
||||
if cfg.MaxAmount != 1000 {
|
||||
t.Fatalf("MaxAmount = %v, want 1000", cfg.MaxAmount)
|
||||
}
|
||||
if cfg.DailyLimit != 5000 {
|
||||
t.Fatalf("DailyLimit = %v, want 5000", cfg.DailyLimit)
|
||||
}
|
||||
if cfg.OrderTimeoutMin != 15 {
|
||||
t.Fatalf("OrderTimeoutMin = %v, want 15", cfg.OrderTimeoutMin)
|
||||
}
|
||||
if cfg.MaxPendingOrders != 5 {
|
||||
t.Fatalf("MaxPendingOrders = %v, want 5", cfg.MaxPendingOrders)
|
||||
}
|
||||
if len(cfg.EnabledTypes) != 3 {
|
||||
t.Fatalf("EnabledTypes len = %d, want 3", len(cfg.EnabledTypes))
|
||||
}
|
||||
if cfg.EnabledTypes[0] != "alipay" || cfg.EnabledTypes[1] != "wxpay" || cfg.EnabledTypes[2] != "stripe" {
|
||||
t.Fatalf("EnabledTypes = %v, want [alipay wxpay stripe]", cfg.EnabledTypes)
|
||||
}
|
||||
if !cfg.BalanceDisabled {
|
||||
t.Fatal("expected BalanceDisabled=true")
|
||||
}
|
||||
if cfg.LoadBalanceStrategy != "least_amount" {
|
||||
t.Fatalf("LoadBalanceStrategy = %q, want %q", cfg.LoadBalanceStrategy, "least_amount")
|
||||
}
|
||||
if cfg.ProductNamePrefix != "PRE" {
|
||||
t.Fatalf("ProductNamePrefix = %q, want %q", cfg.ProductNamePrefix, "PRE")
|
||||
}
|
||||
if cfg.ProductNameSuffix != "SUF" {
|
||||
t.Fatalf("ProductNameSuffix = %q, want %q", cfg.ProductNameSuffix, "SUF")
|
||||
}
|
||||
if !cfg.AlipayMobilePrecreateDeepLink {
|
||||
t.Fatal("expected AlipayMobilePrecreateDeepLink=true")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("enabled types with spaces are trimmed", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
vals := map[string]string{
|
||||
SettingEnabledPaymentTypes: " alipay , wxpay ",
|
||||
}
|
||||
cfg := svc.parsePaymentConfig(vals)
|
||||
if len(cfg.EnabledTypes) != 2 {
|
||||
t.Fatalf("EnabledTypes len = %d, want 2", len(cfg.EnabledTypes))
|
||||
}
|
||||
if cfg.EnabledTypes[0] != "alipay" || cfg.EnabledTypes[1] != "wxpay" {
|
||||
t.Fatalf("EnabledTypes = %v, want [alipay wxpay]", cfg.EnabledTypes)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("enabled types are normalized to visible methods and deduplicated", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
vals := map[string]string{
|
||||
SettingEnabledPaymentTypes: "alipay_direct, alipay, wxpay_direct, wxpay",
|
||||
}
|
||||
cfg := svc.parsePaymentConfig(vals)
|
||||
if len(cfg.EnabledTypes) != 2 {
|
||||
t.Fatalf("EnabledTypes len = %d, want 2", len(cfg.EnabledTypes))
|
||||
}
|
||||
if cfg.EnabledTypes[0] != "alipay" || cfg.EnabledTypes[1] != "wxpay" {
|
||||
t.Fatalf("EnabledTypes = %v, want [alipay wxpay]", cfg.EnabledTypes)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("custom enabled types are preserved", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
vals := map[string]string{
|
||||
SettingEnabledPaymentTypes: "alipay,ldc,usdt_trc20",
|
||||
}
|
||||
cfg := svc.parsePaymentConfig(vals)
|
||||
want := []string{"alipay", "ldc", "usdt_trc20"}
|
||||
if len(cfg.EnabledTypes) != len(want) {
|
||||
t.Fatalf("EnabledTypes len = %d, want %d (%v)", len(cfg.EnabledTypes), len(want), cfg.EnabledTypes)
|
||||
}
|
||||
for i := range want {
|
||||
if cfg.EnabledTypes[i] != want[i] {
|
||||
t.Fatalf("EnabledTypes[%d] = %q, want %q (full=%v)", i, cfg.EnabledTypes[i], want[i], cfg.EnabledTypes)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("empty enabled types string", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
vals := map[string]string{
|
||||
SettingEnabledPaymentTypes: "",
|
||||
}
|
||||
cfg := svc.parsePaymentConfig(vals)
|
||||
if len(cfg.EnabledTypes) != 0 {
|
||||
t.Fatalf("expected empty EnabledTypes for empty string, got %v", cfg.EnabledTypes)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetBasePaymentType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{payment.TypeEasyPay, payment.TypeEasyPay},
|
||||
{payment.TypeStripe, payment.TypeStripe},
|
||||
{payment.TypeCard, payment.TypeStripe},
|
||||
{payment.TypeLink, payment.TypeStripe},
|
||||
{payment.TypeAlipay, payment.TypeAlipay},
|
||||
{payment.TypeAlipayDirect, payment.TypeAlipay},
|
||||
{payment.TypeWxpay, payment.TypeWxpay},
|
||||
{payment.TypeWxpayDirect, payment.TypeWxpay},
|
||||
{"unknown", "unknown"},
|
||||
{"", ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.input, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got := payment.GetBasePaymentType(tt.input)
|
||||
if got != tt.expected {
|
||||
t.Fatalf("GetBasePaymentType(%q) = %q, want %q", tt.input, got, tt.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyVisibleMethodRoutingToEnabledTypes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
base := []string{"alipay", "wxpay", "stripe"}
|
||||
vals := map[string]string{
|
||||
SettingPaymentVisibleMethodAlipayEnabled: "true",
|
||||
SettingPaymentVisibleMethodAlipaySource: VisibleMethodSourceOfficialAlipay,
|
||||
SettingPaymentVisibleMethodWxpayEnabled: "true",
|
||||
SettingPaymentVisibleMethodWxpaySource: VisibleMethodSourceOfficialWechat,
|
||||
}
|
||||
available := map[string]bool{
|
||||
VisibleMethodSourceOfficialAlipay: true,
|
||||
VisibleMethodSourceOfficialWechat: false,
|
||||
}
|
||||
|
||||
got := applyVisibleMethodRoutingToEnabledTypes(base, vals, available)
|
||||
want := []string{"alipay", "stripe"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("applyVisibleMethodRoutingToEnabledTypes len = %d, want %d (%v)", len(got), len(want), got)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("applyVisibleMethodRoutingToEnabledTypes[%d] = %q, want %q (full=%v)", i, got[i], want[i], got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestApplyVisibleMethodRoutingAddsConfiguredVisibleMethod(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
base := []string{"stripe"}
|
||||
vals := map[string]string{
|
||||
SettingPaymentVisibleMethodAlipayEnabled: "true",
|
||||
SettingPaymentVisibleMethodAlipaySource: VisibleMethodSourceEasyPayAlipay,
|
||||
}
|
||||
available := map[string]bool{
|
||||
VisibleMethodSourceEasyPayAlipay: true,
|
||||
}
|
||||
|
||||
got := applyVisibleMethodRoutingToEnabledTypes(base, vals, available)
|
||||
want := []string{"stripe", "alipay"}
|
||||
if len(got) != len(want) {
|
||||
t.Fatalf("applyVisibleMethodRoutingToEnabledTypes len = %d, want %d (%v)", len(got), len(want), got)
|
||||
}
|
||||
for i := range want {
|
||||
if got[i] != want[i] {
|
||||
t.Fatalf("applyVisibleMethodRoutingToEnabledTypes[%d] = %q, want %q (full=%v)", i, got[i], want[i], got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildVisibleMethodSourceAvailability(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
instances := []*dbent.PaymentProviderInstance{
|
||||
{ProviderKey: payment.TypeAlipay, SupportedTypes: "alipay"},
|
||||
{ProviderKey: payment.TypeEasyPay, SupportedTypes: "wxpay_direct, alipay"},
|
||||
{ProviderKey: payment.TypeWxpay, SupportedTypes: "wxpay_direct"},
|
||||
}
|
||||
|
||||
got := buildVisibleMethodSourceAvailability(instances)
|
||||
if !got[VisibleMethodSourceOfficialAlipay] {
|
||||
t.Fatalf("expected %q to be available", VisibleMethodSourceOfficialAlipay)
|
||||
}
|
||||
if !got[VisibleMethodSourceEasyPayAlipay] {
|
||||
t.Fatalf("expected %q to be available", VisibleMethodSourceEasyPayAlipay)
|
||||
}
|
||||
if !got[VisibleMethodSourceOfficialWechat] {
|
||||
t.Fatalf("expected %q to be available", VisibleMethodSourceOfficialWechat)
|
||||
}
|
||||
if !got[VisibleMethodSourceEasyPayWechat] {
|
||||
t.Fatalf("expected %q to be available", VisibleMethodSourceEasyPayWechat)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPaymentConfigKeepsStoredEnabledTypes(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
client := newPaymentConfigServiceTestClient(t)
|
||||
|
||||
_, err := client.PaymentProviderInstance.Create().
|
||||
SetProviderKey(payment.TypeEasyPay).
|
||||
SetName("EasyPay Alipay").
|
||||
SetConfig("{}").
|
||||
SetSupportedTypes("alipay").
|
||||
SetEnabled(true).
|
||||
Save(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("create easypay instance: %v", err)
|
||||
}
|
||||
|
||||
svc := &PaymentConfigService{
|
||||
entClient: client,
|
||||
settingRepo: &paymentConfigSettingRepoStub{
|
||||
values: map[string]string{
|
||||
SettingEnabledPaymentTypes: "alipay,wxpay,stripe",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cfg, err := svc.GetPaymentConfig(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("GetPaymentConfig returned error: %v", err)
|
||||
}
|
||||
|
||||
want := []string{payment.TypeAlipay, payment.TypeWxpay, payment.TypeStripe}
|
||||
if len(cfg.EnabledTypes) != len(want) {
|
||||
t.Fatalf("EnabledTypes len = %d, want %d (%v)", len(cfg.EnabledTypes), len(want), cfg.EnabledTypes)
|
||||
}
|
||||
for i := range want {
|
||||
if cfg.EnabledTypes[i] != want[i] {
|
||||
t.Fatalf("EnabledTypes[%d] = %q, want %q (full=%v)", i, cfg.EnabledTypes[i], want[i], cfg.EnabledTypes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func newPaymentConfigServiceTestClient(t *testing.T) *dbent.Client {
|
||||
t.Helper()
|
||||
|
||||
dbName := fmt.Sprintf(
|
||||
"file:%s?mode=memory&cache=shared",
|
||||
strings.NewReplacer("/", "_", " ", "_").Replace(t.Name()),
|
||||
)
|
||||
db, err := sql.Open("sqlite", dbName)
|
||||
if err != nil {
|
||||
t.Fatalf("open sqlite: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { _ = db.Close() })
|
||||
|
||||
if _, err := db.Exec("PRAGMA foreign_keys = ON"); err != nil {
|
||||
t.Fatalf("enable foreign keys: %v", err)
|
||||
}
|
||||
|
||||
drv := entsql.OpenDB(dialect.SQLite, db)
|
||||
client := enttest.NewClient(t, enttest.WithOptions(dbent.Driver(drv)))
|
||||
t.Cleanup(func() { _ = client.Close() })
|
||||
return client
|
||||
}
|
||||
|
||||
type paymentConfigSettingRepoStub struct {
|
||||
values map[string]string
|
||||
updates map[string]string
|
||||
}
|
||||
|
||||
func (s *paymentConfigSettingRepoStub) Get(context.Context, string) (*Setting, error) {
|
||||
return nil, nil
|
||||
}
|
||||
func (s *paymentConfigSettingRepoStub) GetValue(_ context.Context, key string) (string, error) {
|
||||
return s.values[key], nil
|
||||
}
|
||||
func (s *paymentConfigSettingRepoStub) Set(context.Context, string, string) error { return nil }
|
||||
func (s *paymentConfigSettingRepoStub) GetMultiple(_ context.Context, keys []string) (map[string]string, error) {
|
||||
out := make(map[string]string, len(keys))
|
||||
for _, key := range keys {
|
||||
out[key] = s.values[key]
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
func (s *paymentConfigSettingRepoStub) SetMultiple(_ context.Context, values map[string]string) error {
|
||||
s.updates = make(map[string]string, len(values))
|
||||
for key, value := range values {
|
||||
s.updates[key] = value
|
||||
if s.values == nil {
|
||||
s.values = map[string]string{}
|
||||
}
|
||||
s.values[key] = value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (s *paymentConfigSettingRepoStub) GetAll(context.Context) (map[string]string, error) {
|
||||
return s.values, nil
|
||||
}
|
||||
func (s *paymentConfigSettingRepoStub) Delete(context.Context, string) error { return nil }
|
||||
|
||||
func TestUpdatePaymentConfig_PersistsVisibleMethodRouting(t *testing.T) {
|
||||
repo := &paymentConfigSettingRepoStub{values: map[string]string{
|
||||
SettingPaymentVisibleMethodAlipayEnabled: "false",
|
||||
SettingPaymentVisibleMethodAlipaySource: VisibleMethodSourceOfficialAlipay,
|
||||
SettingPaymentVisibleMethodWxpayEnabled: "true",
|
||||
SettingPaymentVisibleMethodWxpaySource: VisibleMethodSourceEasyPayWechat,
|
||||
}}
|
||||
svc := &PaymentConfigService{settingRepo: repo}
|
||||
|
||||
alipayEnabled := true
|
||||
wxpayEnabled := false
|
||||
err := svc.UpdatePaymentConfig(context.Background(), UpdatePaymentConfigRequest{
|
||||
VisibleMethodAlipayEnabled: &alipayEnabled,
|
||||
VisibleMethodAlipaySource: paymentConfigStrPtr(VisibleMethodSourceEasyPayAlipay),
|
||||
VisibleMethodWxpayEnabled: &wxpayEnabled,
|
||||
VisibleMethodWxpaySource: paymentConfigStrPtr(VisibleMethodSourceOfficialWechat),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdatePaymentConfig returned error: %v", err)
|
||||
}
|
||||
|
||||
if repo.values[SettingPaymentVisibleMethodAlipayEnabled] != "true" {
|
||||
t.Fatalf("alipay enabled = %q, want true", repo.values[SettingPaymentVisibleMethodAlipayEnabled])
|
||||
}
|
||||
if repo.values[SettingPaymentVisibleMethodAlipaySource] != VisibleMethodSourceEasyPayAlipay {
|
||||
t.Fatalf("alipay source = %q, want %q", repo.values[SettingPaymentVisibleMethodAlipaySource], VisibleMethodSourceEasyPayAlipay)
|
||||
}
|
||||
if repo.values[SettingPaymentVisibleMethodWxpayEnabled] != "false" {
|
||||
t.Fatalf("wxpay enabled = %q, want false", repo.values[SettingPaymentVisibleMethodWxpayEnabled])
|
||||
}
|
||||
if repo.values[SettingPaymentVisibleMethodWxpaySource] != VisibleMethodSourceOfficialWechat {
|
||||
t.Fatalf("wxpay source = %q, want %q", repo.values[SettingPaymentVisibleMethodWxpaySource], VisibleMethodSourceOfficialWechat)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePaymentConfig_OmittedVisibleMethodRoutingIsPreserved(t *testing.T) {
|
||||
wantVisibleMethods := map[string]string{
|
||||
SettingPaymentVisibleMethodAlipayEnabled: "true",
|
||||
SettingPaymentVisibleMethodAlipaySource: VisibleMethodSourceEasyPayAlipay,
|
||||
SettingPaymentVisibleMethodWxpayEnabled: "false",
|
||||
SettingPaymentVisibleMethodWxpaySource: VisibleMethodSourceOfficialWechat,
|
||||
}
|
||||
initial := make(map[string]string, len(wantVisibleMethods))
|
||||
for key, value := range wantVisibleMethods {
|
||||
initial[key] = value
|
||||
}
|
||||
repo := &paymentConfigSettingRepoStub{values: initial}
|
||||
svc := &PaymentConfigService{settingRepo: repo}
|
||||
|
||||
enabled := true
|
||||
err := svc.UpdatePaymentConfig(context.Background(), UpdatePaymentConfigRequest{Enabled: &enabled})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdatePaymentConfig returned error: %v", err)
|
||||
}
|
||||
|
||||
visibleMethodKeys := []string{
|
||||
SettingPaymentVisibleMethodAlipayEnabled,
|
||||
SettingPaymentVisibleMethodAlipaySource,
|
||||
SettingPaymentVisibleMethodWxpayEnabled,
|
||||
SettingPaymentVisibleMethodWxpaySource,
|
||||
}
|
||||
for _, key := range visibleMethodKeys {
|
||||
if _, ok := repo.updates[key]; ok {
|
||||
t.Fatalf("omitted visible method setting %q was written", key)
|
||||
}
|
||||
if repo.values[key] != wantVisibleMethods[key] {
|
||||
t.Fatalf("visible method setting %q = %q, want preserved value %q", key, repo.values[key], wantVisibleMethods[key])
|
||||
}
|
||||
}
|
||||
if repo.updates[SettingPaymentEnabled] != "true" {
|
||||
t.Fatalf("payment enabled update = %q, want true", repo.updates[SettingPaymentEnabled])
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdatePaymentConfig_PersistsExplicitEmptyAndFalseValues(t *testing.T) {
|
||||
repo := &paymentConfigSettingRepoStub{values: map[string]string{
|
||||
SettingEnabledPaymentTypes: "alipay,wxpay",
|
||||
SettingBalancePayDisabled: "true",
|
||||
SettingProductNamePrefix: "existing",
|
||||
}}
|
||||
svc := &PaymentConfigService{settingRepo: repo}
|
||||
|
||||
falseValue := false
|
||||
emptyString := ""
|
||||
err := svc.UpdatePaymentConfig(context.Background(), UpdatePaymentConfigRequest{
|
||||
EnabledTypes: []string{},
|
||||
BalanceDisabled: &falseValue,
|
||||
ProductNamePrefix: &emptyString,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("UpdatePaymentConfig returned error: %v", err)
|
||||
}
|
||||
|
||||
want := map[string]string{
|
||||
SettingEnabledPaymentTypes: "",
|
||||
SettingBalancePayDisabled: "false",
|
||||
SettingProductNamePrefix: "",
|
||||
}
|
||||
if len(repo.updates) != len(want) {
|
||||
t.Fatalf("updates = %v, want exactly %v", repo.updates, want)
|
||||
}
|
||||
for key, value := range want {
|
||||
if repo.updates[key] != value {
|
||||
t.Fatalf("update %q = %q, want %q", key, repo.updates[key], value)
|
||||
}
|
||||
if repo.values[key] != value {
|
||||
t.Fatalf("stored %q = %q, want %q", key, repo.values[key], value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func paymentConfigStrPtr(value string) *string {
|
||||
return &value
|
||||
}
|
||||
Reference in New Issue
Block a user