批量优化
This commit is contained in:
1 parent
438145cae7
commit
c925b198d1
50 files changed
+5716
-291
No files matched your search
@@ -2,10 +2,14 @@
|
||||
//
|
||||
// 与 services/wechatmp(公众号)分开:小程序走 sns/jscode2session 与
|
||||
// wxa/business/getuserphonenumber,两者的 AppID / AppSecret 互不相通。
|
||||
//
|
||||
// 配置存储:多应用表 yz_platform_wechat_mini_app(docs/sql/create_wechat_mini_app.sql),
|
||||
// 旧单行表 yz_platform_wechat_mini_config 仅作为未迁移部署的回退数据源。
|
||||
package wechatmini
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -17,6 +21,7 @@ import (
|
||||
// Config 小程序运行配置(敏感字段已解密)
|
||||
type Config struct {
|
||||
ID uint64
|
||||
Name string
|
||||
AppID string
|
||||
AppSecret string // 明文
|
||||
Enabled bool
|
||||
@@ -27,18 +32,11 @@ type Config struct {
|
||||
// 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
|
||||
}
|
||||
// appFromRow 解密行数据为运行配置
|
||||
func appFromRow(row models.WechatMiniApp) (*Config, error) {
|
||||
cfg := &Config{
|
||||
ID: row.ID,
|
||||
Name: row.Name,
|
||||
AppID: strings.TrimSpace(row.AppID),
|
||||
Enabled: row.Enabled == 1,
|
||||
AutoBind: row.AutoBind != 0,
|
||||
@@ -54,6 +52,44 @@ func LoadConfig() (*Config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// LoadConfig 读取小程序配置(多应用表第一条,敏感字段解密)。
|
||||
// 新表无数据时回退旧单行表(未执行迁移 SQL 的存量部署);均未配置返回 ErrNotConfigured
|
||||
func LoadConfig() (*Config, error) {
|
||||
var rows []models.WechatMiniApp
|
||||
_, err := models.Orm.QueryTable(new(models.WechatMiniApp)).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("id").
|
||||
All(&rows)
|
||||
if err == nil && len(rows) > 0 {
|
||||
return appFromRow(rows[0])
|
||||
}
|
||||
|
||||
// 旧单行表回退
|
||||
var legacy models.WechatMiniConfig
|
||||
err = models.Orm.QueryTable(new(models.WechatMiniConfig)).OrderBy("id").One(&legacy)
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
return nil, ErrNotConfigured
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
cfg := &Config{
|
||||
ID: legacy.ID,
|
||||
AppID: strings.TrimSpace(legacy.AppID),
|
||||
Enabled: legacy.Enabled == 1,
|
||||
AutoBind: legacy.AutoBind != 0,
|
||||
Remark: legacy.Remark,
|
||||
}
|
||||
if legacy.AppSecret != "" {
|
||||
plain, derr := wechatmp.DecryptSecret(legacy.AppSecret)
|
||||
if derr != nil {
|
||||
return nil, derr
|
||||
}
|
||||
cfg.AppSecret = plain
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// LoadEnabledConfig 读取并校验启用状态
|
||||
func LoadEnabledConfig() (*Config, error) {
|
||||
cfg, err := LoadConfig()
|
||||
@@ -66,61 +102,180 @@ func LoadEnabledConfig() (*Config, error) {
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// SaveInput 保存配置入参(AppSecret 支持掩码表示不修改)
|
||||
type SaveInput struct {
|
||||
AppID string
|
||||
AppSecret string // 掩码 / 空串 = 保持不变
|
||||
Enabled bool
|
||||
AutoBind bool
|
||||
Remark string
|
||||
// LoadEnabledAppByAppID 按小程序 AppID 精确读取启用配置(多小程序场景,
|
||||
// 认证端按客户端传入的 appid 选择对应应用)
|
||||
func LoadEnabledAppByAppID(appID string) (*Config, error) {
|
||||
appID = strings.TrimSpace(appID)
|
||||
if appID == "" {
|
||||
return nil, ErrNotConfigured
|
||||
}
|
||||
var row models.WechatMiniApp
|
||||
err := models.Orm.QueryTable(new(models.WechatMiniApp)).
|
||||
Filter("app_id", appID).
|
||||
Filter("delete_time__isnull", true).
|
||||
One(&row)
|
||||
if err != nil {
|
||||
if err == orm.ErrNoRows {
|
||||
return nil, ErrNotConfigured
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
cfg, err := appFromRow(row)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !cfg.Enabled || cfg.AppSecret == "" {
|
||||
return nil, ErrNotConfigured
|
||||
}
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// SaveConfig 保存小程序配置(不存在则创建)
|
||||
func SaveConfig(in SaveInput) error {
|
||||
if strings.TrimSpace(in.AppID) == "" {
|
||||
return errors.New("AppID 不能为空")
|
||||
}
|
||||
// ListApps 应用列表(软删除外,AppSecret 不回显)
|
||||
func ListApps() ([]models.WechatMiniApp, error) {
|
||||
var rows []models.WechatMiniApp
|
||||
_, err := models.Orm.QueryTable(new(models.WechatMiniApp)).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("id").
|
||||
All(&rows)
|
||||
return rows, err
|
||||
}
|
||||
|
||||
var row models.WechatMiniConfig
|
||||
err := models.Orm.QueryTable(new(models.WechatMiniConfig)).OrderBy("id").One(&row)
|
||||
// SaveAppInput 保存应用入参(AppSecret 支持掩码表示不修改)
|
||||
type SaveAppInput struct {
|
||||
ID uint64
|
||||
Name string
|
||||
AppID string
|
||||
AppSecret string // 掩码 / 空串 = 保持不变
|
||||
Enabled bool
|
||||
AutoBind bool
|
||||
Remark string
|
||||
}
|
||||
|
||||
// SaveApp 新增/更新小程序应用(AppID 全局唯一,排除自身)
|
||||
func SaveApp(in SaveAppInput) (uint64, error) {
|
||||
appID := strings.TrimSpace(in.AppID)
|
||||
if appID == "" {
|
||||
return 0, errors.New("AppID 不能为空")
|
||||
}
|
||||
now := time.Now()
|
||||
isNew := false
|
||||
if err != nil {
|
||||
if err != orm.ErrNoRows {
|
||||
return err
|
||||
|
||||
var row models.WechatMiniApp
|
||||
if in.ID > 0 {
|
||||
err := models.Orm.QueryTable(new(models.WechatMiniApp)).
|
||||
Filter("id", in.ID).
|
||||
Filter("delete_time__isnull", true).
|
||||
One(&row)
|
||||
if err != nil {
|
||||
return 0, errors.New("应用不存在或已删除")
|
||||
}
|
||||
isNew = true
|
||||
row = models.WechatMiniConfig{}
|
||||
} else {
|
||||
row = models.WechatMiniApp{CreateTime: now}
|
||||
}
|
||||
|
||||
// AppID 唯一性校验(排除自身)
|
||||
dupQ := models.Orm.QueryTable(new(models.WechatMiniApp)).
|
||||
Filter("app_id", appID).
|
||||
Filter("delete_time__isnull", true)
|
||||
if in.ID > 0 {
|
||||
dupQ = dupQ.Filter("id__ne", in.ID)
|
||||
}
|
||||
var dup models.WechatMiniApp
|
||||
if err := dupQ.One(&dup); err == nil {
|
||||
name := strings.TrimSpace(dup.Name)
|
||||
if name == "" {
|
||||
name = dup.AppID
|
||||
}
|
||||
return 0, fmt.Errorf("AppID 已被应用「%s」占用", name)
|
||||
}
|
||||
|
||||
row.Name = strings.TrimSpace(in.Name)
|
||||
row.AppID = appID
|
||||
secret := strings.TrimSpace(in.AppSecret)
|
||||
if secret != "" && !wechatmp.IsMasked(secret) {
|
||||
enc, eerr := wechatmp.EncryptSecret(secret)
|
||||
if eerr != nil {
|
||||
return eerr
|
||||
return 0, eerr
|
||||
}
|
||||
row.AppSecret = enc
|
||||
}
|
||||
|
||||
row.AppID = strings.TrimSpace(in.AppID)
|
||||
row.Remark = strings.TrimSpace(in.Remark)
|
||||
row.Enabled = 0
|
||||
if in.Enabled {
|
||||
row.Enabled = 1
|
||||
} else {
|
||||
row.Enabled = 0
|
||||
}
|
||||
row.AutoBind = 0
|
||||
if in.AutoBind {
|
||||
row.AutoBind = 1
|
||||
} else {
|
||||
row.AutoBind = 0
|
||||
}
|
||||
row.Remark = strings.TrimSpace(in.Remark)
|
||||
row.UpdateTime = &now
|
||||
|
||||
if isNew {
|
||||
row.CreateTime = now
|
||||
_, err = models.Orm.Insert(&row)
|
||||
return err
|
||||
if row.ID == 0 {
|
||||
id, err := models.Orm.Insert(&row)
|
||||
return uint64(id), err
|
||||
}
|
||||
_, err = models.Orm.Update(&row)
|
||||
if _, err := models.Orm.Update(&row); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return row.ID, nil
|
||||
}
|
||||
|
||||
// DeleteApp 删除应用(软删并停用)
|
||||
func DeleteApp(id uint64) error {
|
||||
if id == 0 {
|
||||
return errors.New("无效ID")
|
||||
}
|
||||
now := time.Now()
|
||||
_, err := models.Orm.QueryTable(new(models.WechatMiniApp)).
|
||||
Filter("id", id).
|
||||
Filter("delete_time__isnull", true).
|
||||
Update(map[string]interface{}{
|
||||
"delete_time": now,
|
||||
"update_time": now,
|
||||
"enabled": 0,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// SaveInput 旧单行配置保存入参(AppSecret 支持掩码表示不修改)——兼容旧端点,
|
||||
// 现写入新多应用表的第一行(无行时插入)
|
||||
type SaveInput struct {
|
||||
AppID string
|
||||
AppSecret string // 掩码 / 空串 = 保持不变
|
||||
Enabled bool
|
||||
AutoBind bool
|
||||
Remark string
|
||||
}
|
||||
|
||||
// SaveConfig 保存配置(兼容旧单行端点:写入新表第一行,不存在则创建)
|
||||
func SaveConfig(in SaveInput) error {
|
||||
var row models.WechatMiniApp
|
||||
err := models.Orm.QueryTable(new(models.WechatMiniApp)).
|
||||
Filter("delete_time__isnull", true).
|
||||
OrderBy("id").
|
||||
One(&row)
|
||||
|
||||
if err == orm.ErrNoRows {
|
||||
_, serr := SaveApp(SaveAppInput{
|
||||
Name: "默认小程序",
|
||||
AppID: in.AppID,
|
||||
AppSecret: in.AppSecret,
|
||||
Enabled: in.Enabled,
|
||||
AutoBind: in.AutoBind,
|
||||
Remark: in.Remark,
|
||||
})
|
||||
return serr
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, serr := SaveApp(SaveAppInput{
|
||||
ID: row.ID,
|
||||
Name: row.Name,
|
||||
AppID: in.AppID,
|
||||
AppSecret: in.AppSecret,
|
||||
Enabled: in.Enabled,
|
||||
AutoBind: in.AutoBind,
|
||||
Remark: in.Remark,
|
||||
})
|
||||
return serr
|
||||
}
|
||||
Reference in new issue
Block a user