|
|
|
|
package wechatcallback
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/xml"
|
|
|
|
|
"fmt"
|
|
|
|
|
"key_performance_indicators/middleware/wechatapp/wechatstatice"
|
|
|
|
|
"key_performance_indicators/models/wechatcallback"
|
|
|
|
|
"key_performance_indicators/overall"
|
|
|
|
|
"key_performance_indicators/overall/publicmethod"
|
|
|
|
|
"strconv"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// 企业微信回调入口
|
|
|
|
|
func (a *ApiRouter) Index(c *gin.Context) {
|
|
|
|
|
outputCont := publicmethod.MapOut[string]()
|
|
|
|
|
outputCont["index"] = "企业微信回调入口"
|
|
|
|
|
publicmethod.Result(0, outputCont, c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
@ 作者: 秦东
|
|
|
|
|
@ 时间: 2022-09-27 11:33:29
|
|
|
|
|
@ 功能: 回调入口
|
|
|
|
|
@ 参数
|
|
|
|
|
|
|
|
|
|
#MsgSignature 企业微信加密签名,msg_signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体。
|
|
|
|
|
#Timestamp 时间戳。与nonce结合使用,用于防止请求重放攻击。
|
|
|
|
|
#Nonce 随机数。与timestamp结合使用,用于防止请求重放攻击。
|
|
|
|
|
#Echostr 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文
|
|
|
|
|
|
|
|
|
|
@ 返回值
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
*/
|
|
|
|
|
func (a *ApiRouter) 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即为消息内容明文
|
|
|
|
|
EchostrType := c.Query("type")
|
|
|
|
|
SystemApp := c.Query("systemapp")
|
|
|
|
|
|
|
|
|
|
if EchostrType == "" {
|
|
|
|
|
EchostrType = "json"
|
|
|
|
|
}
|
|
|
|
|
if SystemApp == "" {
|
|
|
|
|
SystemApp = "kpi"
|
|
|
|
|
}
|
|
|
|
|
// fmt.Printf("(1)SystemApp---------->%v--->EchostrType---------->%v--->MsgSignature---------->%v--->Timestamp---------->%v--->Nonce---------->%v--->Echostr---------->%v\n", SystemApp, EchostrType, MsgSignature, Timestamp, Nonce, Echostr)
|
|
|
|
|
|
|
|
|
|
var basicValueCallback CallBackData //企业微信回调基础参数
|
|
|
|
|
basicValueCallback.MsgSignature = MsgSignature
|
|
|
|
|
basicValueCallback.Timestamp = Timestamp
|
|
|
|
|
basicValueCallback.Nonce = Nonce
|
|
|
|
|
basicValueCallback.DataType = EchostrType
|
|
|
|
|
basicValueCallback.SystemApp = SystemApp
|
|
|
|
|
var msgStr string
|
|
|
|
|
if Echostr != "" {
|
|
|
|
|
//Api地址验证
|
|
|
|
|
basicValueCallback.Echostr = Echostr
|
|
|
|
|
msgStr = basicValueCallback.VerificationUrl()
|
|
|
|
|
c.String(200, msgStr)
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
//回调事件
|
|
|
|
|
fmt.Printf("回调事件\n")
|
|
|
|
|
var callBackXmlMsg XmlMsgCont
|
|
|
|
|
xmlErr := c.ShouldBindXML(&callBackXmlMsg)
|
|
|
|
|
if xmlErr != nil {
|
|
|
|
|
fmt.Printf("回调事件失败!%v\n", xmlErr)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
var jieMiCont DecryptMsgCont
|
|
|
|
|
jieMiCont.MsgSignature = MsgSignature
|
|
|
|
|
jieMiCont.Timestamp = Timestamp
|
|
|
|
|
jieMiCont.Nonce = Nonce
|
|
|
|
|
jieMiCont.ToUsername = callBackXmlMsg.ToUsername
|
|
|
|
|
jieMiCont.Agentid = callBackXmlMsg.Agentid
|
|
|
|
|
jieMiCont.Encrypt = callBackXmlMsg.Encrypt
|
|
|
|
|
decryptMsgCont, jsonErr := jieMiCont.DecryptMsgInfo()
|
|
|
|
|
fmt.Printf("Xml----->%v\n\n", string(decryptMsgCont))
|
|
|
|
|
if jsonErr != nil {
|
|
|
|
|
fmt.Printf("回调事件失败!%v\n", jsonErr)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
var msgCont MsgContentXml
|
|
|
|
|
errXml := xml.Unmarshal(decryptMsgCont, &msgCont)
|
|
|
|
|
if errXml != nil {
|
|
|
|
|
fmt.Printf("回调事件失败!%v\n", errXml)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("XmlCont----->%v\nwxcptJson----->%v\n", string(decryptMsgCont), msgCont)
|
|
|
|
|
switch msgCont.MsgType {
|
|
|
|
|
/*消息格式类型
|
|
|
|
|
*/
|
|
|
|
|
case "text": //文本
|
|
|
|
|
case "image": //图片
|
|
|
|
|
case "voice": //语音
|
|
|
|
|
case "video": //视频
|
|
|
|
|
case "location": //位置
|
|
|
|
|
GeographicalPosition(decryptMsgCont)
|
|
|
|
|
case "link": //链接
|
|
|
|
|
/*事件格式类型*/
|
|
|
|
|
case "event":
|
|
|
|
|
/*
|
|
|
|
|
事件附属格式
|
|
|
|
|
*/
|
|
|
|
|
EventProcessing(decryptMsgCont, jieMiCont, c)
|
|
|
|
|
// return
|
|
|
|
|
default:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// fmt.Printf("(3)CallbackMessageApi---------->%v------------------->%v\n", msgStr, basicValueCallback)
|
|
|
|
|
|
|
|
|
|
// publicmethod.Result(1, basicValueCallback, c, msgStr)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证URL
|
|
|
|
|
func (c *CallBackData) VerificationUrl() (msg string) {
|
|
|
|
|
|
|
|
|
|
switch c.DataType {
|
|
|
|
|
case "json":
|
|
|
|
|
wxcptJson := wechatstatice.WechatDecryptJson(c.SystemApp)
|
|
|
|
|
echoStr, cryptErr := wxcptJson.VerifyURL(c.MsgSignature, c.Timestamp, c.Nonce, c.Echostr)
|
|
|
|
|
// fmt.Printf("(2)wxcptJson---------->%v-----MsgSignature--->%v----Timestamp---->%v-----Nonce--->%v-----c.Echostr--->%v------------echoStr------->%v----cryptErr---->%v\n", wxcptJson, c.MsgSignature, c.Timestamp, c.Nonce, c.Echostr, string(echoStr), cryptErr)
|
|
|
|
|
msg = string(echoStr)
|
|
|
|
|
if cryptErr != nil {
|
|
|
|
|
fmt.Println("verifyUrl fail", cryptErr)
|
|
|
|
|
}
|
|
|
|
|
// var callbackLog wechatcallback.CallbackLog
|
|
|
|
|
// callbackLog.MsgSignature = c.MsgSignature
|
|
|
|
|
// TimestampInt, _ := strconv.ParseInt(c.Timestamp, 10, 64)
|
|
|
|
|
// callbackLog.TimeStamp = TimestampInt
|
|
|
|
|
// callbackLog.Nonce = c.Nonce
|
|
|
|
|
// callbackLog.Echostr = c.Echostr
|
|
|
|
|
// callbackLog.Xmlstr = string(echoStr)
|
|
|
|
|
// // callbackLog.Reqdata = string(reqData)
|
|
|
|
|
// callbackLog.AddTime = time.Now().Unix()
|
|
|
|
|
// overall.CONSTANT_DB_WECHAT_LOG.Create(&callbackLog)
|
|
|
|
|
default:
|
|
|
|
|
wxcptXml := wechatstatice.WechatDecryptXml(c.SystemApp)
|
|
|
|
|
echoStr, cryptErr := wxcptXml.VerifyURL(c.MsgSignature, c.Timestamp, c.Nonce, c.Echostr)
|
|
|
|
|
// fmt.Printf("wxcptXml---------->%v------------echoStr------->%v----cryptErr---->%v-----MsgSignature--->%v----Timestamp---->%v-----Nonce--->%v-----Echostr--->%v\n", wxcptXml, string(echoStr), cryptErr, c.MsgSignature, c.Timestamp, c.Nonce, c.Echostr)
|
|
|
|
|
msg = string(echoStr)
|
|
|
|
|
if cryptErr != nil {
|
|
|
|
|
fmt.Println("verifyUrl fail", cryptErr)
|
|
|
|
|
}
|
|
|
|
|
// var callbackLog wechatcallback.CallbackLog
|
|
|
|
|
// callbackLog.MsgSignature = c.MsgSignature
|
|
|
|
|
// TimestampInt, _ := strconv.ParseInt(c.Timestamp, 10, 64)
|
|
|
|
|
// callbackLog.TimeStamp = TimestampInt
|
|
|
|
|
// callbackLog.Nonce = c.Nonce
|
|
|
|
|
// callbackLog.Echostr = c.Echostr
|
|
|
|
|
// callbackLog.Xmlstr = string(echoStr)
|
|
|
|
|
// // callbackLog.Reqdata = string(reqData)
|
|
|
|
|
// callbackLog.AddTime = time.Now().Unix()
|
|
|
|
|
// overall.CONSTANT_DB_WECHAT_LOG.Create(&callbackLog)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 解密文档
|
|
|
|
|
func (d *DecryptMsgCont) DecryptMsgInfo() (msg []byte, err error) {
|
|
|
|
|
decryptStr := fmt.Sprintf(`{"tousername":"%v","encrypt":"%v","agentid":"%v"}`, d.ToUsername, d.Encrypt, d.Agentid)
|
|
|
|
|
|
|
|
|
|
reqData := []byte(decryptStr)
|
|
|
|
|
|
|
|
|
|
wxcptJson := wechatstatice.WechatDecryptJson(d.SystemApp)
|
|
|
|
|
|
|
|
|
|
msg, cryptErr := wxcptJson.DecryptMsg(d.MsgSignature, d.Timestamp, d.Nonce, reqData)
|
|
|
|
|
if cryptErr != nil {
|
|
|
|
|
err = fmt.Errorf("解密失败1")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var callbackLog wechatcallback.CallbackLog
|
|
|
|
|
callbackLog.MsgSignature = d.MsgSignature
|
|
|
|
|
TimestampInt, _ := strconv.ParseInt(d.Timestamp, 10, 64)
|
|
|
|
|
callbackLog.TimeStamp = TimestampInt
|
|
|
|
|
callbackLog.Nonce = d.Nonce
|
|
|
|
|
callbackLog.Echostr = d.Encrypt
|
|
|
|
|
callbackLog.Xmlstr = string(msg)
|
|
|
|
|
// callbackLog.Reqdata = string(reqData)
|
|
|
|
|
callbackLog.AddTime = time.Now().Unix()
|
|
|
|
|
overall.CONSTANT_DB_WECHAT_LOG.Create(&callbackLog)
|
|
|
|
|
// var decryptMsgCont DecryptMsgCont
|
|
|
|
|
// decryptMsgCont.ToUsername = d.ToUsername
|
|
|
|
|
// decryptMsgCont.Agentid = d.Agentid
|
|
|
|
|
// decryptMsgCont.Encrypt = d.Encrypt
|
|
|
|
|
// decryptMsgCont.MsgSignature = d.MsgSignature
|
|
|
|
|
// decryptMsgCont.Timestamp = d.Timestamp
|
|
|
|
|
// decryptMsgCont.Nonce = d.Nonce
|
|
|
|
|
// decryptMsgCont.SystemApp = d.SystemApp
|
|
|
|
|
|
|
|
|
|
// msgStr := publicmethod.MapOut[string]()
|
|
|
|
|
// jsonDecry, _ := json.Marshal(decryptMsgCont)
|
|
|
|
|
// msgStr["DecryptMsgCont"] = string(jsonDecry) //
|
|
|
|
|
// msgStr["MsgCont"] = string(msg)
|
|
|
|
|
// // jsonStr, _ := json.Marshal(msgStr)
|
|
|
|
|
|
|
|
|
|
// //API Token数据
|
|
|
|
|
// redisFileKeyStr := fmt.Sprintf("WorkWechat:CallBack:Xml_%v_%v_%v", d.ToUsername, d.Nonce, d.Agentid)
|
|
|
|
|
// redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS3)
|
|
|
|
|
// redisClient.SetRedisTime(86400)
|
|
|
|
|
// redisClient.HashMsetAdd(redisFileKeyStr, msgStr)
|
|
|
|
|
// fmt.Printf("msg:-----------%v\n cryptErr:-----------%v----->all\n\n", string(jsonDecry), redisFileKeyStr)
|
|
|
|
|
return
|
|
|
|
|
}
|