Browse Source

企业微信进入上报地址回调处理完毕

qin_1
超级管理员 4 years ago
parent
commit
a17dbe019a
  1. 4
      gin_server_admin/api/index/assessment/assesshandle.go
  2. 1
      gin_server_admin/api/v1/custom/customhandle.go
  3. 9
      gin_server_admin/api/v1/examtestpage/examtype.go
  4. 55
      gin_server_admin/api/v1/examtestpage/healthreportstathand.go
  5. 120
      gin_server_admin/api/v1/shiyan/shiyan.go
  6. 193
      gin_server_admin/api/wechatapp/callback/apphandle.go
  7. 67
      gin_server_admin/api/wechatapp/callback/eventprocessing.go
  8. 99
      gin_server_admin/api/wechatapp/callback/type.go
  9. 31
      gin_server_admin/api/wechatapp/callback/updatehandle.go
  10. 2
      gin_server_admin/api/wechatapp/enter.go
  11. 152
      gin_server_admin/api/wechatapp/sendmessage/apphandle.go
  12. 29
      gin_server_admin/api/wechatapp/sendmessage/examineapprove.go
  13. 418
      gin_server_admin/api/wechatapp/sendmessage/type.go
  14. 156
      gin_server_admin/api/wechatapp/sharemethod/handle.go
  15. 9
      gin_server_admin/api/wechatapp/sharemethod/type.go
  16. 2
      gin_server_admin/api/workwechatcallback/callbackes/callbacktype.go
  17. 2
      gin_server_admin/api/workwechatcallback/callbackes/enter.go
  18. 4
      gin_server_admin/api/workwechatcallback/callbackes/workwechatcallback.go
  19. 4
      gin_server_admin/api/workwechatcallback/enter.go
  20. 111
      gin_server_admin/commonus/coordinatetransformation.go
  21. 9
      gin_server_admin/config.yaml
  22. 1
      gin_server_admin/config/config.go
  23. 14
      gin_server_admin/config/wechat.go
  24. 4
      gin_server_admin/core/server.go
  25. 3
      gin_server_admin/global/global.go
  26. 16
      gin_server_admin/initialize/redis.go
  27. 3
      gin_server_admin/middleware/myjwt.go
  28. 3
      gin_server_admin/router/examtestpage/healthreporthandle.go
  29. 2
      gin_server_admin/router/shiyan/sys_shiyan.go
  30. 7
      gin_server_admin/router/wechatapp/callback.go
  31. 230
      gin_server_admin/utils/redishandel/myredis.go
  32. 4
      gin_server_admin/其他支持文件/config.yaml

4
gin_server_admin/api/index/assessment/assesshandle.go

@ -219,12 +219,12 @@ func (a *Assessment) AddAssessmentScore(c *gin.Context) {
return return
} }
if requestData.DeductPoints > departDutyCont.Rescore { if requestData.DeductPoints > departDutyCont.Rescore*10 {
response.Result(108, err, "扣分不能高于参考值!", c) response.Result(108, err, "扣分不能高于参考值!", c)
return return
} }
if requestData.ExtraPoints > departDutyCont.Rescore { if requestData.ExtraPoints > departDutyCont.Rescore*10 {
response.Result(108, err, "加分不能高于参考值!", c) response.Result(108, err, "加分不能高于参考值!", c)
return return
} }

1
gin_server_admin/api/v1/custom/customhandle.go

@ -59,6 +59,7 @@ func (cu *CustomHandle) CustomLogin(c *gin.Context) {
redisClient := redishandel.RunRedis() redisClient := redishandel.RunRedis()
redisClient.SetRedisTime(10800) redisClient.SetRedisTime(10800)
// redisClient.SetRedisTime(60)
writeRedisData := map[string]interface{}{ writeRedisData := map[string]interface{}{
"userkey": user.KeyStr, "userkey": user.KeyStr,
"usernumber": user.Number, "usernumber": user.Number,

9
gin_server_admin/api/v1/examtestpage/examtype.go

@ -1,5 +1,7 @@
package examtestpage package examtestpage
import "github.com/flipped-aurora/gin-vue-admin/server/commonus"
//获取集团架构参数 //获取集团架构参数
type getGroupType struct { type getGroupType struct {
Parentid int64 `json:"parentid"` Parentid int64 `json:"parentid"`
@ -20,3 +22,10 @@ type groupUser struct {
Number string `json:"number"` Number string `json:"number"`
Children []groupUser `json:"groupUser"` Children []groupUser `json:"groupUser"`
} }
//健康上报查询
type QueryHealthReportType struct {
commonus.PageSetLimt
StartTime string `json:"starttime"`
EndTime string `json:"endtime"`
}

55
gin_server_admin/api/v1/examtestpage/healthreportstathand.go

@ -499,3 +499,58 @@ func (h *HealthReportStat) SendRelevantPersonnelTodayMsg(c *gin.Context) {
response.Result(0, "", "获取成功", c) response.Result(0, "", "获取成功", c)
} }
} }
//查询
func (h *HealthReportStat) QueryHealthReport(c *gin.Context) {
var requestData QueryHealthReportType
c.ShouldBindJSON(&requestData)
if requestData.PageSize == 0 {
requestData.PageSize = 20
}
if requestData.Page <= 0 {
requestData.Page = 1
}
var startTime int64
var endTime int64
startTime = 0
endTime = 0
if requestData.StartTime != "" {
startTimeStr := requestData.StartTime + " 00:00:00"
startTime, _ = commonus.DateToTimeStampEs(startTimeStr)
}
if requestData.EndTime != "" {
endTimeStr := requestData.StartTime + " 23:59:59"
endTime, _ = commonus.DateToTimeStampEs(endTimeStr)
} else {
endTime = time.Now().Unix()
}
offSetPage := commonus.CalculatePages(requestData.Page, requestData.PageSize)
gormDb := global.GVA_DB_HealthReport.Model(&locationing.ReportAddress{})
if startTime != 0 && endTime != 0 {
gormDb = gormDb.Where("`calcultime` BETWEEN ? AND ?", startTime, endTime)
} else if startTime != 0 && endTime == 0 {
gormDb = gormDb.Where("`calcultime` >= ?", startTime)
} else if startTime == 0 && endTime != 0 {
gormDb = gormDb.Where("`calcultime` <= ?", endTime)
}
gormDb = gormDb.Where("(`city` LIKE ? OR `city` LIKE ?)", "%济南%", "%聊城%")
var total int64
totalErr := gormDb.Count(&total).Error
if totalErr != nil {
total = 0
}
var reportAdd []locationing.ReportAddress
assessListerr := gormDb.Limit(requestData.PageSize).Offset(offSetPage).Order("id desc").Find(&reportAdd).Error
if assessListerr != nil {
response.Result(102, assessListerr, "数据获取失败!", c)
return
}
countSum := len(reportAdd)
printData := commonus.OutPutList(total, int64(countSum), requestData.Page, requestData.PageSize, reportAdd)
response.Result(0, printData, "查询成功!", c)
}

120
gin_server_admin/api/v1/shiyan/shiyan.go

@ -8,6 +8,7 @@ import (
"strconv" "strconv"
"time" "time"
"github.com/flipped-aurora/gin-vue-admin/server/api/wechatapp/sendmessage"
"github.com/flipped-aurora/gin-vue-admin/server/commonus" "github.com/flipped-aurora/gin-vue-admin/server/commonus"
"github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/approvalprocess" "github.com/flipped-aurora/gin-vue-admin/server/model/approvalprocess"
@ -1022,7 +1023,8 @@ func (s *ShiyanApi) SendButtonMessageAll(c *gin.Context) {
//模板卡片消息 //模板卡片消息
//文本通知型 //文本通知型
func (s *ShiyanApi) SendTextMessageAll(c *gin.Context) { func (s *ShiyanApi) SendTextMessageAll(c *gin.Context) {
var sendTextMsg commonus.TextNotice // var sendTextMsg commonus.TextNotice
var sendTextMsg sendmessage.TextNoticeTemplateSimplify
sendTextMsg.Touser = "KaiXinGuo" sendTextMsg.Touser = "KaiXinGuo"
sendTextMsg.MsgType = "template_card" sendTextMsg.MsgType = "template_card"
appId, _ := strconv.ParseInt(global.GVA_CONFIG.WorkWechatSchool.AgentId, 10, 64) appId, _ := strconv.ParseInt(global.GVA_CONFIG.WorkWechatSchool.AgentId, 10, 64)
@ -1037,16 +1039,16 @@ func (s *ShiyanApi) SendTextMessageAll(c *gin.Context) {
sendTextMsg.TemplateCard.Source.Desc = "知行学院" sendTextMsg.TemplateCard.Source.Desc = "知行学院"
sendTextMsg.TemplateCard.Source.DescColor = 2 sendTextMsg.TemplateCard.Source.DescColor = 2
sendTextMsg.TemplateCard.ActionMenu.Desc = "是否继续关注" // sendTextMsg.TemplateCard.ActionMenu.Desc = "是否继续关注"
var actionList []commonus.ActionListStruct // var actionList []commonus.ActionListStruct
var actionCont commonus.ActionListStruct // var actionCont commonus.ActionListStruct
actionCont.Text = "接受推送" // actionCont.Text = "接受推送"
actionCont.Key = "A" // actionCont.Key = "A"
actionList = append(actionList, actionCont) // actionList = append(actionList, actionCont)
actionCont.Text = "不再推" // actionCont.Text = "不再推"
actionCont.Key = "b" // actionCont.Key = "b"
actionList = append(actionList, actionCont) // actionList = append(actionList, actionCont)
sendTextMsg.TemplateCard.ActionMenu.ActionList = actionList // sendTextMsg.TemplateCard.ActionMenu.ActionList = actionList
//任务id,同一个应用任务id不能重复,只能由数字、字母和“_-@”组成,最长128字节 (必填) //任务id,同一个应用任务id不能重复,只能由数字、字母和“_-@”组成,最长128字节 (必填)
taskId := commonus.GetFileNumberEs() taskId := commonus.GetFileNumberEs()
@ -1056,49 +1058,47 @@ func (s *ShiyanApi) SendTextMessageAll(c *gin.Context) {
sendTextMsg.TemplateCard.MainTitle.Desc = "请你认真查询审批内容!" //标题辅助信息,建议不超过44个字,(支持id转译) sendTextMsg.TemplateCard.MainTitle.Desc = "请你认真查询审批内容!" //标题辅助信息,建议不超过44个字,(支持id转译)
//引用文献样式 //引用文献样式
sendTextMsg.TemplateCard.QuoteArea.Type = 1 // sendTextMsg.TemplateCard.QuoteArea.Type = 1
sendTextMsg.TemplateCard.QuoteArea.Url = "http://www.hxgk.group" // sendTextMsg.TemplateCard.QuoteArea.Url = "http://www.hxgk.group"
sendTextMsg.TemplateCard.QuoteArea.Title = "用车编号" // sendTextMsg.TemplateCard.QuoteArea.Title = "用车编号"
sendTextMsg.TemplateCard.QuoteArea.QuoteText = "用车理由:\n工作需要 \n目的地:宁阳" // sendTextMsg.TemplateCard.QuoteArea.QuoteText = "用车理由:\n工作需要 \n目的地:宁阳"
sendTextMsg.TemplateCard.EmphasisContent.Title = "100" // sendTextMsg.TemplateCard.EmphasisContent.Title = "100"
sendTextMsg.TemplateCard.EmphasisContent.DescStruct.Desc = "核心数据" // sendTextMsg.TemplateCard.EmphasisContent.DescStruct.Desc = "核心数据"
//二级普通文本,建议不超过160个字(非必填) //二级普通文本,建议不超过160个字(非必填)
sendTextMsg.TemplateCard.SubTitleText = "二级普通文本,下载企业微信还能抢红包!" // sendTextMsg.TemplateCard.SubTitleText = "二级普通文本,下载企业微信还能抢红包!"
//二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6(非必填) //二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6(非必填)
var htalConListStrMap []commonus.HorizontalContentListStruct // var htalConListStrMap []sendmessage.HorizontalContentListType
var htalConListStrCon commonus.HorizontalContentListStruct // var htalConListStrCon sendmessage.HorizontalContentListType
htalConListStrCon.Type = 3 // htalConListStrCon.Type = 3
htalConListStrCon.KeyName = "申请人" // htalConListStrCon.KeyName = "申请人"
htalConListStrCon.Value = "秦东" // htalConListStrCon.Value = "秦东"
htalConListStrCon.UserId = "KaiXinGuo" // htalConListStrCon.UserId = "KaiXinGuo"
htalConListStrMap = append(htalConListStrMap, htalConListStrCon) // htalConListStrMap = append(htalConListStrMap, htalConListStrCon)
htalConListStrCon.Type = 1 // htalConListStrCon.Type = 1
htalConListStrCon.KeyName = "企业微信官网" // htalConListStrCon.KeyName = "企业微信官网"
htalConListStrCon.Value = "点击访问" // htalConListStrCon.Value = "点击访问"
htalConListStrCon.Url = "tel:15069130853" // htalConListStrCon.Url = "tel:15069130853"
htalConListStrMap = append(htalConListStrMap, htalConListStrCon) // htalConListStrMap = append(htalConListStrMap, htalConListStrCon)
htalConListStrCon.Type = 3 // htalConListStrCon.Type = 3
htalConListStrCon.KeyName = "乘车人" // htalConListStrCon.KeyName = "乘车人"
htalConListStrCon.Value = "秦东" // htalConListStrCon.Value = "秦东"
htalConListStrCon.UserId = "KaiXinGuo" // htalConListStrCon.UserId = "KaiXinGuo"
htalConListStrMap = append(htalConListStrMap, htalConListStrCon) // htalConListStrMap = append(htalConListStrMap, htalConListStrCon)
sendTextMsg.TemplateCard.HorizontalContentList = htalConListStrMap // sendTextMsg.TemplateCard.HorizontalContentList = htalConListStrMap
var jumpListStruct commonus.JumpListStruct
var jumpListStruct sendmessage.JumpListType
jumpListStruct.Type = 1 jumpListStruct.Type = 1
jumpListStruct.Title = "知行学院官网" jumpListStruct.Title = "查看详情"
jumpListStruct.Url = "http://www.hxgk.group" jumpListStruct.Url = "http://www.hxgk.group"
sendTextMsg.TemplateCard.JumpList = append(sendTextMsg.TemplateCard.JumpList, jumpListStruct) sendTextMsg.TemplateCard.JumpList = append(sendTextMsg.TemplateCard.JumpList, jumpListStruct)
sendTextMsg.TemplateCard.CardAction.Type = 1 sendTextMsg.TemplateCard.CardAction.Type = 1
sendTextMsg.TemplateCard.CardAction.Url = "http://admin.hxgk.group" sendTextMsg.TemplateCard.CardAction.Url = "http://admin.hxgk.group"
callbakcMsg, isTrueCall, callBackCont := sendTextMsg.SendTextTemplateCard() callbakcMsg, isTrueCall, callBackCont := sendTextMsg.SendMessage("school")
outData := commonus.MapOut() outData := commonus.MapOut()
outData["callbakcMsg"] = string(callbakcMsg) outData["callbakcMsg"] = string(callbakcMsg)
outData["isTrueCall"] = isTrueCall outData["isTrueCall"] = isTrueCall
@ -1108,7 +1108,9 @@ func (s *ShiyanApi) SendTextMessageAll(c *gin.Context) {
//图文展示型 //图文展示型
func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) { func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) {
var sendTextMsg commonus.ImageTextTemplate // var sendTextMsg commonus.ImageTextTemplate
var sendTextMsg sendmessage.ImgTextTemplate
sendTextMsg.Touser = "KaiXinGuo" sendTextMsg.Touser = "KaiXinGuo"
sendTextMsg.MsgType = "template_card" sendTextMsg.MsgType = "template_card"
@ -1125,8 +1127,8 @@ func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) {
sendTextMsg.TemplateCard.Source.DescColor = 2 sendTextMsg.TemplateCard.Source.DescColor = 2
sendTextMsg.TemplateCard.ActionMenu.Desc = "是否继续关注" sendTextMsg.TemplateCard.ActionMenu.Desc = "是否继续关注"
var actionList []commonus.ActionListStruct var actionList []sendmessage.ActionListType
var actionCont commonus.ActionListStruct var actionCont sendmessage.ActionListType
actionCont.Text = "接受推送" actionCont.Text = "接受推送"
actionCont.Key = "A" actionCont.Key = "A"
actionList = append(actionList, actionCont) actionList = append(actionList, actionCont)
@ -1157,7 +1159,7 @@ func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) {
sendTextMsg.TemplateCard.CardImage.Url = "https://docu.hxgk.group/images/2022_01/3f7a1120a559e9bee3991b85eb34d103.png" sendTextMsg.TemplateCard.CardImage.Url = "https://docu.hxgk.group/images/2022_01/3f7a1120a559e9bee3991b85eb34d103.png"
sendTextMsg.TemplateCard.CardImage.AspectRatio = 1.3 sendTextMsg.TemplateCard.CardImage.AspectRatio = 1.3
var verCont commonus.VerticalContentListStr var verCont sendmessage.EmphasisContentType
verCont.Title = "惊喜红包等你来拿" verCont.Title = "惊喜红包等你来拿"
verCont.Desc = "下载企业微信还能抢红包!" verCont.Desc = "下载企业微信还能抢红包!"
sendTextMsg.TemplateCard.VerticalContentList = append(sendTextMsg.TemplateCard.VerticalContentList, verCont) sendTextMsg.TemplateCard.VerticalContentList = append(sendTextMsg.TemplateCard.VerticalContentList, verCont)
@ -1165,7 +1167,7 @@ func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) {
verCont.Desc = "====>下载企业微信还能抢红包!" verCont.Desc = "====>下载企业微信还能抢红包!"
sendTextMsg.TemplateCard.VerticalContentList = append(sendTextMsg.TemplateCard.VerticalContentList, verCont) sendTextMsg.TemplateCard.VerticalContentList = append(sendTextMsg.TemplateCard.VerticalContentList, verCont)
var htalConListStrCon commonus.HorizontalContentListStruct var htalConListStrCon sendmessage.HorizontalContentListType
htalConListStrCon.Type = 3 htalConListStrCon.Type = 3
htalConListStrCon.KeyName = "申请人" htalConListStrCon.KeyName = "申请人"
htalConListStrCon.Value = "秦东" htalConListStrCon.Value = "秦东"
@ -1182,7 +1184,7 @@ func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) {
htalConListStrCon.UserId = "KaiXinGuo" htalConListStrCon.UserId = "KaiXinGuo"
sendTextMsg.TemplateCard.HorizontalContentList = append(sendTextMsg.TemplateCard.HorizontalContentList, htalConListStrCon) sendTextMsg.TemplateCard.HorizontalContentList = append(sendTextMsg.TemplateCard.HorizontalContentList, htalConListStrCon)
var jumpListStruct commonus.JumpListStruct var jumpListStruct sendmessage.JumpListType
jumpListStruct.Type = 1 jumpListStruct.Type = 1
jumpListStruct.Title = "知行学院官网" jumpListStruct.Title = "知行学院官网"
@ -1199,7 +1201,7 @@ func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) {
sendTextMsg.TemplateCard.CardAction.Type = 1 sendTextMsg.TemplateCard.CardAction.Type = 1
sendTextMsg.TemplateCard.CardAction.Url = "http://admin.hxgk.group" sendTextMsg.TemplateCard.CardAction.Url = "http://admin.hxgk.group"
callbakcMsg, isTrueCall, callBackCont := sendTextMsg.SendImageTemplateCard() callbakcMsg, isTrueCall, callBackCont := sendTextMsg.SendMessage("school")
outData := commonus.MapOut() outData := commonus.MapOut()
outData["callbakcMsg"] = string(callbakcMsg) outData["callbakcMsg"] = string(callbakcMsg)
outData["isTrueCall"] = isTrueCall outData["isTrueCall"] = isTrueCall
@ -1207,3 +1209,25 @@ func (s *ShiyanApi) SendImageMessageAll(c *gin.Context) {
outData["sendTextMsg"] = sendTextMsg outData["sendTextMsg"] = sendTextMsg
response.Result(0, outData, "查询成功", c) response.Result(0, outData, "查询成功", c)
} }
//获取审批模板详情
func (s *ShiyanApi) GetEatilTemplate(c *gin.Context) {
var requestData sendmessage.TemplatedEtailType
err := c.ShouldBindJSON(&requestData)
if err != nil {
response.Result(101, err, "参数错误!请重新提交!", c)
return
}
// msgbtye, isTrue, msg := requestData.GetTemplatedeTail("school")
msgbtyees, isTruees, msges := sendmessage.JsSdkSignAlgorithm("school")
outData := commonus.MapOut()
// outData["msgbtye"] = msgbtye
// outData["isTrue"] = isTrue
// outData["msg"] = msg
outData["msgbtyees"] = msgbtyees
outData["isTruees"] = isTruees
outData["msges"] = msges
response.Result(0, outData, "查询成功", c)
}

193
gin_server_admin/api/wechatapp/callback/apphandle.go

@ -1,8 +1,17 @@
package callback package callback
import ( import (
"encoding/json"
"encoding/xml"
"fmt"
"strconv"
"time"
"github.com/flipped-aurora/gin-vue-admin/server/commonus" "github.com/flipped-aurora/gin-vue-admin/server/commonus"
"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/model/common/response"
"github.com/flipped-aurora/gin-vue-admin/server/model/wechatcallback"
"github.com/flipped-aurora/gin-vue-admin/server/wechatjiexi/wxbizmsgcrypt"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -11,3 +20,187 @@ func (a *CallBackApi) Index(c *gin.Context) {
outPut := commonus.MapOut() outPut := commonus.MapOut()
response.Result(0, outPut, "企业微信回调入口", c) response.Result(0, outPut, "企业微信回调入口", c)
} }
//回调入口
func (a *CallBackApi) CallbackMessageApi(c *gin.Context) {
MsgSignature := c.Query("msg_signature") //企业微信加密签名,msg_signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体。
Timestamp := c.Query("timestamp") //时间戳。与nonce结合使用,用于防止请求重放攻击。
Nonce := c.Query("nonce") //随机数。与timestamp结合使用,用于防止请求重放攻击。
Echostr := c.Query("echostr") //加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文
var basicValueCallback CallBackData //企业微信回调基础参数
basicValueCallback.MsgSignature = MsgSignature
timeStampInt, timeStampIntErr := strconv.ParseInt(Timestamp, 10, 64)
if timeStampIntErr == nil {
basicValueCallback.Timestamp = timeStampInt
}
basicValueCallback.Nonce = Nonce
if Echostr != "" {
//Api地址验证
basicValueCallback.Echostr = Echostr
msgStr := basicValueCallback.VerificationUrl()
c.String(200, msgStr)
} else {
var xmlMessageStr CallBackVerificationXml
xmlErr := c.ShouldBindXML(&xmlMessageStr)
if xmlErr != nil {
response.Result(101, xmlErr, "XML获取错误!", c)
return
}
// fmt.Printf("Xml----->%v\n", xmlMessageStr)
basicValueCallback.ToUserName = xmlMessageStr.ToUserName.Text
basicValueCallback.Encrypt = xmlMessageStr.Encrypt.Text
basicValueCallback.AgentID = xmlMessageStr.AgentID.Text
basicValueCallback.DecryptMessage()
}
}
//启动企业微信验证程序
func WechatVerification() (wxcpt *wxbizmsgcrypt.WXBizMsgCrypt) {
//正式数据
// token := "kkUA3s2s3"
token := global.GVA_CONFIG.WorkWechatSchool.WechatTokening
receiverId := global.GVA_CONFIG.WorkWechatId.CompanyId
encodingAeskey := global.GVA_CONFIG.WorkWechatSchool.EncodingAESKey
// fmt.Printf("------->%v------->%v------->%v\n", token, receiverId, encodingAeskey)
//测试数据
// token := "QDG6eK"
// receiverId := "wx5823bf96d3bd56c7"
// encodingAeskey := "jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C"
wxcpt = wxbizmsgcrypt.NewWXBizMsgCrypt(token, encodingAeskey, receiverId, wxbizmsgcrypt.XmlType)
return
}
//验证URL
func (c *CallBackData) VerificationUrl() (msg string) {
wecahtCpt := WechatVerification()
timestampStr := strconv.FormatInt(c.Timestamp, 10)
echoStr, cryptErr := wecahtCpt.VerifyURL(c.MsgSignature, timestampStr, c.Nonce, c.Echostr)
var callbackLog wechatcallback.CallbackLog
//
callbackLog.MsgSignature = c.MsgSignature
callbackLog.TimeStamp = c.Timestamp
callbackLog.Nonce = c.Nonce
callbackLog.Echostr = c.Echostr
callbackLog.Xmlstr = string(echoStr)
// callbackLog.Reqdata = string(reqData)
callbackLog.AddTime = time.Now().Unix()
global.GVA_DB_WechatCallBack.Create(&callbackLog)
if nil != cryptErr {
fmt.Println("verifyUrl fail", cryptErr)
}
msg = string(echoStr)
return
// fmt.Println(string(echoStr))
// fmt.Print(string(echoStr))
}
//解析消息结构
func (c *CallBackData) DecryptMessage() {
wecahtCpt := WechatVerification()
timestampStr := strconv.FormatInt(c.Timestamp, 10)
reqData := []byte("<xml><ToUserName><![CDATA[" + c.ToUserName + "]]></ToUserName><Encrypt><![CDATA[" + c.Encrypt + "]]></Encrypt><AgentID><![CDATA[" + c.AgentID + "]]></AgentID></xml>")
msg, cryptErr := wecahtCpt.DecryptMsg(c.MsgSignature, timestampStr, c.Nonce, reqData)
// fmt.Printf("%v=====>%v=====>%v\n: ", c.ToUserName, c.Encrypt, c.AgentID)
if nil != cryptErr {
fmt.Println("DecryptMsg fail", cryptErr)
}
// fmt.Println("after decrypt msg: ", string(msg))
var msgContent MsgContent
err := xml.Unmarshal(msg, &msgContent)
if nil != err {
fmt.Println("Unmarshal fail")
}
// fmt.Printf("1========>%v========>%v\n ", msgContent.MsgType, msgContent.Event)
switch msgContent.MsgType {
/*消息格式类型
*/
case "text": //文本
case "image": //图片
case "voice": //语音
case "video": //视频
case "location": //位置
case "link": //链接
/*事件格式类型*/
case "event":
/*
事件附属格式
*/
EventProcessing(msgContent.Event, msg)
default:
}
var callbackLog wechatcallback.CallbackLog
//
callbackLog.MsgSignature = c.MsgSignature
callbackLog.TimeStamp = c.Timestamp
callbackLog.Nonce = c.Nonce
callbackLog.Echostr = c.Echostr
callbackLog.Xmlstr = string(msg)
callbackLog.Reqdata = string(reqData)
msgCont, jsonErr := json.Marshal(msgContent)
if jsonErr == nil {
callbackLog.Jsonstr = string(msgCont)
}
callbackLog.AddTime = time.Now().Unix()
if msgContent.Event != "LOCATION" {
global.GVA_DB_WechatCallBack.Create(&callbackLog)
}
}
//企业微信事件处理
func EventProcessing(event string, decryptMsg []byte) {
var msgContent MsgContentMailList
err := xml.Unmarshal(decryptMsg, &msgContent)
if nil != err {
fmt.Println("Unmarshal fail")
}
switch event {
case "subscribe": //关注
case "unsubscribe": //取消关注
case "enter_agent": //本事件在成员进入企业微信的应用时触发
case "LOCATION": //上报地理位置
GeographicalPosition(decryptMsg)
case "batch_job_result": //异步任务完成事件推送
case "change_contact": //通讯录变更事件
WorkWechatMailList(msgContent.ChangeType, decryptMsg)
case "click": //点击菜单拉取消息的事件推送
case "view": //点击菜单跳转链接的事件推送
case "scancode_push": //扫码推事件的事件推送
case "scancode_waitmsg": //扫码推事件且弹出“消息接收中”提示框的事件推送
case "pic_sysphoto": //弹出系统拍照发图的事件推送
case "pic_photo_or_album": //弹出拍照或者相册发图的事件推送
case "pic_weixin": //弹出微信相册发图器的事件推送
case "location_select": //弹出地理位置选择器的事件推送
case "open_approval_change": //审批状态通知事件
case "share_agent_change": //企业互联共享应用事件回调
case "share_chain_change": //上下游共享应用事件回调
case "template_card_event": //模板卡片事件推送
templateEventPush(decryptMsg)
case "template_card_menu_event": //通用模板卡片右上角菜单事件推送
default:
}
}
//企业微信通讯录变更事件处理
func WorkWechatMailList(changeType string, decryptMsg []byte) {
switch changeType {
case "create_party": //新增部门事件
case "update_party": //更新部门事件
case "delete_party": //删除部门事件
case "update_tag": //标签成员变更事件
case "batch_job_result": //异步任务完成事件推送
case "change_contact": //通讯录变更事件
case "create_user": //新增成员事件
case "update_user": //更新成员事件
case "delete_user": //删除成员事件
default:
}
}

67
gin_server_admin/api/wechatapp/callback/eventprocessing.go

@ -0,0 +1,67 @@
package callback
import (
"encoding/json"
"encoding/xml"
"fmt"
"strconv"
"time"
"github.com/flipped-aurora/gin-vue-admin/server/commonus"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/utils/redishandel"
)
//相关事件处理
func GeographicalPosition(eventMsg []byte) {
var msgContent GeographicalPositionType
err := xml.Unmarshal(eventMsg, &msgContent)
if nil != err {
fmt.Println("***********Unmarshal fail")
}
userAddress := commonus.MapOut()
userAddress["userid"] = msgContent.FromUsername //userID
userAddress["latitude"] = msgContent.Latitude //地理位置纬度
userAddress["longitude"] = msgContent.Longitude //地理位置经度
userAddress["precision"] = msgContent.Precision //地理位置精度
userAddress["time"] = time.Now().Unix()
marshal, err := json.Marshal(userAddress)
if err != nil {
marshal = []byte{}
}
redisPrefix := "Location:GeographicalPosition_" + global.GVA_CONFIG.RedisPrefix.PreFix + ":userId_" + msgContent.FromUsername //redis KEY
redisClient := redishandel.RunRedis()
redisClient.SetRedisDb(1)
// fmt.Printf("button===101===>%v\n", string(marshal))
locationJson, locationErr := redisClient.Lindex(redisPrefix, 0)
// fmt.Printf("button===102===>%v===>%v\n", locationJson, locationErr)
if locationErr != nil {
redisClient.Lpush(redisPrefix, string(marshal))
// fmt.Printf("button===1===>%v\n", marshal)
} else {
var geographicalPositionRedis GeographicalPositionRedis
jsonErr := json.Unmarshal([]byte(locationJson), &geographicalPositionRedis)
// fmt.Printf("button===2111===>%v===>%v\n", jsonErr, geographicalPositionRedis)
if jsonErr != nil {
redisClient.Lpush(redisPrefix, string(marshal))
// fmt.Printf("button===2===>%v===>%v\n", jsonErr, locationJson)
} else {
timeVal := geographicalPositionRedis.Time
if time.Now().Unix()-timeVal >= 1800 {
redisClient.Lpush(redisPrefix, string(marshal))
// fmt.Printf("button===4===>%v\n", marshal)
} else {
// fmt.Printf("button===412===>%v===>%v\n", timeVal, time.Now().Unix()-timeVal)
}
}
}
longFloat, _ := strconv.ParseFloat(msgContent.Longitude, 64)
latFloat, _ := strconv.ParseFloat(msgContent.Latitude, 64)
long, latg := commonus.GCJ02toBD09(longFloat, latFloat)
fmt.Printf("button======>%v======>%v======>%v\n", msgContent, long, latg)
}

99
gin_server_admin/api/wechatapp/callback/type.go

@ -2,3 +2,102 @@ package callback
//企业微信回调 //企业微信回调
type CallBackApi struct{} type CallBackApi struct{}
//企业微信回调基础参数
type CallBackData struct {
MsgSignature string `json:"msg_signature"`
Timestamp int64 `json:"timestamp"`
Nonce string `json:"nonce"`
Echostr string `json:"echostr"`
ToUserName string `json:"tousername"`
AgentID string `json:"agentid"`
Encrypt string `json:"encrypt"`
}
//企业微信回调验证(xml)
type CallBackVerificationXml struct {
ToUserName struct {
CallBackText
} `xml:"ToUserName"`
AgentID struct {
CallBackText
} `xml:"AgentID"`
Encrypt struct {
CallBackText
} `xml:"Encrypt"`
}
type CallBackText struct {
Text string `xml:",chardata"`
}
//通用更新切片
type CurrencyMessage struct {
ToUsername string `xml:"ToUserName"`
FromUsername string `xml:"FromUserName"`
CreateTime uint32 `xml:"CreateTime"`
MsgType string `xml:"MsgType"`
Agentid uint32 `xml:"AgentID"`
Event string `xml:"Event"`
EventKey string `xml:"EventKey"`
// TaskId string `xml:"TaskId"`
}
//XML数据解密
type MsgContent struct {
CurrencyMessage
Content string `xml:"Content"`
Msgid string `xml:"MsgId"`
}
//上报地理位置
type GeographicalPositionType struct {
CurrencyMessage
Latitude string `xml:"Latitude"`
Longitude string `xml:"Longitude"`
Precision string `xml:"Precision"`
AppType string `xml:"AppType"`
}
//上报地理位置Redis
type GeographicalPositionRedis struct {
UserId string `json:"userid"`
Latitude string `json:"latitude"`
Longitude string `json:"longitude"`
Precision string `json:"precision"`
Time int64 `json:"time"`
}
//通讯录主表
type MsgContentMailList struct {
MsgContent
ChangeType string `xml:"ChangeType"`
}
/*
模板卡片事件推送
*/
//通用模板卡片右上角菜单事件推送
type TemplateCardPushCurrency struct {
CurrencyMessage
TaskId string `xml:"TaskId"`
CardType string `xml:"CardType"`
ResponseCode string `xml:"ResponseCode"`
}
//模板卡片事件推送
type TemplateCardPush struct {
TemplateCardPushCurrency
SelectedItems SelectedItemStruct `xml:"SelectedItems"`
}
//卡片右上角事件
type SelectedItemStruct struct {
SelectedItem []SelectedItemList `xml:"SelectedItem"`
}
type SelectedItemList struct {
QuestionKey string `xml:"QuestionKey"`
OptionIds []OptionIdsStr `xml:"OptionIds"`
}
type OptionIdsStr struct {
OptionId string `xml:"OptionId"`
}

31
gin_server_admin/api/wechatapp/callback/updatehandle.go

@ -0,0 +1,31 @@
package callback
import (
"encoding/json"
"encoding/xml"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/commonus"
)
//更新数据
func templateEventPush(eventMsg []byte) {
var msgContent TemplateCardPush
err := xml.Unmarshal(eventMsg, &msgContent)
if nil != err {
fmt.Println("***********Unmarshal fail")
}
fmt.Printf("button======>%v\n", msgContent)
jsonStr, _ := json.Marshal(msgContent)
fmt.Printf("jsonStr======>%v\n", string(jsonStr))
var updateButtonNotClickable commonus.UpdateButtonNotClickable
updateButtonNotClickable.Userids = append(updateButtonNotClickable.Userids, "KaiXinGuo")
updateButtonNotClickable.Atall = 0
updateButtonNotClickable.Agentid = msgContent.Agentid
updateButtonNotClickable.ResponseCode = msgContent.ResponseCode
updateButtonNotClickable.Button.ReplaceName = "已提交更新"
callbakcMsg, isTrueCall, callBackCont := updateButtonNotClickable.UpdateSendButtonMessage()
fmt.Printf("更新销售发送信息返回:%v-----------%v----------->%v\n", string(callbakcMsg), isTrueCall, callBackCont)
}

2
gin_server_admin/api/wechatapp/enter.go

@ -1,8 +1,8 @@
package wechatapp package wechatapp
import ( import (
"github.com/flipped-aurora/gin-vue-admin/server/api/wechatapp/callback"
"github.com/flipped-aurora/gin-vue-admin/server/api/wechatapp/sendmessage" "github.com/flipped-aurora/gin-vue-admin/server/api/wechatapp/sendmessage"
"github.com/flipped-aurora/gin-vue-admin/server/api/workwechatcallback/callback"
) )
//企业微信应用 //企业微信应用

152
gin_server_admin/api/wechatapp/sendmessage/apphandle.go

@ -1,6 +1,9 @@
package sendmessage package sendmessage
import ( import (
"encoding/json"
"github.com/flipped-aurora/gin-vue-admin/server/api/wechatapp/sharemethod"
"github.com/flipped-aurora/gin-vue-admin/server/commonus" "github.com/flipped-aurora/gin-vue-admin/server/commonus"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response" "github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@ -11,3 +14,152 @@ func (s *SendMessageApi) Index(c *gin.Context) {
outPut := commonus.MapOut() outPut := commonus.MapOut()
response.Result(0, outPut, "企业微信回调入口", c) response.Result(0, outPut, "企业微信回调入口", c)
} }
//发送文本信息
func (s *SendText) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//文本卡片消息
func (s *TextcardStruct) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//发送markdown文本信息
func (s *SendMarkDown) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//发送图文信息
func (s *SendImgCont) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//图文消息(mpnews)
func (s *NewsImages) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
/**
============================================================================================================================
模板卡片消息
============================================================================================================================
*/
//文本通知型
func (s *TextNoticeTemplate) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//文本通知型简化
func (s *TextNoticeTemplateSimplify) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//图文展示型
func (s *ImgTextTemplate) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//图文展示型(简化)
func (s *ImgTextTemplateSimplify) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//按钮交互型
func (s *ButtonTemplate) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//投票选择型
func (s *VoteTemplate) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//多项选择型
func (s *MultipleTemplate) SendMessage(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetSendMsgTokenUrl(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
// fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}

29
gin_server_admin/api/wechatapp/sendmessage/examineapprove.go

@ -0,0 +1,29 @@
package sendmessage
import (
"encoding/json"
"fmt"
"github.com/flipped-aurora/gin-vue-admin/server/api/wechatapp/sharemethod"
"github.com/flipped-aurora/gin-vue-admin/server/commonus"
)
//审批相关操作
func (s *TemplatedEtailType) GetTemplatedeTail(appName string) ([]byte, bool, string) {
sendUrl, IsTrue, msg := sharemethod.GetExamineApprove(appName)
if IsTrue == false {
return nil, false, msg
}
sendJsonData, _ := json.Marshal(s)
addDePartMent := commonus.CurlPostJosn(sendUrl, sendJsonData)
fmt.Printf("%v-------------->%v\n", string(sendJsonData), string(addDePartMent))
return addDePartMent, true, msg
}
//获取企业的jsapi_ticket
//计算JS-SDK使用权限签名算法
func JsSdkSignAlgorithm(appName string) (sendUrlstr string, isTrue bool, msg string) {
sendUrlstr, isTrue, msg = sharemethod.GetExamineApproveSign(appName, 1)
return
}

418
gin_server_admin/api/wechatapp/sendmessage/type.go

@ -2,3 +2,421 @@ package sendmessage
//向企业微信发送信息 //向企业微信发送信息
type SendMessageApi struct{} type SendMessageApi struct{}
//消息类型
type SendPublic struct {
Touser string `json:"touser" form:"touser"`
ToParty string `json:"toparty" form:"toparty"`
ToTag string `json:"totag" form:"totag"`
MsgType string `json:"msgtype" form:"msgtype"`
AgentId int64 `json:"agentid" form:"agentid"`
EnableDuplicateCheck int `json:"enable_duplicate_check" form:"enable_duplicate_check"`
DuplicateCheckInterval int `json:"duplicate_check_interval" form:"duplicate_check_interval"`
}
//文本消息
type SendText struct {
SendPublic
Safe int `json:"safe" form:"safe"`
EnableIdTrans int `json:"enable_id_trans" form:"enable_id_trans"`
Text SendTextStruct `json:"text" form:"text"`
}
type SendTextStruct struct {
Content string `json:"content" form:"content"`
}
//markdown消息
type SendMarkDown struct {
SendPublic
Text SendTextStruct `json:"markdown" form:"markdown"`
}
//发送图文信息
type SendImgCont struct {
SendPublic
EnableIdTrans int `json:"enable_id_trans" form:"enable_id_trans"`
News SendNewsStruct `json:"news" form:"news"`
}
//图文具体内容
type SendNewsStruct struct {
Articles []ArticlesStruct `json:"articles" form:"articles"`
}
type ArticlesStruct struct {
Title string `json:"title" form:"title"`
Description string `json:"description" form:"description"`
URL string `json:"url" form:"url"`
Picurl string `json:"picurl" form:"picurl"`
Appid string `json:"appid" form:"appid"`
Pagepath string `json:"pagepath" form:"pagepath"`
}
//图片类型
type SendPicture struct {
SendPublic
Images MediaIdStruct `json:"image" form:"image"`
Safe int `json:"safe" form:"safe"`
}
type MediaIdStruct struct {
MediaId string `json:"media_id" form:"media_id"`
}
//语音信息
type VoiceMsg struct {
SendPublic
Voice MediaIdStruct `json:"image" form:"voice"`
}
//视频消息
type VideoStruct struct {
SendPublic
Safe int `json:"safe" form:"safe"`
Video VideoListStruct `json:"image" form:"video"`
}
type VideoListStruct struct {
MediaIdStruct
Title string `json:"title" form:"title"`
Description string `json:"description" form:"description"`
}
//文件消息
type FileStruct struct {
SendPublic
Safe int `json:"safe" form:"safe"`
File MediaIdStruct `json:"file" form:"file"`
}
//文本卡片消息
type TextcardStruct struct {
SendPublic
EnableIdTrans int `json:"enable_id_trans" form:"enable_id_trans"`
Textcard TextcardCont `json:"textcard" form:"textcard"`
}
type TextcardCont struct {
Title string `json:"title" form:"title"`
Description string `json:"description" form:"description"`
URL string `json:"url" form:"url"`
Btntxt string `json:"btntxt" form:"btntxt"`
}
//图文消息(mpnews)
type NewsImages struct {
SendPublic
EnableIdTrans int `json:"enable_id_trans" form:"enable_id_trans"`
Mpnews SendNewsStructs `json:"mpnews" form:"mpnews"`
Safe int `json:"safe" form:"safe"`
}
type SendNewsStructs struct {
Articles []ArticlesStructs `json:"articles" form:"articles"`
}
type ArticlesStructs struct {
Title string `json:"title" form:"title"`
ThumbMediaId string `json:"thumb_media_id" form:"thumb_media_id"`
Author string `json:"author" form:"author"`
ContentSourceUrl string `json:"content_source_url" form:"content_source_url"`
Content string `json:"content" form:"content"`
Digest string `json:"digest" form:"digest"`
}
/**
============================================================================================================================
模板卡片消息
============================================================================================================================
*/
//通用字段
type ShareField struct {
Touser string `json:"touser"`
ToParty string `json:"toparty"`
ToTag string `json:"totag"`
MsgType string `json:"msgtype"`
AgentId int64 `json:"agentid"`
EnableIdTrans int `json:"enable_id_trans"`
EnableDuplicateCheck int `json:"enable_duplicate_check"`
DuplicateCheckInterval int `json:"duplicate_check_interval"`
}
//任务id,同一个应用任务id不能重复,只能由数字、字母和“_-@”组成,最长128字节,填了action_menu字段的话本字段必填
type TaskIdType struct {
TaskId string `json:"task_id"`
}
//模板卡片类型
type CardTypeClass struct {
CardType string `json:"card_type"`
}
//操作描述
type DescStruct struct {
Desc string `json:"desc"`
}
//操作的描述文案标题
type TitleType struct {
Title string `json:"title"`
}
//卡片来源样式信息,不需要来源样式可不填写
type SourceType struct {
IconUrl string `json:"icon_url"`
DescStruct
DescColor int `json:"desc_color"`
}
//卡片右上角更多操作按钮
type ActionMenuType struct {
DescStruct
ActionList []ActionListType `json:"action_list"`
}
//卡片右上角操作列表,列表长度取值范围为 [1, 3]
type ActionListType struct {
Text string `json:"text"` //操作的描述文案
Key string `json:"key"` //操作key值,用户点击后,会产生回调事件将本参数作为EventKey返回,回调事件会带上该key值,最长支持1024字节,不可重复
}
//一级标题属性
type MainTitleType struct {
TitleType
DescStruct
}
//引用文献
type QuoteAreaType struct {
UrlAndType
Title string `json:"title"`
QuoteText string `json:"quote_text"`
AppletField
}
//关键数据样式
type EmphasisContentType struct {
TitleType
DescStruct
}
//二级普通文本,建议不超过160个字,(支持id转译)
type SubTitleTextType struct {
SubTitleText string `json:"sub_title_text"`
}
//二级标题+文本列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过6
type HorizontalContentListType struct {
UrlAndType
KeyName string `json:"keyname"`
Value string `json:"value"`
MediaId string `json:"media_id"`
UserId string `json:"userid"`
}
//跳转指引样式的列表,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过3
type JumpListType struct {
UrlAndType
Title string `json:"title"`
AppletField
}
//整体卡片的点击跳转事件,text_notice必填本字段
type CardActionType struct {
UrlAndType
AppletField
}
//类型和地址
type UrlAndType struct {
Type int `json:"type"`
Url string `json:"url"`
}
//小程序相关字段
type AppletField struct {
Appid string `json:"appid"`
Pagepath string `json:"pagepath"`
}
//左图右文样式,news_notice类型的卡片,card_image和image_text_area两者必填一个字段,不可都不填
type ImageTextAreaType struct {
UrlAndType
EmphasisContentType
ImageUrl string `json:"image_url"`
}
//图片样式,news_notice类型的卡片,card_image和image_text_area两者必填一个字段,不可都不填
type CardImageType struct {
Url string `json:"url"`
AspectRatio float32 `json:"aspect_ratio"`
}
//下拉式的选择器的
type ButtonSelectionType struct {
QuestionKey string `json:"question_key"`
Title string `json:"title"`
SelectedId string `json:"selected_id"`
OptionList []OptionListType `json:"option_list"` //选项列表,下拉选项不超过 10 个,最少1个
}
//选项列表,下拉选项不超过 10 个,最少1个
type OptionListType struct {
Id string `json:"id"`
Text string `json:"text"`
IsChecked bool `json:"is_checked"`
}
//按钮列表,列表长度不超过6
type ButtonListtype struct {
UrlAndType
ActionListType
Style int `json:"style"`
}
//选择题样式
type CheckBoxType struct {
QuestionKey string `json:"question_key"`
OptionList []OptionListType `json:"option_list"` //选项列表,下拉选项不超过 10 个,最少1个
Mode int `json:"mode"`
}
//模板卡片通用参数
type ShareTemplateCard struct {
CardTypeClass
Source SourceType `json:"source"` //卡片来源样式信息,不需要来源样式可不填写
TaskIdType
}
//文本结构体(完整版)
type TextTemplateCardType struct {
ShareTemplateCard
MainTitle MainTitleType `json:"main_title"` //一级标题
ActionMenu ActionMenuType `json:"action_menu"` //卡片右上角更多操作按钮
QuoteArea QuoteAreaType `json:"quote_area"` //引用文献样式
EmphasisContent EmphasisContentType `json:"emphasis_content"` //关键数据样式
SubTitleTextType //二级普通文本
HorizontalContentList []HorizontalContentListType `json:"horizontal_content_list"` //二级标题+文本列表
JumpList []JumpListType `json:"jump_list"` //跳转指引样式的列表,该字段可为空数组
CardAction CardActionType `json:"card_action"`
}
//文本通知型(完整版)
type TextNoticeTemplate struct {
ShareField
TemplateCard TextTemplateCardType `json:"template_card"`
}
//文本结构体(简化)
type TextTemplateCardTypeSimplify struct {
ShareTemplateCard
MainTitle MainTitleType `json:"main_title"`
JumpList []JumpListType `json:"jump_list"` //跳转指引样式的列表,该字段可为空数组
CardAction CardActionType `json:"card_action"`
}
//文本通知型(简化)
type TextNoticeTemplateSimplify struct {
ShareField
TemplateCard TextTemplateCardTypeSimplify `json:"template_card"`
}
//图文展示型(完整版)
type ImgTextTemplateCardType struct {
ShareTemplateCard
MainTitle MainTitleType `json:"main_title"`
ActionMenu ActionMenuType `json:"action_menu"` //卡片右上角更多操作按钮
QuoteArea QuoteAreaType `json:"quote_area"` //引用文献样式
ImageTextArea ImageTextAreaType `json:"image_text_area"` //左图右文样式,news_notice类型的卡片,card_image和image_text_area两者必填一个字段,不可都不填
CardImage CardImageType `json:"card_image"` //图片样式,news_notice类型的卡片,card_image和image_text_area两者必填一个字段,不可都不填
VerticalContentList []EmphasisContentType `json:"vertical_content_list"` //卡片二级垂直内容,该字段可为空数组,但有数据的话需确认对应字段是否必填,列表长度不超过4
HorizontalContentList []HorizontalContentListType `json:"horizontal_content_list"` //二级标题+文本列表
JumpList []JumpListType `json:"jump_list"` //跳转指引样式的列表,该字段可为空数组
CardAction CardActionType `json:"card_action"`
}
//图文展示型(完整版)
type ImgTextTemplate struct {
ShareField
TemplateCard ImgTextTemplateCardType `json:"template_card"`
}
//图文展示型(简化)
type ImgTextTemplateCardTypeSimplify struct {
ShareTemplateCard
QuoteArea QuoteAreaType `json:"quote_area"` //引用文献样式
CardImage CardImageType `json:"card_image"` //图片样式,news_notice类型的卡片,card_image和image_text_area两者必填一个字段,不可都不填
JumpList []JumpListType `json:"jump_list"` //跳转指引样式的列表,该字段可为空数组
CardAction CardActionType `json:"card_action"`
}
//图文展示型(简化)
type ImgTextTemplateSimplify struct {
ShareField
TemplateCard ImgTextTemplateCardTypeSimplify `json:"template_card"`
}
//按钮交互型(完整版)
type ButtonTemplateCardType struct {
ShareTemplateCard
MainTitle MainTitleType `json:"main_title"`
ActionMenu ActionMenuType `json:"action_menu"` //卡片右上角更多操作按钮
QuoteArea QuoteAreaType `json:"quote_area"` //引用文献样式
SubTitleTextType
ButtonSelection ButtonSelectionType `json:"button_selection"` //下拉式的选择器的
ButtonList []ButtonListtype `json:"button_list"` //按钮列表,列表长度不超过6
HorizontalContentList []HorizontalContentListType `json:"horizontal_content_list"` //二级标题+文本列表
CardAction CardActionType `json:"card_action"`
}
//按钮交互型(完整版)
type ButtonTemplate struct {
ShareField
TemplateCard ButtonTemplateCardType `json:"template_card"`
}
//投票选择型(完整版)
type VoteTemplateCardType struct {
ShareTemplateCard
MainTitle MainTitleType `json:"main_title"`
CheckBox CheckBoxType `json:"checkbox"` //选择题样式
SubmitButton ActionListType `json:"submit_button"` //提交按钮样式
}
//投票选择型(完整版)
type VoteTemplate struct {
ShareField
TemplateCard VoteTemplateCardType `json:"template_card"`
}
//多项选择型(完整版)
type MultipleTemplateCardType struct {
ShareTemplateCard
MainTitle MainTitleType `json:"main_title"`
SelectList []ButtonSelectionType `json:"select_list"` //下拉式的选择器列表,multiple_interaction类型的卡片该字段不可为空,一个消息最多支持 3 个选择器
SubmitButton ActionListType `json:"submit_button"` //提交按钮样式
}
//多项选择型(完整版)
type MultipleTemplate struct {
ShareField
TemplateCard MultipleTemplateCardType `json:"template_card"`
}
/*
=====================================================================================================
企业微信审批相关
=====================================================================================================
*/
//审批模板详情
type TemplatedEtailType struct {
TemplateId string `json:"template_id"`
}

156
gin_server_admin/api/wechatapp/sharemethod/handle.go

@ -0,0 +1,156 @@
package sharemethod
import (
"encoding/json"
"github.com/flipped-aurora/gin-vue-admin/server/commonus"
"github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/flipped-aurora/gin-vue-admin/server/utils/redishandel"
)
//获取企业微信token
//获取企业微信token
func GetWechatToken(types string) (tokenInfo string, redisClient *redishandel.RedisStoreType, err error) {
redisClient = redishandel.RunRedis()
redisClient.SetRedisDb(1)
isTrue := false
companyId := global.GVA_CONFIG.WorkWechatId.CompanyId //企业ID
secretStr := global.GVA_CONFIG.WorkWechatSchool.SecretStr //应用Secret
redisPrefix := global.GVA_CONFIG.RedisPrefix.PreFix + ":WorkWeChatToken_" //redis 前缀
switch types {
case "maillist":
redisPrefix = redisPrefix + "Mail_"
secretStr = global.GVA_CONFIG.WorkWechatMailList.SecretStr
case "health":
redisPrefix = redisPrefix + "Health_"
secretStr = global.GVA_CONFIG.WorkHealthReport.SecretStr
case "school":
redisPrefix = redisPrefix + "School_"
secretStr = global.GVA_CONFIG.WorkWechatSchool.SecretStr
default:
}
isTrue, tokenInfo = redisClient.Get(redisPrefix + global.GVA_CONFIG.RedisPrefix.Alias)
if isTrue == true {
return
} else {
//企业微信获取token地址
getTokenUrl := "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + companyId + "&corpsecret=" + secretStr
token := commonus.CurlGet(getTokenUrl) //访问token地址
var callBackData weChatCallBack
err = json.Unmarshal(token, &callBackData)
if err != nil {
return
}
if callBackData.Errcode != 0 {
return
}
tokenInfo = callBackData.Accesstoken
redisClient.SetRedisTime(7200)
redisClient.Set(redisPrefix+global.GVA_CONFIG.RedisPrefix.Alias, tokenInfo)
}
return
}
//获取发送应用消息地址及相关地址参数
func GetSendMsgTokenUrl(appName string) (sendUrlstr string, isTrue bool, msg string) {
isTrue = false
ton, _, err := GetWechatToken(appName)
if err != nil {
msg = "获取ToKen失败!"
return
}
isTrue = true
msg = "获取ToKen成功!"
sendUrlstr = "https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=" + ton
return
}
//获取更新模板消息地址及相关地址参数
func GetUpdateMsgTokenUrl(appName string) (sendUrlstr string, isTrue bool, msg string) {
isTrue = false
ton, _, err := GetWechatToken(appName)
if err != nil {
msg = "获取ToKen失败!"
return
}
isTrue = true
msg = "获取ToKen成功!"
sendUrlstr = "https://qyapi.weixin.qq.com/cgi-bin/message/update_template_card?access_token=" + ton
return
}
//获取审批模板详情
func GetExamineApprove(appName string) (sendUrlstr string, isTrue bool, msg string) {
isTrue = false
ton, _, err := GetWechatToken(appName)
if err != nil {
msg = "获取ToKen失败!"
return
}
isTrue = true
msg = "获取ToKen成功!"
sendUrlstr = "https://qyapi.weixin.qq.com/cgi-bin/oa/gettemplatedetail?access_token=" + ton
return
}
//获取企业的jsapi_ticket 或 获取应用的jsapi_ticket
//获取审批模板详情
func GetExamineApproveSign(appName string, state int) (sendUrlstr string, isTrue bool, msg string) {
isTrue = false
ton, _, err := GetWechatToken(appName)
if err != nil {
msg = "获取ToKen失败!"
return
}
isTrue = true
msg = "获取ToKen成功!"
state = 1
if state != 1 {
sendUrlstr = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=" + ton
} else {
sendUrlstr = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=" + ton + "&type=agent_config"
}
msg, err = GetJsapiTicket(appName, sendUrlstr)
if err != nil {
isTrue = false
}
return
}
func GetJsapiTicket(types, callUrl string) (tokenInfo string, err error) {
redisClient := redishandel.RunRedis()
redisClient.SetRedisDb(1)
isTrue := false
redisPrefix := global.GVA_CONFIG.RedisPrefix.PreFix + ":WorkJsapiTicket_" //redis 前缀
switch types {
case "maillist":
redisPrefix = redisPrefix + "Mail_"
case "health":
redisPrefix = redisPrefix + "Health_"
case "school":
redisPrefix = redisPrefix + "School_"
default:
}
isTrue, tokenInfo = redisClient.Get(redisPrefix + global.GVA_CONFIG.RedisPrefix.Alias)
if isTrue == true {
return
} else {
//企业微信获取token地址
token := commonus.CurlGet(callUrl) //访问token地址
var callBackData weChatCallBack
err = json.Unmarshal(token, &callBackData)
if err != nil {
return
}
if callBackData.Errcode != 0 {
return
}
tokenInfo = callBackData.Accesstoken
redisClient.SetRedisTime(7200)
redisClient.Set(redisPrefix+global.GVA_CONFIG.RedisPrefix.Alias, tokenInfo)
}
return
}

9
gin_server_admin/api/wechatapp/sharemethod/type.go

@ -0,0 +1,9 @@
package sharemethod
//组织架构返回统类
type weChatCallBack struct {
Errcode int `json:"errcode"`
Errmsg string `json:"errmsg"`
Accesstoken string `json:"access_token"`
Expiresin int64 `json:"expires_in"`
}

2
gin_server_admin/api/workwechatcallback/callback/callbacktype.go → gin_server_admin/api/workwechatcallback/callbackes/callbacktype.go

@ -1,4 +1,4 @@
package callback package callbackes
//企业微信回调 //企业微信回调
type WorkWeChatCallBackApi struct{} type WorkWeChatCallBackApi struct{}

2
gin_server_admin/api/workwechatcallback/callback/enter.go → gin_server_admin/api/workwechatcallback/callbackes/enter.go

@ -1,4 +1,4 @@
package callback package callbackes
//企业微信回调 //企业微信回调
type ApiGroup struct { type ApiGroup struct {

4
gin_server_admin/api/workwechatcallback/callback/workwechatcallback.go → gin_server_admin/api/workwechatcallback/callbackes/workwechatcallback.go

@ -1,4 +1,4 @@
package callback package callbackes
import ( import (
"github.com/flipped-aurora/gin-vue-admin/server/commonus" "github.com/flipped-aurora/gin-vue-admin/server/commonus"
@ -9,5 +9,5 @@ import (
//验证URL //验证URL
func (w *WorkWeChatCallBackApi) Index(c *gin.Context) { func (w *WorkWeChatCallBackApi) Index(c *gin.Context) {
outPut := commonus.MapOut() outPut := commonus.MapOut()
response.Result(0, outPut, "企业微信回调入口", c) response.Result(0, outPut, "企业微信回调入口1231234213", c)
} }

4
gin_server_admin/api/workwechatcallback/enter.go

@ -1,10 +1,10 @@
package workwechatcallback package workwechatcallback
import "github.com/flipped-aurora/gin-vue-admin/server/api/workwechatcallback/callback" import "github.com/flipped-aurora/gin-vue-admin/server/api/workwechatcallback/callbackes"
//企业微信回调 //企业微信回调
type ApiGroup struct { type ApiGroup struct {
WorkWeChatApi callback.ApiGroup WorkWeChatApi callbackes.ApiGroup
} }
var ApiGroupApp = new(ApiGroup) var ApiGroupApp = new(ApiGroup)

111
gin_server_admin/commonus/coordinatetransformation.go

@ -0,0 +1,111 @@
package commonus
import "math"
//地理坐标转换
// WGS84坐标系:即地球坐标系,国际上通用的坐标系。
// GCJ02坐标系:即火星坐标系,WGS84坐标系经加密后的坐标系。Google Maps,高德在用。
// BD09坐标系:即百度坐标系,GCJ02坐标系经加密后的坐标系。
const (
X_PI = math.Pi * 3000.0 / 180.0
OFFSET = 0.00669342162296594323
AXIS = 6378245.0
)
//BD09toGCJ02 百度坐标系->火星坐标系
func BD09toGCJ02(lon, lat float64) (float64, float64) {
x := lon - 0.0065
y := lat - 0.006
z := math.Sqrt(x*x+y*y) - 0.00002*math.Sin(y*X_PI)
theta := math.Atan2(y, x) - 0.000003*math.Cos(x*X_PI)
gLon := z * math.Cos(theta)
gLat := z * math.Sin(theta)
return gLon, gLat
}
//GCJ02toBD09 火星坐标系->百度坐标系
func GCJ02toBD09(lon, lat float64) (float64, float64) {
z := math.Sqrt(lon*lon+lat*lat) + 0.00002*math.Sin(lat*X_PI)
theta := math.Atan2(lat, lon) + 0.000003*math.Cos(lon*X_PI)
bdLon := z*math.Cos(theta) + 0.0065
bdLat := z*math.Sin(theta) + 0.006
return bdLon, bdLat
}
//WGS84toGCJ02 WGS84坐标系->火星坐标系
func WGS84toGCJ02(lon, lat float64) (float64, float64) {
if isOutOFChina(lon, lat) {
return lon, lat
}
mgLon, mgLat := delta(lon, lat)
return mgLon, mgLat
}
//GCJ02toWGS84 火星坐标系->WGS84坐标系
func GCJ02toWGS84(lon, lat float64) (float64, float64) {
if isOutOFChina(lon, lat) {
return lon, lat
}
mgLon, mgLat := delta(lon, lat)
return lon*2 - mgLon, lat*2 - mgLat
}
//BD09toWGS84 百度坐标系->WGS84坐标系
func BD09toWGS84(lon, lat float64) (float64, float64) {
lon, lat = BD09toGCJ02(lon, lat)
return GCJ02toWGS84(lon, lat)
}
//WGS84toBD09 WGS84坐标系->百度坐标系
func WGS84toBD09(lon, lat float64) (float64, float64) {
lon, lat = WGS84toGCJ02(lon, lat)
return GCJ02toBD09(lon, lat)
}
func delta(lon, lat float64) (float64, float64) {
dlat := transformlat(lon-105.0, lat-35.0)
dlon := transformlng(lon-105.0, lat-35.0)
radlat := lat / 180.0 * math.Pi
magic := math.Sin(radlat)
magic = 1 - OFFSET*magic*magic
sqrtmagic := math.Sqrt(magic)
dlat = (dlat * 180.0) / ((AXIS * (1 - OFFSET)) / (magic * sqrtmagic) * math.Pi)
dlon = (dlon * 180.0) / (AXIS / sqrtmagic * math.Cos(radlat) * math.Pi)
mgLat := lat + dlat
mgLon := lon + dlon
return mgLon, mgLat
}
func transformlat(lon, lat float64) float64 {
var ret = -100.0 + 2.0*lon + 3.0*lat + 0.2*lat*lat + 0.1*lon*lat + 0.2*math.Sqrt(math.Abs(lon))
ret += (20.0*math.Sin(6.0*lon*math.Pi) + 20.0*math.Sin(2.0*lon*math.Pi)) * 2.0 / 3.0
ret += (20.0*math.Sin(lat*math.Pi) + 40.0*math.Sin(lat/3.0*math.Pi)) * 2.0 / 3.0
ret += (160.0*math.Sin(lat/12.0*math.Pi) + 320*math.Sin(lat*math.Pi/30.0)) * 2.0 / 3.0
return ret
}
func transformlng(lon, lat float64) float64 {
var ret = 300.0 + lon + 2.0*lat + 0.1*lon*lon + 0.1*lon*lat + 0.1*math.Sqrt(math.Abs(lon))
ret += (20.0*math.Sin(6.0*lon*math.Pi) + 20.0*math.Sin(2.0*lon*math.Pi)) * 2.0 / 3.0
ret += (20.0*math.Sin(lon*math.Pi) + 40.0*math.Sin(lon/3.0*math.Pi)) * 2.0 / 3.0
ret += (150.0*math.Sin(lon/12.0*math.Pi) + 300.0*math.Sin(lon/30.0*math.Pi)) * 2.0 / 3.0
return ret
}
func isOutOFChina(lon, lat float64) bool {
return !(lon > 73.66 && lon < 135.05 && lat > 3.86 && lat < 53.55)
}

9
gin_server_admin/config.yaml

@ -22,6 +22,10 @@ redis:
db: 0 db: 0
addr: 127.0.0.1:6379 addr: 127.0.0.1:6379
password: "" password: ""
rediswechat:
db: 1
addr: 127.0.0.1:6379
password: ""
redisprefix: redisprefix:
prefix: "HXGK_GO_ZhixingCollege" prefix: "HXGK_GO_ZhixingCollege"
alias: "dev" alias: "dev"
@ -313,7 +317,7 @@ workwechatschool: #知行学院
agentid: 1000008 agentid: 1000008
secretstr: 'YJOHrmHtvevAdctg-06TMLnPokIaLHdfrQMyQolZQC8' secretstr: 'YJOHrmHtvevAdctg-06TMLnPokIaLHdfrQMyQolZQC8'
#知行学院API接收消息 #知行学院API接收消息
workwechattoken: 'kkUA3s2s3' #Token wechattokening: 'kkUA3s2s3' #Token
encodingaeskey: 'ZI29of85mTgQPik8LLjDnYKlAECDbI23Pq886VJ9Azf' #EncodingAESKey encodingaeskey: 'ZI29of85mTgQPik8LLjDnYKlAECDbI23Pq886VJ9Azf' #EncodingAESKey
workwechatappmaillist: #通讯录 workwechatappmaillist: #通讯录
@ -338,6 +342,9 @@ workwechatids:
workwechatschools: #测试 workwechatschools: #测试
agentid: 1000021 agentid: 1000021
secretstr: 'rbqos2un6vVY5k_c2aOFK6HUuONeJsiBqwRZXTDVBKU' secretstr: 'rbqos2un6vVY5k_c2aOFK6HUuONeJsiBqwRZXTDVBKU'
#知行学院API接收消息
wechattokening: 'kkUA3s2s3' #Token
encodingaeskey: 'ZI29of85mTgQPik8LLjDnYKlAECDbI23Pq886VJ9Azf' #EncodingAESKey
workwechatappmaillists: #通讯录 workwechatappmaillists: #通讯录
secretstr: 'TSSsJXiqh3RKl0NYIoB-sPc43MUIRJ1ppALWtzyLY94' secretstr: 'TSSsJXiqh3RKl0NYIoB-sPc43MUIRJ1ppALWtzyLY94'

1
gin_server_admin/config/config.go

@ -4,6 +4,7 @@ type Server struct {
JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"` JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"` Zap Zap `mapstructure:"zap" json:"zap" yaml:"zap"`
Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"` Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
WechatRedis Redis `mapstructure:"rediswechat" json:"rediswechat" yaml:"rediswechat"`
RedisPrefix RedisPrefixStr `mapstructure:"redisprefix" json:"redisprefix" yaml:"redisprefix"` //redis键浅醉 RedisPrefix RedisPrefixStr `mapstructure:"redisprefix" json:"redisprefix" yaml:"redisprefix"` //redis键浅醉
Email Email `mapstructure:"email" json:"email" yaml:"email"` Email Email `mapstructure:"email" json:"email" yaml:"email"`
Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"` Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"`

14
gin_server_admin/config/wechat.go

@ -4,17 +4,17 @@ package config
//企业微信ID //企业微信ID
type workWechatId struct { type workWechatId struct {
CompanyId string `json:id` //企业ID CompanyId string `json:id` //企业ID
WechatToken string `json:workwechattoken` //企业ID WechatToken string `json:wechattokening` //企业ID
EncodingAESKey string `json:encodingaeskey` //企业ID EncodingAESKey string `json:encodingaeskey` //企业ID
} }
//企业微信应用配置 //企业微信应用配置
type workWechatApplication struct { type workWechatApplication struct {
AgentId string `json:agentid` //应用ID AgentId string `json:agentid` //应用ID
SecretStr string `json:secretstr` //应用Secret SecretStr string `json:secretstr` //应用Secret
WechatTokening string `json:workwechattoken` //企业ID WechatTokening string `json:wechattokening` //企业ID
EncodingAESKey string `json:encodingaeskey` //企业ID EncodingAESKey string `json:encodingaeskey` //企业ID
} }
//企业微信内置应用 //企业微信内置应用

4
gin_server_admin/core/server.go

@ -15,6 +15,10 @@ type server interface {
} }
func RunWindowsServer() { func RunWindowsServer() {
//初始化企业微信redis
initialize.WechatRedis()
if global.GVA_CONFIG.System.UseMultipoint { if global.GVA_CONFIG.System.UseMultipoint {
// 初始化redis服务 // 初始化redis服务
initialize.Redis() initialize.Redis()

3
gin_server_admin/global/global.go

@ -42,6 +42,9 @@ var (
GVA_DB_Performanceappraisal *gorm.DB GVA_DB_Performanceappraisal *gorm.DB
GVA_DB_WechatCallBack *gorm.DB GVA_DB_WechatCallBack *gorm.DB
//企业微信专用redis
GVA_REDIS_WeChat *redis.Client
//个人配置 //个人配置
// GVA_MyConfig config.MyConfig // GVA_MyConfig config.MyConfig
//鉴权 //鉴权

16
gin_server_admin/initialize/redis.go

@ -24,3 +24,19 @@ func Redis() {
global.GVA_REDIS = client global.GVA_REDIS = client
} }
} }
func WechatRedis() {
redisCfg := global.GVA_CONFIG.WechatRedis
client := redis.NewClient(&redis.Options{
Addr: redisCfg.Addr,
Password: redisCfg.Password, // no password set
DB: redisCfg.DB, // use default DB
})
pong, err := client.Ping(context.Background()).Result()
if err != nil {
global.GVA_LOG.Error("企业微信Redis链接失败!, err:", zap.Any("err", err))
} else {
global.GVA_LOG.Info("企业微信Redis链接成功:", zap.String("pong", pong))
global.GVA_REDIS_WeChat = client
}
}

3
gin_server_admin/middleware/myjwt.go

@ -44,7 +44,7 @@ func MyAuthentication() gin.HandlerFunc {
} else { } else {
tokenErr := mapstructure.Decode(tokenInfo, &myCustomIdentify) tokenErr := mapstructure.Decode(tokenInfo, &myCustomIdentify)
if tokenErr != nil { if tokenErr != nil {
response.FailWithDetailed(gin.H{"reload": true, "code": 4}, "您的帐户异地登陆或令牌失效", c) response.FailWithDetailed(gin.H{"reload": true, "code": 3}, "您的帐户异地登陆或令牌失效", c)
c.Abort() c.Abort()
return return
} }
@ -61,6 +61,7 @@ func MyAuthentication() gin.HandlerFunc {
} }
} }
redisClient.SetRedisTime(10800) redisClient.SetRedisTime(10800)
// redisClient.SetRedisTime(60)
writeRedisData := map[string]interface{}{ writeRedisData := map[string]interface{}{
"userkey": myCustomIdentify.UserKey, "userkey": myCustomIdentify.UserKey,
"usernumber": myCustomIdentify.UserNumber, "usernumber": myCustomIdentify.UserNumber,

3
gin_server_admin/router/examtestpage/healthreporthandle.go

@ -39,6 +39,9 @@ func (g *GroupHandleRouter) InitHealthReporRouter(Router *gin.RouterGroup) (R gi
groupCodeRouter.POST("/postreportanswerlisttodayall", authorityApi.PostReportAnswerListTodayAll) //获取当日9点之前全部上报人员 groupCodeRouter.POST("/postreportanswerlisttodayall", authorityApi.PostReportAnswerListTodayAll) //获取当日9点之前全部上报人员
groupCodeRouter.GET("/postreportanswerlisttodayall", authorityApi.PostReportAnswerListTodayAll) //获取当日9点之前全部上报人员 groupCodeRouter.GET("/postreportanswerlisttodayall", authorityApi.PostReportAnswerListTodayAll) //获取当日9点之前全部上报人员
groupCodeRouter.POST("/sendrelevantpersonneltodaymsg", authorityApi.SendRelevantPersonnelTodayMsg) //向相关人员发送信息当日9点 groupCodeRouter.POST("/sendrelevantpersonneltodaymsg", authorityApi.SendRelevantPersonnelTodayMsg) //向相关人员发送信息当日9点
groupCodeRouter.POST("/queryhealthreport", authorityApi.QueryHealthReport) //按日期查询
} }
return groupCodeRouter return groupCodeRouter
} }

2
gin_server_admin/router/shiyan/sys_shiyan.go

@ -23,5 +23,7 @@ func (s *ShiyanRouter) InitShiyanRouter(Router *gin.RouterGroup) {
shiyanCodeRouter.POST("/sendtextmsgall", authorityApi.SendTextMessageAll) //实验发送按钮操作全按钮 shiyanCodeRouter.POST("/sendtextmsgall", authorityApi.SendTextMessageAll) //实验发送按钮操作全按钮
shiyanCodeRouter.POST("/sendimagemsgall", authorityApi.SendImageMessageAll) //实验发送按钮操作全按钮 shiyanCodeRouter.POST("/sendimagemsgall", authorityApi.SendImageMessageAll) //实验发送按钮操作全按钮
shiyanCodeRouter.POST("/geteatiltemplate", authorityApi.GetEatilTemplate)
} }
} }

7
gin_server_admin/router/wechatapp/callback.go

@ -9,7 +9,7 @@ import (
type CallBackWeCahtApi struct{} type CallBackWeCahtApi struct{}
func (g *CallBackWeCahtApi) InitGroupRouter(Router *gin.RouterGroup) { func (g *CallBackWeCahtApi) InitGroupRouter(Router *gin.RouterGroup) {
groupCodeRouter := Router.Group("wechatcallback") groupCodeRouter := Router.Group("callback")
var authorityApi = wechatapp.ApiGroupApp.WorkWeChatCallBackApi.WeChatCallBackApi var authorityApi = wechatapp.ApiGroupApp.WorkWeChatCallBackApi.WeChatCallBackApi
{ {
groupCodeRouter.POST("", authorityApi.Index) groupCodeRouter.POST("", authorityApi.Index)
@ -17,5 +17,10 @@ func (g *CallBackWeCahtApi) InitGroupRouter(Router *gin.RouterGroup) {
groupCodeRouter.GET("", authorityApi.Index) groupCodeRouter.GET("", authorityApi.Index)
groupCodeRouter.GET("/", authorityApi.Index) groupCodeRouter.GET("/", authorityApi.Index)
groupCodeRouter.POST("callbackmsgapi", authorityApi.CallbackMessageApi)
// groupCodeRouter.POST("/callbackmsgapi", authorityApi.CallbackMessageApi)
groupCodeRouter.GET("callbackmsgapi", authorityApi.CallbackMessageApi)
// groupCodeRouter.GET("/callbackmsgapi", authorityApi.CallbackMessageApi)
} }
} }

230
gin_server_admin/utils/redishandel/myredis.go

@ -5,6 +5,7 @@ import (
"time" "time"
"github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/global"
"github.com/go-redis/redis/v8"
) )
//redis 基础设定 //redis 基础设定
@ -12,6 +13,7 @@ type RedisStoreType struct {
Expiration time.Duration Expiration time.Duration
PreKey string PreKey string
Context context.Context Context context.Context
RedisDb *redis.Client
} }
//启动redis //启动redis
@ -21,6 +23,7 @@ func RunRedis() *RedisStoreType {
redisStoreType.Expiration = time.Second * 300 redisStoreType.Expiration = time.Second * 300
redisStoreType.PreKey = global.GVA_CONFIG.RedisPrefix.PreFix + ":" redisStoreType.PreKey = global.GVA_CONFIG.RedisPrefix.PreFix + ":"
redisStoreType.Context = context.Background() redisStoreType.Context = context.Background()
redisStoreType.RedisDb = global.GVA_REDIS
return &redisStoreType return &redisStoreType
// return &RedisStoreType{ // return &RedisStoreType{
// Expiration: time.Second * 300, // Expiration: time.Second * 300,
@ -29,6 +32,18 @@ func RunRedis() *RedisStoreType {
// } // }
} }
//选择其他数据库
func (r *RedisStoreType) SetRedisDb(dbId int) {
switch dbId {
case 0:
r.RedisDb = global.GVA_REDIS
case 1:
r.RedisDb = global.GVA_REDIS_WeChat
default:
r.RedisDb = global.GVA_REDIS
}
}
//设置键前缀 //设置键前缀
func (r *RedisStoreType) SetRedisPrefix(prefix string) { func (r *RedisStoreType) SetRedisPrefix(prefix string) {
r.PreKey = prefix r.PreKey = prefix
@ -41,7 +56,7 @@ func (r *RedisStoreType) SetRedisTime(timeDate int64) {
//设置字符串 //设置字符串
func (r *RedisStoreType) Set(key string, value string) bool { func (r *RedisStoreType) Set(key string, value string) bool {
err := global.GVA_REDIS.Set(r.Context, r.PreKey+key, value, r.Expiration).Err() err := r.RedisDb.Set(r.Context, r.PreKey+key, value, r.Expiration).Err()
if err != nil { if err != nil {
return false return false
} }
@ -50,7 +65,7 @@ func (r *RedisStoreType) Set(key string, value string) bool {
//获取字符串 //获取字符串
func (r *RedisStoreType) Get(key string) (bool, string) { func (r *RedisStoreType) Get(key string) (bool, string) {
err := global.GVA_REDIS.Get(r.Context, r.PreKey+key) err := r.RedisDb.Get(r.Context, r.PreKey+key)
if err.Err() != nil { if err.Err() != nil {
return false, "" return false, ""
} }
@ -67,7 +82,7 @@ callback
hashVal 获得值 hashVal 获得值
*/ */
func (r *RedisStoreType) HashGet(hashName, hashKey string) (errs bool, hashVal string) { func (r *RedisStoreType) HashGet(hashName, hashKey string) (errs bool, hashVal string) {
err := global.GVA_REDIS.HGet(r.Context, r.PreKey+hashName, hashKey) err := r.RedisDb.HGet(r.Context, r.PreKey+hashName, hashKey)
if err.Err() != nil { if err.Err() != nil {
return false, "" return false, ""
} }
@ -81,14 +96,14 @@ func (r *RedisStoreType) HashGet(hashName, hashKey string) (errs bool, hashVal s
@hashVal 要添加的值 @hashVal 要添加的值
*/ */
func (r *RedisStoreType) HashSet(hashName, hashKey, hashVal string) bool { func (r *RedisStoreType) HashSet(hashName, hashKey, hashVal string) bool {
err := global.GVA_REDIS.HSet(r.Context, r.PreKey+hashName, hashKey, hashVal).Err() err := r.RedisDb.HSet(r.Context, r.PreKey+hashName, hashKey, hashVal).Err()
if err != nil { if err != nil {
return false return false
} }
if r.Expiration == 0 { if r.Expiration == 0 {
global.GVA_REDIS.Persist(r.Context, r.PreKey+hashName) r.RedisDb.Persist(r.Context, r.PreKey+hashName)
} else { } else {
global.GVA_REDIS.PExpire(r.Context, r.PreKey+hashName, r.Expiration) r.RedisDb.PExpire(r.Context, r.PreKey+hashName, r.Expiration)
} }
// global.GVA_REDIS.PExpire(r.Context, r.PreKey+hashName, r.Expiration) // global.GVA_REDIS.PExpire(r.Context, r.PreKey+hashName, r.Expiration)
return true return true
@ -101,15 +116,15 @@ func (r *RedisStoreType) HashSet(hashName, hashKey, hashVal string) bool {
*/ */
func (r *RedisStoreType) HashMsetAdd(hashName string, hashVal map[string]interface{}) bool { func (r *RedisStoreType) HashMsetAdd(hashName string, hashVal map[string]interface{}) bool {
// rdb := RedisInit() // rdb := RedisInit()
err := global.GVA_REDIS.HMSet(r.Context, r.PreKey+hashName, hashVal).Err() err := r.RedisDb.HMSet(r.Context, r.PreKey+hashName, hashVal).Err()
// err := rdb.HMSet(ctx, "userfg", hashVal).Err() // err := rdb.HMSet(ctx, "userfg", hashVal).Err()
if err != nil { if err != nil {
return false return false
} }
if r.Expiration == 0 { if r.Expiration == 0 {
global.GVA_REDIS.Persist(r.Context, r.PreKey+hashName) r.RedisDb.Persist(r.Context, r.PreKey+hashName)
} else { } else {
global.GVA_REDIS.PExpire(r.Context, r.PreKey+hashName, r.Expiration) r.RedisDb.PExpire(r.Context, r.PreKey+hashName, r.Expiration)
} }
// fmt.Printf("错误sss=========》%v\n", hashVal) // fmt.Printf("错误sss=========》%v\n", hashVal)
@ -117,15 +132,15 @@ func (r *RedisStoreType) HashMsetAdd(hashName string, hashVal map[string]interfa
} }
func (r *RedisStoreType) HashMsetAddAry(hashName string, hashVal []map[string]interface{}) bool { func (r *RedisStoreType) HashMsetAddAry(hashName string, hashVal []map[string]interface{}) bool {
// rdb := RedisInit() // rdb := RedisInit()
err := global.GVA_REDIS.HMSet(r.Context, r.PreKey+hashName, hashVal).Err() err := r.RedisDb.HMSet(r.Context, r.PreKey+hashName, hashVal).Err()
// err := rdb.HMSet(ctx, "userfg", hashVal).Err() // err := rdb.HMSet(ctx, "userfg", hashVal).Err()
if err != nil { if err != nil {
return false return false
} }
if r.Expiration == 0 { if r.Expiration == 0 {
global.GVA_REDIS.Persist(r.Context, r.PreKey+hashName) r.RedisDb.Persist(r.Context, r.PreKey+hashName)
} else { } else {
global.GVA_REDIS.PExpire(r.Context, r.PreKey+hashName, r.Expiration) r.RedisDb.PExpire(r.Context, r.PreKey+hashName, r.Expiration)
} }
// global.GVA_REDIS.PExpire(r.Context, r.PreKey+hashName, r.Expiration) // global.GVA_REDIS.PExpire(r.Context, r.PreKey+hashName, r.Expiration)
// fmt.Printf("错误sss=========》%v\n", hashVal) // fmt.Printf("错误sss=========》%v\n", hashVal)
@ -139,7 +154,7 @@ func (r *RedisStoreType) HashMsetAddAry(hashName string, hashVal []map[string]in
*/ */
func (r *RedisStoreType) HashGetAll(hashName string) (map[string]string, bool) { func (r *RedisStoreType) HashGetAll(hashName string) (map[string]string, bool) {
// rdb := RedisInit() // rdb := RedisInit()
val, err := global.GVA_REDIS.HGetAll(r.Context, r.PreKey+hashName).Result() val, err := r.RedisDb.HGetAll(r.Context, r.PreKey+hashName).Result()
if err != nil { if err != nil {
return val, false return val, false
} }
@ -148,3 +163,192 @@ func (r *RedisStoreType) HashGetAll(hashName string) (map[string]string, bool) {
} }
return val, true return val, true
} }
//Redis 列表(List)
/**
Linsert 命令用于在列表的元素前或者后插入元素当指定元素不存在于列表中时不执行任何操作
当列表不存在时被视为空列表不执行任何操作
如果 key 不是列表类型返回一个错误
@key 列表
@op 插入状态 (1:在pivot之后2在pivot之前)
@pivot 定位值
@value 要插入值
*/
func (r *RedisStoreType) Linsert(key string, op int, pivot, value interface{}) (int64, bool) {
BeforeOrAfter := "BEFORE"
if op != 1 {
BeforeOrAfter = "AFTER"
}
linsert, linsertErr := r.RedisDb.LInsert(r.Context, key, BeforeOrAfter, pivot, value).Result()
if linsertErr != nil {
return 0, false
}
return linsert, true
}
/**
Lindex 命令用于通过索引获取列表中的元素你也可以使用负数下标 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推
@key 列表
@index 索引
*/
func (r *RedisStoreType) Lindex(key string, index int64) (val string, err error) {
val, err = r.RedisDb.LIndex(r.Context, key, index).Result()
return
}
/**
Llen 命令用于返回列表的长度 如果列表 key 不存在 key 被解释为一个空列表返回 0 如果 key 不是列表类型返回一个错误
@key 列表
*/
func (r *RedisStoreType) Llen(key string) (val int64, err error) {
val, err = r.RedisDb.LLen(r.Context, key).Result()
return
}
/**
Lpop 命令用于移除并返回列表的第一个元素
@key 列表
*/
func (r *RedisStoreType) Lpop(key string) (val string, err error) {
val, err = r.RedisDb.LPop(r.Context, key).Result()
return
}
/**
Lpush 命令将一个或多个值插入到列表头部 如果 key 不存在一个空列表会被创建并执行 LPUSH 操作 key 存在但不是列表类型时返回一个错误
@key 列表
@value 要插入的字符串
*/
func (r *RedisStoreType) Lpush(key string, value ...interface{}) (val int64, err error) {
val, err = r.RedisDb.LPush(r.Context, key, value).Result()
return
}
/**
Lpushx 将一个值插入到已存在的列表头部列表不存在时操作无效
@key 列表
@value 要插入的字符串
*/
func (r *RedisStoreType) Lpushx(key, value string) (val int64, err error) {
val, err = r.RedisDb.LPushX(r.Context, key, value).Result()
return
}
/**
Lrange 返回列表中指定区间内的元素区间以偏移量 START END 指定 其中 0 表示列表的第一个元素 1 表示列表的第二个元素以此类推 你也可以使用负数下标 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推
@key 列表
@start 起始值
@stop 结束值
*/
func (r *RedisStoreType) Lrange(key string, start, stop int64) (val []string, err error) {
val, err = r.RedisDb.LRange(r.Context, key, start, stop).Result()
return
}
/**
Lrem 根据参数 COUNT 的值移除列表中与参数 VALUE 相等的元素
COUNT 的值可以是以下几种
count > 0 : 从表头开始向表尾搜索移除与 VALUE 相等的元素数量为 COUNT
count < 0 : 从表尾开始向表头搜索移除与 VALUE 相等的元素数量为 COUNT 的绝对值
count = 0 : 移除表中所有与 VALUE 相等的值
@start = COUNT
@key 列表
*/
func (r *RedisStoreType) Lrem(key string, start int64, value ...interface{}) (val int64, err error) {
val, err = r.RedisDb.LRem(r.Context, key, start, value).Result()
return
}
/**
Redis Lset 通过索引来设置元素的值
当索引参数超出范围或对一个空列表进行 LSET 返回一个错误
@key 列表
@indexes 索引值
*/
func (r *RedisStoreType) Lset(key string, indexes int64, value ...interface{}) (val string, err error) {
val, err = r.RedisDb.LSet(r.Context, key, indexes, value).Result()
return
}
/**
Ltrim 对一个列表进行修剪(trim)就是说让列表只保留指定区间内的元素不在指定区间之内的元素都将被删除
下标 0 表示列表的第一个元素 1 表示列表的第二个元素以此类推 你也可以使用负数下标 -1 表示列表的最后一个元素 -2 表示列表的倒数第二个元素以此类推
@key 列表
@start 起始值
@stop 结束值
*/
func (r *RedisStoreType) Ltrim(key string, start, stop int64) (val string, err error) {
val, err = r.RedisDb.LTrim(r.Context, key, start, stop).Result()
return
}
/**
Rpop 命令用于移除列表的最后一个元素返回值为移除的元素
@key 列表
*/
func (r *RedisStoreType) Rpop(key string) (val string, err error) {
val, err = r.RedisDb.RPop(r.Context, key).Result()
return
}
/**
Rpoplpush 命令用于移除列表的最后一个元素并将该元素添加到另一个列表并返回
@sourceKey 源列表
@newKey 目标列表
*/
func (r *RedisStoreType) Rpoplpush(sourceKey, newKey string) (val string, err error) {
val, err = r.RedisDb.RPopLPush(r.Context, sourceKey, newKey).Result()
return
}
/**
Rpush 命令用于将一个或多个值插入到列表的尾部(最右边)
如果列表不存在一个空列表会被创建并执行 RPUSH 操作 当列表存在但不是列表类型时返回一个错误
@key 列表
@value 要插入的字符串
*/
func (r *RedisStoreType) Rpush(key string, value ...interface{}) (val int64, err error) {
val, err = r.RedisDb.RPush(r.Context, key, value).Result()
return
}
/**
Rpushx 命令用于将一个值插入到已存在的列表尾部(最右边)如果列表不存在操作无效
@key 列表
@value 要插入的字符串
*/
func (r *RedisStoreType) Rpushx(key string, value ...interface{}) (val int64, err error) {
val, err = r.RedisDb.RPushX(r.Context, key, value).Result()
return
}
/**
Blpop 命令移出并获取列表的第一个元素 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
@key 列表
*/
func (r *RedisStoreType) Blpop(key string) (val []string, err error) {
val, err = r.RedisDb.BLPop(r.Context, r.Expiration, key).Result()
return
}
/**
Brpop 命令移出并获取列表的最后一个元素 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
@key 列表
*/
func (r *RedisStoreType) Brpop(key string) (val []string, err error) {
val, err = r.RedisDb.BRPop(r.Context, r.Expiration, key).Result()
return
}
/**
Brpoplpush 命令从列表中取出最后一个元素并插入到另外一个列表的头部 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止
@source 源列表
@destination 目标列表
*/
func (r *RedisStoreType) Brpoplpush(source, destination string) (val string, err error) {
val, err = r.RedisDb.BRPopLPush(r.Context, source, destination, r.Expiration).Result()
return
}

4
gin_server_admin/其他支持文件/config.yaml

@ -272,7 +272,7 @@ workwechatschool: #知行学院
agentid: 1000008 agentid: 1000008
secretstr: 'YJOHrmHtvevAdctg-06TMLnPokIaLHdfrQMyQolZQC8' secretstr: 'YJOHrmHtvevAdctg-06TMLnPokIaLHdfrQMyQolZQC8'
#知行学院API接收消息 #知行学院API接收消息
workwechattoken: 'kkUA3s2s3' #workwechattoken wechattokening: 'kkUA3s2s3' #Token
encodingaeskey: 'ZI29of85mTgQPik8LLjDnYKlAECDbI23Pq886VJ9Azf' #EncodingAESKey encodingaeskey: 'ZI29of85mTgQPik8LLjDnYKlAECDbI23Pq886VJ9Azf' #EncodingAESKey
workwechatappmaillist: #通讯录 workwechatappmaillist: #通讯录
@ -290,7 +290,7 @@ workwechatschools: #测试
agentid: 1000021 agentid: 1000021
secretstr: 'rbqos2un6vVY5k_c2aOFK6HUuONeJsiBqwRZXTDVBKU' secretstr: 'rbqos2un6vVY5k_c2aOFK6HUuONeJsiBqwRZXTDVBKU'
#知行学院API接收消息 #知行学院API接收消息
workwechattoken: 'kkUA3s2s3' #Token wechattokening: 'kkUA3s2s3' #Token
encodingaeskey: 'ZI29of85mTgQPik8LLjDnYKlAECDbI23Pq886VJ9Azf' #EncodingAESKey encodingaeskey: 'ZI29of85mTgQPik8LLjDnYKlAECDbI23Pq886VJ9Azf' #EncodingAESKey
workwechatappmaillists: #通讯录 workwechatappmaillists: #通讯录

Loading…
Cancel
Save