From 3e2719f682dba213ede898c710617319aedb4663 Mon Sep 17 00:00:00 2001 From: hy001 Date: Thu, 23 Apr 2026 12:24:32 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B9=B8=E8=BF=90=E7=A4=BC?= =?UTF-8?q?=E7=89=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/config/config.go | 6 +- internal/config/config_test.go | 47 ++++---- internal/service/luckygift/draw.go | 9 +- internal/service/luckygift/runtime_config.go | 105 ++++++++++++++++++ .../service/luckygift/runtime_config_test.go | 78 +++++++++++++ 5 files changed, 213 insertions(+), 32 deletions(-) create mode 100644 internal/service/luckygift/runtime_config.go create mode 100644 internal/service/luckygift/runtime_config_test.go diff --git a/internal/config/config.go b/internal/config/config.go index 3c650b7..e36cbb4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -307,13 +307,13 @@ func normalizeLuckyGiftConfigs( item.AppID = strings.TrimSpace(item.AppID) item.AppChannel = strings.TrimSpace(item.AppChannel) item.AppKey = strings.TrimSpace(item.AppKey) - if sharedBaishunAppID != "" { + if item.AppID == "" && sharedBaishunAppID != "" { item.AppID = sharedBaishunAppID } - if sharedBaishunAppChannel != "" { + if item.AppChannel == "" && sharedBaishunAppChannel != "" { item.AppChannel = sharedBaishunAppChannel } - if sharedBaishunAppKey != "" { + if item.AppKey == "" && sharedBaishunAppKey != "" { item.AppKey = sharedBaishunAppKey } if item.URL == "" || item.AppID == "" || item.AppChannel == "" || item.AppKey == "" { diff --git a/internal/config/config_test.go b/internal/config/config_test.go index e4d7781..3ee8913 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -5,7 +5,7 @@ import ( "testing" ) -func TestNormalizeLuckyGiftConfigsUsesSharedBaishunAppKey(t *testing.T) { +func TestNormalizeLuckyGiftConfigsKeepsDedicatedAccountWhenSharedPresent(t *testing.T) { configs := normalizeLuckyGiftConfigs([]LuckyGiftProviderConfig{ { StandardID: 18816, @@ -18,30 +18,6 @@ func TestNormalizeLuckyGiftConfigsUsesSharedBaishunAppKey(t *testing.T) { if len(configs) != 1 { t.Fatalf("expected 1 config, got %d", len(configs)) } - if got := configs[0].AppID; got != "shared-baishun-app-id" { - t.Fatalf("expected baishun app id override, got %q", got) - } - if got := configs[0].AppChannel; got != "shared-baishun-app-channel" { - t.Fatalf("expected baishun app channel override, got %q", got) - } - if got := configs[0].AppKey; got != "shared-baishun-key" { - t.Fatalf("expected baishun key override, got %q", got) - } -} - -func TestNormalizeLuckyGiftConfigsKeepsDedicatedKeyWhenSharedBlank(t *testing.T) { - configs := normalizeLuckyGiftConfigs([]LuckyGiftProviderConfig{ - { - StandardID: 18816, - URL: "https://provider.example.com", - AppID: "lucky-app-id", - AppChannel: "lucky-app-channel", - AppKey: "legacy-lucky-key", - }, - }, "", "", "") - if len(configs) != 1 { - t.Fatalf("expected 1 config, got %d", len(configs)) - } if got := configs[0].AppID; got != "lucky-app-id" { t.Fatalf("expected dedicated lucky gift app id, got %q", got) } @@ -53,6 +29,27 @@ func TestNormalizeLuckyGiftConfigsKeepsDedicatedKeyWhenSharedBlank(t *testing.T) } } +func TestNormalizeLuckyGiftConfigsFallsBackToSharedAccountWhenDedicatedBlank(t *testing.T) { + configs := normalizeLuckyGiftConfigs([]LuckyGiftProviderConfig{ + { + StandardID: 18816, + URL: "https://provider.example.com", + }, + }, "shared-baishun-app-id", "shared-baishun-app-channel", "shared-baishun-key") + if len(configs) != 1 { + t.Fatalf("expected 1 config, got %d", len(configs)) + } + if got := configs[0].AppID; got != "shared-baishun-app-id" { + t.Fatalf("expected shared baishun app id fallback, got %q", got) + } + if got := configs[0].AppChannel; got != "shared-baishun-app-channel" { + t.Fatalf("expected shared baishun app channel fallback, got %q", got) + } + if got := configs[0].AppKey; got != "shared-baishun-key" { + t.Fatalf("expected shared baishun key fallback, got %q", got) + } +} + func TestGetEnvBoolAliasSupportsLegacyLuckyGiftKey(t *testing.T) { t.Setenv("LUCKY_GIFT_GO_ENABLED", "true") if got := getEnvBoolAny([]string{"LUCKY_GIFT_ENABLED", "LUCKY_GIFT_GO_ENABLED"}, false); !got { diff --git a/internal/service/luckygift/draw.go b/internal/service/luckygift/draw.go index 7c90de3..739fdb6 100644 --- a/internal/service/luckygift/draw.go +++ b/internal/service/luckygift/draw.go @@ -24,8 +24,9 @@ func (s *LuckyGiftService) Draw(ctx context.Context, req LuckyGiftDrawRequest) ( if !s.cfg.LuckyGift.Enabled { return nil, NewAppError(http.StatusServiceUnavailable, "lucky_gift_disabled", "lucky gift service is disabled") } - if _, ok := findLuckyGiftConfig(s.cfg.LuckyGift.Providers, req.StandardID); !ok { - return nil, NewAppError(http.StatusServiceUnavailable, "lucky_gift_config_missing", "lucky gift provider config is missing") + account, err := s.resolveProviderConfig(ctx, req) + if err != nil { + return nil, err } if cached, err := s.loadSuccessfulResponse(ctx, req.BusinessID); err != nil { @@ -65,7 +66,7 @@ func (s *LuckyGiftService) Draw(ctx context.Context, req LuckyGiftDrawRequest) ( return nil, err } - results, providerCode, rewardTotal, rawProviderResponse, err := s.resolveProviderResults(ctx, req, record, walletEventID) + results, providerCode, rewardTotal, rawProviderResponse, err := s.resolveProviderResults(ctx, account, req, record, walletEventID) if err != nil { _ = s.markRequestFailed(ctx, req.BusinessID, providerCode, rawProviderResponse, err.Error()) return nil, err @@ -145,6 +146,7 @@ func (s *LuckyGiftService) Draw(ctx context.Context, req LuckyGiftDrawRequest) ( // resolveProviderResults 优先复用已缓存的三方响应,否则真正调用三方抽奖接口。 func (s *LuckyGiftService) resolveProviderResults( ctx context.Context, + account config.LuckyGiftProviderConfig, req LuckyGiftDrawRequest, record *model.LuckyGiftDrawRequestRecord, walletEventID string, @@ -161,7 +163,6 @@ func (s *LuckyGiftService) resolveProviderResults( return results, providerCode, rewardTotal, record.ProviderResponseJSON, nil } - account, _ := findLuckyGiftConfig(s.cfg.LuckyGift.Providers, req.StandardID) rawResponse, providerCode, results, rewardTotal, err := s.callLuckyGiftProvider(ctx, account, req) if err != nil { return nil, providerCode, 0, rawResponse, err diff --git a/internal/service/luckygift/runtime_config.go b/internal/service/luckygift/runtime_config.go new file mode 100644 index 0000000..5fc381e --- /dev/null +++ b/internal/service/luckygift/runtime_config.go @@ -0,0 +1,105 @@ +package luckygift + +import ( + "chatapp3-golang/internal/config" + "chatapp3-golang/internal/model" + "context" + "net/http" + "strconv" + "strings" + + "gorm.io/gorm" +) + +type luckyGiftRuntimeAccount struct { + AppID string + AppChannel string + AppKey string +} + +func (s *LuckyGiftService) resolveProviderConfig(ctx context.Context, req LuckyGiftDrawRequest) (config.LuckyGiftProviderConfig, error) { + base, ok := findLuckyGiftConfig(s.cfg.LuckyGift.Providers, req.StandardID) + if !ok { + return config.LuckyGiftProviderConfig{}, NewAppError( + http.StatusServiceUnavailable, + "lucky_gift_config_missing", + "lucky gift provider config is missing", + ) + } + + runtimeAccount, err := s.resolveRuntimeAccount(ctx, req.SysOrigin) + if err != nil { + return config.LuckyGiftProviderConfig{}, NewAppError( + http.StatusInternalServerError, + "lucky_gift_runtime_config_failed", + err.Error(), + ) + } + return mergeLuckyGiftProviderConfig(base, runtimeAccount), nil +} + +func (s *LuckyGiftService) resolveRuntimeAccount(ctx context.Context, sysOrigin string) (luckyGiftRuntimeAccount, error) { + account := defaultLuckyGiftRuntimeAccount(s.cfg) + + var row model.BaishunProviderConfig + err := s.repo.DB.WithContext(ctx). + Where("sys_origin = ?", normalizeLuckyGiftSysOrigin(sysOrigin)). + Limit(1). + First(&row).Error + if err == nil { + return applyLuckyGiftRuntimeAccount(account, row), nil + } + if err == gorm.ErrRecordNotFound { + return account, nil + } + return luckyGiftRuntimeAccount{}, err +} + +func defaultLuckyGiftRuntimeAccount(cfg config.Config) luckyGiftRuntimeAccount { + account := luckyGiftRuntimeAccount{ + AppChannel: strings.TrimSpace(cfg.Baishun.AppChannel), + AppKey: strings.TrimSpace(cfg.Baishun.AppKey), + } + if cfg.Baishun.AppID > 0 { + account.AppID = strconv.FormatInt(cfg.Baishun.AppID, 10) + } + return account +} + +func applyLuckyGiftRuntimeAccount(base luckyGiftRuntimeAccount, row model.BaishunProviderConfig) luckyGiftRuntimeAccount { + if row.AppID > 0 { + base.AppID = strconv.FormatInt(row.AppID, 10) + } + if strings.TrimSpace(row.AppChannel) != "" { + base.AppChannel = strings.TrimSpace(row.AppChannel) + } + if strings.TrimSpace(row.AppKey) != "" { + base.AppKey = strings.TrimSpace(row.AppKey) + } + return base +} + +func mergeLuckyGiftProviderConfig( + base config.LuckyGiftProviderConfig, + runtime luckyGiftRuntimeAccount, +) config.LuckyGiftProviderConfig { + merged := base + if runtime.AppID != "" { + merged.AppID = runtime.AppID + } + if runtime.AppChannel != "" { + merged.AppChannel = runtime.AppChannel + } + if runtime.AppKey != "" { + merged.AppKey = runtime.AppKey + } + return merged +} + +func normalizeLuckyGiftSysOrigin(sysOrigin string) string { + sysOrigin = strings.ToUpper(strings.TrimSpace(sysOrigin)) + if sysOrigin == "" { + return "LIKEI" + } + return sysOrigin +} diff --git a/internal/service/luckygift/runtime_config_test.go b/internal/service/luckygift/runtime_config_test.go new file mode 100644 index 0000000..d953b29 --- /dev/null +++ b/internal/service/luckygift/runtime_config_test.go @@ -0,0 +1,78 @@ +package luckygift + +import ( + "chatapp3-golang/internal/config" + "chatapp3-golang/internal/model" + "testing" +) + +func TestMergeLuckyGiftProviderConfigPrefersRuntimeAccount(t *testing.T) { + base := config.LuckyGiftProviderConfig{ + StandardID: 18816, + URL: "https://provider.example.com/lucky_gift/start_game", + AppID: "base-app-id", + AppChannel: "base-app-channel", + AppKey: "base-app-key", + } + + merged := mergeLuckyGiftProviderConfig(base, luckyGiftRuntimeAccount{ + AppID: "runtime-app-id", + AppChannel: "runtime-app-channel", + AppKey: "runtime-app-key", + }) + + if merged.URL != base.URL { + t.Fatalf("expected url to keep base value, got %q", merged.URL) + } + if merged.AppID != "runtime-app-id" { + t.Fatalf("expected runtime app id, got %q", merged.AppID) + } + if merged.AppChannel != "runtime-app-channel" { + t.Fatalf("expected runtime app channel, got %q", merged.AppChannel) + } + if merged.AppKey != "runtime-app-key" { + t.Fatalf("expected runtime app key, got %q", merged.AppKey) + } +} + +func TestApplyLuckyGiftRuntimeAccountUsesProviderConfigRow(t *testing.T) { + account := applyLuckyGiftRuntimeAccount(luckyGiftRuntimeAccount{ + AppID: "fallback-app-id", + AppChannel: "fallback-app-channel", + AppKey: "fallback-app-key", + }, model.BaishunProviderConfig{ + AppID: 4581045902, + AppChannel: "yumiparty", + AppKey: "test-key", + }) + + if account.AppID != "4581045902" { + t.Fatalf("expected row app id, got %q", account.AppID) + } + if account.AppChannel != "yumiparty" { + t.Fatalf("expected row app channel, got %q", account.AppChannel) + } + if account.AppKey != "test-key" { + t.Fatalf("expected row app key, got %q", account.AppKey) + } +} + +func TestDefaultLuckyGiftRuntimeAccountUsesBaishunConfig(t *testing.T) { + account := defaultLuckyGiftRuntimeAccount(config.Config{ + Baishun: config.BaishunConfig{ + AppID: 7485318192, + AppChannel: "yumiparty", + AppKey: "shared-key", + }, + }) + + if account.AppID != "7485318192" { + t.Fatalf("expected baishun app id, got %q", account.AppID) + } + if account.AppChannel != "yumiparty" { + t.Fatalf("expected baishun app channel, got %q", account.AppChannel) + } + if account.AppKey != "shared-key" { + t.Fatalf("expected baishun app key, got %q", account.AppKey) + } +}