parent
ad86421cb8
commit
dbcb0ee85b
@ -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("请求类型不支持")
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
package config
|
||||
|
||||
const Api = "https://oapi.dingtalk.com/robot/send"
|
@ -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)
|
||||
}
|
@ -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"`
|
||||
}
|
@ -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"
|
||||
)
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
@ -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)
|
||||
}
|
Loading…
Reference in new issue