156 lines
4.9 KiB
Go
156 lines
4.9 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"encoding/base64"
|
||
"flag"
|
||
"fmt"
|
||
"os"
|
||
|
||
"bindbox-game/configs"
|
||
"bindbox-game/internal/pkg/logger"
|
||
"bindbox-game/internal/repository/mysql"
|
||
"bindbox-game/internal/repository/mysql/dao"
|
||
"bindbox-game/internal/service/sysconfig"
|
||
)
|
||
|
||
var (
|
||
dryRun = flag.Bool("dry-run", false, "仅打印将要写入的配置,不实际写入数据库")
|
||
force = flag.Bool("force", false, "强制覆盖已存在的配置")
|
||
)
|
||
|
||
func main() {
|
||
flag.Parse()
|
||
|
||
// 初始化数据库
|
||
dbRepo, err := mysql.New()
|
||
if err != nil {
|
||
fmt.Printf("数据库连接失败: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
// 初始化 logger (简化版)
|
||
customLogger, err := logger.NewCustomLogger(dao.Use(dbRepo.GetDbW()),
|
||
logger.WithDebugLevel(),
|
||
logger.WithOutputInConsole(),
|
||
)
|
||
if err != nil {
|
||
fmt.Printf("Logger 初始化失败: %v\n", err)
|
||
os.Exit(1)
|
||
}
|
||
|
||
ctx := context.Background()
|
||
|
||
// 创建动态配置服务
|
||
dynamicCfg := sysconfig.NewDynamicConfig(customLogger, dbRepo)
|
||
staticCfg := configs.Get()
|
||
|
||
// 定义要迁移的配置项
|
||
type configItem struct {
|
||
Key string
|
||
Value string
|
||
Remark string
|
||
}
|
||
|
||
// 读取证书文件内容并 Base64 编码
|
||
readAndEncode := func(path string) string {
|
||
if path == "" {
|
||
return ""
|
||
}
|
||
data, err := os.ReadFile(path)
|
||
if err != nil {
|
||
fmt.Printf("警告: 读取文件 %s 失败: %v\n", path, err)
|
||
return ""
|
||
}
|
||
return base64.StdEncoding.EncodeToString(data)
|
||
}
|
||
|
||
items := []configItem{
|
||
// COS 配置
|
||
{sysconfig.KeyCOSBucket, staticCfg.COS.Bucket, "COS Bucket名称"},
|
||
{sysconfig.KeyCOSRegion, staticCfg.COS.Region, "COS 地域"},
|
||
{sysconfig.KeyCOSSecretID, staticCfg.COS.SecretID, "COS SecretID (加密存储)"},
|
||
{sysconfig.KeyCOSSecretKey, staticCfg.COS.SecretKey, "COS SecretKey (加密存储)"},
|
||
{sysconfig.KeyCOSBaseURL, staticCfg.COS.BaseURL, "COS 自定义域名"},
|
||
|
||
// 微信小程序配置
|
||
{sysconfig.KeyWechatAppID, staticCfg.Wechat.AppID, "微信小程序 AppID"},
|
||
{sysconfig.KeyWechatAppSecret, staticCfg.Wechat.AppSecret, "微信小程序 AppSecret (加密存储)"},
|
||
{sysconfig.KeyWechatLotteryResultTemplateID, staticCfg.Wechat.LotteryResultTemplateID, "中奖结果订阅消息模板ID"},
|
||
|
||
// 微信支付配置
|
||
{sysconfig.KeyWechatPayMchID, staticCfg.WechatPay.MchID, "微信支付商户号"},
|
||
{sysconfig.KeyWechatPaySerialNo, staticCfg.WechatPay.SerialNo, "微信支付证书序列号"},
|
||
{sysconfig.KeyWechatPayPrivateKey, readAndEncode(staticCfg.WechatPay.PrivateKeyPath), "微信支付私钥 (Base64编码, 加密存储)"},
|
||
{sysconfig.KeyWechatPayApiV3Key, staticCfg.WechatPay.ApiV3Key, "微信支付 API v3 密钥 (加密存储)"},
|
||
{sysconfig.KeyWechatPayNotifyURL, staticCfg.WechatPay.NotifyURL, "微信支付回调地址"},
|
||
{sysconfig.KeyWechatPayPublicKeyID, staticCfg.WechatPay.PublicKeyID, "微信支付公钥ID"},
|
||
{sysconfig.KeyWechatPayPublicKey, readAndEncode(staticCfg.WechatPay.PublicKeyPath), "微信支付公钥 (Base64编码, 加密存储)"},
|
||
|
||
// 阿里云短信配置
|
||
{sysconfig.KeyAliyunSMSAccessKeyID, staticCfg.AliyunSMS.AccessKeyID, "阿里云短信 AccessKeyID"},
|
||
{sysconfig.KeyAliyunSMSAccessKeySecret, staticCfg.AliyunSMS.AccessKeySecret, "阿里云短信 AccessKeySecret (加密存储)"},
|
||
{sysconfig.KeyAliyunSMSSignName, staticCfg.AliyunSMS.SignName, "短信签名"},
|
||
{sysconfig.KeyAliyunSMSTemplateCode, staticCfg.AliyunSMS.TemplateCode, "短信模板Code"},
|
||
}
|
||
|
||
fmt.Println("========== 配置迁移工具 ==========")
|
||
fmt.Printf("环境: %s\n", configs.ProjectName)
|
||
fmt.Printf("Dry Run: %v\n", *dryRun)
|
||
fmt.Printf("Force: %v\n", *force)
|
||
fmt.Println()
|
||
|
||
successCount := 0
|
||
skipCount := 0
|
||
failCount := 0
|
||
|
||
for _, item := range items {
|
||
if item.Value == "" {
|
||
fmt.Printf("[跳过] %s: 值为空\n", item.Key)
|
||
skipCount++
|
||
continue
|
||
}
|
||
|
||
// 检查是否已存在
|
||
existing := dynamicCfg.Get(ctx, item.Key)
|
||
if existing != "" && !*force {
|
||
fmt.Printf("[跳过] %s: 已存在 (使用 -force 覆盖)\n", item.Key)
|
||
skipCount++
|
||
continue
|
||
}
|
||
|
||
// 脱敏显示
|
||
displayValue := item.Value
|
||
if sysconfig.IsSensitiveKey(item.Key) {
|
||
if len(displayValue) > 8 {
|
||
displayValue = displayValue[:4] + "****" + displayValue[len(displayValue)-4:]
|
||
} else {
|
||
displayValue = "****"
|
||
}
|
||
} else if len(displayValue) > 50 {
|
||
displayValue = displayValue[:50] + "..."
|
||
}
|
||
|
||
if *dryRun {
|
||
fmt.Printf("[预览] %s = %s\n", item.Key, displayValue)
|
||
successCount++
|
||
} else {
|
||
if err := dynamicCfg.Set(ctx, item.Key, item.Value, item.Remark); err != nil {
|
||
fmt.Printf("[失败] %s: %v\n", item.Key, err)
|
||
failCount++
|
||
} else {
|
||
fmt.Printf("[成功] %s = %s\n", item.Key, displayValue)
|
||
successCount++
|
||
}
|
||
}
|
||
}
|
||
|
||
fmt.Println()
|
||
fmt.Printf("========== 迁移结果 ==========\n")
|
||
fmt.Printf("成功: %d, 跳过: %d, 失败: %d\n", successCount, skipCount, failCount)
|
||
|
||
if *dryRun {
|
||
fmt.Println("\n这只是预览,使用不带 -dry-run 参数执行实际迁移")
|
||
}
|
||
}
|