2026-02-09 14:33:41 +08:00
|
|
|
|
package config
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"os"
|
2026-02-10 15:54:02 +08:00
|
|
|
|
"path/filepath"
|
2026-02-09 18:19:12 +08:00
|
|
|
|
"strings"
|
2026-02-09 14:33:41 +08:00
|
|
|
|
|
|
|
|
|
|
"github.com/joho/godotenv"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2026-02-09 18:19:12 +08:00
|
|
|
|
// Config 应用配置(从环境变量读取,启动时加载 .env)
|
2026-02-09 14:33:41 +08:00
|
|
|
|
type Config struct {
|
2026-02-09 18:19:12 +08:00
|
|
|
|
Port string
|
|
|
|
|
|
Mode string
|
|
|
|
|
|
DBDSN string
|
2026-02-09 14:33:41 +08:00
|
|
|
|
TrustedProxies []string
|
2026-02-09 18:19:12 +08:00
|
|
|
|
CORSOrigins []string
|
|
|
|
|
|
Version string // APP_VERSION,打包/部署前写在 .env,/health 返回
|
2026-02-09 19:26:19 +08:00
|
|
|
|
|
2026-02-09 18:19:12 +08:00
|
|
|
|
// 微信小程序配置
|
2026-02-11 12:05:54 +08:00
|
|
|
|
WechatAppID string
|
|
|
|
|
|
WechatAppSecret string
|
|
|
|
|
|
WechatMchID string
|
|
|
|
|
|
WechatMchKey string
|
|
|
|
|
|
WechatNotifyURL string
|
|
|
|
|
|
WechatMiniProgramState string // 订阅消息跳转版本:developer/formal,从 .env WECHAT_MINI_PROGRAM_STATE 读取
|
2026-02-09 19:26:19 +08:00
|
|
|
|
|
2026-02-09 18:19:12 +08:00
|
|
|
|
// 微信转账配置(API v3)
|
|
|
|
|
|
WechatAPIv3Key string
|
|
|
|
|
|
WechatCertPath string
|
|
|
|
|
|
WechatKeyPath string
|
|
|
|
|
|
WechatSerialNo string
|
|
|
|
|
|
WechatTransferURL string // 转账回调地址
|
2026-02-10 14:15:32 +08:00
|
|
|
|
|
|
|
|
|
|
// 管理端登录(与 next-project 一致:ADMIN_USERNAME / ADMIN_PASSWORD / ADMIN_SESSION_SECRET)
|
|
|
|
|
|
AdminUsername string
|
|
|
|
|
|
AdminPassword string
|
|
|
|
|
|
AdminSessionSecret string
|
2026-02-09 18:19:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 默认 CORS 允许的源(零配置:不设环境变量也能用)
|
|
|
|
|
|
var defaultCORSOrigins = []string{
|
|
|
|
|
|
"http://localhost:5174",
|
|
|
|
|
|
"http://127.0.0.1:5174",
|
|
|
|
|
|
"https://soul.quwanzhi.com",
|
|
|
|
|
|
"http://soul.quwanzhi.com",
|
2026-02-09 19:26:19 +08:00
|
|
|
|
"http://souladmin.quwanzhi.com",
|
2026-02-09 18:19:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-10 14:15:32 +08:00
|
|
|
|
// current 由 main 在 Load 后设置,供 handler/middleware 读取
|
|
|
|
|
|
var current *Config
|
|
|
|
|
|
|
|
|
|
|
|
// SetCurrent 设置全局配置(main 启动时调用一次)
|
|
|
|
|
|
func SetCurrent(cfg *Config) { current = cfg }
|
|
|
|
|
|
|
|
|
|
|
|
// Get 返回当前配置,未设置时返回 nil
|
|
|
|
|
|
func Get() *Config { return current }
|
|
|
|
|
|
|
2026-02-09 18:19:12 +08:00
|
|
|
|
// parseCORSOrigins 从环境变量 CORS_ORIGINS 读取(逗号分隔),未设置则用默认值
|
|
|
|
|
|
func parseCORSOrigins() []string {
|
|
|
|
|
|
s := os.Getenv("CORS_ORIGINS")
|
|
|
|
|
|
if s == "" {
|
|
|
|
|
|
return defaultCORSOrigins
|
|
|
|
|
|
}
|
|
|
|
|
|
parts := strings.Split(s, ",")
|
|
|
|
|
|
origins := make([]string, 0, len(parts))
|
|
|
|
|
|
for _, p := range parts {
|
|
|
|
|
|
if o := strings.TrimSpace(p); o != "" {
|
|
|
|
|
|
origins = append(origins, o)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(origins) == 0 {
|
|
|
|
|
|
return defaultCORSOrigins
|
|
|
|
|
|
}
|
|
|
|
|
|
return origins
|
2026-02-09 14:33:41 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-10 15:54:02 +08:00
|
|
|
|
// Load 加载配置,端口等从 .env 读取。优先从可执行文件同目录加载 .env,再试当前目录
|
2026-02-09 14:33:41 +08:00
|
|
|
|
func Load() (*Config, error) {
|
2026-02-10 15:54:02 +08:00
|
|
|
|
if execPath, err := os.Executable(); err == nil {
|
|
|
|
|
|
_ = godotenv.Load(filepath.Join(filepath.Dir(execPath), ".env"))
|
|
|
|
|
|
}
|
|
|
|
|
|
_ = godotenv.Load(".env")
|
2026-02-09 14:33:41 +08:00
|
|
|
|
|
|
|
|
|
|
port := os.Getenv("PORT")
|
|
|
|
|
|
if port == "" {
|
|
|
|
|
|
port = "8080"
|
|
|
|
|
|
}
|
|
|
|
|
|
mode := os.Getenv("GIN_MODE")
|
|
|
|
|
|
if mode == "" {
|
|
|
|
|
|
mode = "debug"
|
|
|
|
|
|
}
|
|
|
|
|
|
dsn := os.Getenv("DB_DSN")
|
|
|
|
|
|
if dsn == "" {
|
|
|
|
|
|
dsn = "user:pass@tcp(127.0.0.1:3306)/soul?charset=utf8mb4&parseTime=True"
|
|
|
|
|
|
}
|
2026-02-09 18:19:12 +08:00
|
|
|
|
version := os.Getenv("APP_VERSION")
|
|
|
|
|
|
if version == "" {
|
|
|
|
|
|
version = "0.0.0"
|
|
|
|
|
|
}
|
2026-02-09 19:26:19 +08:00
|
|
|
|
|
2026-02-09 18:19:12 +08:00
|
|
|
|
// 微信配置
|
|
|
|
|
|
wechatAppID := os.Getenv("WECHAT_APPID")
|
|
|
|
|
|
if wechatAppID == "" {
|
|
|
|
|
|
wechatAppID = "wxb8bbb2b10dec74aa" // 默认小程序AppID
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatAppSecret := os.Getenv("WECHAT_APPSECRET")
|
|
|
|
|
|
if wechatAppSecret == "" {
|
|
|
|
|
|
wechatAppSecret = "3c1fb1f63e6e052222bbcead9d07fe0c" // 默认小程序AppSecret
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatMchID := os.Getenv("WECHAT_MCH_ID")
|
|
|
|
|
|
if wechatMchID == "" {
|
|
|
|
|
|
wechatMchID = "1318592501" // 默认商户号
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatMchKey := os.Getenv("WECHAT_MCH_KEY")
|
|
|
|
|
|
if wechatMchKey == "" {
|
|
|
|
|
|
wechatMchKey = "wx3e31b068be59ddc131b068be59ddc2" // 默认API密钥(v2)
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatNotifyURL := os.Getenv("WECHAT_NOTIFY_URL")
|
|
|
|
|
|
if wechatNotifyURL == "" {
|
|
|
|
|
|
wechatNotifyURL = "https://soul.quwanzhi.com/api/miniprogram/pay/notify" // 默认回调地址
|
|
|
|
|
|
}
|
2026-02-11 12:05:54 +08:00
|
|
|
|
wechatMiniProgramState := os.Getenv("WECHAT_MINI_PROGRAM_STATE")
|
|
|
|
|
|
if wechatMiniProgramState != "developer" && wechatMiniProgramState != "trial" {
|
|
|
|
|
|
wechatMiniProgramState = "formal" // 默认正式版
|
|
|
|
|
|
}
|
2026-02-09 19:26:19 +08:00
|
|
|
|
|
2026-02-09 18:19:12 +08:00
|
|
|
|
// 转账配置
|
|
|
|
|
|
wechatAPIv3Key := os.Getenv("WECHAT_APIV3_KEY")
|
|
|
|
|
|
if wechatAPIv3Key == "" {
|
|
|
|
|
|
wechatAPIv3Key = "wx3e31b068be59ddc131b068be59ddc2" // 默认 API v3 密钥
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatCertPath := os.Getenv("WECHAT_CERT_PATH")
|
|
|
|
|
|
if wechatCertPath == "" {
|
|
|
|
|
|
wechatCertPath = "certs/apiclient_cert.pem" // 默认证书路径
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatKeyPath := os.Getenv("WECHAT_KEY_PATH")
|
|
|
|
|
|
if wechatKeyPath == "" {
|
|
|
|
|
|
wechatKeyPath = "certs/apiclient_key.pem" // 默认私钥路径
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatSerialNo := os.Getenv("WECHAT_SERIAL_NO")
|
|
|
|
|
|
if wechatSerialNo == "" {
|
|
|
|
|
|
wechatSerialNo = "4A1DB62CD5C9BE0B6FC51C30621D6F99686E75C5" // 默认证书序列号
|
|
|
|
|
|
}
|
|
|
|
|
|
wechatTransferURL := os.Getenv("WECHAT_TRANSFER_URL")
|
|
|
|
|
|
if wechatTransferURL == "" {
|
|
|
|
|
|
wechatTransferURL = "https://soul.quwanzhi.com/api/payment/wechat/transfer/notify" // 默认转账回调地址
|
|
|
|
|
|
}
|
2026-02-09 14:33:41 +08:00
|
|
|
|
|
2026-02-10 14:15:32 +08:00
|
|
|
|
adminUsername := os.Getenv("ADMIN_USERNAME")
|
|
|
|
|
|
if adminUsername == "" {
|
|
|
|
|
|
adminUsername = "admin"
|
|
|
|
|
|
}
|
|
|
|
|
|
adminPassword := os.Getenv("ADMIN_PASSWORD")
|
|
|
|
|
|
if adminPassword == "" {
|
|
|
|
|
|
adminPassword = "admin123"
|
|
|
|
|
|
}
|
|
|
|
|
|
adminSessionSecret := os.Getenv("ADMIN_SESSION_SECRET")
|
|
|
|
|
|
if adminSessionSecret == "" {
|
|
|
|
|
|
adminSessionSecret = "soul-admin-secret-change-in-prod"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-09 14:33:41 +08:00
|
|
|
|
return &Config{
|
2026-02-10 17:00:20 +08:00
|
|
|
|
Port: port,
|
|
|
|
|
|
Mode: mode,
|
|
|
|
|
|
DBDSN: dsn,
|
|
|
|
|
|
TrustedProxies: []string{"127.0.0.1", "::1"},
|
|
|
|
|
|
CORSOrigins: parseCORSOrigins(),
|
|
|
|
|
|
Version: version,
|
2026-02-11 12:05:54 +08:00
|
|
|
|
WechatAppID: wechatAppID,
|
|
|
|
|
|
WechatAppSecret: wechatAppSecret,
|
|
|
|
|
|
WechatMchID: wechatMchID,
|
|
|
|
|
|
WechatMchKey: wechatMchKey,
|
|
|
|
|
|
WechatNotifyURL: wechatNotifyURL,
|
|
|
|
|
|
WechatMiniProgramState: wechatMiniProgramState,
|
|
|
|
|
|
WechatAPIv3Key: wechatAPIv3Key,
|
2026-02-10 17:00:20 +08:00
|
|
|
|
WechatCertPath: wechatCertPath,
|
|
|
|
|
|
WechatKeyPath: wechatKeyPath,
|
|
|
|
|
|
WechatSerialNo: wechatSerialNo,
|
|
|
|
|
|
WechatTransferURL: wechatTransferURL,
|
|
|
|
|
|
AdminUsername: adminUsername,
|
|
|
|
|
|
AdminPassword: adminPassword,
|
2026-02-10 14:15:32 +08:00
|
|
|
|
AdminSessionSecret: adminSessionSecret,
|
2026-02-09 14:33:41 +08:00
|
|
|
|
}, nil
|
|
|
|
|
|
}
|