package config import ( "log" "strings" "github.com/spf13/viper" ) type Config struct { Server ServerConfig Database DatabaseConfig AlipaySandbox AlipaySandboxConfig `mapstructure:"alipay_sandbox"` QuerySync QuerySyncConfig `mapstructure:"query_sync"` } type ServerConfig struct { Port string `mapstructure:"port"` Mode string `mapstructure:"mode"` // debug | release BaseURL string `mapstructure:"base_url"` // 拼 notify_url / return_url 的公网根地址;沙箱回调需公网可达(内网穿透) } type DatabaseConfig struct { Driver string `mapstructure:"driver"` // sqlite | mysql DSN string `mapstructure:"dsn"` // sqlite 为文件路径;mysql 为完整 DSN } // AlipaySandboxConfig 启动时据此 upsert 一个支付宝(沙箱)商户,方便开箱联调。 // 生产/多商户请改为通过管理接口或 seed 写入 merchants 表。 type AlipaySandboxConfig struct { Enabled bool `mapstructure:"enabled"` Production bool `mapstructure:"production"` // false=沙箱网关;true=正式网关(真钱) MerchantCode string `mapstructure:"merchant_code"` // 业务标识,如 yanmei MerchantName string `mapstructure:"merchant_name"` AppID string `mapstructure:"app_id"` AppPrivateKey string `mapstructure:"app_private_key"` // 应用私钥(PKCS1/PKCS8 皆可,无 PEM 头亦可) AlipayPublicKey string `mapstructure:"alipay_public_key"` // 支付宝公钥(公钥模式) } // QuerySyncConfig 兜底主动查单:定时把待支付订单拿去 alipay.trade.query 核对,防回调丢失。 type QuerySyncConfig struct { Enabled bool `mapstructure:"enabled"` IntervalSec int `mapstructure:"interval_sec"` // 轮询间隔(秒) MaxAgeMin int `mapstructure:"max_age_min"` // 只查创建时间在该分钟数内的待支付单 } var C Config func Load() { viper.SetConfigName("config") viper.SetConfigType("yaml") viper.AddConfigPath(".") viper.AddConfigPath("./config") viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) viper.AutomaticEnv() // 敏感项支持环境变量覆盖(部署时不写进 config.yaml) _ = viper.BindEnv("alipay_sandbox.app_private_key", "ALIPAY_APP_PRIVATE_KEY") _ = viper.BindEnv("alipay_sandbox.alipay_public_key", "ALIPAY_PUBLIC_KEY") _ = viper.BindEnv("database.dsn", "DATABASE_DSN") viper.SetDefault("server.port", "8080") viper.SetDefault("server.mode", "debug") viper.SetDefault("server.base_url", "http://localhost:8080") viper.SetDefault("database.driver", "sqlite") viper.SetDefault("database.dsn", "pay.db") viper.SetDefault("alipay_sandbox.enabled", false) viper.SetDefault("alipay_sandbox.merchant_code", "yanmei") viper.SetDefault("alipay_sandbox.merchant_name", "演么测试商户") viper.SetDefault("query_sync.enabled", true) viper.SetDefault("query_sync.interval_sec", 30) viper.SetDefault("query_sync.max_age_min", 30) if err := viper.ReadInConfig(); err != nil { log.Println("[config] 未找到 config.yaml,使用默认值 + 环境变量") } if err := viper.Unmarshal(&C); err != nil { log.Fatalf("[config] 解析配置失败: %v", err) } }