dddd
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

206 lines
7.2 KiB

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/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"
)
//入口
func (a *CallBackApi) Index(c *gin.Context) {
outPut := commonus.MapOut()
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:
}
}