From e37ea8b29fae90fcae851eb3a32c63e1d2a79b6f Mon Sep 17 00:00:00 2001 From: dengbiao Date: Thu, 22 Aug 2024 11:00:02 +0800 Subject: [PATCH] update --- app/db/dao/sys_cfg_dao.go | 2 +- app/db/implement/sys_cfg_implement.go | 10 +- app/db/model/sys_cfg.go | 7 - app/enum/enum_sys_cfg.go | 57 +++ app/hdl/hdl_set_center.go | 464 +++++++++++++++++ app/lib/wechat/enum/adunit_enum.go | 64 +++ app/lib/wechat/helpers.go | 68 +++ app/lib/wechat/md/cache_key_md.go | 7 + app/lib/wechat/md/wechat_api_md.go | 62 +++ app/lib/wechat/message.go | 254 ++++++++++ app/lib/wechat/prpcrypt.go | 61 +++ app/lib/wechat/wechat_api.go | 322 ++++++++++++ app/lib/wechat/wechat_err_code.go | 11 + app/lib/wechat/wechat_message.go | 200 ++++++++ app/md/md_oss_bucket_region.go | 50 ++ app/md/md_set_center.go | 49 ++ app/router/router.go | 24 + app/svc/svc_sys_cfg_get.go | 56 +-- docs/docs.go | 690 ++++++++++++++++++++++++++ docs/swagger.json | 690 ++++++++++++++++++++++++++ docs/swagger.yaml | 466 +++++++++++++++++ go.mod | 2 +- 22 files changed, 3563 insertions(+), 53 deletions(-) delete mode 100644 app/db/model/sys_cfg.go create mode 100644 app/enum/enum_sys_cfg.go create mode 100644 app/hdl/hdl_set_center.go create mode 100644 app/lib/wechat/enum/adunit_enum.go create mode 100644 app/lib/wechat/helpers.go create mode 100644 app/lib/wechat/md/cache_key_md.go create mode 100644 app/lib/wechat/md/wechat_api_md.go create mode 100644 app/lib/wechat/message.go create mode 100644 app/lib/wechat/prpcrypt.go create mode 100644 app/lib/wechat/wechat_api.go create mode 100644 app/lib/wechat/wechat_err_code.go create mode 100644 app/lib/wechat/wechat_message.go create mode 100644 app/md/md_oss_bucket_region.go create mode 100644 app/md/md_set_center.go diff --git a/app/db/dao/sys_cfg_dao.go b/app/db/dao/sys_cfg_dao.go index d66f4f3..a4f9308 100644 --- a/app/db/dao/sys_cfg_dao.go +++ b/app/db/dao/sys_cfg_dao.go @@ -1,6 +1,6 @@ package dao -import "applet/app/db/model" +import "code.fnuoos.com/zhimeng/model.git/src/model" type SysCfgDao interface { SysCfgGetAll() (*[]model.SysCfg, error) diff --git a/app/db/implement/sys_cfg_implement.go b/app/db/implement/sys_cfg_implement.go index b9d9f90..0690a77 100644 --- a/app/db/implement/sys_cfg_implement.go +++ b/app/db/implement/sys_cfg_implement.go @@ -2,10 +2,10 @@ import ( "applet/app/db/dao" - "applet/app/db/model" "applet/app/md" "applet/app/utils/cache" "applet/app/utils/logx" + "code.fnuoos.com/zhimeng/model.git/src/model" "fmt" "xorm.io/xorm" ) @@ -51,7 +51,7 @@ func (s SysCfgDb) SysCfgGetOne(key string) (*model.SysCfg, error) { } func (s SysCfgDb) SysCfgInsert(key, val, memo string) bool { - cfg := model.SysCfg{Key: key, Val: val, Memo: memo} + cfg := model.SysCfg{K: key, V: val, Memo: memo} _, err := s.Db.InsertOne(&cfg) if err != nil { logx.Error(err) @@ -61,7 +61,7 @@ func (s SysCfgDb) SysCfgInsert(key, val, memo string) bool { } func (s SysCfgDb) SysCfgUpdate(key, val string) bool { - cfg := model.SysCfg{Key: key, Val: val} + cfg := model.SysCfg{K: key, V: val} _, err := s.Db.Where("`key`=?", key).Cols("val").Update(&cfg) if err != nil { logx.Error(err) @@ -88,7 +88,7 @@ func (s SysCfgDb) SysCfgGetWithDb(HKey string) string { } // 设置缓存 - _, err = cache.HSet(cacheKey, HKey, cfg.Val) + _, err = cache.HSet(cacheKey, HKey, cfg.V) if err != nil { _ = logx.Error(err) return "" @@ -100,7 +100,7 @@ func (s SysCfgDb) SysCfgGetWithDb(HKey string) string { return "" } } - return cfg.Val + return cfg.V } return get } diff --git a/app/db/model/sys_cfg.go b/app/db/model/sys_cfg.go deleted file mode 100644 index 22d906b..0000000 --- a/app/db/model/sys_cfg.go +++ /dev/null @@ -1,7 +0,0 @@ -package model - -type SysCfg struct { - Key string `json:"key" xorm:"not null pk comment('键') VARCHAR(127)"` - Val string `json:"val" xorm:"comment('值') TEXT"` - Memo string `json:"memo" xorm:"not null default '' comment('备注') VARCHAR(255)"` -} diff --git a/app/enum/enum_sys_cfg.go b/app/enum/enum_sys_cfg.go new file mode 100644 index 0000000..cef0134 --- /dev/null +++ b/app/enum/enum_sys_cfg.go @@ -0,0 +1,57 @@ +package enum + +type SysCfg string + +const ( + AppName = "app_name" + + FileBucketHost = "file_bucket_host" + FileBucketRegion = "file_bucket_region" + FileBucketScheme = "file_bucket_scheme" + FileExt = "file_ext" + FileSecretKey = "file_secret_key" + FileUserUploadMaxSize = "file_user_upload_max_size" + FileAccessKey = "file_access_key" + FileBucket = "file_bucket" + + WxOpenAppletServerDomain = "wx_open_applet_server_domain" + WxOpenAuthorizationEventReceivingConfiguration = "wx_open_authorization_event_receiving_configuration" + WxOpenDomainOfTheInitiatingPageForLoginAuthorization = "wx_open_domain_of_the_initiating_page_for_login_authorization" + WxOpenMessageAndEventReceptionConfiguration = "wx_open_message_and_event_reception_configuration" + WxOpenWhiteListIp = "wx_open_white_list_ip" +) + +func (gt SysCfg) String() string { + switch gt { + case AppName: + return "项目名称" + case FileBucketHost: + return "对象存储域名" + case FileBucketRegion: + return "对象存储域名" + case FileBucketScheme: + return "文件上传模式" + case FileExt: + return "文件上传后缀,后台用户不限制后缀" + case FileSecretKey: + return "对象存储SecretToken" + case FileUserUploadMaxSize: + return "用户单文件最大上传大小,byte" + case FileAccessKey: + return "对象存储AccessToken" + case FileBucket: + return "对象存储bucket" + case WxOpenAppletServerDomain: + return "微信开放平台-小程序服务器域名" + case WxOpenAuthorizationEventReceivingConfiguration: + return "微信开放平台-授权事件接收配置" + case WxOpenDomainOfTheInitiatingPageForLoginAuthorization: + return "微信开放平台-登录授权的发起页域名" + case WxOpenMessageAndEventReceptionConfiguration: + return "微信开放平台-消息与事件接收配置" + case WxOpenWhiteListIp: + return "微信开放平台-白名单ip" + default: + return "未知" + } +} diff --git a/app/hdl/hdl_set_center.go b/app/hdl/hdl_set_center.go new file mode 100644 index 0000000..2978e70 --- /dev/null +++ b/app/hdl/hdl_set_center.go @@ -0,0 +1,464 @@ +package hdl + +import ( + "applet/app/cfg" + implement2 "applet/app/db/implement" + "applet/app/e" + "applet/app/enum" + "applet/app/lib/validate" + "applet/app/lib/wechat" + "applet/app/md" + "applet/app/svc" + "applet/app/utils" + db "code.fnuoos.com/zhimeng/model.git/src" + "code.fnuoos.com/zhimeng/model.git/src/super/implement" + "code.fnuoos.com/zhimeng/model.git/src/super/model" + "github.com/gin-gonic/gin" + "time" +) + +// SetOss +// @Summary oss设置 +// @Tags 设置中心-基础设置 +// @Description 基础设置-oss设置 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Param args body md.SetOssReq true "请求参数" +// @Success 200 {string} "success" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/basic/setOss [POST] +func SetOss(c *gin.Context) { + var req md.SetOssReq + err := c.ShouldBindJSON(&req) + if err != nil { + err = validate.HandleValidateErr(err) + err1 := err.(e.E) + e.OutErr(c, err1.Code, err1.Error()) + return + } + masterId := svc.GetMasterId(c) + engine := db.DBs[masterId] + sysCfgDb := implement2.NewSysCfgDb(engine, masterId) + sysCfgDb.SysCfgUpdate(enum.FileAccessKey, req.FileAccessKey) + sysCfgDb.SysCfgUpdate(enum.FileSecretKey, req.FileSecretKey) + sysCfgDb.SysCfgUpdate(enum.FileBucketHost, req.FileBucketHost) + sysCfgDb.SysCfgUpdate(enum.FileBucketRegion, req.FileBucketRegion) + sysCfgDb.SysCfgUpdate(enum.FileBucket, req.FileBucket) + e.OutSuc(c, "success", nil) + return +} + +// GetOss +// @Summary oss获取 +// @Tags 设置中心-基础设置 +// @Description 基础设置-oss获取 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Success 200 {object} md.SetOssResp +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/basic/getOss [GET] +func GetOss(c *gin.Context) { + masterId := svc.GetMasterId(c) + engine := db.DBs[masterId] + sysCfgDb := implement2.NewSysCfgDb(engine, masterId) + res := sysCfgDb.SysCfgFindWithDb(enum.FileAccessKey, enum.FileSecretKey, enum.FileBucketHost, enum.FileBucketRegion, enum.FileBucket) + + e.OutSuc(c, md.SetOssResp{ + Data: md.SetOssReq{ + FileAccessKey: res[enum.FileAccessKey], + FileSecretKey: res[enum.FileSecretKey], + FileBucketHost: res[enum.FileBucketHost], + FileBucketRegion: res[enum.FileBucketRegion], + FileBucket: res[enum.FileBucket], + }, + QiNiuBucketRegionList: md.QiNiuBucketRegionList, + }, nil) + return +} + +// WxOpenSet +// @Summary 微信三方应用设置 +// @Tags 设置中心-基础设置 +// @Description 基础设置-微信三方应用设置 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Param args body md.WxOpenSetReq true "请求参数" +// @Success 200 {string} "success" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/basic/wxOpenSet [POST] +func WxOpenSet(c *gin.Context) { + var req md.WxOpenSetReq + err := c.ShouldBindJSON(&req) + if err != nil { + err = validate.HandleValidateErr(err) + err1 := err.(e.E) + e.OutErr(c, err1.Code, err1.Error()) + return + } + masterId := svc.GetMasterId(c) + //1、查找对应 wx_open_third_party_app_list 记录 + wxOpenThirdPartyAppListDb := implement.NewWxOpenThirdPartyAppListDb(db.Db) + UserWxAppletList, err := wxOpenThirdPartyAppListDb.GetWxOpenThirdPartyAppList(utils.StrToInt(masterId)) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + if UserWxAppletList == nil { + UserWxAppletList = &model.WxOpenThirdPartyAppList{ + Uuid: utils.StrToInt(masterId), + Token: req.Token, + AesKey: req.AesKey, + Appid: req.Appid, + AppSecret: req.AppSecret, + ComponentVerifyTicket: "", + ComponentAccessToken: "", + CreateAt: time.Now().Format("2006-01-02 15:04:05"), + UpdateAt: time.Now().Format("2006-01-02 15:04:05"), + } + _, err = wxOpenThirdPartyAppListDb.WxOpenThirdPartyAppListInsert(UserWxAppletList) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + } else { + UserWxAppletList.Token = req.Token + UserWxAppletList.AesKey = req.AesKey + UserWxAppletList.Appid = req.Appid + UserWxAppletList.AppSecret = req.AppSecret + _, err = wxOpenThirdPartyAppListDb.UpdateWxOpenThirdPartyAppList(UserWxAppletList, + "token", "aes_key", "appid", "app_secret") + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + } + e.OutSuc(c, "success", nil) + return +} + +// WxOpenGet +// @Summary 微信三方应用获取 +// @Tags 设置中心-基础设置 +// @Description 基础设置-微信三方应用获取 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Success 200 {object} md.WxOpenGetResp +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/basic/wxOpenGet [GET] +func WxOpenGet(c *gin.Context) { + masterId := svc.GetMasterId(c) + //1、查找对应 wx_open_third_party_app_list 记录 + wxOpenThirdPartyAppListDb := implement.NewWxOpenThirdPartyAppListDb(db.Db) + UserWxAppletList, err := wxOpenThirdPartyAppListDb.GetWxOpenThirdPartyAppList(utils.StrToInt(masterId)) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + if UserWxAppletList == nil { + UserWxAppletList = &model.WxOpenThirdPartyAppList{ + Uuid: utils.StrToInt(masterId), + Token: "", + AesKey: "", + Appid: "", + AppSecret: "", + ComponentVerifyTicket: "", + ComponentAccessToken: "", + CreateAt: time.Now().Format("2006-01-02 15:04:05"), + UpdateAt: time.Now().Format("2006-01-02 15:04:05"), + } + _, err = wxOpenThirdPartyAppListDb.WxOpenThirdPartyAppListInsert(UserWxAppletList) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + } + sysCfgDb := implement2.NewSysCfgDb(db.Db, "") + res := sysCfgDb.SysCfgFindWithDb(enum.WxOpenAppletServerDomain, enum.WxOpenAuthorizationEventReceivingConfiguration, + enum.WxOpenDomainOfTheInitiatingPageForLoginAuthorization, enum.WxOpenMessageAndEventReceptionConfiguration, enum.WxOpenWhiteListIp) + e.OutSuc(c, md.WxOpenGetResp{ + Token: UserWxAppletList.Token, + AesKey: UserWxAppletList.AesKey, + Appid: UserWxAppletList.Appid, + AppSecret: UserWxAppletList.AppSecret, + WxOpenAppletServerDomain: res[enum.WxOpenAppletServerDomain], + WxOpenAuthorizationEventReceivingConfiguration: res[enum.WxOpenAuthorizationEventReceivingConfiguration], + WxOpenDomainOfTheInitiatingPageForLoginAuthorization: res[enum.WxOpenDomainOfTheInitiatingPageForLoginAuthorization], + WxOpenMessageAndEventReceptionConfiguration: res[enum.WxOpenMessageAndEventReceptionConfiguration], + WxOpenWhiteListIp: res[enum.WxOpenWhiteListIp], + }, nil) + return +} + +type WxOpenThirdPartyAppList struct { + Id int `json:"id" xorm:"not null pk autoincr unique(IDX_UUID_TYPE) INT(11)"` + Uuid int `json:"uuid" xorm:"not null comment('站长id') index unique(IDX_UUID_TYPE) INT(10)"` + Token string `json:"token" xorm:"not null default '' comment('消息校验Token') VARCHAR(255)"` + AesKey string `json:"aes_key" xorm:"not null default '' comment('消息加解密Key') VARCHAR(255)"` + Appid string `json:"appid" xorm:"not null default '' comment('appid') CHAR(50)"` + AppSecret string `json:"app_secret" xorm:"not null default '' comment('appSecret') VARCHAR(255)"` + ComponentVerifyTicket string `json:"component_verify_ticket" xorm:"not null default '' comment('验证票据') VARCHAR(255)"` + ComponentAccessToken string `json:"component_access_token" xorm:"not null default '' comment('接口令牌') VARCHAR(255)"` + CreateAt string `json:"create_at" xorm:"not null default 'CURRENT_TIMESTAMP' DATETIME"` + UpdateAt string `json:"update_at" xorm:"not null default 'CURRENT_TIMESTAMP' DATETIME"` +} + +// AppletList +// @Summary 列表 +// @Tags 设置中心-小程序设置 +// @Description 小程序设置-列表 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Success 200 {object} WxOpenThirdPartyAppList +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/applet/list [GET] +func AppletList(c *gin.Context) { + masterId := svc.GetMasterId(c) + //1、查找对应 user_wx_applet_list 记录 + userWxAppletListDb := implement.NewUserWxAppletListDb(db.Db) + UserWxAppletList, err := userWxAppletListDb.GetUserWxAppletList(masterId) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + e.OutSuc(c, UserWxAppletList, nil) + return +} + +// AppletAdd +// @Summary 新增 +// @Tags 设置中心-小程序设置 +// @Description 小程序设置-新增 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Param args body md.AppletAddReq true "请求参数" +// @Success 200 {string} "success" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/applet/add [POST] +func AppletAdd(c *gin.Context) { + var req md.AppletAddReq + err := c.ShouldBindJSON(&req) + if err != nil { + err = validate.HandleValidateErr(err) + err1 := err.(e.E) + e.OutErr(c, err1.Code, err1.Error()) + return + } + masterId := svc.GetMasterId(c) + //1、查找对应 user_wx_applet_list 记录 + userWxAppletListDb := implement.NewUserWxAppletListDb(db.Db) + UserWxAppletList, err := userWxAppletListDb.GetUserWxAppletList(masterId) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + if UserWxAppletList != nil { + e.OutErr(c, e.ERR, "当前仅支持单个小程序") + return + } + _, err = userWxAppletListDb.UserWxAppletListInsert(&model.UserWxAppletList{ + Name: req.Name, + Logo: req.Logo, + Appid: req.Appid, + OriginalId: req.OriginalId, + AuthorizerRefreshToken: "", + IsAuth: 0, + Uuid: masterId, + CreateAt: time.Now().Format("2006-01-02 15:04:05"), + UpdateAt: time.Now().Format("2006-01-02 15:04:05"), + }) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + + e.OutSuc(c, "success", nil) + return +} + +// AppletUpdate +// @Summary 更新 +// @Tags 设置中心-小程序设置 +// @Description 小程序设置-更新 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Param args body md.AppletUpdateReq true "请求参数" +// @Success 200 {string} "success" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/applet/update [POST] +func AppletUpdate(c *gin.Context) { + var req md.AppletUpdateReq + err := c.ShouldBindJSON(&req) + if err != nil { + err = validate.HandleValidateErr(err) + err1 := err.(e.E) + e.OutErr(c, err1.Code, err1.Error()) + return + } + masterId := svc.GetMasterId(c) + //1、查找对应 user_wx_applet_list 记录 + userWxAppletListDb := implement.NewUserWxAppletListDb(db.Db) + UserWxAppletList, err := userWxAppletListDb.GetUserWxAppletList(masterId) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + if UserWxAppletList == nil { + e.OutErr(c, e.ERR_NO_DATA, "未查询到对应记录") + return + } + UserWxAppletList.Logo = req.Logo + UserWxAppletList.Name = req.Logo + _, err = userWxAppletListDb.UpdateUserWxAppletList(UserWxAppletList, "logo", "name") + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + + e.OutSuc(c, "success", nil) + return +} + +// AppletDelete +// @Summary 删除 +// @Tags 设置中心-小程序设置 +// @Description 小程序设置-删除 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Success 200 {string} "success" +// @Failure 400 {object} md.Response "具体错误" +// @Router /v1/banner/delete/{$id} [DELETE] +func AppletDelete(c *gin.Context) { + id := c.Param("id") + + masterId := svc.GetMasterId(c) + //1、查找对应 user_wx_applet_list 记录 + userWxAppletListDb := implement.NewUserWxAppletListDb(db.Db) + UserWxAppletList, err := userWxAppletListDb.GetUserWxAppletList(masterId) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + if UserWxAppletList == nil { + e.OutErr(c, e.ERR_NO_DATA, "未查询到对应记录") + return + } + + _, err = userWxAppletListDb.UserWxAppletListDelete(id) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + e.OutSuc(c, "success", nil) + return +} + +// AppletAuthorize +// @Summary 设置中心-基础设置-微信三方应用获取 +// @Tags 设置中心 +// @Description 设置中心-基础设置 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Success 200 {string} "微信授权界面url" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/applet/authorize [GET] +func AppletAuthorize(c *gin.Context) { + masterId := svc.GetMasterId(c) + url := "http://super.advertisement.dengbiao.top/api/wxOpen/getPreAuthCode?master_id=" + masterId + if cfg.Prd { + url = "http://super.advertisement.dengbiao.top/api/wxOpen/getPreAuthCode?master_id=" + masterId + } + e.OutSuc(c, map[string]string{ + "url": url, + }, nil) + return +} + +// AppletUnauthorized +// @Summary 设置中心-基础设置-微信三方应用获取 +// @Tags 设置中心 +// @Description 设置中心-基础设置 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Success 200 {string} "success" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/applet/unauthorized [GET] +func AppletUnauthorized(c *gin.Context) { + appId := c.DefaultQuery("app_id", "") + masterId := svc.GetMasterId(c) + //1、查找对应 user_wx_applet_list 记录 + userWxAppletListDb := implement.NewUserWxAppletListDb(db.Db) + UserWxAppletList, err := userWxAppletListDb.GetUserWxAppletList(masterId) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + if UserWxAppletList == nil { + e.OutErr(c, e.ERR_NO_DATA, "未查询到对应记录") + return + } + + wxOpenThirdPartyAppListDb := implement.NewWxOpenThirdPartyAppListDb(db.Db) + wxOpenThirdPartyAppList, err := wxOpenThirdPartyAppListDb.GetWxOpenThirdPartyAppList(utils.StrToInt(masterId)) + if err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + if wxOpenThirdPartyAppList == nil { + e.OutErr(c, e.ERR_NOT_FAN, "未查询到对应三方应用记录") + return + } + + wxApiService, err := wechat.NewWxApiService(masterId, wxOpenThirdPartyAppList.Appid, wxOpenThirdPartyAppList.AppSecret) + if err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + err = wxApiService.DelAuthorize(appId) + if err != nil { + e.OutErr(c, e.ERR, err.Error()) + return + } + e.OutSuc(c, "success", nil) + return +} + +// ShareIndex +// @Summary 邀请链接 +// @Tags 设置中心-邀请链接 +// @Description 邀请链接界面接口 +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Accept json +// @Produce json +// @Success 200 {object} md.ShareIndexResp +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/setCenter/share/index [GET] +func ShareIndex(c *gin.Context) { + masterId := svc.GetMasterId(c) + userAppDomainDb := implement.NewUserAppDomainDb(db.DBs[masterId]) + agent, err := userAppDomainDb.GetAppDomainByType("agent", masterId) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + medium, err := userAppDomainDb.GetAppDomainByType("medium", masterId) + if err != nil { + e.OutErr(c, e.ERR_DB_ORM, err.Error()) + return + } + e.OutSuc(c, md.ShareIndexResp{ + MasterId: masterId, + AgentDomain: agent.Domain, + MediumDomain: medium.Domain, + }, nil) + return +} diff --git a/app/lib/wechat/enum/adunit_enum.go b/app/lib/wechat/enum/adunit_enum.go new file mode 100644 index 0000000..e83088a --- /dev/null +++ b/app/lib/wechat/enum/adunit_enum.go @@ -0,0 +1,64 @@ +package enum + +type AdunitType string //广告单元类型 + +const ( + AdunitTypeForBanner = "SLOT_ID_WEAPP_BANNER" + AdunitTypeForRewardVideo = "SLOT_ID_WEAPP_REWARD_VIDEO" + AdunitTypeForInterstitial = "SLOT_ID_WEAPP_INTERSTITIAL" + AdunitTypeForVideoFeeds = "SLOT_ID_WEAPP_VIDEO_FEEDS" + AdunitTypeForVideoBegin = "SLOT_ID_WEAPP_VIDEO_BEGIN" +) + +func (gt AdunitType) String() string { + switch gt { + case AdunitTypeForBanner: + return "小程序banner" + case AdunitTypeForRewardVideo: + return "小程序激励视频" + case AdunitTypeForInterstitial: + return "小程序插屏广告" + case AdunitTypeForVideoFeeds: + return "小程序视频广告" + case AdunitTypeForVideoBegin: + return "小程序视频贴片广告" + default: + return "未知" + } +} + +type AdunitStatus string //广告单元开关状态 + +const ( + AdunitStatusForOn = "AD_UNIT_STATUS_ON" + AdunitStatusForOff = "AD_UNIT_STATUS_OFF" +) + +func (gt AdunitStatus) String() string { + switch gt { + case AdunitStatusForOn: + return "开通" + case AdunitStatusForOff: + return "关闭" + default: + return "未知" + } +} + +type SetCoverAdposStatus int32 //广告单元开关状态 + +const ( + SetCoverAdposStatusForOn = 1 + SetCoverAdposStatusForOff = 4 +) + +func (gt SetCoverAdposStatus) String() string { + switch gt { + case SetCoverAdposStatusForOn: + return "开通" + case SetCoverAdposStatusForOff: + return "关闭" + default: + return "未知" + } +} diff --git a/app/lib/wechat/helpers.go b/app/lib/wechat/helpers.go new file mode 100644 index 0000000..09ecbd1 --- /dev/null +++ b/app/lib/wechat/helpers.go @@ -0,0 +1,68 @@ +package wechat + +import ( + "bytes" + "crypto/sha1" + "fmt" + "io" + "math/rand" + "sort" + "strings" +) + +// GetSignature 获取签名 +func GetSignature(timestamp, nonce string, encrypted string, token string) string { + data := []string{ + encrypted, + token, + timestamp, + nonce, + } + sort.Strings(data) + s := sha1.New() + _, err := io.WriteString(s, strings.Join(data, "")) + if err != nil { + panic("签名错误:sign error") + } + return fmt.Sprintf("%x", s.Sum(nil)) +} + +func makeRandomString(length int) string { + randStr := "" + strSource := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyl" + maxLength := len(strSource) - 1 + for i := 0; i < length; i++ { + randomNum := rand.Intn(maxLength) + randStr += strSource[randomNum : randomNum+1] + } + return randStr +} + +func pKCS7Pad(plainText []byte, blockSize int) []byte { + // block size must be bigger or equal 2 + if blockSize < 1<<1 { + panic("block size is too small (minimum is 2 bytes)") + } + // block size up to 255 requires 1 byte padding + if blockSize < 1<<8 { + // calculate padding length + padLen := padLength(len(plainText), blockSize) + + // define PKCS7 padding block + padding := bytes.Repeat([]byte{byte(padLen)}, padLen) + + // apply padding + padded := append(plainText, padding...) + return padded + } + // block size bigger or equal 256 is not currently supported + panic("unsupported block size") +} + +func padLength(sliceLength, blockSize int) int { + padLen := blockSize - sliceLength%blockSize + if padLen == 0 { + padLen = blockSize + } + return padLen +} diff --git a/app/lib/wechat/md/cache_key_md.go b/app/lib/wechat/md/cache_key_md.go new file mode 100644 index 0000000..85942f2 --- /dev/null +++ b/app/lib/wechat/md/cache_key_md.go @@ -0,0 +1,7 @@ +package md + +const ( + MasterComponentVerifyTicket = "master_component_verify_ticket:%s" + MasterComponentAccessToken = "master_component_access_token:%s" + //MasterApiAuthorizerToken = "master_api_authorizer_token:%s:%s" //站长id:小程序授权id +) diff --git a/app/lib/wechat/md/wechat_api_md.go b/app/lib/wechat/md/wechat_api_md.go new file mode 100644 index 0000000..c5e9fd6 --- /dev/null +++ b/app/lib/wechat/md/wechat_api_md.go @@ -0,0 +1,62 @@ +package md + +type GetComponentAccessToken struct { + ComponentAccessToken string `json:"component_access_token" example:"第三方平台 access_token"` + ExpiresIn int `json:"expires_in" example:"有效期,单位:秒"` +} + +type GetPreAuthCode struct { + PreAuthCode string `json:"pre_auth_code" example:"预授权码"` + ExpiresIn int `json:"expires_in" example:"有效期,单位:秒"` +} + +type GetAuthorizerAccessTokenByAuthCode struct { + AuthorizationInfo struct { + AuthorizerAppid string `json:"authorizer_appid" example:"授权方 appid"` + AuthorizerAccessToken string `json:"authorizer_access_token" example:"接口调用令牌"` + ExpiresIn int `json:"expires_in" example:"authorizer_access_token 的有效期(在授权的公众号/小程序具备API权限时,才有此返回值),单位:秒"` + AuthorizerRefreshToken string `json:"authorizer_refresh_token" example:"刷新令牌(在授权的公众号具备API权限时,才有此返回值),刷新令牌主要用于第三方平台获取和刷新已授权用户的 authorizer_access_token。一旦丢失,只能让用户重新授权,才能再次拿到新的刷新令牌。用户重新授权后,之前的刷新令牌会失效"` + } `json:"authorization_info" example:"预授权码"` +} + +type ApiAuthorizerToken struct { + AuthorizerAccessToken string `json:"authorizer_access_token" example:"接口调用令牌"` + ExpiresIn int `json:"expires_in" example:"authorizer_access_token 的有效期(在授权的公众号/小程序具备API权限时,才有此返回值),单位:秒"` + AuthorizerRefreshToken string `json:"authorizer_refresh_token" example:"刷新令牌(在授权的公众号具备API权限时,才有此返回值),刷新令牌主要用于第三方平台获取和刷新已授权用户的 authorizer_access_token。一旦丢失,只能让用户重新授权,才能再次拿到新的刷新令牌。用户重新授权后,之前的刷新令牌会失效"` +} + +type DelAuthorize struct { + ErrCode int `json:"errcode" example:"错误码"` + ErrMsg string `json:"errmsg" example:"错误信息"` +} + +type AgencyCreateAdunit struct { + Ret int `json:"ret" example:"错误码"` + ErrMsg string `json:"err_msg" example:"错误信息"` + AdUnitId string `json:"ad_unit_id" example:"广告单元ID"` +} + +type AgencyUpdateAdunit struct { + Ret int `json:"ret" example:"错误码"` + ErrMsg string `json:"err_msg" example:"错误信息"` +} + +type SetCoverAdposStatus struct { + Ret int `json:"ret" example:"错误码"` + ErrMsg string `json:"err_msg" example:"错误信息"` +} + +type GetAdunitList struct { + Ret int `json:"ret" example:"错误码"` + ErrMsg string `json:"err_msg" example:"错误信息"` + AdUnit []struct { + AdSlot string `json:"ad_slot" example:"广告位类型名称"` + AdUnitId string `json:"ad_unit_id" example:"广告单元ID"` + AdUnitName string `json:"ad_unit_name" example:"广告单元名称"` + AdUnitSize []map[string]interface{} `json:"ad_unit_size" example:"广告单元大小"` + AdUnitStatus int `json:"ad_unit_status" example:"广告单元开关状态 1:开启 2:关闭"` + VideoDurationMax int `json:"video_duration_max" example:"广告展示时长最大值"` + VideoDurationMin int `json:"video_duration_min" example:"广告展示时长最小值"` + } `json:"ad_unit"` + TotalNum int `json:"total_num" example:"总广告单元数据量"` +} diff --git a/app/lib/wechat/message.go b/app/lib/wechat/message.go new file mode 100644 index 0000000..143950e --- /dev/null +++ b/app/lib/wechat/message.go @@ -0,0 +1,254 @@ +package wechat + +import ( + "bytes" + "encoding/binary" + "encoding/xml" + "errors" + "strconv" + "time" +) + +var EventTicket = "component_verify_ticket" //ticket推送 +var EventUnauthorized = "unauthorized" //取消授权 +var EventUpdateAuthorized = "updateauthorized" //更新授权 +var EventAuthorized = "authorized" //授权成功 + +var MsgTypeText = "text" //文本消息 +var MsgTypeImage = "image" //文本消息 +var MsgTypeVoice = "voice" //语音消息 +var MsgTypeVideo = "Video" //视频消息 +var MsgTypeMusic = "music" //音乐消息 +var MsgTypeNews = "news" //图文消息 + +// EventMessageBody 事件推送 +type EventMessageBody struct { + XMLName xml.Name `xml:"xml"` + AppId string `xml:"AppId" json:"app_id"` + CreateTime int `xml:"CreateTime" json:"create_time"` + InfoType string `xml:"InfoType" json:"info_type"` + ComponentVerifyTicket string `xml:"ComponentVerifyTicket" json:"component_verify_ticket"` + AuthorizerAppid string `xml:"AuthorizerAppid" json:"authorizer_appid"` + AuthorizationCode string `xml:"AuthorizationCode" json:"authorization_code"` + AuthorizationCodeExpiredTime string `xml:"AuthorizationCodeExpiredTime" json:"authorization_code_expired_time"` + PreAuthCode string `xml:"PreAuthCode" json:"pre_auth_code"` +} + +// MessageBodyDecrypt 消息体 +type MessageBodyDecrypt struct { + XMLName xml.Name `xml:"xml"` + ToUserName string `xml:"ToUserName"` + FromUserName string `xml:"FromUserName"` + CreateTime string `xml:"CreateTime"` + MsgType string `xml:"MsgType"` + Url string `xml:"Url"` + PicUrl string `xml:"PicUrl"` + MediaId string `xml:"MediaId"` + ThumbMediaId string `xml:"ThumbMediaId"` + Content string `xml:"Content"` + MsgId int `xml:"MsgId"` + Location_X string `xml:"Location_x"` + Location_Y string `xml:"Location_y"` + Label string `xml:"Label"` +} + +type MessageEncryptBody struct { + XMLName xml.Name `xml:"xml"` + Encrypt CDATA `xml:"Encrypt"` + MsgSignature CDATA `xml:"MsgSignature"` + TimeStamp string `xml:"TimeStamp"` + Nonce CDATA `xml:"Nonce"` +} + +type MessageText struct { + XMLName xml.Name `xml:"xml"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` + CreateTime string `xml:"CreateTime"` + MsgType CDATA `xml:"MsgType"` + Content CDATA `xml:"Content"` +} + +type MessageImage struct { + XMLName xml.Name `xml:"xml"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` + CreateTime string `xml:"CreateTime"` + MsgType CDATA `xml:"MsgType"` + Image Media `xml:"Image"` +} + +type MessageVoice struct { + XMLName xml.Name `xml:"xml"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` + CreateTime string `xml:"CreateTime"` + MsgType CDATA `xml:"MsgType"` + Voice Media `xml:"Voice"` +} + +type MessageVideo struct { + XMLName xml.Name `xml:"xml"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` + CreateTime string `xml:"CreateTime"` + MsgType CDATA `xml:"MsgType"` + Video Video `xml:"Video"` +} + +type MessageMusic struct { + XMLName xml.Name `xml:"xml"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` + CreateTime string `xml:"CreateTime"` + MsgType CDATA `xml:"MsgType"` + Music Music `xml:"Music"` +} + +type MessageArticle struct { + XMLName xml.Name `xml:"xml"` + ToUserName CDATA `xml:"ToUserName"` + FromUserName CDATA `xml:"FromUserName"` + CreateTime string `xml:"CreateTime"` + MsgType CDATA `xml:"MsgType"` + ArticleCount string `xml:"ArticleCount"` + Articles []ArticleItem `xml:"Articles"` +} + +type CDATA struct { + Text string `xml:",innerxml"` +} + +type Media struct { + MediaId CDATA `xml:"MediaId"` +} + +type Video struct { + MediaId CDATA `xml:"MediaId"` + Title CDATA `xml:"Title"` + Description CDATA `xml:"Description"` +} + +type Music struct { + Title CDATA `xml:"Title"` + Description CDATA `xml:"Description"` + MusicUrl CDATA `xml:"MusicUrl"` + HQMusicUrl CDATA `xml:"HQMusicUrl"` + ThumbMediaId CDATA `xml:"ThumbMediaId"` +} + +type ArticleItem struct { + Title CDATA `xml:"Title"` + Description CDATA `xml:"Description"` + PicUrl CDATA `xml:"PicUrl"` + Url CDATA `xml:"Url"` +} + +func FormatMessage(plainText []byte, data interface{}) (*interface{}, error) { + length := GetMessageLength(plainText) + err := xml.Unmarshal(plainText[20:20+length], data) + if err != nil { + return nil, errors.New("格式化消息失败:format message error") + } + return &data, nil +} + +func GetMessageLength(plainText []byte) int32 { + // Read length + buf := bytes.NewBuffer(plainText[16:20]) + var length int32 + err := binary.Read(buf, binary.BigEndian, &length) + if err != nil { + panic("获取消息长度失败:read message length error") + } + return length +} + +func ValueToCDATA(content string) CDATA { + return CDATA{""} +} + +// FormatTextMessage 格式化文本消息 +func FormatTextMessage(fromUserName string, toUserName string, content string) []byte { + timestamp := strconv.Itoa(int(time.Now().Unix())) + textMessage := MessageText{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), Content: ValueToCDATA(content), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeText)} + messageBytes, err := xml.MarshalIndent(textMessage, " ", " ") + if err != nil { + panic("格式化文本消息失败:xml marsha1 error;" + err.Error()) + } + return messageBytes +} + +// FormatImageMessage 格式化图片消息 +func FormatImageMessage(fromUserName string, toUserName string, mediaId string) []byte { + timestamp := strconv.Itoa(int(time.Now().Unix())) + imageMessage := MessageImage{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeImage), Image: Media{ValueToCDATA(mediaId)}} + messageBytes, err := xml.MarshalIndent(imageMessage, " ", " ") + if err != nil { + panic("格式化图片消息失败:xml marsha1 error;" + err.Error()) + } + return messageBytes +} + +// FormatVoiceMessage 格式语音消息 +func FormatVoiceMessage(fromUserName string, toUserName string, mediaId string) []byte { + timestamp := strconv.Itoa(int(time.Now().Unix())) + voiceMessage := MessageVoice{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeVoice), Voice: Media{ValueToCDATA(mediaId)}} + messageBytes, err := xml.MarshalIndent(voiceMessage, " ", " ") + if err != nil { + panic("格式化语音消息失败:xml marsha1 error;" + err.Error()) + } + return messageBytes +} + +// FormatVideoMessage 格式化视频消息 +func FormatVideoMessage(fromUserName string, toUserName string, mediaId string, title string, description string) []byte { + timestamp := strconv.Itoa(int(time.Now().Unix())) + videoMessage := MessageVideo{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeVideo), Video: Video{ + MediaId: ValueToCDATA(mediaId), + Title: ValueToCDATA(title), + Description: ValueToCDATA(description), + }} + messageBytes, err := xml.MarshalIndent(videoMessage, " ", " ") + if err != nil { + panic("格式化语音消息失败:xml marsha1 error;" + err.Error()) + } + return messageBytes +} + +// FormatMusicMessage 格式化音乐消息 +func FormatMusicMessage(fromUserName string, toUserName string, thumbMediaId string, title string, description string, musicUrl string, hQMusicUrl string) []byte { + timestamp := strconv.Itoa(int(time.Now().Unix())) + musicMessage := MessageMusic{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeMusic), Music: Music{ + Title: ValueToCDATA(title), + Description: ValueToCDATA(description), + MusicUrl: ValueToCDATA(musicUrl), + HQMusicUrl: ValueToCDATA(hQMusicUrl), + ThumbMediaId: ValueToCDATA(thumbMediaId), + }} + messageBytes, err := xml.MarshalIndent(musicMessage, " ", " ") + if err != nil { + panic("格式化音乐消息失败:xml marsha1 error;" + err.Error()) + } + return messageBytes +} + +// FormatArticlesMessage 格式化音乐消息 +func FormatArticlesMessage(fromUserName string, toUserName string, items []ArticleItem) []byte { + timestamp := strconv.Itoa(int(time.Now().Unix())) + articleNum := strconv.Itoa(len(items)) + musicMessage := MessageArticle{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeNews), Articles: items, ArticleCount: articleNum} + messageBytes, err := xml.MarshalIndent(musicMessage, " ", " ") + if err != nil { + panic("格式化图文消息失败:xml marsha1 error;" + err.Error()) + } + return messageBytes +} + +// FormatEncryptData 格式化微信加密数据 +func FormatEncryptData(encrypted string, token string) MessageEncryptBody { + nonce := makeRandomString(16) + timestamp := strconv.Itoa(int(time.Now().Unix())) + data := MessageEncryptBody{Encrypt: ValueToCDATA(encrypted), Nonce: ValueToCDATA(nonce), MsgSignature: ValueToCDATA(GetSignature(timestamp, nonce, encrypted, token)), TimeStamp: timestamp} + return data +} diff --git a/app/lib/wechat/prpcrypt.go b/app/lib/wechat/prpcrypt.go new file mode 100644 index 0000000..75d4bfc --- /dev/null +++ b/app/lib/wechat/prpcrypt.go @@ -0,0 +1,61 @@ +package wechat + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "io" +) + +type prpCrypt struct { + Key []byte + Iv []byte +} + +func NewPrpCrypt(aesKey string) *prpCrypt { + instance := new(prpCrypt) + //网络字节序 + instance.Key, _ = base64.StdEncoding.DecodeString(aesKey + "=") + instance.Iv = randomIv() + return instance +} + +func randomIv() []byte { + iv := make([]byte, aes.BlockSize) + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + panic("random iv error") + } + return iv +} + +func (prp *prpCrypt) decrypt(encrypted string) ([]byte, error) { + encryptedBytes, _ := base64.StdEncoding.DecodeString(encrypted) + k := len(prp.Key) //PKCS#7 + if len(encryptedBytes)%k != 0 { + panic("ciphertext size is not multiple of aes key length") + } + block, err := aes.NewCipher(prp.Key) + if err != nil { + return nil, err + } + blockMode := cipher.NewCBCDecrypter(block, prp.Iv) + plainText := make([]byte, len(encryptedBytes)) + blockMode.CryptBlocks(plainText, encryptedBytes) + return plainText, nil +} + +func (prp *prpCrypt) encrypt(plainText []byte) ([]byte, error) { + k := len(prp.Key) + if len(plainText)%k != 0 { + plainText = pKCS7Pad(plainText, k) + } + block, err := aes.NewCipher(prp.Key) + if err != nil { + return nil, err + } + cipherData := make([]byte, len(plainText)) + blockMode := cipher.NewCBCEncrypter(block, prp.Iv) + blockMode.CryptBlocks(cipherData, plainText) + return cipherData, nil +} diff --git a/app/lib/wechat/wechat_api.go b/app/lib/wechat/wechat_api.go new file mode 100644 index 0000000..ff4fe89 --- /dev/null +++ b/app/lib/wechat/wechat_api.go @@ -0,0 +1,322 @@ +package wechat + +import ( + "applet/app/cfg" + "applet/app/lib/wechat/enum" + "applet/app/lib/wechat/md" + "applet/app/utils" + "applet/app/utils/cache" + db "code.fnuoos.com/zhimeng/model.git/src" + "code.fnuoos.com/zhimeng/model.git/src/super/implement" + "encoding/json" + "errors" + "fmt" +) + +type WxApiService struct { + ComponentAppid string `json:"component_appid"` + ComponentAppsecret string `json:"component_appsecret"` + ComponentVerifyTicket string `json:"component_verify_ticket"` + MasterId string `json:"master_id"` + Host string `json:"host"` +} + +func NewWxApiService(masterId, componentAppid, componentAppsecret string) (wxApiService WxApiService, err error) { // set方法 + wxApiService.MasterId = masterId + wxApiService.ComponentAppid = componentAppid + wxApiService.ComponentAppsecret = componentAppsecret + wxApiService.Host = "http://super.advertisement.dengbiao.top" + if cfg.Prd { + wxApiService.Host = "http://www.baidu.com" + } + cacheKey := fmt.Sprintf(md.MasterComponentVerifyTicket, wxApiService.MasterId) + cacheComponentVerifyTicket, _ := cache.GetString(cacheKey) + if cacheComponentVerifyTicket == "" { + return wxApiService, errors.New("微信验证票据ticket未获取到") + } + wxApiService.ComponentVerifyTicket = cacheComponentVerifyTicket + return +} + +// GetComponentAccessToken 获取接口调用令牌token +func (wxApiService *WxApiService) GetComponentAccessToken() (cacheComponentAccessToken string, err error) { // set方法 + cacheKey := fmt.Sprintf(md.MasterComponentAccessToken, wxApiService.MasterId) + cacheComponentAccessToken, _ = cache.GetString(cacheKey) + if cacheComponentAccessToken == "" { + url := "https://api.weixin.qq.com/cgi-bin/component/api_component_token" + params := map[string]string{ + "component_appid": wxApiService.ComponentAppid, + "component_appsecret": wxApiService.ComponentAppsecret, + "component_verify_ticket": wxApiService.ComponentVerifyTicket, + } + postBody, err1 := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err1 != nil { + return cacheComponentAccessToken, err1 + } + var postData md.GetComponentAccessToken + err = json.Unmarshal(postBody, &postData) + if err != nil { + return + } + if postData.ComponentAccessToken == "" { + err = errors.New("获取接口令牌token失败") + return + } + cacheComponentAccessToken = postData.ComponentAccessToken + cache.SetEx(cacheKey, cacheComponentAccessToken, postData.ExpiresIn-600) + wxOpenThirdPartyAppListDb := implement.NewWxOpenThirdPartyAppListDb(db.Db) + wxOpenThirdPartyAppList, err1 := wxOpenThirdPartyAppListDb.GetWxOpenThirdPartyAppListByAppId(wxApiService.ComponentAppid) + if err1 != nil { + return cacheComponentAccessToken, err1 + } + if wxOpenThirdPartyAppList == nil { + err = errors.New("未查询到对应三方应用App记录") + return + } + wxOpenThirdPartyAppList.ComponentAccessToken = cacheComponentAccessToken + _, err = wxOpenThirdPartyAppListDb.UpdateWxOpenThirdPartyAppList(wxOpenThirdPartyAppList, "component_access_token") + if err != nil { + return + } + } + return +} + +// GetAuth 获取接口调用令牌 +func (wxApiService *WxApiService) GetAuth(appId string) (cacheApiAuthorizerToken string, err error) { // set方法 + userWxAppletListDb := implement.NewUserWxAppletListDb(db.Db) + userWxAppletList, err1 := userWxAppletListDb.GetUserWxAppletListByAppId(appId) + if err1 != nil { + return cacheApiAuthorizerToken, err1 + } + if userWxAppletList == nil { + err = errors.New("未查询到对应小程序App记录") + return + } + + //获取/刷新接口调用令牌 + componentAccessToken, err := wxApiService.GetComponentAccessToken() + if err != nil { + return + } + url := "https://api.weixin.qq.com/cgi-bin/component/api_authorizer_token?component_access_token=" + componentAccessToken + params := map[string]string{ + "component_appid": wxApiService.ComponentAppid, + "authorizer_appid": appId, + "authorizer_refresh_token": userWxAppletList.AuthorizerRefreshToken, + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + + var resp md.ApiAuthorizerToken + err = json.Unmarshal(postBody, &resp) + if err != nil { + return + } + if resp.AuthorizerAccessToken == "" { + err = errors.New("获取/刷新接口调用令牌") + return + } + cacheApiAuthorizerToken = resp.AuthorizerAccessToken + return +} + +// GetPreAuthCode 获取预授权码 +func (wxApiService *WxApiService) GetPreAuthCode() (preAuthCode string, err error) { // set方法 + componentAccessToken, err := wxApiService.GetComponentAccessToken() + if err != nil { + return + } + url := "https://api.weixin.qq.com/cgi-bin/component/api_create_preauthcode?component_access_token=" + componentAccessToken + params := map[string]string{ + "component_appid": wxApiService.ComponentAppid, + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + var postData md.GetPreAuthCode + err = json.Unmarshal(postBody, &postData) + if err != nil { + return + } + if postData.PreAuthCode == "" { + err = errors.New("获取预授权码失败") + return + } + preAuthCode = postData.PreAuthCode + return +} + +// GetAuthorizerAccessTokenByAuthCode 使用授权码获取授权信息 +func (wxApiService *WxApiService) GetAuthorizerAccessTokenByAuthCode(authCode string) (resp md.GetAuthorizerAccessTokenByAuthCode, err error) { // set方法 + componentAccessToken, err := wxApiService.GetComponentAccessToken() + if err != nil { + return + } + url := "https://api.weixin.qq.com/cgi-bin/component/api_query_auth?component_access_token=" + componentAccessToken + params := map[string]string{ + "component_appid": wxApiService.ComponentAppid, + "authorization_code": authCode, + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + err = json.Unmarshal(postBody, &resp) + if err != nil { + return + } + if resp.AuthorizationInfo.AuthorizerAppid == "" { + err = errors.New("获取授权信息失败") + return + } + return +} + +// DelAuthorize 取消授权 +func (wxApiService *WxApiService) DelAuthorize(appId string) (err error) { // set方法 + apiAuthorizerToken, err := wxApiService.GetAuth(appId) + if err != nil { + return + } + url := "https://api.weixin.qq.com/wxaapi/wxaembedded/del_authorize?access_token=" + apiAuthorizerToken + params := map[string]string{ + "appid": appId, + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + var resp md.DelAuthorize + err = json.Unmarshal(postBody, &resp) + if err != nil { + return + } + if resp.ErrCode != 0 { + err = errors.New(resp.ErrMsg) + } + return +} + +// AgencyCreateAdunit 创建广告单元 +func (wxApiService *WxApiService) AgencyCreateAdunit(appId, name string, adunitType enum.AdunitType) (err error, adUnitId string) { // set方法 + apiAuthorizerToken, err := wxApiService.GetAuth(appId) + if err != nil { + return + } + url := "https://api.weixin.qq.com/wxa/operationams?action=agency_create_adunit&access_token=" + apiAuthorizerToken + params := map[string]interface{}{ + "name": name, + "type": string(adunitType), + } + if adunitType == enum.AdunitTypeForVideoFeeds { + params["video_duration_min"] = 6 + params["video_duration_max"] = 60 + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + var resp md.AgencyCreateAdunit + err = json.Unmarshal(postBody, &resp) + if err != nil { + return + } + if resp.Ret != 0 { + err = errors.New(resp.ErrMsg) + } + adUnitId = resp.AdUnitId + return +} + +// AgencyUpdateAdunit 更新广告单元 +func (wxApiService *WxApiService) AgencyUpdateAdunit(appId, adUnitId, name string, adunitType enum.AdunitType, adunitStatus enum.AdunitStatus) (err error) { // set方法 + apiAuthorizerToken, err := wxApiService.GetAuth(appId) + if err != nil { + return + } + url := "https://api.weixin.qq.com/wxa/operationams?action=agency_update_adunit&access_token=" + apiAuthorizerToken + params := map[string]interface{}{ + "name": name, + "ad_unit_id": adUnitId, + "status": string(adunitStatus), + } + if adunitType == enum.AdunitTypeForVideoFeeds { + params["video_duration_min"] = 6 + params["video_duration_max"] = 60 + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + var resp md.AgencyUpdateAdunit + err = json.Unmarshal(postBody, &resp) + if err != nil { + return + } + if resp.Ret != 0 { + err = errors.New(resp.ErrMsg) + } + return +} + +// SetCoverAdposStatus 设置小程序封面广告位开关状态 +func (wxApiService *WxApiService) SetCoverAdposStatus(appId string, setCoverAdposStatus enum.SetCoverAdposStatus) (err error) { // set方法 + apiAuthorizerToken, err := wxApiService.GetAuth(appId) + if err != nil { + return + } + url := "https://api.weixin.qq.com/wxa/operationams?action=agency_set_cover_adpos_status&access_token=" + apiAuthorizerToken + params := map[string]interface{}{ + "status": int32(setCoverAdposStatus), + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + var resp md.SetCoverAdposStatus + err = json.Unmarshal(postBody, &resp) + if err != nil { + return + } + if resp.Ret != 0 { + err = errors.New(resp.ErrMsg) + } + return +} + +/* +GetAdunitList 获取广告位(除封面广告位)或指定广告单元的信息 +@params adSlot 广告位类型名称(非必传) +@params adUnitId 广告单元ID(非必传) +@Remark 返回的广告单元列表按照创建时间倒序,请以分页的形式获取。当需要获取全部广告位的清单时,无需传递广告位类型名称及广告单元ID;当需要获取某类型广告位的清单时,仅需传递广告位类型名称;当需要获取某广告位 id 的数据时,仅需传递广告单元ID。 +*/ +func (wxApiService *WxApiService) GetAdunitList(appId string, page, pageSize int, adSlot enum.AdunitType, adUnitId string) (err error, resp md.GetAdunitList) { // set方法 + apiAuthorizerToken, err := wxApiService.GetAuth(appId) + if err != nil { + return + } + url := "https://api.weixin.qq.com/wxa/operationams?action=agency_get_adunit_list&access_token=" + apiAuthorizerToken + params := map[string]interface{}{ + "page": page, + "pageSize": pageSize, + "ad_slot": adSlot, + "ad_unit_id": adUnitId, + } + postBody, err := utils.CurlPost(url, utils.SerializeStr(params), nil) + if err != nil { + return + } + + err = json.Unmarshal(postBody, &resp) + if err != nil { + return + } + if resp.Ret != 0 { + err = errors.New(resp.ErrMsg) + } + return +} diff --git a/app/lib/wechat/wechat_err_code.go b/app/lib/wechat/wechat_err_code.go new file mode 100644 index 0000000..ecd020b --- /dev/null +++ b/app/lib/wechat/wechat_err_code.go @@ -0,0 +1,11 @@ +package wechat + +var SuccessCode = 0 +var ValidateSignatureError = -40001 +var ParseXmlError = -40002 +var ComputeSignatureError = -40003 +var IllegalAesKey = -40004 +var ValidateAppidError = -40005 +var EncryptAESError = -40006 +var DecryptAESError = -40007 +var IllegalBuffer = -40008 diff --git a/app/lib/wechat/wechat_message.go b/app/lib/wechat/wechat_message.go new file mode 100644 index 0000000..995b39d --- /dev/null +++ b/app/lib/wechat/wechat_message.go @@ -0,0 +1,200 @@ +package wechat + +import ( + "bytes" + "encoding/base64" + "encoding/binary" + "encoding/xml" + "errors" + "fmt" +) + +type msgCrypt struct { + token string + aesKey string + appid string +} + +// EventEncryptRequest 微信事件推送结构体 +type EventEncryptRequest struct { + XMLName xml.Name `xml:"xml"` + Encrypt string `xml:"Encrypt"` + Appid string `xml:"Appid"` +} + +// MessageEncryptRequest 微信消息加密结构体 +type MessageEncryptRequest struct { + XMLName xml.Name `xml:"xml"` + Encrypt string `xml:"Encrypt"` + MsgSignature string `xml:"MsgSignature"` + TimeStamp string `xml:"TimeStamp"` + Nonce string `xml:"Nonce"` +} + +// NewWechatMsgCrypt 实例化微信加解密 +func NewWechatMsgCrypt(token string, aesKey string, appid string) *msgCrypt { + instance := new(msgCrypt) + instance.token = token + instance.aesKey = aesKey + instance.appid = appid + return instance +} + +// WechatEventDecrypt 微信事件推送解密 +func (w *msgCrypt) WechatEventDecrypt(eventRequest EventEncryptRequest, msgSignature string, timestamp, nonce string) EventMessageBody { + errCode, data := w.decryptMsg(msgSignature, timestamp, nonce, eventRequest.Encrypt) + if errCode != SuccessCode { + panic(fmt.Sprintf("消息解密失败,code:%d", errCode)) + } + message := EventMessageBody{} + _, err := FormatMessage(data, &message) + if err != nil { + panic(fmt.Sprintf("消息格式化失败,%s", err.Error())) + } + return message +} + +// WechatMessageDecrypt 微信消息解密 +func (w *msgCrypt) WechatMessageDecrypt(messageEncryptRequest MessageEncryptRequest) interface{} { + errCode, data := w.decryptMsg(messageEncryptRequest.MsgSignature, messageEncryptRequest.TimeStamp, messageEncryptRequest.Nonce, messageEncryptRequest.Encrypt) + if errCode != SuccessCode { + panic(fmt.Sprintf("消息解密失败,code:%d", errCode)) + } + message := MessageBodyDecrypt{} + _, err := FormatMessage(data, &message) + if err != nil { + panic(fmt.Sprintf("消息格式化失败,%s", err.Error())) + } + return message +} + +// WechatTextMessage 微信文本消息加密 +func (w *msgCrypt) WechatTextMessage(fromUserName string, toUserName string, content string) MessageEncryptBody { + message := FormatTextMessage(fromUserName, toUserName, content) + encrypted, err := w.encryptMsg(message) + if err != nil { + panic("消息加密失败:" + err.Error()) + } + data := FormatEncryptData(encrypted, w.token) + return data +} + +// WechatImageMessage 微信图片消息加密 +func (w *msgCrypt) WechatImageMessage(fromUserName string, toUserName string, mediaId string) MessageEncryptBody { + message := FormatImageMessage(fromUserName, toUserName, mediaId) + encrypted, err := w.encryptMsg(message) + if err != nil { + panic("消息加密失败:" + err.Error()) + } + data := FormatEncryptData(encrypted, w.token) + return data +} + +// WechatVoiceMessage 微信语音消息加密 +func (w *msgCrypt) WechatVoiceMessage(fromUserName string, toUserName string, mediaId string) MessageEncryptBody { + message := FormatVoiceMessage(fromUserName, toUserName, mediaId) + encrypted, err := w.encryptMsg(message) + if err != nil { + panic("消息加密失败:" + err.Error()) + } + data := FormatEncryptData(encrypted, w.token) + return data +} + +// WechatVideoMessage 微信视频消息加密 +func (w *msgCrypt) WechatVideoMessage(fromUserName string, toUserName string, mediaId string, title string, description string) MessageEncryptBody { + message := FormatVideoMessage(fromUserName, toUserName, mediaId, title, description) + encrypted, err := w.encryptMsg(message) + if err != nil { + panic("消息加密失败:" + err.Error()) + } + data := FormatEncryptData(encrypted, w.token) + return data +} + +// WechatMusicMessage 微信音乐消息加密 +func (w *msgCrypt) WechatMusicMessage(fromUserName string, toUserName string, thumbMediaId string, title string, description string, musicUrl string, hQMusicUrl string) MessageEncryptBody { + message := FormatMusicMessage(fromUserName, toUserName, thumbMediaId, title, description, musicUrl, hQMusicUrl) + encrypted, err := w.encryptMsg(message) + if err != nil { + panic("消息加密失败:" + err.Error()) + } + data := FormatEncryptData(encrypted, w.token) + return data +} + +// WechatArticlesMessage 微信图文消息加密 +func (w *msgCrypt) WechatArticlesMessage(fromUserName string, toUserName string, items []ArticleItem) MessageEncryptBody { + message := FormatArticlesMessage(fromUserName, toUserName, items) + encrypted, err := w.encryptMsg(message) + if err != nil { + panic("消息加密失败:" + err.Error()) + } + data := FormatEncryptData(encrypted, w.token) + return data +} + +// decryptMsg aes消息解密 +func (w *msgCrypt) decryptMsg(msgSignature string, timestamp, nonce string, encrypted string) (int, []byte) { + //验证aes + if len(w.aesKey) != 43 { + return IllegalAesKey, nil + } + //判断签名是否一致 + if err := w.validSignature(msgSignature, timestamp, nonce, encrypted); err != nil { + return ValidateSignatureError, nil + } + //解密 + prp := NewPrpCrypt(w.aesKey) + plainText, err := prp.decrypt(encrypted) + if err != nil { + return DecryptAESError, nil + } + //验证appid是否一致(消息来源是否一致) + if err := w.validMessageSource(plainText); err != nil { + return ValidateAppidError, nil + } + return SuccessCode, plainText +} + +// encryptMsg aes消息加密 +func (w *msgCrypt) encryptMsg(message []byte) (string, error) { + //计算消息长度 + buf := new(bytes.Buffer) + err := binary.Write(buf, binary.BigEndian, int32(len(message))) + if err != nil { + return "", err + } + messageLength := buf.Bytes() + //生成随机字符串 + randBytes := []byte(makeRandomString(16)) + plainData := bytes.Join([][]byte{randBytes, messageLength, message, []byte(w.appid)}, nil) + prp := NewPrpCrypt(w.aesKey) + //消息加密 + encrypted, err := prp.encrypt(plainData) + if err != nil { + return "", err + } + return base64.StdEncoding.EncodeToString(encrypted), nil +} + +// validSignature 验证签名是否一致 +func (w *msgCrypt) validSignature(msgSignature string, timestamp, nonce string, encrypted string) error { + validSignature := GetSignature(timestamp, nonce, encrypted, w.token) + if validSignature != msgSignature { + return errors.New("签名不一致:valid sign error") + } + return nil +} + +// validMessageSource 验证消息来源 +func (w *msgCrypt) validMessageSource(plainText []byte) error { + messageLength := GetMessageLength(plainText) + //获取appid位置 + appIdStartPos := 20 + messageLength + id := plainText[appIdStartPos : int(appIdStartPos)+len(w.appid)] + if string(id) != w.appid { + return errors.New("消息来源不一致:Appid is invalid") + } + return nil +} diff --git a/app/md/md_oss_bucket_region.go b/app/md/md_oss_bucket_region.go new file mode 100644 index 0000000..c2060de --- /dev/null +++ b/app/md/md_oss_bucket_region.go @@ -0,0 +1,50 @@ +package md + +type QiNiuBucketRegion struct { + RegionId string `json:"region_id" example:"区域id"` + RegionName string `json:"region_name" example:"区域名称"` + RegionDomain string `json:"region_domain" example:"区域域名"` +} + +var QiNiuBucketRegionList = []QiNiuBucketRegion{ + { + RegionId: "z0", + RegionName: "华东-浙江", + RegionDomain: "up-z0.qiniup.com", + }, + { + RegionId: "cn-east-2", + RegionName: "华东-浙江2", + RegionDomain: "up-cn-east-2.qiniup.com", + }, + { + RegionId: "z1", + RegionName: "华北-河北", + RegionDomain: "up-z1.qiniup.com", + }, + { + RegionId: "z2", + RegionName: "华南-广东", + RegionDomain: "up-z2.qiniup.com", + }, + { + RegionId: "na0", + RegionName: "北美-洛杉矶", + RegionDomain: "up-na0.qiniup.com", + }, + { + RegionId: "as0", + RegionName: "亚太-新加坡(原东南亚)", + RegionDomain: "up-as0.qiniup.com", + }, + { + RegionId: "ap-southeast-2", + RegionName: "亚太-河内", + RegionDomain: "up-ap-southeast-2.qiniup.com", + }, + { + RegionId: "ap-southeast-3", + RegionName: "亚太-胡志明", + RegionDomain: "up-ap-southeast-3.qiniup.com", + }, +} diff --git a/app/md/md_set_center.go b/app/md/md_set_center.go new file mode 100644 index 0000000..d641ec1 --- /dev/null +++ b/app/md/md_set_center.go @@ -0,0 +1,49 @@ +package md + +type SetOssReq struct { + FileAccessKey string `json:"file_access_key" binding:"required" example:"对象存储AccessToken"` + FileSecretKey string `json:"file_secret_key" binding:"required" example:"对象存储SecretToken"` + FileBucketHost string `json:"file_bucket_host" binding:"required" example:"对象存储域名"` + FileBucketRegion string `json:"file_bucket_region" binding:"required" example:"文件所属区域"` + FileBucket string `json:"file_bucket" binding:"required" example:"对象存储bucket(空间)"` +} +type SetOssResp struct { + Data SetOssReq `json:"data"` //数据内容 + QiNiuBucketRegionList []QiNiuBucketRegion `json:"qi_niu_bucket_region_list"` //七牛云存储区域列表 +} + +type WxOpenSetReq struct { + Token string `json:"token" binding:"required" example:"消息校验Token"` + AesKey string `json:"aes_key" binding:"required" example:"消息加解密Key"` + Appid string `json:"appid" binding:"required" example:"appid"` + AppSecret string `json:"app_secret" binding:"required" example:"appSecret"` +} +type WxOpenGetResp struct { + Token string `json:"token" example:"消息校验Token"` + AesKey string `json:"aes_key" example:"消息加解密Key"` + Appid string `json:"appid" example:"appid"` + AppSecret string `json:"app_secret" example:"appSecret"` + WxOpenAppletServerDomain string `json:"wx_open_applet_server_domain" example:"微信开放平台-小程序服务器域名"` + WxOpenAuthorizationEventReceivingConfiguration string `json:"wx_open_authorization_event_receiving_configuration" example:"微信开放平台-授权事件接收配置"` + WxOpenDomainOfTheInitiatingPageForLoginAuthorization string `json:"wx_open_domain_of_the_initiating_page_for_login_authorization" example:"微信开放平台-登录授权的发起页域名"` + WxOpenMessageAndEventReceptionConfiguration string `json:"wx_open_message_and_event_reception_configuration" example:"微信开放平台-消息与事件接收配置"` + WxOpenWhiteListIp string `json:"wx_open_white_list_ip" example:"微信开放平台-白名单ip"` +} + +type AppletAddReq struct { + Name string `json:"name" binding:"required" example:"小程序名称"` + Logo string `json:"logo" binding:"required" example:"小程序logo"` + Appid string `json:"appid" binding:"required" example:"授权小程序appid"` + OriginalId string `json:"original_id" binding:"required" example:"授权小程序原始id"` +} +type AppletUpdateReq struct { + Id int `json:"id" binding:"required"` + Name string `json:"name" binding:"required" example:"小程序名称"` + Logo string `json:"logo" binding:"required" example:"小程序logo"` +} + +type ShareIndexResp struct { + MasterId string `json:"master_id"` + AgentDomain string `json:"agent_domain" example:"代理分享地址"` + MediumDomain string `json:"medium_domain" example:"媒体分享地址"` +} diff --git a/app/router/router.go b/app/router/router.go index 28067cc..1a14e8e 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -65,6 +65,7 @@ func route(r *gin.RouterGroup) { rRole(r.Group("/role")) //权限管理 rAgentQualification(r.Group("/agentQualification")) //渠道-资质 rMediumQualification(r.Group("/mediumQualification")) //媒体-资质 + rSetCenter(r.Group("/setCenter")) //设置中心 } func rRole(r *gin.RouterGroup) { @@ -99,3 +100,26 @@ func rMediumQualification(r *gin.RouterGroup) { r.POST("/contact", hdl.MediumQualificationContactInfo) //联系方式 r.POST("/contact/audit", hdl.MediumQualificationContactInfoAudit) //联系方式 } +func rSetCenter(r *gin.RouterGroup) { + rBasicSetCenter := r.Group("/basic") + { + rBasicSetCenter.POST("/setOss", hdl.SetOss) + rBasicSetCenter.GET("/getOss", hdl.GetOss) + rBasicSetCenter.POST("/wxOpenSet", hdl.WxOpenSet) + rBasicSetCenter.GET("/wxOpenGet", hdl.WxOpenGet) + } + rAppletSetCenter := r.Group("/applet") + { + rAppletSetCenter.GET("/list", hdl.AppletList) + rAppletSetCenter.POST("/add", hdl.AppletAdd) + rAppletSetCenter.POST("/update", hdl.AppletUpdate) + rAppletSetCenter.DELETE("/delete/:id", hdl.AppletDelete) + rAppletSetCenter.GET("/authorize", hdl.AppletAuthorize) + rAppletSetCenter.GET("/unauthorized", hdl.AppletUnauthorized) + } + rShareSetCenter := r.Group("/share") + { + rShareSetCenter.GET("/index", hdl.ShareIndex) + } + +} diff --git a/app/svc/svc_sys_cfg_get.go b/app/svc/svc_sys_cfg_get.go index bb99785..060a84b 100644 --- a/app/svc/svc_sys_cfg_get.go +++ b/app/svc/svc_sys_cfg_get.go @@ -1,6 +1,7 @@ package svc import ( + "applet/app/db/implement" db "code.fnuoos.com/zhimeng/model.git/src" "github.com/gin-gonic/gin" "xorm.io/xorm" @@ -11,9 +12,10 @@ import ( // 单挑记录获取 func SysCfgGet(c *gin.Context, key string) string { - mid := c.GetString("mid") - eg := db.DBs[mid] - return db.SysCfgGetWithDb(eg, mid, key) + masterId := GetMasterId(c) + eg := db.DBs[masterId] + sysCfgDb := implement.NewSysCfgDb(eg, masterId) + return sysCfgDb.SysCfgGetWithDb(key) } // 多条记录获取 @@ -22,7 +24,7 @@ func SysCfgFind(c *gin.Context, keys ...string) map[string]string { if c == nil { masterId = "" } else { - masterId = c.GetString("mid") + masterId = GetMasterId(c) } tmp := SysCfgFindComm(masterId, keys...) return tmp @@ -36,51 +38,23 @@ func SysCfgFindComm(masterId string, keys ...string) map[string]string { } res := map[string]string{} //TODO::判断keys长度(大于10个直接查数据库) + sysCfgDb := implement.NewSysCfgDb(eg, masterId) if len(keys) > 10 { - cfgList, _ := db.SysCfgGetAll(eg) + cfgList, _ := sysCfgDb.SysCfgGetAll() if cfgList == nil { return nil } for _, v := range *cfgList { - res[v.Key] = v.Val + res[v.K] = v.V } } else { for _, key := range keys { - res[key] = db.SysCfgGetWithDb(eg, masterId, key) + res[key] = sysCfgDb.SysCfgGetWithDb(key) } } return res } -// 多条记录获取 -func EgSysCfgFind(keys ...string) map[string]string { - var e *xorm.Engine - res := map[string]string{} - if len(res) == 0 { - cfgList, _ := db.SysCfgGetAll(e) - if cfgList == nil { - return nil - } - for _, v := range *cfgList { - res[v.Key] = v.Val - } - // 先不设置缓存 - // cache.SetJson(md.KEY_SYS_CFG_CACHE, res, 60) - } - if len(keys) == 0 { - return res - } - tmp := map[string]string{} - for _, v := range keys { - if val, ok := res[v]; ok { - tmp[v] = val - } else { - tmp[v] = "" - } - } - return tmp -} - // 清理系统配置信息 func SysCfgCleanCache() { cache.Del(md.KEY_SYS_CFG_CACHE) @@ -88,13 +62,17 @@ func SysCfgCleanCache() { // 写入系统设置 func SysCfgSet(c *gin.Context, key, val, memo string) bool { - cfg, err := db.SysCfgGetOne(db.DBs[c.GetString("mid")], key) + masterId := GetMasterId(c) + eg := db.DBs[masterId] + sysCfgDb := implement.NewSysCfgDb(eg, masterId) + + cfg, err := sysCfgDb.SysCfgGetOne(key) if err != nil || cfg == nil { - return db.SysCfgInsert(db.DBs[c.GetString("mid")], key, val, memo) + return sysCfgDb.SysCfgInsert(key, val, memo) } if memo != "" && cfg.Memo != memo { cfg.Memo = memo } SysCfgCleanCache() - return db.SysCfgUpdate(db.DBs[c.GetString("mid")], key, val, cfg.Memo) + return sysCfgDb.SysCfgUpdate(key, val) } diff --git a/docs/docs.go b/docs/docs.go index aa80e1b..a18802a 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1265,6 +1265,422 @@ const docTemplate = `{ } } }, + "/api/setCenter/applet/add": { + "post": { + "description": "小程序设置-新增", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "新增", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.AppletAddReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/authorize": { + "get": { + "description": "设置中心-基础设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心" + ], + "summary": "设置中心-基础设置-微信三方应用获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "微信授权界面url", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/list": { + "get": { + "description": "小程序设置-列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "列表", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/hdl.WxOpenThirdPartyAppList" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/unauthorized": { + "get": { + "description": "设置中心-基础设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心" + ], + "summary": "设置中心-基础设置-微信三方应用获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/update": { + "post": { + "description": "小程序设置-更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "更新", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.AppletUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/getOss": { + "get": { + "description": "基础设置-oss获取", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "oss获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/md.SetOssResp" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/setOss": { + "post": { + "description": "基础设置-oss设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "oss设置", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.SetOssReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/wxOpenGet": { + "get": { + "description": "基础设置-微信三方应用获取", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "微信三方应用获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/md.WxOpenGetResp" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/wxOpenSet": { + "post": { + "description": "基础设置-微信三方应用设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "微信三方应用设置", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.WxOpenSetReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/share/index": { + "get": { + "description": "邀请链接界面接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-邀请链接" + ], + "summary": "邀请链接", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/md.ShareIndexResp" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, "/role/permissionGroupList": { "get": { "description": "权限管理-权限组列表", @@ -1309,9 +1725,82 @@ const docTemplate = `{ } } } + }, + "/v1/banner/delete/{$id}": { + "delete": { + "description": "小程序设置-删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "删除", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } } }, "definitions": { + "hdl.WxOpenThirdPartyAppList": { + "type": "object", + "properties": { + "aes_key": { + "type": "string" + }, + "app_secret": { + "type": "string" + }, + "appid": { + "type": "string" + }, + "component_access_token": { + "type": "string" + }, + "component_verify_ticket": { + "type": "string" + }, + "create_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "token": { + "type": "string" + }, + "update_at": { + "type": "string" + }, + "uuid": { + "type": "integer" + } + } + }, "md.AddAdminReq": { "type": "object", "required": [ @@ -1662,6 +2151,54 @@ const docTemplate = `{ } } }, + "md.AppletAddReq": { + "type": "object", + "required": [ + "appid", + "logo", + "name", + "original_id" + ], + "properties": { + "appid": { + "type": "string", + "example": "授权小程序appid" + }, + "logo": { + "type": "string", + "example": "小程序logo" + }, + "name": { + "type": "string", + "example": "小程序名称" + }, + "original_id": { + "type": "string", + "example": "授权小程序原始id" + } + } + }, + "md.AppletUpdateReq": { + "type": "object", + "required": [ + "id", + "logo", + "name" + ], + "properties": { + "id": { + "type": "integer" + }, + "logo": { + "type": "string", + "example": "小程序logo" + }, + "name": { + "type": "string", + "example": "小程序名称" + } + } + }, "md.BindAdminRoleReq": { "type": "object", "required": [ @@ -1923,6 +2460,23 @@ const docTemplate = `{ } } }, + "md.QiNiuBucketRegion": { + "type": "object", + "properties": { + "region_domain": { + "type": "string", + "example": "区域域名" + }, + "region_id": { + "type": "string", + "example": "区域id" + }, + "region_name": { + "type": "string", + "example": "区域名称" + } + } + }, "md.RegisterForAgentReq": { "type": "object", "required": [ @@ -2011,6 +2565,74 @@ const docTemplate = `{ } } }, + "md.SetOssReq": { + "type": "object", + "required": [ + "file_access_key", + "file_bucket", + "file_bucket_host", + "file_bucket_region", + "file_secret_key" + ], + "properties": { + "file_access_key": { + "type": "string", + "example": "对象存储AccessToken" + }, + "file_bucket": { + "type": "string", + "example": "对象存储bucket(空间)" + }, + "file_bucket_host": { + "type": "string", + "example": "对象存储域名" + }, + "file_bucket_region": { + "type": "string", + "example": "文件所属区域" + }, + "file_secret_key": { + "type": "string", + "example": "对象存储SecretToken" + } + } + }, + "md.SetOssResp": { + "type": "object", + "properties": { + "data": { + "description": "数据内容", + "allOf": [ + { + "$ref": "#/definitions/md.SetOssReq" + } + ] + }, + "qi_niu_bucket_region_list": { + "description": "七牛云存储区域列表", + "type": "array", + "items": { + "$ref": "#/definitions/md.QiNiuBucketRegion" + } + } + } + }, + "md.ShareIndexResp": { + "type": "object", + "properties": { + "agent_domain": { + "type": "string", + "example": "代理分享地址" + }, + "master_id": { + "type": "string" + }, + "medium_domain": { + "type": "string", + "example": "媒体分享地址" + } + } + }, "md.UpdateAdminReq": { "type": "object", "required": [ @@ -2081,6 +2703,74 @@ const docTemplate = `{ "type": "integer" } } + }, + "md.WxOpenGetResp": { + "type": "object", + "properties": { + "aes_key": { + "type": "string", + "example": "消息加解密Key" + }, + "app_secret": { + "type": "string", + "example": "appSecret" + }, + "appid": { + "type": "string", + "example": "appid" + }, + "token": { + "type": "string", + "example": "消息校验Token" + }, + "wx_open_applet_server_domain": { + "type": "string", + "example": "微信开放平台-小程序服务器域名" + }, + "wx_open_authorization_event_receiving_configuration": { + "type": "string", + "example": "微信开放平台-授权事件接收配置" + }, + "wx_open_domain_of_the_initiating_page_for_login_authorization": { + "type": "string", + "example": "微信开放平台-登录授权的发起页域名" + }, + "wx_open_message_and_event_reception_configuration": { + "type": "string", + "example": "微信开放平台-消息与事件接收配置" + }, + "wx_open_white_list_ip": { + "type": "string", + "example": "微信开放平台-白名单ip" + } + } + }, + "md.WxOpenSetReq": { + "type": "object", + "required": [ + "aes_key", + "app_secret", + "appid", + "token" + ], + "properties": { + "aes_key": { + "type": "string", + "example": "消息加解密Key" + }, + "app_secret": { + "type": "string", + "example": "appSecret" + }, + "appid": { + "type": "string", + "example": "appid" + }, + "token": { + "type": "string", + "example": "消息校验Token" + } + } } }, "securityDefinitions": { diff --git a/docs/swagger.json b/docs/swagger.json index a996d9e..ea3cae5 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -1257,6 +1257,422 @@ } } }, + "/api/setCenter/applet/add": { + "post": { + "description": "小程序设置-新增", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "新增", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.AppletAddReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/authorize": { + "get": { + "description": "设置中心-基础设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心" + ], + "summary": "设置中心-基础设置-微信三方应用获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "微信授权界面url", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/list": { + "get": { + "description": "小程序设置-列表", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "列表", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/hdl.WxOpenThirdPartyAppList" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/unauthorized": { + "get": { + "description": "设置中心-基础设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心" + ], + "summary": "设置中心-基础设置-微信三方应用获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/applet/update": { + "post": { + "description": "小程序设置-更新", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "更新", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.AppletUpdateReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/getOss": { + "get": { + "description": "基础设置-oss获取", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "oss获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/md.SetOssResp" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/setOss": { + "post": { + "description": "基础设置-oss设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "oss设置", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.SetOssReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/wxOpenGet": { + "get": { + "description": "基础设置-微信三方应用获取", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "微信三方应用获取", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/md.WxOpenGetResp" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/basic/wxOpenSet": { + "post": { + "description": "基础设置-微信三方应用设置", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-基础设置" + ], + "summary": "微信三方应用设置", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + }, + { + "description": "请求参数", + "name": "args", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/md.WxOpenSetReq" + } + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, + "/api/setCenter/share/index": { + "get": { + "description": "邀请链接界面接口", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-邀请链接" + ], + "summary": "邀请链接", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/md.ShareIndexResp" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } + }, "/role/permissionGroupList": { "get": { "description": "权限管理-权限组列表", @@ -1301,9 +1717,82 @@ } } } + }, + "/v1/banner/delete/{$id}": { + "delete": { + "description": "小程序设置-删除", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "设置中心-小程序设置" + ], + "summary": "删除", + "parameters": [ + { + "type": "string", + "description": "验证参数Bearer和token空格拼接", + "name": "Authorization", + "in": "header", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "type": "string" + } + }, + "400": { + "description": "具体错误", + "schema": { + "$ref": "#/definitions/md.Response" + } + } + } + } } }, "definitions": { + "hdl.WxOpenThirdPartyAppList": { + "type": "object", + "properties": { + "aes_key": { + "type": "string" + }, + "app_secret": { + "type": "string" + }, + "appid": { + "type": "string" + }, + "component_access_token": { + "type": "string" + }, + "component_verify_ticket": { + "type": "string" + }, + "create_at": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "token": { + "type": "string" + }, + "update_at": { + "type": "string" + }, + "uuid": { + "type": "integer" + } + } + }, "md.AddAdminReq": { "type": "object", "required": [ @@ -1654,6 +2143,54 @@ } } }, + "md.AppletAddReq": { + "type": "object", + "required": [ + "appid", + "logo", + "name", + "original_id" + ], + "properties": { + "appid": { + "type": "string", + "example": "授权小程序appid" + }, + "logo": { + "type": "string", + "example": "小程序logo" + }, + "name": { + "type": "string", + "example": "小程序名称" + }, + "original_id": { + "type": "string", + "example": "授权小程序原始id" + } + } + }, + "md.AppletUpdateReq": { + "type": "object", + "required": [ + "id", + "logo", + "name" + ], + "properties": { + "id": { + "type": "integer" + }, + "logo": { + "type": "string", + "example": "小程序logo" + }, + "name": { + "type": "string", + "example": "小程序名称" + } + } + }, "md.BindAdminRoleReq": { "type": "object", "required": [ @@ -1915,6 +2452,23 @@ } } }, + "md.QiNiuBucketRegion": { + "type": "object", + "properties": { + "region_domain": { + "type": "string", + "example": "区域域名" + }, + "region_id": { + "type": "string", + "example": "区域id" + }, + "region_name": { + "type": "string", + "example": "区域名称" + } + } + }, "md.RegisterForAgentReq": { "type": "object", "required": [ @@ -2003,6 +2557,74 @@ } } }, + "md.SetOssReq": { + "type": "object", + "required": [ + "file_access_key", + "file_bucket", + "file_bucket_host", + "file_bucket_region", + "file_secret_key" + ], + "properties": { + "file_access_key": { + "type": "string", + "example": "对象存储AccessToken" + }, + "file_bucket": { + "type": "string", + "example": "对象存储bucket(空间)" + }, + "file_bucket_host": { + "type": "string", + "example": "对象存储域名" + }, + "file_bucket_region": { + "type": "string", + "example": "文件所属区域" + }, + "file_secret_key": { + "type": "string", + "example": "对象存储SecretToken" + } + } + }, + "md.SetOssResp": { + "type": "object", + "properties": { + "data": { + "description": "数据内容", + "allOf": [ + { + "$ref": "#/definitions/md.SetOssReq" + } + ] + }, + "qi_niu_bucket_region_list": { + "description": "七牛云存储区域列表", + "type": "array", + "items": { + "$ref": "#/definitions/md.QiNiuBucketRegion" + } + } + } + }, + "md.ShareIndexResp": { + "type": "object", + "properties": { + "agent_domain": { + "type": "string", + "example": "代理分享地址" + }, + "master_id": { + "type": "string" + }, + "medium_domain": { + "type": "string", + "example": "媒体分享地址" + } + } + }, "md.UpdateAdminReq": { "type": "object", "required": [ @@ -2073,6 +2695,74 @@ "type": "integer" } } + }, + "md.WxOpenGetResp": { + "type": "object", + "properties": { + "aes_key": { + "type": "string", + "example": "消息加解密Key" + }, + "app_secret": { + "type": "string", + "example": "appSecret" + }, + "appid": { + "type": "string", + "example": "appid" + }, + "token": { + "type": "string", + "example": "消息校验Token" + }, + "wx_open_applet_server_domain": { + "type": "string", + "example": "微信开放平台-小程序服务器域名" + }, + "wx_open_authorization_event_receiving_configuration": { + "type": "string", + "example": "微信开放平台-授权事件接收配置" + }, + "wx_open_domain_of_the_initiating_page_for_login_authorization": { + "type": "string", + "example": "微信开放平台-登录授权的发起页域名" + }, + "wx_open_message_and_event_reception_configuration": { + "type": "string", + "example": "微信开放平台-消息与事件接收配置" + }, + "wx_open_white_list_ip": { + "type": "string", + "example": "微信开放平台-白名单ip" + } + } + }, + "md.WxOpenSetReq": { + "type": "object", + "required": [ + "aes_key", + "app_secret", + "appid", + "token" + ], + "properties": { + "aes_key": { + "type": "string", + "example": "消息加解密Key" + }, + "app_secret": { + "type": "string", + "example": "appSecret" + }, + "appid": { + "type": "string", + "example": "appid" + }, + "token": { + "type": "string", + "example": "消息校验Token" + } + } } }, "securityDefinitions": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 78d7e06..92aceeb 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -1,4 +1,27 @@ definitions: + hdl.WxOpenThirdPartyAppList: + properties: + aes_key: + type: string + app_secret: + type: string + appid: + type: string + component_access_token: + type: string + component_verify_ticket: + type: string + create_at: + type: string + id: + type: integer + token: + type: string + update_at: + type: string + uuid: + type: integer + type: object md.AddAdminReq: properties: memo: @@ -244,6 +267,41 @@ definitions: $ref: '#/definitions/md.SelectData' type: array type: object + md.AppletAddReq: + properties: + appid: + example: 授权小程序appid + type: string + logo: + example: 小程序logo + type: string + name: + example: 小程序名称 + type: string + original_id: + example: 授权小程序原始id + type: string + required: + - appid + - logo + - name + - original_id + type: object + md.AppletUpdateReq: + properties: + id: + type: integer + logo: + example: 小程序logo + type: string + name: + example: 小程序名称 + type: string + required: + - id + - logo + - name + type: object md.BindAdminRoleReq: properties: adm_id: @@ -427,6 +485,18 @@ definitions: $ref: '#/definitions/md.SelectData' type: array type: object + md.QiNiuBucketRegion: + properties: + region_domain: + example: 区域域名 + type: string + region_id: + example: 区域id + type: string + region_name: + example: 区域名称 + type: string + type: object md.RegisterForAgentReq: properties: code: @@ -488,6 +558,53 @@ definitions: example: 值 type: string type: object + md.SetOssReq: + properties: + file_access_key: + example: 对象存储AccessToken + type: string + file_bucket: + example: 对象存储bucket(空间) + type: string + file_bucket_host: + example: 对象存储域名 + type: string + file_bucket_region: + example: 文件所属区域 + type: string + file_secret_key: + example: 对象存储SecretToken + type: string + required: + - file_access_key + - file_bucket + - file_bucket_host + - file_bucket_region + - file_secret_key + type: object + md.SetOssResp: + properties: + data: + allOf: + - $ref: '#/definitions/md.SetOssReq' + description: 数据内容 + qi_niu_bucket_region_list: + description: 七牛云存储区域列表 + items: + $ref: '#/definitions/md.QiNiuBucketRegion' + type: array + type: object + md.ShareIndexResp: + properties: + agent_domain: + example: 代理分享地址 + type: string + master_id: + type: string + medium_domain: + example: 媒体分享地址 + type: string + type: object md.UpdateAdminReq: properties: adm_id: @@ -536,6 +653,56 @@ definitions: - role_id - state type: object + md.WxOpenGetResp: + properties: + aes_key: + example: 消息加解密Key + type: string + app_secret: + example: appSecret + type: string + appid: + example: appid + type: string + token: + example: 消息校验Token + type: string + wx_open_applet_server_domain: + example: 微信开放平台-小程序服务器域名 + type: string + wx_open_authorization_event_receiving_configuration: + example: 微信开放平台-授权事件接收配置 + type: string + wx_open_domain_of_the_initiating_page_for_login_authorization: + example: 微信开放平台-登录授权的发起页域名 + type: string + wx_open_message_and_event_reception_configuration: + example: 微信开放平台-消息与事件接收配置 + type: string + wx_open_white_list_ip: + example: 微信开放平台-白名单ip + type: string + type: object + md.WxOpenSetReq: + properties: + aes_key: + example: 消息加解密Key + type: string + app_secret: + example: appSecret + type: string + appid: + example: appid + type: string + token: + example: 消息校验Token + type: string + required: + - aes_key + - app_secret + - appid + - token + type: object host: localhost:1002 or xxxx.advertisement.dengbiao.top info: contact: @@ -1366,6 +1533,280 @@ paths: summary: 修改角色状态 tags: - 权限管理 + /api/setCenter/applet/add: + post: + consumes: + - application/json + description: 小程序设置-新增 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + - description: 请求参数 + in: body + name: args + required: true + schema: + $ref: '#/definitions/md.AppletAddReq' + produces: + - application/json + responses: + "200": + description: success + schema: + type: string + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 新增 + tags: + - 设置中心-小程序设置 + /api/setCenter/applet/authorize: + get: + consumes: + - application/json + description: 设置中心-基础设置 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: 微信授权界面url + schema: + type: string + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 设置中心-基础设置-微信三方应用获取 + tags: + - 设置中心 + /api/setCenter/applet/list: + get: + consumes: + - application/json + description: 小程序设置-列表 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/hdl.WxOpenThirdPartyAppList' + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 列表 + tags: + - 设置中心-小程序设置 + /api/setCenter/applet/unauthorized: + get: + consumes: + - application/json + description: 设置中心-基础设置 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: success + schema: + type: string + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 设置中心-基础设置-微信三方应用获取 + tags: + - 设置中心 + /api/setCenter/applet/update: + post: + consumes: + - application/json + description: 小程序设置-更新 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + - description: 请求参数 + in: body + name: args + required: true + schema: + $ref: '#/definitions/md.AppletUpdateReq' + produces: + - application/json + responses: + "200": + description: success + schema: + type: string + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 更新 + tags: + - 设置中心-小程序设置 + /api/setCenter/basic/getOss: + get: + consumes: + - application/json + description: 基础设置-oss获取 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/md.SetOssResp' + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: oss获取 + tags: + - 设置中心-基础设置 + /api/setCenter/basic/setOss: + post: + consumes: + - application/json + description: 基础设置-oss设置 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + - description: 请求参数 + in: body + name: args + required: true + schema: + $ref: '#/definitions/md.SetOssReq' + produces: + - application/json + responses: + "200": + description: success + schema: + type: string + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: oss设置 + tags: + - 设置中心-基础设置 + /api/setCenter/basic/wxOpenGet: + get: + consumes: + - application/json + description: 基础设置-微信三方应用获取 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/md.WxOpenGetResp' + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 微信三方应用获取 + tags: + - 设置中心-基础设置 + /api/setCenter/basic/wxOpenSet: + post: + consumes: + - application/json + description: 基础设置-微信三方应用设置 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + - description: 请求参数 + in: body + name: args + required: true + schema: + $ref: '#/definitions/md.WxOpenSetReq' + produces: + - application/json + responses: + "200": + description: success + schema: + type: string + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 微信三方应用设置 + tags: + - 设置中心-基础设置 + /api/setCenter/share/index: + get: + consumes: + - application/json + description: 邀请链接界面接口 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/md.ShareIndexResp' + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 邀请链接 + tags: + - 设置中心-邀请链接 /role/permissionGroupList: get: consumes: @@ -1396,6 +1837,31 @@ paths: summary: 权限组列表 tags: - 权限管理 + /v1/banner/delete/{$id}: + delete: + consumes: + - application/json + description: 小程序设置-删除 + parameters: + - description: 验证参数Bearer和token空格拼接 + in: header + name: Authorization + required: true + type: string + produces: + - application/json + responses: + "200": + description: success + schema: + type: string + "400": + description: 具体错误 + schema: + $ref: '#/definitions/md.Response' + summary: 删除 + tags: + - 设置中心-小程序设置 securityDefinitions: MasterID: in: header diff --git a/go.mod b/go.mod index d53cee1..75cb412 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 //replace code.fnuoos.com/zhimeng/model.git => E:/company/ad/models require ( - code.fnuoos.com/zhimeng/model.git v0.0.3-0.20240820125928-6ce4c06dda24 + code.fnuoos.com/zhimeng/model.git v0.0.3-0.20240822024421-0129770e24d7 github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 github.com/boombuler/barcode v1.0.1 github.com/dchest/uniuri v0.0.0-20200228104902-7aecb25e1fe5