package controllers import ( "encoding/base64" "encoding/json" "encoding/xml" "io/ioutil" "net/http" "strconv" "wechat-conf/models" "wechat-conf/models/model" "wechat-conf/service/autoreply" "wechat-conf/service/wechat" "wechat-conf/utils" "github.com/astaxie/beego" "github.com/kinisky564477/wechat/component" "github.com/zjxpcyc/wechat/core" ) // WechatController 用户 type WechatController struct { BaseController serv *autoreply.AutoreplyServ wechatServ *wechat.WechatServ } // Constructor 初始化 Controller // @Title Constructor // @Description 初始化 Controller, 系统自动调用 func (c *WechatController) Constructor() { c.serv = autoreply.NewAutoreplyServ(c.Context) c.wechatServ = wechat.NewWechatServ(c.Context) } const ( INFOTYPE_TICKET = "component_verify_ticket" INFOTYPE_AUTHORIZED = "authorized" INFOTYPE_UNAUTHORIZED = "unauthorized" INFOTYPE_UPDATEAUTHORIZED = "updateauthorized" ) // ComponentPush 第三方平台推送 func (c *WechatController) ComponentPush() { utils.LogError("推送开始") r := c.Ctx.Request defer r.Body.Close() con, _ := ioutil.ReadAll(r.Body) utils.LogError("推送消息:", string(con)) // 解析xml xp := &core.XMLParse{} resMsg, err := xp.Parse(string(con)) if err != nil { utils.LogError("xml解析失败:", err) c.ResponseRaw([]byte("success")) } encrypt := resMsg["Encrypt"] conf, err := c.wechatServ.GetComponentInfo() if err != nil || conf == nil || conf.Appid == "" { utils.LogError("读取微信配置文件失败") c.ResponseRaw([]byte("success")) } EncodingAESKey := conf.Aeskey AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=") if err != nil { utils.LogError("DecodeString失败:", err) c.ResponseRaw([]byte("success")) } EncryptVal, err := base64.StdEncoding.DecodeString(encrypt) if err != nil { utils.LogError("密文base64解析", err) c.ResponseRaw([]byte("success")) } msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey) if err != nil { utils.LogError("解密失败:", err) c.ResponseRaw([]byte("success")) } utils.LogError("解密成功") // 解析xml msg, err := xp.Parse(string(msgbyte)) if err != nil { utils.LogError("xml解析失败:", err) c.ResponseRaw([]byte("success")) } utils.LogError("xml解析成功:", msg) switch msg["InfoType"] { case INFOTYPE_TICKET: // 更新ticket conf.Ticket = msg["ComponentVerifyTicket"] err := c.wechatServ.UpdateComponentTicket(conf) if err != nil { utils.LogError("修改ticket失败:", err) } utils.RefreshComponentTicket(msg["ComponentVerifyTicket"]) break case INFOTYPE_AUTHORIZED: // 授权成功 var cert = map[string]string{ "appid": msg["AuthorizerAppid"], "authorization_code": msg["AuthorizationCode"], } beego.Error("授权成功参数:", cert) wxclient := utils.WechatInit(cert, c.wechatServ.UpdateToken) if wxclient == nil { utils.LogError("获取wxclient失败") c.ResponseRaw([]byte("success")) } beego.Error(wxclient) utils.AppendWxClient(wxclient) // 获取微信信息 info, err := wxclient.GetWechatInfo() if err != nil { utils.LogError("获取微信信息失败") c.ResponseRaw([]byte("success")) } beego.Error(info) authorizerInfo := (info["authorizer_info"]).(map[string]interface{}) beego.Error(info["authorizer_info"]) // 插入数据库 mjson, _ := json.Marshal(msg) HeadImg := "" if authorizerInfo["head_img"] != nil { HeadImg = authorizerInfo["head_img"].(string) } var conf = model.SysWechatConf{ Appid: msg["AuthorizerAppid"], AuthorizationCode: msg["AuthorizationCode"], AuthorizationInfo: string(mjson), WxNikeName: authorizerInfo["nick_name"].(string), HeadImg: HeadImg, UserName: authorizerInfo["user_name"].(string), PrincipalName: authorizerInfo["principal_name"].(string), QrcodeUrl: authorizerInfo["qrcode_url"].(string), } err = c.wechatServ.SaveWechatConf(conf) if err != nil { utils.LogError("保存微信授权信息失败:", err) c.ResponseRaw([]byte("success")) } break case INFOTYPE_UPDATEAUTHORIZED: // 授权更新 break case INFOTYPE_UNAUTHORIZED: // 取消授权 // 删除wechatConf信息,同时将org解绑 appid := msg["AuthorizerAppid"] c.wechatServ.UnAuthorized(appid) // 删除第三方中的微信信息 utils.Component.DelWxClient(appid) break } c.ResponseRaw([]byte("success")) } // WechatInfo 微信接入 func (c *WechatController) WechatInfo() { method := c.Ctx.Input.Method() if method == http.MethodGet { echostr := c.GetString("echostr") c.ResponseRaw([]byte(echostr)) } else { c.WxReceive() } } // WxReceive 微信消息接收 func (c *WechatController) WxReceive() { beego.Error("微信消息接入") appid := c.GetString(":appid") wechat, err := utils.Component.GetWxClient(appid) if err != nil { utils.LogError("获取微信失败: " + err.Error()) } msg, err := wechat.TransformMessage(string(c.Ctx.Input.RequestBody)) if err != nil { utils.LogError("读取微信服务发送内容失败: " + err.Error()) c.ResponseRaw([]byte("")) } xp := &core.XMLParse{} beego.Error("消息:", msg) encrypt := msg["Encrypt"] conf, err := c.wechatServ.GetComponentInfo() if err != nil || conf == nil || conf.Appid == "" { utils.LogError("读取微信配置文件失败") c.ResponseRaw([]byte("success")) } EncodingAESKey := conf.Aeskey AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=") if err != nil { utils.LogError("DecodeString失败:", err) c.ResponseRaw([]byte("success")) } EncryptVal, err := base64.StdEncoding.DecodeString(encrypt) if err != nil { utils.LogError("密文base64解析", err) c.ResponseRaw([]byte("success")) } msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey) if err != nil { utils.LogError("解密失败:", err) c.ResponseRaw([]byte("success")) } utils.LogError("解密成功") // 解析xml val, err := xp.Parse(string(msgbyte)) if err != nil { utils.LogError("xml解析失败:", err) c.ResponseRaw([]byte("success")) } utils.LogError("xml解析成功:", val) var replay = new(model.TaAutoReply) switch val["MsgType"] { case "text": content := val["Content"] // 获取数据库存储返回类型 replay, err = c.serv.GetAutoReplayByAppID(appid, content) break case "event": if val["Event"] == "subscribe" { replay, err = c.serv.GetSubscribeByAppID(appid) } break } if err != nil { utils.LogError("获取微信自动回复信息失败: " + err.Error()) c.ResponseRaw([]byte("")) } if replay == nil { c.ResponseRaw([]byte("")) } openID := val["FromUserName"] signature := c.GetString("msg_signature") nonce := c.GetString("nonce") timestamp, _ := strconv.Atoi(c.GetString("timestamp")) beego.Error("signature:", signature, ",nonce:", nonce, ",timestamp:", timestamp) message, err := c.getReplayMessage(replay, openID, AESKey, wechat) if err != nil { utils.LogError("转换回复信息失败: " + err.Error()) c.ResponseRaw([]byte("")) } // message, err = utils.AesEncrypt(message, AESKey) // if err != nil { // utils.LogError("加密失败:", err) // c.ResponseRaw([]byte("")) // } // beego.Error(string(message)) // data := PassiveMessage{ // Encrypt: component.CDATA{string(message)}, // MsgSignature: component.CDATA{signature}, // TimeStamp: int64(timestamp), // Nonce: component.CDATA{nonce}, // } // beego.Error(data) // res, err := xml.Marshal(data) // beego.Error(err) // beego.Error(string(res)) c.ResponseRaw(message) c.DestroyContext() c.StopRun() } // PassiveMessage 加密后的返回信息 type PassiveMessage struct { XMLName xml.Name `xml:"xml"` Encrypt component.CDATA `xml:"Encrypt"` MsgSignature component.CDATA `xml:"MsgSignature"` TimeStamp int64 `xml:"TimeStamp"` Nonce component.CDATA `xml:"Nonce"` } func (c *WechatController) getReplayMessage(replay *model.TaAutoReply, openid string, Aeskey []byte, wx *component.WxClient) ([]byte, error) { switch replay.MessageType { case models.MESSAGE_TYPE_PARAGRAPH: msg, err := wx.ResponseMessageText(openid, replay.MessageParagraph) return msg, err case models.MESSAGE_TYPE_IMG: msg, err := wx.ResponseMessageImage(openid, replay.MessageImg) return msg, err // case models.MESSAGE_TYPE_PARAGRAPH: // msg, err := wx.ResponseMessageNews(openid, replay.MessageImg) // return msg, err } return nil, nil } // GetPreAuthCode 获取预授权码 func (c *WechatController) GetPreAuthCode() { code, err := utils.Component.GetPreAuthCode() if err != nil { utils.LogError("获取预授权码错误: " + err.Error()) c.ResponseError(err) } appid := utils.Component.GetCertificate()["appid"] c.ResponseJSON(map[string]string{ "appid": appid, "code": code, }) } // GetWechatMenuByAppID 根据appid获取微信详情 func (c *WechatController) GetWechatInfoByAppID() { appid := c.GetString(":appid") wxclient, err := utils.Component.GetWxClient(appid) if err != nil { utils.LogError("获取微信信息失败: " + err.Error()) c.ResponseError(err) } info, err := wxclient.GetWechatInfo() if err != nil { utils.LogError("获取微信详情失败: " + err.Error()) c.ResponseError(err) } c.ResponseJSON(info) } // GetWechatMenuByAppID 获取菜单 func (c *WechatController) GetWechatMenuByAppID() { appid := c.GetString(":appid") wxclient, err := utils.Component.GetWxClient(appid) if err != nil { utils.LogError("获取微信信息失败: " + err.Error()) c.ResponseError(err) } menus, err := wxclient.GetMenu() if err != nil { utils.LogError("获取微信详情失败: " + err.Error()) c.ResponseError(err) } c.ResponseJSON(menus) } // GetWechatByCode 根据code获取微信信息 func (c *WechatController) GetWechatByCode() { code := c.GetString(":code") beego.Error(code) conf, err := c.wechatServ.GetWechatByCode(code) if err != nil { utils.LogError("获取微信详情失败: " + err.Error()) c.ResponseError(err) } beego.Error(conf) if conf == nil || conf.ConfId == "" || conf.Status == models.STATUS_NORMAL { c.ResponseJSON("") } c.ResponseJSON(map[string]string{ "ConfId": conf.ConfId, "NickName": conf.WxNikeName, "HeadImg": conf.HeadImg, }) }