// Package wechatmini 微信小程序服务端能力:配置、code 换 openid、手机号快速验证。 // // 与 services/wechatmp(公众号)分开:小程序走 sns/jscode2session 与 // wxa/business/getuserphonenumber,两者的 AppID / AppSecret 互不相通。 package wechatmini import ( "errors" "strings" "time" "github.com/beego/beego/v2/client/orm" "server/models" "server/services/wechatmp" ) // Config 小程序运行配置(敏感字段已解密) type Config struct { ID uint64 AppID string AppSecret string // 明文 Enabled bool AutoBind bool Remark string } // ErrNotConfigured 未配置或未启用 var ErrNotConfigured = errors.New("微信小程序未配置或未启用") // LoadConfig 读取小程序配置(单行,敏感字段解密);未配置返回 ErrNotConfigured func LoadConfig() (*Config, error) { var row models.WechatMiniConfig err := models.Orm.QueryTable(new(models.WechatMiniConfig)).OrderBy("id").One(&row) if err != nil { if err == orm.ErrNoRows { return nil, ErrNotConfigured } return nil, err } cfg := &Config{ ID: row.ID, AppID: strings.TrimSpace(row.AppID), Enabled: row.Enabled == 1, AutoBind: row.AutoBind != 0, Remark: row.Remark, } if row.AppSecret != "" { plain, derr := wechatmp.DecryptSecret(row.AppSecret) if derr != nil { return nil, derr } cfg.AppSecret = plain } return cfg, nil } // LoadEnabledConfig 读取并校验启用状态 func LoadEnabledConfig() (*Config, error) { cfg, err := LoadConfig() if err != nil { return nil, err } if !cfg.Enabled || cfg.AppID == "" || cfg.AppSecret == "" { return nil, ErrNotConfigured } return cfg, nil } // SaveInput 保存配置入参(AppSecret 支持掩码表示不修改) type SaveInput struct { AppID string AppSecret string // 掩码 / 空串 = 保持不变 Enabled bool AutoBind bool Remark string } // SaveConfig 保存小程序配置(不存在则创建) func SaveConfig(in SaveInput) error { if strings.TrimSpace(in.AppID) == "" { return errors.New("AppID 不能为空") } var row models.WechatMiniConfig err := models.Orm.QueryTable(new(models.WechatMiniConfig)).OrderBy("id").One(&row) now := time.Now() isNew := false if err != nil { if err != orm.ErrNoRows { return err } isNew = true row = models.WechatMiniConfig{} } secret := strings.TrimSpace(in.AppSecret) if secret != "" && !wechatmp.IsMasked(secret) { enc, eerr := wechatmp.EncryptSecret(secret) if eerr != nil { return eerr } row.AppSecret = enc } row.AppID = strings.TrimSpace(in.AppID) row.Remark = strings.TrimSpace(in.Remark) if in.Enabled { row.Enabled = 1 } else { row.Enabled = 0 } if in.AutoBind { row.AutoBind = 1 } else { row.AutoBind = 0 } row.UpdateTime = &now if isNew { row.CreateTime = now _, err = models.Orm.Insert(&row) return err } _, err = models.Orm.Update(&row) return err }