From 04d61a2fc7f35e9c66f5be8333402f1810c94b93 Mon Sep 17 00:00:00 2001 From: Espoir <450646331@qq.com> Date: Thu, 26 Aug 2021 21:10:13 +0800 Subject: [PATCH 1/9] feat(): notify dingding --- server/config.yaml | 23 +++-- server/config/config.go | 15 ++-- server/config/dingding.go | 7 ++ server/initialize/router.go | 8 ++ server/plugin/notify/README.MD | 14 +++ server/plugin/notify/api/api.go | 21 +++++ server/plugin/notify/api/enter.go | 7 ++ server/plugin/notify/config/dingding.go | 7 ++ server/plugin/notify/global/gloabl.go | 5 ++ server/plugin/notify/main.go | 28 ++++++ server/plugin/notify/router/enter.go | 7 ++ server/plugin/notify/router/router.go | 18 ++++ server/plugin/notify/service/enter.go | 7 ++ server/plugin/notify/service/notify.go | 114 ++++++++++++++++++++++++ server/plugin/notify/utils/utils.go | 1 + 15 files changed, 266 insertions(+), 16 deletions(-) create mode 100644 server/config/dingding.go create mode 100644 server/plugin/notify/README.MD create mode 100644 server/plugin/notify/api/api.go create mode 100644 server/plugin/notify/api/enter.go create mode 100644 server/plugin/notify/config/dingding.go create mode 100644 server/plugin/notify/global/gloabl.go create mode 100644 server/plugin/notify/main.go create mode 100644 server/plugin/notify/router/enter.go create mode 100644 server/plugin/notify/router/router.go create mode 100644 server/plugin/notify/service/enter.go create mode 100644 server/plugin/notify/service/notify.go create mode 100644 server/plugin/notify/utils/utils.go diff --git a/server/config.yaml b/server/config.yaml index 66a4cf9e..19b1d78b 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -34,6 +34,11 @@ email: secret: 'xxx' nickname: 'test' +dingding: + url: 'https://oapi.dingtalk.com/robot/send' + secret: 'SEC38425b7bd57c6bca9ce20611c41b437994ed65e0ddbd42e840ffa7a8c7da2106' + token: '77d18293e221b3b7bdae7330d19a213c3cbb20fa07de5f4c273c0363ae475c34' + # casbin configuration casbin: model-path: './resource/rbac_model.conf' @@ -55,15 +60,15 @@ captcha: # mysql connect configuration # 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://www.github.com/flipped-aurora/gin-vue-admin/server.com/docs/first) mysql: - path: '' - config: '' - db-name: '' - username: '' - password: '' - max-idle-conns: 10 - max-open-conns: 100 - log-mode: false - log-zap: "" + path: 8.141.51.112:3306 + config: charset=utf8mb4&parseTime=True&loc=Local + db-name: gva + username: root + password: 768f952daae626d9 + max-idle-conns: 0 + max-open-conns: 0 + log-mode: "" + log-zap: false # local configuration local: diff --git a/server/config/config.go b/server/config/config.go index 83d256f4..196823d6 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -1,13 +1,14 @@ package config type Server struct { - JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"` - Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"` - Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"` - Email Email `mapstructure:"email" json:"email" yaml:"email"` - Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"` - System System `mapstructure:"system" json:"system" yaml:"system"` - Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"` + JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"` + Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"` + Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"` + Email Email `mapstructure:"email" json:"email" yaml:"email"` + DingDing DingDing `mapstructure:"dingding" json:"dingding" yaml:"dingding"` + Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"` + System System `mapstructure:"system" json:"system" yaml:"system"` + Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"` // auto AutoCode Autocode `mapstructure:"autoCode" json:"autoCode" yaml:"autoCode"` // gorm diff --git a/server/config/dingding.go b/server/config/dingding.go new file mode 100644 index 00000000..3a47f99f --- /dev/null +++ b/server/config/dingding.go @@ -0,0 +1,7 @@ +package config + +type DingDing struct { + Url string `mapstructure:"url" json:"url" yaml:"url"` // 发件人 你自己要发邮件的邮箱 + Token string `mapstructure:"token" json:"token" yaml:"token"` // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议 + Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥 +} diff --git a/server/initialize/router.go b/server/initialize/router.go index 0dcb61e8..7a40befe 100644 --- a/server/initialize/router.go +++ b/server/initialize/router.go @@ -4,6 +4,7 @@ import ( //email "github.com/flipped-aurora/gva-plug-email" // 在线仓库模式 "github.com/flipped-aurora/gin-vue-admin/server/plugin/email" // 本地插件仓库地址模式 "github.com/flipped-aurora/gin-vue-admin/server/plugin/example_plugin" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify" "net/http" _ "github.com/flipped-aurora/gin-vue-admin/server/docs" @@ -65,6 +66,13 @@ func Routers() *gin.Engine { // 添加开放权限的插件 示例 PluginInit(PublicGroup, example_plugin.ExamplePlugin) + // 钉钉通知,暂时开放权限 + PluginInit(PublicGroup, notify.CreateDDPlug( + global.GVA_CONFIG.DingDing.Url, + global.GVA_CONFIG.DingDing.Secret, + global.GVA_CONFIG.DingDing.Token, + )) + // 添加跟角色挂钩权限的插件 示例 本地示例模式于在线仓库模式注意上方的import 可以自行切换 效果相同 PluginInit(PrivateGroup, email.CreateEmailPlug( global.GVA_CONFIG.Email.To, diff --git a/server/plugin/notify/README.MD b/server/plugin/notify/README.MD new file mode 100644 index 00000000..f85799ce --- /dev/null +++ b/server/plugin/notify/README.MD @@ -0,0 +1,14 @@ +## GVA 钉钉群通知插件 + +### 使用步骤 + +#### 1. + +config.yaml 文件中配置钉钉通知的URL ,Token 等 + +#### 2. 配置说明 + + + +### 方法API + diff --git a/server/plugin/notify/api/api.go b/server/plugin/notify/api/api.go new file mode 100644 index 00000000..3320575f --- /dev/null +++ b/server/plugin/notify/api/api.go @@ -0,0 +1,21 @@ +package api + +import ( + "github.com/flipped-aurora/gin-vue-admin/server/global" + "github.com/flipped-aurora/gin-vue-admin/server/model/common/response" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/service" + "github.com/gin-gonic/gin" + "go.uber.org/zap" +) + +type Api struct { +} + +func (s *Api) NotifyController(c *gin.Context) { + if err := service.ServiceGroupApp.Send(); err != nil { + global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) + response.FailWithMessage("发送失败", c) + } else { + response.OkWithData("发送成功", c) + } +} diff --git a/server/plugin/notify/api/enter.go b/server/plugin/notify/api/enter.go new file mode 100644 index 00000000..5fe286c1 --- /dev/null +++ b/server/plugin/notify/api/enter.go @@ -0,0 +1,7 @@ +package api + +type ApiGroup struct { + Api +} + +var ApiGroupApp = new(ApiGroup) diff --git a/server/plugin/notify/config/dingding.go b/server/plugin/notify/config/dingding.go new file mode 100644 index 00000000..9cf0d24d --- /dev/null +++ b/server/plugin/notify/config/dingding.go @@ -0,0 +1,7 @@ +package config + +type DingDing struct { + Url string `mapstructure:"url" json:"url" yaml:"url"` // Url + Token string `mapstructure:"token" json:"token" yaml:"token"` // Token + Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 +} diff --git a/server/plugin/notify/global/gloabl.go b/server/plugin/notify/global/gloabl.go new file mode 100644 index 00000000..dd7033ab --- /dev/null +++ b/server/plugin/notify/global/gloabl.go @@ -0,0 +1,5 @@ +package global + +import "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/config" + +var GlobalConfig = new(config.DingDing) diff --git a/server/plugin/notify/main.go b/server/plugin/notify/main.go new file mode 100644 index 00000000..6b07158c --- /dev/null +++ b/server/plugin/notify/main.go @@ -0,0 +1,28 @@ +package notify + +import ( + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/global" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/router" + "github.com/gin-gonic/gin" +) + +type ddPlugin struct { + Secret string + Token string + Url string +} + +func CreateDDPlug(Url string, Secret string, Token string) *ddPlugin { + global.GlobalConfig.Secret = Secret + global.GlobalConfig.Token = Token + global.GlobalConfig.Url = Url + return &ddPlugin{} +} + +func (*ddPlugin) Register(group *gin.RouterGroup) { + router.RouterGroupApp.InitRouter(group) +} + +func (*ddPlugin) RouterPath() string { + return "notify" +} diff --git a/server/plugin/notify/router/enter.go b/server/plugin/notify/router/enter.go new file mode 100644 index 00000000..30aca42c --- /dev/null +++ b/server/plugin/notify/router/enter.go @@ -0,0 +1,7 @@ +package router + +type RouterGroup struct { + NotifyRouter +} + +var RouterGroupApp = new(RouterGroup) diff --git a/server/plugin/notify/router/router.go b/server/plugin/notify/router/router.go new file mode 100644 index 00000000..c9ea140b --- /dev/null +++ b/server/plugin/notify/router/router.go @@ -0,0 +1,18 @@ +package router + +import ( + "github.com/flipped-aurora/gin-vue-admin/server/middleware" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/api" + "github.com/gin-gonic/gin" +) + +type NotifyRouter struct { +} + +func (s *NotifyRouter) InitRouter(Router *gin.RouterGroup) { + emailRouter := Router.Use(middleware.OperationRecord()) + var Controller = api.ApiGroupApp.Api.NotifyController + { + emailRouter.POST("dingding", Controller) + } +} diff --git a/server/plugin/notify/service/enter.go b/server/plugin/notify/service/enter.go new file mode 100644 index 00000000..0eb00088 --- /dev/null +++ b/server/plugin/notify/service/enter.go @@ -0,0 +1,7 @@ +package service + +type ServiceGroup struct { + NotifyService +} + +var ServiceGroupApp = new(ServiceGroup) diff --git a/server/plugin/notify/service/notify.go b/server/plugin/notify/service/notify.go new file mode 100644 index 00000000..3d7ea361 --- /dev/null +++ b/server/plugin/notify/service/notify.go @@ -0,0 +1,114 @@ +package service + +import ( + "bytes" + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "encoding/json" + "fmt" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/global" + "io/ioutil" + "net/http" + "net/url" + "time" +) + +type NotifyService struct { +} + +func SendTextMessage(content string) error { + msg := map[string]interface{}{ + "msgtype": "text", + "text": map[string]string{ + "content": content, + }, + //"at": map[string]interface{}{ + // "atMobiles": atMobiles, + // "isAtAll": isAtAll, + //}, + } + return SendMessage(msg) +} + +func SendMessage(msg interface{}) error { + body := bytes.NewBuffer(nil) + err := json.NewEncoder(body).Encode(msg) + if err != nil { + return fmt.Errorf("msg json failed, msg: %v, err: %v", msg, err.Error()) + } + + value := url.Values{} + value.Set("access_token", global.GlobalConfig.Token) + if global.GlobalConfig.Secret != "" { + t := time.Now().UnixNano() / 1e6 + value.Set("timestamp", fmt.Sprintf("%d", t)) + value.Set("sign", sign(t, global.GlobalConfig.Secret)) + } + + request, err := http.NewRequest(http.MethodPost, global.GlobalConfig.Url, body) + if err != nil { + return fmt.Errorf("error request: %v", err.Error()) + } + request.URL.RawQuery = value.Encode() + request.Header.Add("Content-Type", "application/json") + res, err := (&http.Client{}).Do(request) + if err != nil { + return fmt.Errorf("send dingTalk message failed, error: %v", err.Error()) + } + defer func() { _ = res.Body.Close() }() + result, err := ioutil.ReadAll(res.Body) + + if res.StatusCode != 200 { + return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, "http code is not 200")) + } + if err != nil { + return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, err.Error())) + } + + type response struct { + ErrCode int `json:"errcode"` + } + var ret response + + if err := json.Unmarshal(result, &ret); err != nil { + return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, err.Error())) + } + + if ret.ErrCode != 0 { + return fmt.Errorf("send dingTalk message failed, %s", httpError(request, res, result, "errcode is not 0")) + } + + return nil +} + +func httpError(request *http.Request, response *http.Response, body []byte, error string) string { + return fmt.Sprintf( + "http request failure, error: %s, status code: %d, %s %s, body:\n%s", + error, + response.StatusCode, + request.Method, + request.URL.String(), + string(body), + ) +} +func sign(t int64, secret string) string { + strToHash := fmt.Sprintf("%d\n%s", t, secret) + hmac256 := hmac.New(sha256.New, []byte(secret)) + hmac256.Write([]byte(strToHash)) + data := hmac256.Sum(nil) + return base64.StdEncoding.EncodeToString(data) +} + +//@author: [Espoir](https://github.com/nightsimon) +//@function: NotifyController +//@description: 钉钉通知测试 +//@return: err error + +func (e *NotifyService) Send() (err error) { + err = SendTextMessage("test") + if err != nil { + return err + } + return err +} diff --git a/server/plugin/notify/utils/utils.go b/server/plugin/notify/utils/utils.go new file mode 100644 index 00000000..d4b585bf --- /dev/null +++ b/server/plugin/notify/utils/utils.go @@ -0,0 +1 @@ +package utils From 6f30c8576ffc79b707979e51313210edb97d2f2c Mon Sep 17 00:00:00 2001 From: Espoir <450646331@qq.com> Date: Thu, 26 Aug 2021 21:31:00 +0800 Subject: [PATCH 2/9] fix(): fix config --- server/config.yaml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/server/config.yaml b/server/config.yaml index 19b1d78b..2f5ad5dd 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -60,15 +60,15 @@ captcha: # mysql connect configuration # 未初始化之前请勿手动修改数据库信息!!!如果一定要手动初始化请看(https://www.github.com/flipped-aurora/gin-vue-admin/server.com/docs/first) mysql: - path: 8.141.51.112:3306 - config: charset=utf8mb4&parseTime=True&loc=Local - db-name: gva - username: root - password: 768f952daae626d9 - max-idle-conns: 0 - max-open-conns: 0 - log-mode: "" - log-zap: false + path: '' + config: '' + db-name: '' + username: '' + password: '' + max-idle-conns: 10 + max-open-conns: 100 + log-mode: false + log-zap: "" # local configuration local: From 60a95797b22f39816da9c06a272cc173279dda3b Mon Sep 17 00:00:00 2001 From: Espoir <450646331@qq.com> Date: Thu, 26 Aug 2021 22:44:36 +0800 Subject: [PATCH 3/9] =?UTF-8?q?fix():=20=E9=92=89=E9=92=89=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E5=8F=96=E6=B6=88=E5=85=A8=E5=B1=80=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/config.yaml | 5 ----- server/config/config.go | 15 +++++++-------- server/config/dingding.go | 7 ------- server/initialize/router.go | 6 +----- server/plugin/notify/global/gloabl.go | 5 ----- server/plugin/notify/global/global.go | 9 +++++++++ server/plugin/notify/main.go | 6 +----- server/plugin/notify/service/notify.go | 8 ++++---- 8 files changed, 22 insertions(+), 39 deletions(-) delete mode 100644 server/config/dingding.go delete mode 100644 server/plugin/notify/global/gloabl.go create mode 100644 server/plugin/notify/global/global.go diff --git a/server/config.yaml b/server/config.yaml index 2f5ad5dd..66a4cf9e 100644 --- a/server/config.yaml +++ b/server/config.yaml @@ -34,11 +34,6 @@ email: secret: 'xxx' nickname: 'test' -dingding: - url: 'https://oapi.dingtalk.com/robot/send' - secret: 'SEC38425b7bd57c6bca9ce20611c41b437994ed65e0ddbd42e840ffa7a8c7da2106' - token: '77d18293e221b3b7bdae7330d19a213c3cbb20fa07de5f4c273c0363ae475c34' - # casbin configuration casbin: model-path: './resource/rbac_model.conf' diff --git a/server/config/config.go b/server/config/config.go index 196823d6..83d256f4 100644 --- a/server/config/config.go +++ b/server/config/config.go @@ -1,14 +1,13 @@ package config type Server struct { - JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"` - Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"` - Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"` - Email Email `mapstructure:"email" json:"email" yaml:"email"` - DingDing DingDing `mapstructure:"dingding" json:"dingding" yaml:"dingding"` - Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"` - System System `mapstructure:"system" json:"system" yaml:"system"` - Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"` + JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"` + Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"` + Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"` + Email Email `mapstructure:"email" json:"email" yaml:"email"` + Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"` + System System `mapstructure:"system" json:"system" yaml:"system"` + Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"` // auto AutoCode Autocode `mapstructure:"autoCode" json:"autoCode" yaml:"autoCode"` // gorm diff --git a/server/config/dingding.go b/server/config/dingding.go deleted file mode 100644 index 3a47f99f..00000000 --- a/server/config/dingding.go +++ /dev/null @@ -1,7 +0,0 @@ -package config - -type DingDing struct { - Url string `mapstructure:"url" json:"url" yaml:"url"` // 发件人 你自己要发邮件的邮箱 - Token string `mapstructure:"token" json:"token" yaml:"token"` // 服务器地址 例如 smtp.qq.com 请前往QQ或者你要发邮件的邮箱查看其smtp协议 - Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 用于登录的密钥 最好不要用邮箱密码 去邮箱smtp申请一个用于登录的密钥 -} diff --git a/server/initialize/router.go b/server/initialize/router.go index 7a40befe..7687d83f 100644 --- a/server/initialize/router.go +++ b/server/initialize/router.go @@ -67,11 +67,7 @@ func Routers() *gin.Engine { PluginInit(PublicGroup, example_plugin.ExamplePlugin) // 钉钉通知,暂时开放权限 - PluginInit(PublicGroup, notify.CreateDDPlug( - global.GVA_CONFIG.DingDing.Url, - global.GVA_CONFIG.DingDing.Secret, - global.GVA_CONFIG.DingDing.Token, - )) + PluginInit(PublicGroup, notify.CreateDDPlug()) // 添加跟角色挂钩权限的插件 示例 本地示例模式于在线仓库模式注意上方的import 可以自行切换 效果相同 PluginInit(PrivateGroup, email.CreateEmailPlug( diff --git a/server/plugin/notify/global/gloabl.go b/server/plugin/notify/global/gloabl.go deleted file mode 100644 index dd7033ab..00000000 --- a/server/plugin/notify/global/gloabl.go +++ /dev/null @@ -1,5 +0,0 @@ -package global - -import "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/config" - -var GlobalConfig = new(config.DingDing) diff --git a/server/plugin/notify/global/global.go b/server/plugin/notify/global/global.go new file mode 100644 index 00000000..376f7ef8 --- /dev/null +++ b/server/plugin/notify/global/global.go @@ -0,0 +1,9 @@ +package global + +import "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/config" + +var GlobalConfig_ = &config.DingDing{ + Url: "https://oapi.dingtalk.com/robot/send", + Token: "77d18293e221b3b7bdae7330d19a213c3cbb20fa07de5f4c273c0363ae475c34", + Secret: "SEC38425b7bd57c6bca9ce20611c41b437994ed65e0ddbd42e840ffa7a8c7da2106", +} diff --git a/server/plugin/notify/main.go b/server/plugin/notify/main.go index 6b07158c..5813b6ce 100644 --- a/server/plugin/notify/main.go +++ b/server/plugin/notify/main.go @@ -1,7 +1,6 @@ package notify import ( - "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/global" "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/router" "github.com/gin-gonic/gin" ) @@ -12,10 +11,7 @@ type ddPlugin struct { Url string } -func CreateDDPlug(Url string, Secret string, Token string) *ddPlugin { - global.GlobalConfig.Secret = Secret - global.GlobalConfig.Token = Token - global.GlobalConfig.Url = Url +func CreateDDPlug() *ddPlugin { return &ddPlugin{} } diff --git a/server/plugin/notify/service/notify.go b/server/plugin/notify/service/notify.go index 3d7ea361..ab992e96 100644 --- a/server/plugin/notify/service/notify.go +++ b/server/plugin/notify/service/notify.go @@ -39,14 +39,14 @@ func SendMessage(msg interface{}) error { } value := url.Values{} - value.Set("access_token", global.GlobalConfig.Token) - if global.GlobalConfig.Secret != "" { + value.Set("access_token", global.GlobalConfig_.Token) + if global.GlobalConfig_.Secret != "" { t := time.Now().UnixNano() / 1e6 value.Set("timestamp", fmt.Sprintf("%d", t)) - value.Set("sign", sign(t, global.GlobalConfig.Secret)) + value.Set("sign", sign(t, global.GlobalConfig_.Secret)) } - request, err := http.NewRequest(http.MethodPost, global.GlobalConfig.Url, body) + request, err := http.NewRequest(http.MethodPost, global.GlobalConfig_.Url, body) if err != nil { return fmt.Errorf("error request: %v", err.Error()) } From 333ccb5ab6a3eaca7a3272bfdcbbfee517218c2c Mon Sep 17 00:00:00 2001 From: Espoir <450646331@qq.com> Date: Thu, 26 Aug 2021 22:58:29 +0800 Subject: [PATCH 4/9] docs(): update readme --- server/plugin/notify/README.MD | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/server/plugin/notify/README.MD b/server/plugin/notify/README.MD index f85799ce..ee856c84 100644 --- a/server/plugin/notify/README.MD +++ b/server/plugin/notify/README.MD @@ -1,14 +1,28 @@ ## GVA 钉钉群通知插件 +本插件用户向钉钉群推送消息 + ### 使用步骤 -#### 1. +#### 1. 使用说明 + +- 当服务运行异常时,可以向钉钉推送异常信息,便于及时发现解决问题 +- 推送一些关键业务的运行日志等 -config.yaml 文件中配置钉钉通知的URL ,Token 等 #### 2. 配置说明 +钉钉 token 等相关信息的获取,请参考 [钉钉官网](https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.7f8710afbfzduV#topic-2026027) + +在`plugin/notify/global/global.go` 文件中配置钉钉通知的URL ,Token 等 +```go +var GlobalConfig_ = &config.DingDing{ + Url: "https://oapi.dingtalk.com/robot/send", + Token: "xxx", + Secret: "xxx", +} +``` ### 方法API From 83db3eeb49ff20ac433807ff41d1879113c8de10 Mon Sep 17 00:00:00 2001 From: Espoir <450646331@qq.com> Date: Thu, 26 Aug 2021 23:05:18 +0800 Subject: [PATCH 5/9] docs(): update readme --- server/plugin/notify/README.MD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/plugin/notify/README.MD b/server/plugin/notify/README.MD index ee856c84..174110a8 100644 --- a/server/plugin/notify/README.MD +++ b/server/plugin/notify/README.MD @@ -1,6 +1,6 @@ ## GVA 钉钉群通知插件 -本插件用户向钉钉群推送消息 +本插件用于向钉钉群推送消息 ### 使用步骤 From b88fb9841f5ce42bf3ce30b6401f04e857736896 Mon Sep 17 00:00:00 2001 From: Espoir <450646331@qq.com> Date: Thu, 26 Aug 2021 23:12:11 +0800 Subject: [PATCH 6/9] docs(): update readme --- server/plugin/notify/README.MD | 20 +++++++++++++++----- server/plugin/notify/api/api.go | 2 +- server/plugin/notify/service/notify.go | 20 ++++++-------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/server/plugin/notify/README.MD b/server/plugin/notify/README.MD index 174110a8..b0b5cc19 100644 --- a/server/plugin/notify/README.MD +++ b/server/plugin/notify/README.MD @@ -2,15 +2,12 @@ 本插件用于向钉钉群推送消息 -### 使用步骤 - -#### 1. 使用说明 +### 1. 使用场景 - 当服务运行异常时,可以向钉钉推送异常信息,便于及时发现解决问题 - 推送一些关键业务的运行日志等 - -#### 2. 配置说明 +### 2. 配置说明 钉钉 token 等相关信息的获取,请参考 [钉钉官网](https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.7f8710afbfzduV#topic-2026027) @@ -23,6 +20,19 @@ var GlobalConfig_ = &config.DingDing{ Secret: "xxx", } ``` +### 3. 使用说明 + +在代码中调用 `SendTextMessage` 方法即可 +```go +func NotifyController(c *gin.Context) { + if err := service.ServiceGroupApp.SendTextMessage("test"); err != nil { + global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) + response.FailWithMessage("发送失败", c) + } else { + response.OkWithData("发送成功", c) + } +} +``` ### 方法API diff --git a/server/plugin/notify/api/api.go b/server/plugin/notify/api/api.go index 3320575f..4874a814 100644 --- a/server/plugin/notify/api/api.go +++ b/server/plugin/notify/api/api.go @@ -12,7 +12,7 @@ type Api struct { } func (s *Api) NotifyController(c *gin.Context) { - if err := service.ServiceGroupApp.Send(); err != nil { + if err := service.ServiceGroupApp.SendTextMessage("test"); err != nil { global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) response.FailWithMessage("发送失败", c) } else { diff --git a/server/plugin/notify/service/notify.go b/server/plugin/notify/service/notify.go index ab992e96..7011d1ad 100644 --- a/server/plugin/notify/service/notify.go +++ b/server/plugin/notify/service/notify.go @@ -17,7 +17,12 @@ import ( type NotifyService struct { } -func SendTextMessage(content string) error { +//@author: [Espoir](https://github.com/nightsimon) +//@function: NotifyController +//@description: 钉钉通知测试 +//@return: err error + +func (e *NotifyService) SendTextMessage(content string) error { msg := map[string]interface{}{ "msgtype": "text", "text": map[string]string{ @@ -99,16 +104,3 @@ func sign(t int64, secret string) string { data := hmac256.Sum(nil) return base64.StdEncoding.EncodeToString(data) } - -//@author: [Espoir](https://github.com/nightsimon) -//@function: NotifyController -//@description: 钉钉通知测试 -//@return: err error - -func (e *NotifyService) Send() (err error) { - err = SendTextMessage("test") - if err != nil { - return err - } - return err -} From b90f061dc9016e15cd6012d6e828b491bacffe6b Mon Sep 17 00:00:00 2001 From: Espoir <450646331@qq.com> Date: Thu, 26 Aug 2021 23:32:24 +0800 Subject: [PATCH 7/9] fix(): update --- server/plugin/notify/router/router.go | 4 ++-- server/plugin/notify/service/notify.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/plugin/notify/router/router.go b/server/plugin/notify/router/router.go index c9ea140b..61842b5e 100644 --- a/server/plugin/notify/router/router.go +++ b/server/plugin/notify/router/router.go @@ -10,9 +10,9 @@ type NotifyRouter struct { } func (s *NotifyRouter) InitRouter(Router *gin.RouterGroup) { - emailRouter := Router.Use(middleware.OperationRecord()) + router := Router.Use(middleware.OperationRecord()) var Controller = api.ApiGroupApp.Api.NotifyController { - emailRouter.POST("dingding", Controller) + router.POST("dingding", Controller) } } diff --git a/server/plugin/notify/service/notify.go b/server/plugin/notify/service/notify.go index 7011d1ad..e21508d1 100644 --- a/server/plugin/notify/service/notify.go +++ b/server/plugin/notify/service/notify.go @@ -22,7 +22,7 @@ type NotifyService struct { //@description: 钉钉通知测试 //@return: err error -func (e *NotifyService) SendTextMessage(content string) error { +func (e *NotifyService) SendTextMessage(content string) (err error) { msg := map[string]interface{}{ "msgtype": "text", "text": map[string]string{ From 904149700a64276e8ba4cdceb4fbae49bb94dd33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=92=8B=E5=90=89=E5=85=86?= <303176530@qq.com> Date: Sat, 28 Aug 2021 00:00:08 +0800 Subject: [PATCH 8/9] =?UTF-8?q?=E6=8F=92=E4=BB=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/initialize/plugin.go | 7 +++++ server/initialize/router.go | 25 --------------- server/plugin/notify/README.MD | 41 ++++++++++++++++++++----- server/plugin/notify/api/api.go | 5 +-- server/plugin/notify/config/dingding.go | 2 +- server/plugin/notify/global/global.go | 6 +--- server/plugin/notify/main.go | 6 +++- server/plugin/notify/router/router.go | 4 +-- server/plugin/notify/service/notify.go | 40 +++++++++++++++++++++--- 9 files changed, 88 insertions(+), 48 deletions(-) diff --git a/server/initialize/plugin.go b/server/initialize/plugin.go index 02f6f1b9..00bbc54f 100644 --- a/server/initialize/plugin.go +++ b/server/initialize/plugin.go @@ -2,6 +2,7 @@ package initialize import ( "github.com/flipped-aurora/gin-vue-admin/server/global" + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify" //email "github.com/flipped-aurora/gva-plug-email" // 在线仓库模式 "github.com/flipped-aurora/gin-vue-admin/server/plugin/email" // 本地插件仓库地址模式 "github.com/flipped-aurora/gin-vue-admin/server/plugin/example_plugin" @@ -30,4 +31,10 @@ func InstallPlugin(PublicGroup *gin.RouterGroup, PrivateGroup *gin.RouterGroup) global.GVA_CONFIG.Email.Port, global.GVA_CONFIG.Email.IsSSL, )) + + // 钉钉通知,暂时开放权限 + PluginInit(PublicGroup, notify.CreateDDPlug( + "https://oapi.dingtalk.com/robot/send", + "8ded23f91917dc4f6275f44ba5ef243e6ed1d2cc74de83f01a6f5f5f39905671", + "SECaecf452bd6e671ab0d47469c3ad933e32fcc47b335333049a1b8961606192f38")) } diff --git a/server/initialize/router.go b/server/initialize/router.go index 3b856420..d04ced5b 100644 --- a/server/initialize/router.go +++ b/server/initialize/router.go @@ -1,12 +1,6 @@ package initialize import ( - - //email "github.com/flipped-aurora/gva-plug-email" // 在线仓库模式 - "github.com/flipped-aurora/gin-vue-admin/server/plugin/email" // 本地插件仓库地址模式 - "github.com/flipped-aurora/gin-vue-admin/server/plugin/example_plugin" - "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify" - "net/http" _ "github.com/flipped-aurora/gin-vue-admin/server/docs" @@ -64,27 +58,8 @@ func Routers() *gin.Engine { // Code generated by github.com/flipped-aurora/gin-vue-admin/server End; DO NOT EDIT. } - - // 添加开放权限的插件 示例 - PluginInit(PublicGroup, example_plugin.ExamplePlugin) - - // 钉钉通知,暂时开放权限 - PluginInit(PublicGroup, notify.CreateDDPlug()) - - // 添加跟角色挂钩权限的插件 示例 本地示例模式于在线仓库模式注意上方的import 可以自行切换 效果相同 - PluginInit(PrivateGroup, email.CreateEmailPlug( - global.GVA_CONFIG.Email.To, - global.GVA_CONFIG.Email.From, - global.GVA_CONFIG.Email.Host, - global.GVA_CONFIG.Email.Secret, - global.GVA_CONFIG.Email.Nickname, - global.GVA_CONFIG.Email.Port, - global.GVA_CONFIG.Email.IsSSL, - )) - InstallPlugin(PublicGroup, PrivateGroup) // 安装插件 - global.GVA_LOG.Info("router register success") return Router } diff --git a/server/plugin/notify/README.MD b/server/plugin/notify/README.MD index b0b5cc19..e2e28e73 100644 --- a/server/plugin/notify/README.MD +++ b/server/plugin/notify/README.MD @@ -14,18 +14,45 @@ 在`plugin/notify/global/global.go` 文件中配置钉钉通知的URL ,Token 等 ```go -var GlobalConfig_ = &config.DingDing{ - Url: "https://oapi.dingtalk.com/robot/send", - Token: "xxx", - Secret: "xxx", + // 在gin-vue-admin 主程序的initialize中的plugin的InstallPlugin 函数中写入如下代码 + PluginInit(PublicGroup, notify.CreateDDPlug( + URL, + Token, + 密钥)) } ``` -### 3. 使用说明 +### 3方法API +```go + +可调用方法 +//content 发送的内容 +//atMobiles 需要艾特的人的手机号 +//isAtAll 是否艾特全体 +SendTextMessage(content string,atMobiles []string,isAtAll bool) + +//content 发送的内容 +//title 内容标题 +//picUrl 配图 +//messageUrl 点击跳转路径 +//atMobiles 需要艾特的人的手机号 +//isAtAll 是否艾特全体 +SendLinkMessage(content,title,picUrl,messageUrl string) + +//content 发送的内容(markdown语法) +//title 内容标题 +//atMobiles 需要艾特的人的手机号 +//isAtAll 是否艾特全体 +SendMarkdownMessage(content,title string,atMobiles []string,isAtAll bool) + +``` + +### 4. 使用示例 在代码中调用 `SendTextMessage` 方法即可 ```go +// 示例 func NotifyController(c *gin.Context) { - if err := service.ServiceGroupApp.SendTextMessage("test"); err != nil { + if err := service.ServiceGroupApp.SendTextMessage("test",[]string{"手机号"},是否艾特全体); err != nil { global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) response.FailWithMessage("发送失败", c) } else { @@ -34,5 +61,5 @@ func NotifyController(c *gin.Context) { } ``` -### 方法API + diff --git a/server/plugin/notify/api/api.go b/server/plugin/notify/api/api.go index 4874a814..54782ea0 100644 --- a/server/plugin/notify/api/api.go +++ b/server/plugin/notify/api/api.go @@ -11,8 +11,9 @@ import ( type Api struct { } -func (s *Api) NotifyController(c *gin.Context) { - if err := service.ServiceGroupApp.SendTextMessage("test"); err != nil { +// +func (s *Api) SendTextMessage(c *gin.Context) { + if err := service.ServiceGroupApp.SendTextMessage("notify", []string{}, false); err != nil { global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) response.FailWithMessage("发送失败", c) } else { diff --git a/server/plugin/notify/config/dingding.go b/server/plugin/notify/config/dingding.go index 9cf0d24d..7ce67b1f 100644 --- a/server/plugin/notify/config/dingding.go +++ b/server/plugin/notify/config/dingding.go @@ -2,6 +2,6 @@ package config type DingDing struct { Url string `mapstructure:"url" json:"url" yaml:"url"` // Url - Token string `mapstructure:"token" json:"token" yaml:"token"` // Token + Token string `mapstructure:"token" json:"token" yaml:"token"` // access_token Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 } diff --git a/server/plugin/notify/global/global.go b/server/plugin/notify/global/global.go index 376f7ef8..12e15ca4 100644 --- a/server/plugin/notify/global/global.go +++ b/server/plugin/notify/global/global.go @@ -2,8 +2,4 @@ package global import "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/config" -var GlobalConfig_ = &config.DingDing{ - Url: "https://oapi.dingtalk.com/robot/send", - Token: "77d18293e221b3b7bdae7330d19a213c3cbb20fa07de5f4c273c0363ae475c34", - Secret: "SEC38425b7bd57c6bca9ce20611c41b437994ed65e0ddbd42e840ffa7a8c7da2106", -} +var GlobalConfig_ = &config.DingDing{} diff --git a/server/plugin/notify/main.go b/server/plugin/notify/main.go index 5813b6ce..2c2d9391 100644 --- a/server/plugin/notify/main.go +++ b/server/plugin/notify/main.go @@ -1,6 +1,7 @@ package notify import ( + "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/global" "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/router" "github.com/gin-gonic/gin" ) @@ -11,7 +12,10 @@ type ddPlugin struct { Url string } -func CreateDDPlug() *ddPlugin { +func CreateDDPlug(url, Token, Secret string) *ddPlugin { + global.GlobalConfig_.Url = url + global.GlobalConfig_.Token = Token + global.GlobalConfig_.Secret = Secret return &ddPlugin{} } diff --git a/server/plugin/notify/router/router.go b/server/plugin/notify/router/router.go index 61842b5e..b500d52c 100644 --- a/server/plugin/notify/router/router.go +++ b/server/plugin/notify/router/router.go @@ -11,8 +11,8 @@ type NotifyRouter struct { func (s *NotifyRouter) InitRouter(Router *gin.RouterGroup) { router := Router.Use(middleware.OperationRecord()) - var Controller = api.ApiGroupApp.Api.NotifyController + var SendTextMessage = api.ApiGroupApp.Api.SendTextMessage { - router.POST("dingding", Controller) + router.POST("sendTextMessage", SendTextMessage) } } diff --git a/server/plugin/notify/service/notify.go b/server/plugin/notify/service/notify.go index e21508d1..07a26540 100644 --- a/server/plugin/notify/service/notify.go +++ b/server/plugin/notify/service/notify.go @@ -22,20 +22,50 @@ type NotifyService struct { //@description: 钉钉通知测试 //@return: err error -func (e *NotifyService) SendTextMessage(content string) (err error) { +func (e *NotifyService) SendTextMessage(content string, atMobiles []string, isAtAll bool) (err error) { msg := map[string]interface{}{ "msgtype": "text", "text": map[string]string{ "content": content, }, - //"at": map[string]interface{}{ - // "atMobiles": atMobiles, - // "isAtAll": isAtAll, - //}, + "at": map[string]interface{}{ + "atMobiles": atMobiles, + "isAtAll": isAtAll, + }, + } + return SendMessage(msg) +} + +func (e *NotifyService) SendLinkMessage(content, title, picUrl, messageUrl string) (err error) { + msg := map[string]interface{}{ + "msgtype": "link", + "link": map[string]string{ + "text": content, + "title": title, + "picUrl": picUrl, + "messageUrl": messageUrl, + }, } return SendMessage(msg) } +func (e *NotifyService) SendMarkdownMessage(content, title string, atMobiles []string, isAtAll bool) (err error) { + msg := map[string]interface{}{ + "msgtype": "markdown", + "markdown": map[string]string{ + "text": content, + "title": title, + }, + "at": map[string]interface{}{ + "atMobiles": atMobiles, + "isAtAll": isAtAll, + }, + } + return SendMessage(msg) +} + +// 其余方法请参考 https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.7f8710afbfzduV#topic-2026027 + func SendMessage(msg interface{}) error { body := bytes.NewBuffer(nil) err := json.NewEncoder(body).Encode(msg) From 7519cc9da9732b912116e819ef345909dea7dc33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=92=8B=E5=90=89=E5=85=86?= <303176530@qq.com> Date: Sat, 28 Aug 2021 12:38:26 +0800 Subject: [PATCH 9/9] =?UTF-8?q?=E8=A7=84=E8=8C=83=E5=8C=96=E6=8F=92?= =?UTF-8?q?=E4=BB=B6=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/plugin/email/README.MD | 28 ++++++++++- server/plugin/email/api/sys_email.go | 19 +++++++ server/plugin/email/model/response/email.go | 7 +++ server/plugin/email/router/sys_email.go | 4 +- server/plugin/email/service/sys_email.go | 13 +++++ server/plugin/notify/README.MD | 43 +++++++++------- server/plugin/notify/api/api.go | 49 ++++++++++++++++++- server/plugin/notify/model/response/notify.go | 21 ++++++++ server/plugin/notify/service/notify.go | 29 +++++++++-- 9 files changed, 187 insertions(+), 26 deletions(-) create mode 100644 server/plugin/email/model/response/email.go create mode 100644 server/plugin/notify/model/response/notify.go diff --git a/server/plugin/email/README.MD b/server/plugin/email/README.MD index 646b24f2..17202838 100644 --- a/server/plugin/email/README.MD +++ b/server/plugin/email/README.MD @@ -1,4 +1,5 @@ ## GVA 邮件发送功能插件 +#### 开发者:GIN-VUE-ADMIN 官方 ### 使用步骤 @@ -27,8 +28,9 @@ true, )) -#### 2. 配置说明 +### 2. 配置说明 +#### 2-1 全局配置结构体说明 //其中 Form 和 Secret 通常来说就是用户名和密码 type Email struct { @@ -40,8 +42,17 @@ Port int // 端口 请前往QQ或者你要发邮件的邮箱查看其smtp协议 大多为 465 IsSSL bool // 是否SSL 是否开启SSL } +#### 2-2 入参结构说明 + //其中 Form 和 Secret 通常来说就是用户名和密码 + + type Email struct { + To string `json:"to"` // 邮件发送给谁 + Subject string `json:"subject"` // 邮件标题 + Body string `json:"body"` // 邮件内容 + } + -### 方法API +### 3. 方法API utils.EmailTest(邮件标题,邮件主体) 发送测试邮件 例:utils.EmailTest("测试邮件","测试邮件") @@ -49,3 +60,16 @@ 例:utils.ErrorToEmail("测试邮件","测试邮件") utils.Email(目标邮箱多个的话用逗号分隔,邮件标题,邮件主体) 发送测试邮件 例:utils.Email(”a.qq.com,b.qq.com“,"测试邮件","测试邮件") + +### 4. 可直接调用的接口 + + 测试接口: /email/emailTest [post] 已配置swagger + + 发送邮件接口接口: /email/emailSend [post] 已配置swagger + 入参: + type Email struct { + To string `json:"to"` // 邮件发送给谁 + Subject string `json:"subject"` // 邮件标题 + Body string `json:"body"` // 邮件内容 + } + diff --git a/server/plugin/email/api/sys_email.go b/server/plugin/email/api/sys_email.go index f21cd59a..03e13afa 100644 --- a/server/plugin/email/api/sys_email.go +++ b/server/plugin/email/api/sys_email.go @@ -3,6 +3,7 @@ package api import ( "github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/model/common/response" + email_response "github.com/flipped-aurora/gin-vue-admin/server/plugin/email/model/response" "github.com/flipped-aurora/gin-vue-admin/server/plugin/email/service" "github.com/gin-gonic/gin" "go.uber.org/zap" @@ -25,3 +26,21 @@ func (s *EmailApi) EmailTest(c *gin.Context) { response.OkWithData("发送成功", c) } } + +// @Tags System +// @Summary 发送邮件 +// @Security ApiKeyAuth +// @Produce application/json +// @Param data body email_response.Email true "发送邮件必须的参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}" +// @Router /email/sendEmail [post] +func (s *EmailApi) SendEmail(c *gin.Context) { + var email email_response.Email + _ = c.ShouldBindJSON(&email) + if err := service.ServiceGroupApp.SendEmail(email.To, email.Subject, email.Body); err != nil { + global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) + response.FailWithMessage("发送失败", c) + } else { + response.OkWithData("发送成功", c) + } +} diff --git a/server/plugin/email/model/response/email.go b/server/plugin/email/model/response/email.go new file mode 100644 index 00000000..ed254750 --- /dev/null +++ b/server/plugin/email/model/response/email.go @@ -0,0 +1,7 @@ +package response + +type Email struct { + To string `json:"to"` // 邮件发送给谁 + Subject string `json:"subject"` // 邮件标题 + Body string `json:"body"` // 邮件内容 +} diff --git a/server/plugin/email/router/sys_email.go b/server/plugin/email/router/sys_email.go index 339f68e8..518bb0bb 100644 --- a/server/plugin/email/router/sys_email.go +++ b/server/plugin/email/router/sys_email.go @@ -12,7 +12,9 @@ type EmailRouter struct { func (s *EmailRouter) InitEmailRouter(Router *gin.RouterGroup) { emailRouter := Router.Use(middleware.OperationRecord()) var EmailApi = api.ApiGroupApp.EmailApi.EmailTest + var SendEmail = api.ApiGroupApp.EmailApi.SendEmail { - emailRouter.POST("emailTest", EmailApi) // 发送测试邮件 + emailRouter.POST("emailTest", EmailApi) // 发送测试邮件 + emailRouter.POST("sendEmail", SendEmail) // 发送邮件 } } diff --git a/server/plugin/email/service/sys_email.go b/server/plugin/email/service/sys_email.go index b031b379..6659fc6f 100644 --- a/server/plugin/email/service/sys_email.go +++ b/server/plugin/email/service/sys_email.go @@ -18,3 +18,16 @@ func (e *EmailService) EmailTest() (err error) { err = utils.EmailTest(subject, body) return err } + +//@author: [maplepie](https://github.com/maplepie) +//@function: EmailTest +//@description: 发送邮件测试 +//@return: err error +//@params to string 收件人 +//@params subject string 标题(主题) +//@params body string 邮件内容 + +func (e *EmailService) SendEmail(to, subject, body string) (err error) { + err = utils.Email(to, subject, body) + return err +} diff --git a/server/plugin/notify/README.MD b/server/plugin/notify/README.MD index e2e28e73..4b8d8f84 100644 --- a/server/plugin/notify/README.MD +++ b/server/plugin/notify/README.MD @@ -21,10 +21,24 @@ 密钥)) } ``` -### 3方法API + +### 3 参数说明 +#### 3-1 全局参数说明 + +```go + Url string `mapstructure:"url" json:"url" yaml:"url"` // Url + Token string `mapstructure:"token" json:"token" yaml:"token"` // access_token + Secret string `mapstructure:"secret" json:"secret" yaml:"secret"` // 密钥 +``` +#### 3-2 请求入参说明 +```go + + +``` + +### 3方法API(可调用方法) ```go -可调用方法 //content 发送的内容 //atMobiles 需要艾特的人的手机号 //isAtAll 是否艾特全体 @@ -34,8 +48,6 @@ SendTextMessage(content string,atMobiles []string,isAtAll bool) //title 内容标题 //picUrl 配图 //messageUrl 点击跳转路径 -//atMobiles 需要艾特的人的手机号 -//isAtAll 是否艾特全体 SendLinkMessage(content,title,picUrl,messageUrl string) //content 发送的内容(markdown语法) @@ -46,20 +58,17 @@ SendMarkdownMessage(content,title string,atMobiles []string,isAtAll bool) ``` -### 4. 使用示例 +### 4. 可直接调用接口 -在代码中调用 `SendTextMessage` 方法即可 -```go -// 示例 -func NotifyController(c *gin.Context) { - if err := service.ServiceGroupApp.SendTextMessage("test",[]string{"手机号"},是否艾特全体); err != nil { - global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) - response.FailWithMessage("发送失败", c) - } else { - response.OkWithData("发送成功", c) - } -} + 发送文字消息接口: /notify/sendTextMessage [post] 已配置swagger + 发送图文链接消息接口: /notify/sendLinkMessage [post] 已配置swagger + 发送markdown消息接口: /notify/sendMarkdownMessage [post] 已配置swagger -``` + 入参: + type Email struct { + To string `json:"to"` // 邮件发送给谁 + Subject string `json:"subject"` // 邮件标题 + Body string `json:"body"` // 邮件内容 + } diff --git a/server/plugin/notify/api/api.go b/server/plugin/notify/api/api.go index 54782ea0..e52102cb 100644 --- a/server/plugin/notify/api/api.go +++ b/server/plugin/notify/api/api.go @@ -3,6 +3,7 @@ package api import ( "github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/model/common/response" + notify_response "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/model/response" "github.com/flipped-aurora/gin-vue-admin/server/plugin/notify/service" "github.com/gin-gonic/gin" "go.uber.org/zap" @@ -11,9 +12,53 @@ import ( type Api struct { } -// +// @Tags Notify +// @Summary 发送文字消息接口 +// @Security ApiKeyAuth +// @Produce application/json +// @Param data body notify_response.TextNotify true "发送文字消息的参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}" +// @Router /notify/sendTextMessage [post] func (s *Api) SendTextMessage(c *gin.Context) { - if err := service.ServiceGroupApp.SendTextMessage("notify", []string{}, false); err != nil { + var textNotify notify_response.TextNotify + _ = c.ShouldBindJSON(&textNotify) + if err := service.ServiceGroupApp.SendTextMessage(textNotify.Content, textNotify.AtMobiles, textNotify.IsAtAll); err != nil { + global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) + response.FailWithMessage("发送失败", c) + } else { + response.OkWithData("发送成功", c) + } +} + +// @Tags Notify +// @Summary 发送图文链接消息接口 +// @Security ApiKeyAuth +// @Produce application/json +// @Param data body notify_response.LinkNotify true "发送图文链接消息的参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}" +// @Router /notify/sendLinkMessage [post] +func (s *Api) SendLinkMessage(c *gin.Context) { + var linkNotify notify_response.LinkNotify + _ = c.ShouldBindJSON(&linkNotify) + if err := service.ServiceGroupApp.SendLinkMessage(linkNotify.Content, linkNotify.Title, linkNotify.PicUrl, linkNotify.MessageUrl); err != nil { + global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) + response.FailWithMessage("发送失败", c) + } else { + response.OkWithData("发送成功", c) + } +} + +// @Tags Notify +// @Summary 发送markdown消息接口 +// @Security ApiKeyAuth +// @Produce application/json +// @Param data body notify_response.MarkdownNotify true "发送markdown消息的参数" +// @Success 200 {string} string "{"success":true,"data":{},"msg":"发送成功"}" +// @Router /notify/sendMarkdownMessage [post] +func (s *Api) SendMarkdownMessage(c *gin.Context) { + var markdownNotify notify_response.MarkdownNotify + _ = c.ShouldBindJSON(&markdownNotify) + if err := service.ServiceGroupApp.SendMarkdownMessage(markdownNotify.Content, markdownNotify.Title, markdownNotify.AtMobiles, markdownNotify.IsAtAll); err != nil { global.GVA_LOG.Error("发送失败!", zap.Any("err", err)) response.FailWithMessage("发送失败", c) } else { diff --git a/server/plugin/notify/model/response/notify.go b/server/plugin/notify/model/response/notify.go new file mode 100644 index 00000000..1555ae58 --- /dev/null +++ b/server/plugin/notify/model/response/notify.go @@ -0,0 +1,21 @@ +package response + +type TextNotify struct { // 文字信息 + Content string `json:"content"` // 发送的内容 + AtMobiles []string `json:"atMobiles"` // 需要艾特的人的手机号 + IsAtAll bool `json:"isAtAll"` // 是否艾特全体 +} + +type LinkNotify struct { // 图文链接信息 + Content string `json:"content"` // 发送的内容 + Title string `json:"title"` // 内容标题 + PicUrl string `json:"picUrl"` // 配图 + MessageUrl string `json:"messageUrl"` // 点击跳转路径 +} + +type MarkdownNotify struct { // markdown信息 + Title string `json:"title"` // 内容标题 + Content string `json:"content"` // 发送的内容 + AtMobiles []string `json:"atMobiles"` // 需要艾特的人的手机号 + IsAtAll bool `json:"isAtAll"` // 是否艾特全体 +} diff --git a/server/plugin/notify/service/notify.go b/server/plugin/notify/service/notify.go index 07a26540..4e3045f6 100644 --- a/server/plugin/notify/service/notify.go +++ b/server/plugin/notify/service/notify.go @@ -18,8 +18,11 @@ type NotifyService struct { } //@author: [Espoir](https://github.com/nightsimon) -//@function: NotifyController -//@description: 钉钉通知测试 +//@function: SendTextMessage +//@description: 发送钉钉文字信息 +//@params content string发送的文字内容 +//@params atMobiles []string 艾特的手机号 +//@params isAtAll bool 是否艾特全体 //@return: err error func (e *NotifyService) SendTextMessage(content string, atMobiles []string, isAtAll bool) (err error) { @@ -36,6 +39,15 @@ func (e *NotifyService) SendTextMessage(content string, atMobiles []string, isAt return SendMessage(msg) } +//@author: [Espoir](https://github.com/nightsimon) +//@function: SendLinkMessage +//@description: 发送钉钉图文链接信息 +//@params content string 发送的文字内容 +//@params title string 发送的标题 +//@params picUrl string 艾特的手机号 +//@params messageUrl string 是否艾特全体 +//@return: err error + func (e *NotifyService) SendLinkMessage(content, title, picUrl, messageUrl string) (err error) { msg := map[string]interface{}{ "msgtype": "link", @@ -49,6 +61,15 @@ func (e *NotifyService) SendLinkMessage(content, title, picUrl, messageUrl strin return SendMessage(msg) } +//@author: [Espoir](https://github.com/nightsimon) +//@function: SendMarkdownMessage +//@description: 发送钉钉Markdown信息 +//@params content 发送的文字内容 +//@params title 发送的标题 +//@params atMobiles []string 艾特的手机号 +//@params isAtAll bool 是否艾特全体 +//@return: err error + func (e *NotifyService) SendMarkdownMessage(content, title string, atMobiles []string, isAtAll bool) (err error) { msg := map[string]interface{}{ "msgtype": "markdown", @@ -64,8 +85,6 @@ func (e *NotifyService) SendMarkdownMessage(content, title string, atMobiles []s return SendMessage(msg) } -// 其余方法请参考 https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.7f8710afbfzduV#topic-2026027 - func SendMessage(msg interface{}) error { body := bytes.NewBuffer(nil) err := json.NewEncoder(body).Encode(msg) @@ -134,3 +153,5 @@ func sign(t int64, secret string) string { data := hmac256.Sum(nil) return base64.StdEncoding.EncodeToString(data) } + +// 其余方法请参考 https://developers.dingtalk.com/document/robots/custom-robot-access?spm=ding_open_doc.document.0.0.7f8710afbfzduV#topic-2026027