first push

This commit is contained in:
renzhiyuan 2025-03-07 16:52:29 +08:00
parent 354c66a1a5
commit 9071be2e14
8 changed files with 515 additions and 0 deletions

View File

@ -0,0 +1,18 @@
## 安装
```bash
$ go get gitea.cdlsxd.cn/self-tools/l_msg_api
```
## 使用
```go
msg, err := l_msg_api.NewMessageCenter(yourKey, yoursecret, ServerIndex, TempIndex)
if err != nil {
panic(err)
}
//短信
res, err := msg.SendSms([]string{"15082245122"}, `{"content": "测试"}`)
```

12
cache/cache.go vendored Normal file
View File

@ -0,0 +1,12 @@
package cache
import "github.com/emirpasic/gods/maps/hashmap"
var cache *hashmap.Map
func InstanceCacheMap() *hashmap.Map {
if cache == nil {
cache = hashmap.New()
}
return cache
}

187
config.go Normal file
View File

@ -0,0 +1,187 @@
package l_msg_api
// 业务系统和模板配置
type (
Base struct {
ServerIndex string `json:"server_index"` // 业务系统
TempIndex string `json:"temp_index"` // 配置模板
}
accessTokenResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
AccessToken string `json:"accessToken"` // 授权token
AccessExpire int `json:"accessExpire"` // 过期时间
} `json:"data"`
}
OACreatePurchaseResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data struct {
IsSuccess bool `json:"is_success"` // 是否成功 true 成功 false 失败
Msg string `json:"msg"`
InstanceId string `json:"instance_id"` // 审批实例id
} `json:"data"`
}
// 封装上游采购审批表单数据
formDataRequest struct {
Base Base `json:"base"`
formsData
}
formsData struct {
FormBase
FormComponentValues []formComponentValues `json:"form_component_values"` // 审批表单数据
}
formComponentValues struct { // 审批表单数据
Name string `json:"name"`
Value string `json:"value"`
ComponentType string `json:"component_type,omitempty"`
ExtValue string `json:"extValue,omitempty"`
}
// 创建OA基础数据
FormBase struct {
OutTradeNo string `json:"out_trade_no"` // 流水号
OriginatorUserId string `json:"originator_user_id"` // 钉钉申请人id
}
// 创建采购审批表单数据
CreatePurchaseForm struct {
FormBase
PurchaseNum string // 采购单号
SupplierName string //供应商名称
TotalCount string //采购总数量
TotalAmount string //采购总金额
WarehouseName string //入库仓库
ExpectArrivalTime string //预计到货时间
Remark string //采购备注
PurchaseType string //采购类型
PayType string //支付类型
TotalAmountUpperCase string //总金额大写
SupplierSettlementBank string //结算账户开户行
SupplierSettlementAccount string //结算账户
PurchaseInGoodsList []PurchaseInGoods
}
// 采购单商品列表
PurchaseInGoods struct {
GoodsCode string `json:"goods_code"` // 商品编码
GoodsName string `json:"goods_name"` // 商品名称
Count string `json:"count"` // 数量
Price string `json:"price"` // 单价
Total string `json:"total"` // 总价
}
// 获取审批实列详情 请求数据
oAGetDetailRequest struct {
Base Base `json:"base"`
OutTradeNo string `json:"out_trade_no"` // 流水号
ProcessInstanceId string `json:"process_instance_id"` // 审批实例id
}
// 获取审批实列详情 返回数据
OAGetDetailData struct {
OutTradeNo string `json:"out_trade_no"` // 流水号
ProcessInstanceId string `json:"process_instance_id"` // 审批实例id
Title string `json:"title"` // 审批标题
Result int `json:"result"` // 审批结果1同意2拒绝
Type string `json:"type"` // 审批类型 '任务状态变更类型,start审批任务开始,finish审批任务正常结束完成或转交
Remarks string `json:"remarks"` // 审批备注
CreateTime string `json:"createTime"` // 审批创建时间
UpdateTime string `json:"updateTime"` // 审批更新时间
}
OAGetDetailResponse struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data OAGetDetailData `json:"data"`
}
// 创建客户充值审批表单数据
CreateCustomerRechargeForm struct {
FormBase
Initiator string //发起人
CustomerName string //客户名称
RecipientAccountName string //收款账户名称
RechargeType string //充值类型
RechargeAmount string //充值金额
Voucher string //充值凭证
Remark string //备注
CreatedAt string //创建时间
}
// 创建供应商充值审批表单数据
CreateSupplierRechargeForm struct {
FormBase
Initiator string //发起人
SupplierName string //供应商名称
RecipientAccountName string //收款账户名称
RechargeType string //充值类型
RechargeAmount string //充值金额
Voucher string //充值凭证
Remark string //备注
CreatedAt string //创建时间
}
/*
OaNotifyData 回调通知数据
Method: POST
{"content-type": "application/json; charset=utf-8"},
*/
OaNotifyData struct {
OutTradeNo string `json:"out_trade_no"` // 下游流水号
ProcessInstanceId string `json:"process_instance_id"` // 创建审批任务返回的 审批实例id
Title string `json:"title"` // 实例标题
StaffId string `json:"staff_id"` // 当前任务的审批人userId操作转交动作的用户userId
Result int32 `json:"result"` // 审批结果1同意2拒绝
Type string `json:"type"` // 任务状态变更类型,start审批任务开始,finish审批任务正常结束完成或转交,comment审批任务评论,cancel说明当前节点有多个审批人并且是或签其中一个人执行了审批其他审批人会推送cancel类型事件
Remark string `json:"remark"` // 操作时写的评论内容
CreatedAt string `json:"created_at"` // 创建时间
UpdatedAt string `json:"updated_at"` // 结束时间
}
SmsRequest struct {
Base Base `json:"base"`
Param string `json:"param"` // 短信模板变量对应的实际值
Tels string `json:"tels"`
}
SmsSendRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data SmsSend `json:"data"`
}
SmsSend struct {
SendList []SmsSendResView `json:"send_list"`
}
SmsSendResView struct {
Tel string `json:"tel"`
IsSuccess uint32 `json:"is_success"`
}
DingTalkBlackBoardSendReq struct {
Base Base `json:"base"`
BlackboardReceiver BlackboardReceiverView `json:"blackboard_receiver"` //公告接收人。
Title string `json:"title,default=公告"` //公告标题
Content string `json:"content,default=大家好"` //公告内容
}
BlackboardReceiverView struct {
DeptidList []int `json:"deptid_list"` //接收部门ID列表最大的列表长度为20。
UseridList []string `json:"userid_list"` //接收部用户ID列表最大的列表长度为20。
}
DefaultRes struct {
Code int `json:"code"`
Msg string `json:"msg"`
Data Default `json:"data"`
}
Default struct {
IsSuccess bool `json:"is_success,default=false"`
Msg string `json:"msg,default=ok"`
}
)

21
const.go Normal file
View File

@ -0,0 +1,21 @@
package l_msg_api
const (
ServerHost = "http://121.199.38.107:8000"
TimeOut = 60
)
const (
DDSelectField = "DDSelectField"
DDTextField = "TextField"
DDTextareaField = "TextareaField"
DDNumberField = "NumberField"
DDDateField = "DDDateField"
)
const (
PathAccessToken = "/oauth/v1/accesstoken"
PathOaCreat = "/msg/v1/dingtalk/oa/create"
PathOaGet = "/msg/v1/dingtalk/oa/create"
SendSms = "/msg/v1//sms/send"
)

12
go.mod Normal file
View File

@ -0,0 +1,12 @@
module gitea.cdlsxd.cn/self-tools/l_msg_api
go 1.23.6
require github.com/valyala/fasthttp v1.59.0
require (
github.com/andybalholm/brotli v1.1.1 // indirect
github.com/emirpasic/gods v1.18.1
github.com/klauspost/compress v1.17.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
)

96
httpclient/fasthttp.go Normal file
View File

@ -0,0 +1,96 @@
package httpclient
import (
"fmt"
"github.com/valyala/fasthttp"
"time"
)
func FastHttpPost(url string, header map[string]string, body []byte, timeout int) ([]byte, error) {
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req) // 用完需要释放资源
// 默认是application/x-www-form-urlencoded
req.Header.SetMethod("POST")
for k, v := range header {
req.Header.Set(k, v)
}
req.SetRequestURI(url)
req.SetBody(body)
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp) // 用完需要释放资源
var err error
if timeout <= 0 {
if err = fasthttp.Do(req, resp); err != nil {
return nil, err
}
} else {
if err := fasthttp.DoTimeout(req, resp, time.Duration(timeout)*time.Second); err != nil {
return nil, err
}
}
b := resp.Body()
//fmt.Println(string(b),"http请求")
return b, nil
}
func FastHttpPostForm(url string, header map[string]string, body map[string]string, timeout int) ([]byte, error) {
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req) // 用完需要释放资源
// 默认是application/x-www-form-urlencoded
req.Header.SetMethod("POST")
for k, v := range header {
req.Header.Set(k, v)
}
req.SetRequestURI(url)
args := &fasthttp.Args{}
for k, v := range body {
args.Add(k, v)
}
req.SetBody(args.QueryString())
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp) // 用完需要释放资源
var err error
if timeout == 0 {
if err = fasthttp.Do(req, resp); err != nil {
return nil, err
}
} else {
if err := fasthttp.DoTimeout(req, resp, time.Duration(timeout)*time.Second); err != nil {
return nil, err
}
}
b := resp.Body()
return b, nil
}
func FastHttpGet(url string, header map[string]string, body map[string]string, timeout int) ([]byte, error) {
req := fasthttp.AcquireRequest()
defer fasthttp.ReleaseRequest(req) // 用完需要释放资源
// 默认是application/x-www-form-urlencoded
req.Header.SetMethod("GET")
for k, v := range header {
req.Header.Set(k, v)
}
if len(body) > 0 {
url += "?"
for k, v := range body {
url += k + "=" + v + "&"
}
url = url[0 : len(url)-1]
}
fmt.Println(url)
req.SetRequestURI(url)
resp := fasthttp.AcquireResponse()
defer fasthttp.ReleaseResponse(resp) // 用完需要释放资源
var err error
if timeout == 0 {
if err = fasthttp.Do(req, resp); err != nil {
return nil, err
}
} else {
if err := fasthttp.DoTimeout(req, resp, time.Duration(timeout)*time.Second); err != nil {
return nil, err
}
}
b := resp.Body()
return b, nil
}

152
msg.go Normal file
View File

@ -0,0 +1,152 @@
package l_msg_api
import (
"encoding/json"
"errors"
"fmt"
"gitea.cdlsxd.cn/self-tools/l_msg_api/cache"
"gitea.cdlsxd.cn/self-tools/l_msg_api/httpclient"
"strings"
)
type MessageCenter struct {
Host string // 消息中心地址
ClientKey string // 客户端id,获取授权token需要
ClientSecret string
header map[string]string
Base
}
func NewMessageCenter(clientKey, clientSecret, serverIndex, tempIndex string) (*MessageCenter, error) {
msg := &MessageCenter{
Host: ServerHost,
ClientKey: clientKey,
ClientSecret: clientSecret,
Base: Base{
ServerIndex: serverIndex,
TempIndex: tempIndex,
},
}
accessToken, err := msg.getAccessToken()
msg.header = map[string]string{"Authorization": accessToken, "content-type": "application/json; charset=utf-8"}
return msg, err
}
/*
获取授权token
AccessExpire 有效期内可缓存起来使用
*/
func (m *MessageCenter) getAccessToken() (string, error) {
if tokenInterface, exist := cache.InstanceCacheMap().Get(m.ClientKey); exist {
return tokenInterface.(string), nil
}
var data accessTokenResponse
url := fmt.Sprintf("%s%s", m.Host, PathAccessToken)
var authParam, _ = json.Marshal(map[string]string{"client_key": m.ClientKey, "client_secret": m.ClientSecret})
res, err := httpclient.FastHttpPost(url, map[string]string{"content-type": "application/json; charset=utf-8"}, authParam, TimeOut)
if err != nil {
return "", err
}
err = json.Unmarshal(res, &data)
if data.Code != 0 {
return "", errors.New(data.Msg)
}
cache.InstanceCacheMap().Put(m.ClientKey, data.Data.AccessToken)
return data.Data.AccessToken, err
}
// 采购单OA审批
func (m *MessageCenter) OACreate(dTalkUserId, treadNo string, checkForm []formComponentValues) (data OACreatePurchaseResponse, err error) {
res, err := httpclient.FastHttpPost(
fmt.Sprintf("%s%s", m.Host, PathOaCreat),
m.header,
m.parseOACreateParam(dTalkUserId, treadNo, checkForm),
TimeOut)
if err != nil {
return
}
err = json.Unmarshal(res, &data)
return
}
func (m *MessageCenter) parseOACreateParam(dTalkUserId, treadNo string, checkForm []formComponentValues) (out []byte) {
req := formDataRequest{
Base: m.Base,
}
req.FormBase = FormBase{
OutTradeNo: treadNo,
OriginatorUserId: dTalkUserId,
}
req.FormComponentValues = checkForm
out, _ = json.Marshal(req)
return
}
func (m *MessageCenter) OAGetDetail(outTradeNo string) (data OAGetDetailData, err error) {
param, _ := json.Marshal(oAGetDetailRequest{
Base: m.Base,
OutTradeNo: outTradeNo,
})
res, err := httpclient.FastHttpPost(fmt.Sprintf("%s%s", m.Host, PathOaGet), m.header, param, TimeOut)
if err != nil {
return
}
// 解析响应参数
body := OAGetDetailResponse{}
err = json.Unmarshal(res, &body)
if err != nil {
return
}
if body.Code != 0 {
err = errors.New(body.Msg)
return
}
return body.Data, nil
}
// 采购单OA审批
func (m *MessageCenter) SendSms(tels []string, jsonParam string) (data SmsSendRes, err error) {
param := m.parseSmsSendParam(tels, jsonParam)
res, err := httpclient.FastHttpPost(
fmt.Sprintf("%s%s", m.Host, SendSms),
m.header,
param,
TimeOut)
if err != nil {
return
}
err = json.Unmarshal(res, &data)
return
}
func (m *MessageCenter) parseSmsSendParam(tels []string, jsonParam string) (out []byte) {
out, _ = json.Marshal(SmsRequest{
Base: m.Base,
Tels: strings.Join(tels, ","),
Param: jsonParam,
})
return
}
func (m *MessageCenter) SendBlackBoard(title, content string, receiver BlackboardReceiverView) (data DefaultRes, err error) {
res, err := httpclient.FastHttpPost(
fmt.Sprintf("%s%s", m.Host, SendSms),
m.header,
m.parseSendBlackBoardParam(title, content, receiver),
TimeOut)
if err != nil {
return
}
err = json.Unmarshal(res, &data)
return
}
func (m *MessageCenter) parseSendBlackBoardParam(title, content string, receiver BlackboardReceiverView) (out []byte) {
out, _ = json.Marshal(DingTalkBlackBoardSendReq{
Base: m.Base,
Content: content,
Title: title,
BlackboardReceiver: receiver,
})
return
}

17
test/msg_test.go Normal file
View File

@ -0,0 +1,17 @@
package test
import (
"fmt"
"gitea.cdlsxd.cn/self-tools/l_msg_api"
"testing"
)
func TestBase(t *testing.T) {
msg, err := l_msg_api.NewMessageCenter("", "", "sms", "cron_sms")
if err != nil {
panic(err)
}
res, err := msg.SendSms([]string{"15082245122"}, `{"content": "测试"}`)
fmt.Println(res, err)
}