feat(v2): 账户配置注册表(config.accounts + env 取凭证 + 渠道/区域筛选)
This commit is contained in:
@@ -16,6 +16,22 @@ type Config struct {
|
|||||||
QuerySync QuerySyncConfig `mapstructure:"query_sync"`
|
QuerySync QuerySyncConfig `mapstructure:"query_sync"`
|
||||||
// Biz 通用:任意业务系统(jiu / dudu / …)在 config 的 biz.<name> 下声明即可接入,无需改代码。
|
// Biz 通用:任意业务系统(jiu / dudu / …)在 config 的 biz.<name> 下声明即可接入,无需改代码。
|
||||||
Biz map[string]BizSystemConfig `mapstructure:"biz"`
|
Biz map[string]BizSystemConfig `mapstructure:"biz"`
|
||||||
|
// Accounts 多账户配置注册表(v2):凭证不写死配置,只存 env 前缀,真值运行时从环境变量取。
|
||||||
|
Accounts []AccountConfig `mapstructure:"accounts"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// AccountConfig 单个收款账户的配置(v2 多账户路由用)。凭证严禁写进 config.yaml,
|
||||||
|
// 只存 CredentialEnvPrefix,真值由 internal/accounts.Registry 运行时从环境变量
|
||||||
|
// `<CredentialEnvPrefix>_<KEY>` 读取。
|
||||||
|
type AccountConfig struct {
|
||||||
|
AccountID string `mapstructure:"account_id"`
|
||||||
|
Channel string `mapstructure:"channel"`
|
||||||
|
Weight int `mapstructure:"weight"`
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
DailyLimit int64 `mapstructure:"daily_limit"`
|
||||||
|
Region string `mapstructure:"region"`
|
||||||
|
Subject string `mapstructure:"subject"`
|
||||||
|
CredentialEnvPrefix string `mapstructure:"credential_env_prefix"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Package accounts loads the payment-account registry from config. Credentials
|
||||||
|
// never live in the config file — only an env-var prefix is stored; the real
|
||||||
|
// secret is read from the environment at call time.
|
||||||
|
package accounts
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/wangjia/pay/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Registry struct{ accts []config.AccountConfig }
|
||||||
|
|
||||||
|
func New(accts []config.AccountConfig) *Registry { return &Registry{accts: accts} }
|
||||||
|
|
||||||
|
// EnabledFor returns enabled accounts for a channel (+region if non-empty).
|
||||||
|
func (r *Registry) EnabledFor(channel, region string) []config.AccountConfig {
|
||||||
|
var out []config.AccountConfig
|
||||||
|
for _, a := range r.accts {
|
||||||
|
if a.Channel != channel || !a.Enabled {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if region != "" && a.Region != "" && a.Region != region {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = append(out, a)
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// Credential reads <CredentialEnvPrefix>_<KEY> from the environment.
|
||||||
|
func (r *Registry) Credential(accountID, key string) string {
|
||||||
|
for _, a := range r.accts {
|
||||||
|
if a.AccountID == accountID {
|
||||||
|
return os.Getenv(strings.ToUpper(a.CredentialEnvPrefix + "_" + key))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package accounts_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/wangjia/pay/config"
|
||||||
|
"github.com/wangjia/pay/internal/accounts"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestEnabledForAndCredential(t *testing.T) {
|
||||||
|
t.Setenv("USDT_A1_XPUB", "xpub-abc")
|
||||||
|
reg := accounts.New([]config.AccountConfig{
|
||||||
|
{AccountID: "usdt-a1", Channel: "crypto", Region: "global", Enabled: true, Weight: 1, CredentialEnvPrefix: "USDT_A1"},
|
||||||
|
{AccountID: "usdt-a2", Channel: "crypto", Region: "global", Enabled: false, Weight: 1, CredentialEnvPrefix: "USDT_A2"},
|
||||||
|
{AccountID: "ali-cn1", Channel: "alipay", Region: "cn", Enabled: true, Weight: 1, CredentialEnvPrefix: "ALI_CN1"},
|
||||||
|
})
|
||||||
|
|
||||||
|
got := reg.EnabledFor("crypto", "global")
|
||||||
|
if len(got) != 1 || got[0].AccountID != "usdt-a1" {
|
||||||
|
t.Fatalf("EnabledFor crypto/global = %+v", got)
|
||||||
|
}
|
||||||
|
if reg.Credential("usdt-a1", "XPUB") != "xpub-abc" {
|
||||||
|
t.Fatalf("Credential xpub 取值失败")
|
||||||
|
}
|
||||||
|
if len(reg.EnabledFor("alipay", "global")) != 0 {
|
||||||
|
t.Fatalf("alipay 在 global 应无账户")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user