diff --git a/service/dingtalk/app.go b/service/dingtalk/app.go new file mode 100644 index 00000000..9e0c7dda --- /dev/null +++ b/service/dingtalk/app.go @@ -0,0 +1,50 @@ +package dingtalk + +import ( + "encoding/json" + "errors" + "fmt" + "github.com/go-redis/redis/v8" + "go.mongodb.org/mongo-driver/mongo" + "go.uber.org/zap" + "gopkg.in/dtapps/go-library.v3/utils/gohttp" + "gorm.io/gorm" + "net/http" +) + +type App struct { + Secret string + AccessToken string + ZapLog *zap.Logger // 日志服务 + Db *gorm.DB // 关系数据库服务 + RDb *redis.Client // 缓存数据库服务 + MDb *mongo.Client // 非关系数据库服务 +} + +func (app *App) request(url string, params map[string]interface{}, method string) ([]byte, error) { + switch method { + case http.MethodGet: + // 请求 + get, err := gohttp.Get(url, params) + // 日志 + if app.ZapLog != nil { + app.ZapLog.Sugar().Info(fmt.Sprintf("%s %s", url, get.Body)) + } + return get.Body, err + case http.MethodPost: + // 请求参数 + paramsMarshal, err := json.Marshal(params) + if err != nil { + return nil, err + } + // 请求 + postJson, err := gohttp.PostJson(url, paramsMarshal) + // 日志 + if app.ZapLog != nil { + app.ZapLog.Sugar().Info(fmt.Sprintf("%s %s", url, postJson.Body)) + } + return postJson.Body, err + default: + return nil, errors.New("请求类型不支持") + } +} diff --git a/service/dingtalk/config/config.go b/service/dingtalk/config/config.go deleted file mode 100644 index ec4fbf95..00000000 --- a/service/dingtalk/config/config.go +++ /dev/null @@ -1,3 +0,0 @@ -package config - -const Api = "https://oapi.dingtalk.com/robot/send" diff --git a/service/dingtalk/dingtalk.go b/service/dingtalk/dingtalk.go deleted file mode 100644 index c864d704..00000000 --- a/service/dingtalk/dingtalk.go +++ /dev/null @@ -1,57 +0,0 @@ -package dingtalk - -import ( - "crypto/hmac" - "crypto/sha256" - "encoding/base64" - "encoding/json" - "fmt" - "gopkg.in/dtapps/go-library.v3/service/dingtalk/config" - "gopkg.in/dtapps/go-library.v3/service/dingtalk/message" - "gopkg.in/dtapps/go-library.v3/utils/gojson" - "io/ioutil" - "net/http" - "strings" - "time" -) - -type DingBot struct { - Secret string - AccessToken string -} - -type Response struct { - Errcode int64 `json:"errcode"` - Errmsg string `json:"errmsg"` -} - -func (bot *DingBot) Send(msg message.Message) (Response, error) { - timestamp := time.Now().UnixNano() / 1e6 - var response Response - signStr := sign(timestamp, bot.Secret) - dingUrl := fmt.Sprintf("%s?access_token=%s×tamp=%d&sign=%s", config.Api, bot.AccessToken, timestamp, signStr) - toString, err := gojson.MarshalToString(msg) - if err != nil { - return response, err - } - resp, e := http.Post(dingUrl, "application/json", strings.NewReader(toString)) - if e != nil { - return response, e - } - defer resp.Body.Close() - - body, _ := ioutil.ReadAll(resp.Body) - e = json.Unmarshal(body, &response) - if e != nil { - return response, e - } - return response, nil -} - -func sign(t int64, secret string) string { - secStr := fmt.Sprintf("%d\n%s", t, secret) - hmac256 := hmac.New(sha256.New, []byte(secret)) - hmac256.Write([]byte(secStr)) - result := hmac256.Sum(nil) - return base64.StdEncoding.EncodeToString(result) -} diff --git a/service/dingtalk/dingtalk_test.go b/service/dingtalk/dingtalk_test.go deleted file mode 100644 index 15edfd08..00000000 --- a/service/dingtalk/dingtalk_test.go +++ /dev/null @@ -1,26 +0,0 @@ -package dingtalk - -import ( - "fmt" - "gopkg.in/dtapps/go-library.v3/service/dingtalk/message" - "testing" -) - -func TestName(t *testing.T) { - bot := DingBot{ - Secret: "gSEC05342ba24a7eb2e1dbeae61b3df997eb1a97b7cda414566876e983f1db0fec0b", - AccessToken: "caad81de7f6b218bb7d085264d4885714c805cc80a460690a0d19db91a05dd174", - } - msg := message.Message{ - MsgType: message.TextStr, - Text: message.Text_{ - Content: "测试", - }, - } - send, err := bot.Send(msg) - fmt.Printf("send:%v\n", send) - if err != nil { - t.Errorf("err:%v\n", err) - return - } -} diff --git a/service/dingtalk/message/message.go b/service/dingtalk/message/message.go deleted file mode 100644 index 3739fddb..00000000 --- a/service/dingtalk/message/message.go +++ /dev/null @@ -1,59 +0,0 @@ -package message - -type Message struct { - MsgType MsgType_ `json:"msgtype"` - Text Text_ `json:"text"` - Link Link_ `json:"link"` - Markdown Markdown_ `json:"markdown"` - ActionCard ActionCard_ `json:"actionCard"` - FeedCard FeedCard_ `json:"feedCard"` -} - -// Text_ text类型 -type Text_ struct { - Content string `json:"content"` - At At_ `json:"at"` -} - -// At_ At类型 -type At_ struct { - AtMobiles []string `json:"atMobiles"` - IsAtAll bool `json:"isAtAll"` -} - -// Link_ link类型 -type Link_ struct { - Text string `json:"text"` - Title string `json:"title"` - PicUrl string `json:"picUrl"` - MessageUrl string `json:"messageUrl"` -} - -// Markdown_ markdown类型 -type Markdown_ struct { - Title string `json:"title"` - Text string `json:"text"` - At At_ `json:"at"` -} - -// ActionCard_ 整体跳转actionCard -type ActionCard_ struct { - Title string `json:"title"` - Text string `json:"text"` - BtnOrientation string `json:"btnOrientation"` - SingleTitle string `json:"singleTitle"` - SingleURL string `json:"singleUrl"` - HideAvatar string `json:"hideAvatar"` - BtnS []Btn_ `json:"btns"` -} - -// Btn_ Btn类型 -type Btn_ struct { - Title string `json:"title"` - ActionURL string `json:"actionURL"` -} - -// FeedCard_ FeedCard类型 -type FeedCard_ struct { - Links []Link_ `json:"links"` -} diff --git a/service/dingtalk/message/msgtype.go b/service/dingtalk/message/msgtype.go deleted file mode 100644 index 1a22d798..00000000 --- a/service/dingtalk/message/msgtype.go +++ /dev/null @@ -1,11 +0,0 @@ -package message - -type MsgType_ string - -const ( - TextStr MsgType_ = "text" - LinkStr MsgType_ = "link" - MarkdownStr MsgType_ = "markdown" - ActionCardStr MsgType_ = "actionCard" - FeedCardStr MsgType_ = "feedCard" -) diff --git a/service/dingtalk/params.go b/service/dingtalk/params.go new file mode 100644 index 00000000..dc4910b4 --- /dev/null +++ b/service/dingtalk/params.go @@ -0,0 +1,27 @@ +package dingtalk + +// Params 请求参数 +type Params map[string]interface{} + +func NewParams() Params { + p := make(Params) + return p +} + +func (app *App) NewParamsWith(params ...Params) Params { + p := make(Params) + for _, v := range params { + p.SetParams(v) + } + return p +} + +func (p Params) Set(key string, value interface{}) { + p[key] = value +} + +func (p Params) SetParams(params Params) { + for key, value := range params { + p[key] = value + } +} diff --git a/service/dingtalk/robot.send.go b/service/dingtalk/robot.send.go new file mode 100644 index 00000000..a5ce7449 --- /dev/null +++ b/service/dingtalk/robot.send.go @@ -0,0 +1,24 @@ +package dingtalk + +import ( + "fmt" + "net/http" + "time" +) + +type RobotSendResult struct { + Errcode int64 `json:"errcode"` + Errmsg string `json:"errmsg"` +} + +// RobotSend 自定义机器人 +// https://open.dingtalk.com/document/group/custom-robot-access +func (app *App) RobotSend(notMustParams ...Params) (body []byte, err error) { + // 参数 + params := app.NewParamsWith(notMustParams...) + // 时间 + timestamp := time.Now().UnixNano() / 1e6 + // 请求 + body, err = app.request(fmt.Sprintf("https://oapi.dingtalk.com/robot/send?access_token=%s×tamp=%d&sign=%s", app.AccessToken, timestamp, app.sign(timestamp)), params, http.MethodPost) + return body, err +} diff --git a/service/dingtalk/sign.go b/service/dingtalk/sign.go new file mode 100644 index 00000000..0d9107b0 --- /dev/null +++ b/service/dingtalk/sign.go @@ -0,0 +1,16 @@ +package dingtalk + +import ( + "crypto/hmac" + "crypto/sha256" + "encoding/base64" + "fmt" +) + +func (app *App) sign(t int64) string { + secStr := fmt.Sprintf("%d\n%s", t, app.Secret) + hmac256 := hmac.New(sha256.New, []byte(app.Secret)) + hmac256.Write([]byte(secStr)) + result := hmac256.Sum(nil) + return base64.StdEncoding.EncodeToString(result) +}