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 }