// Package config 环境变量配置(密钥经部署注入,本地开发用 .env.local / docker compose)。 package config import ( "encoding/json" "log/slog" "os" "strconv" "dudu/server/pkg/protocol" ) type Config struct { Addr string // HTTP 监听地址 PostgresDSN string RedisAddr string RedisDB int JWTSecret string JWTTTLHours int // 微信开放平台 / 商户号(申请中可留空,相关模块降级为 mock) WechatWebAppID string WechatWebSecret string WechatMobileAppID string WechatMobileSecret string WxPayMchID string WxPayCertSerial string WxPayPrivateKeyPEM string WxPayAPIv3Key string WxPayNotifyURL string // ASR ASRProvider string // gummy | mock DashScopeAPIKey string // OSS(反馈图片) OSSEndpoint string OSSBucket string OSSKeyID string OSSKeySecret string // AppLatest 启动时解析 APP_LATEST_JSON 一次(17G):平台→版本信息。 // 解析失败或未配置则为 nil/空,handler 据此返回 204,不 fail-fast。 AppLatest map[string]protocol.AppLatestResponse } func Load() Config { return Config{ Addr: getenv("ADDR", ":8080"), PostgresDSN: getenv("POSTGRES_DSN", "host=localhost user=dudu password=dudu dbname=dudu port=5432 sslmode=disable TimeZone=Asia/Shanghai"), RedisAddr: getenv("REDIS_ADDR", "localhost:6379"), RedisDB: getint("REDIS_DB", 0), JWTSecret: getenv("JWT_SECRET", "dev-secret-change-me"), JWTTTLHours: getint("JWT_TTL_HOURS", 24*7), WechatWebAppID: os.Getenv("WECHAT_WEB_APPID"), WechatWebSecret: os.Getenv("WECHAT_WEB_SECRET"), WechatMobileAppID: os.Getenv("WECHAT_MOBILE_APPID"), WechatMobileSecret: os.Getenv("WECHAT_MOBILE_SECRET"), WxPayMchID: os.Getenv("WXPAY_MCHID"), WxPayCertSerial: os.Getenv("WXPAY_CERT_SERIAL"), WxPayPrivateKeyPEM: os.Getenv("WXPAY_PRIVATE_KEY_PEM"), WxPayAPIv3Key: os.Getenv("WXPAY_APIV3_KEY"), WxPayNotifyURL: os.Getenv("WXPAY_NOTIFY_URL"), ASRProvider: getenv("ASR_PROVIDER", "mock"), DashScopeAPIKey: os.Getenv("DASHSCOPE_API_KEY"), OSSEndpoint: os.Getenv("OSS_ENDPOINT"), OSSBucket: os.Getenv("OSS_BUCKET"), OSSKeyID: os.Getenv("OSS_KEY_ID"), OSSKeySecret: os.Getenv("OSS_KEY_SECRET"), AppLatest: loadAppLatest(), } } // loadAppLatest 启动时解析一次 APP_LATEST_JSON(17G)。失败仅告警并返回 nil, // 不 fail-fast——未配置此项时服务仍需正常启动。 func loadAppLatest() map[string]protocol.AppLatestResponse { raw := os.Getenv("APP_LATEST_JSON") if raw == "" { return nil } var all map[string]protocol.AppLatestResponse if err := json.Unmarshal([]byte(raw), &all); err != nil { slog.Warn("invalid APP_LATEST_JSON, app update disabled", "err", err) return nil } return all } func getenv(k, def string) string { if v := os.Getenv(k); v != "" { return v } return def } func getint(k string, def int) int { if v := os.Getenv(k); v != "" { if n, err := strconv.Atoi(v); err == nil { return n } } return def }