component.go 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. package controllers
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "encoding/xml"
  6. "io/ioutil"
  7. "net/http"
  8. "strconv"
  9. "wechat-conf/models"
  10. "wechat-conf/models/model"
  11. "wechat-conf/service/autoreply"
  12. "wechat-conf/service/wechat"
  13. "wechat-conf/utils"
  14. "github.com/astaxie/beego"
  15. "github.com/kinisky564477/wechat/component"
  16. "github.com/zjxpcyc/wechat/core"
  17. )
  18. // WechatController 用户
  19. type WechatController struct {
  20. BaseController
  21. serv *autoreply.AutoreplyServ
  22. wechatServ *wechat.WechatServ
  23. }
  24. // Constructor 初始化 Controller
  25. // @Title Constructor
  26. // @Description 初始化 Controller, 系统自动调用
  27. func (c *WechatController) Constructor() {
  28. c.serv = autoreply.NewAutoreplyServ(c.Context)
  29. c.wechatServ = wechat.NewWechatServ(c.Context)
  30. }
  31. const (
  32. INFOTYPE_TICKET = "component_verify_ticket"
  33. INFOTYPE_AUTHORIZED = "authorized"
  34. INFOTYPE_UNAUTHORIZED = "unauthorized"
  35. INFOTYPE_UPDATEAUTHORIZED = "updateauthorized"
  36. )
  37. // ComponentPush 第三方平台推送
  38. func (c *WechatController) ComponentPush() {
  39. utils.LogError("推送开始")
  40. r := c.Ctx.Request
  41. defer r.Body.Close()
  42. con, _ := ioutil.ReadAll(r.Body)
  43. utils.LogError("推送消息:", string(con))
  44. // 解析xml
  45. xp := &core.XMLParse{}
  46. resMsg, err := xp.Parse(string(con))
  47. if err != nil {
  48. utils.LogError("xml解析失败:", err)
  49. c.ResponseRaw([]byte("success"))
  50. }
  51. encrypt := resMsg["Encrypt"]
  52. conf, err := c.wechatServ.GetComponentInfo()
  53. if err != nil || conf == nil || conf.Appid == "" {
  54. utils.LogError("读取微信配置文件失败")
  55. c.ResponseRaw([]byte("success"))
  56. }
  57. EncodingAESKey := conf.Aeskey
  58. AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
  59. if err != nil {
  60. utils.LogError("DecodeString失败:", err)
  61. c.ResponseRaw([]byte("success"))
  62. }
  63. EncryptVal, err := base64.StdEncoding.DecodeString(encrypt)
  64. if err != nil {
  65. utils.LogError("密文base64解析", err)
  66. c.ResponseRaw([]byte("success"))
  67. }
  68. msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey)
  69. if err != nil {
  70. utils.LogError("解密失败:", err)
  71. c.ResponseRaw([]byte("success"))
  72. }
  73. utils.LogError("解密成功")
  74. // 解析xml
  75. msg, err := xp.Parse(string(msgbyte))
  76. if err != nil {
  77. utils.LogError("xml解析失败:", err)
  78. c.ResponseRaw([]byte("success"))
  79. }
  80. utils.LogError("xml解析成功:", msg)
  81. switch msg["InfoType"] {
  82. case INFOTYPE_TICKET:
  83. // 更新ticket
  84. conf.Ticket = msg["ComponentVerifyTicket"]
  85. err := c.wechatServ.UpdateComponentTicket(conf)
  86. if err != nil {
  87. utils.LogError("修改ticket失败:", err)
  88. }
  89. utils.RefreshComponentTicket(msg["ComponentVerifyTicket"])
  90. break
  91. case INFOTYPE_AUTHORIZED:
  92. // 授权成功
  93. var cert = map[string]string{
  94. "appid": msg["AuthorizerAppid"],
  95. "authorization_code": msg["AuthorizationCode"],
  96. }
  97. beego.Error("授权成功参数:", cert)
  98. wxclient := utils.WechatInit(cert, c.wechatServ.UpdateToken)
  99. if wxclient == nil {
  100. utils.LogError("获取wxclient失败")
  101. c.ResponseRaw([]byte("success"))
  102. }
  103. beego.Error(wxclient)
  104. utils.AppendWxClient(wxclient)
  105. // 获取微信信息
  106. info, err := wxclient.GetWechatInfo()
  107. if err != nil {
  108. utils.LogError("获取微信信息失败")
  109. c.ResponseRaw([]byte("success"))
  110. }
  111. beego.Error(info)
  112. authorizerInfo := (info["authorizer_info"]).(map[string]interface{})
  113. beego.Error(info["authorizer_info"])
  114. // 插入数据库
  115. mjson, _ := json.Marshal(msg)
  116. HeadImg := ""
  117. if authorizerInfo["head_img"] != nil {
  118. HeadImg = authorizerInfo["head_img"].(string)
  119. }
  120. var conf = model.SysWechatConf{
  121. Appid: msg["AuthorizerAppid"],
  122. AuthorizationCode: msg["AuthorizationCode"],
  123. AuthorizationInfo: string(mjson),
  124. WxNikeName: authorizerInfo["nick_name"].(string),
  125. HeadImg: HeadImg,
  126. UserName: authorizerInfo["user_name"].(string),
  127. PrincipalName: authorizerInfo["principal_name"].(string),
  128. QrcodeUrl: authorizerInfo["qrcode_url"].(string),
  129. }
  130. err = c.wechatServ.SaveWechatConf(conf)
  131. if err != nil {
  132. utils.LogError("保存微信授权信息失败:", err)
  133. c.ResponseRaw([]byte("success"))
  134. }
  135. break
  136. case INFOTYPE_UPDATEAUTHORIZED:
  137. // 授权更新
  138. break
  139. case INFOTYPE_UNAUTHORIZED:
  140. // 取消授权
  141. // 删除wechatConf信息,同时将org解绑
  142. appid := msg["AuthorizerAppid"]
  143. c.wechatServ.UnAuthorized(appid)
  144. // 删除第三方中的微信信息
  145. utils.Component.DelWxClient(appid)
  146. break
  147. }
  148. c.ResponseRaw([]byte("success"))
  149. }
  150. // WechatInfo 微信接入
  151. func (c *WechatController) WechatInfo() {
  152. method := c.Ctx.Input.Method()
  153. if method == http.MethodGet {
  154. echostr := c.GetString("echostr")
  155. c.ResponseRaw([]byte(echostr))
  156. } else {
  157. c.WxReceive()
  158. }
  159. }
  160. // WxReceive 微信消息接收
  161. func (c *WechatController) WxReceive() {
  162. beego.Error("微信消息接入")
  163. appid := c.GetString(":appid")
  164. wechat, err := utils.Component.GetWxClient(appid)
  165. if err != nil {
  166. utils.LogError("获取微信失败: " + err.Error())
  167. }
  168. msg, err := wechat.TransformMessage(string(c.Ctx.Input.RequestBody))
  169. if err != nil {
  170. utils.LogError("读取微信服务发送内容失败: " + err.Error())
  171. c.ResponseRaw([]byte(""))
  172. }
  173. xp := &core.XMLParse{}
  174. beego.Error("消息:", msg)
  175. encrypt := msg["Encrypt"]
  176. conf, err := c.wechatServ.GetComponentInfo()
  177. if err != nil || conf == nil || conf.Appid == "" {
  178. utils.LogError("读取微信配置文件失败")
  179. c.ResponseRaw([]byte("success"))
  180. }
  181. EncodingAESKey := conf.Aeskey
  182. AESKey, err := base64.StdEncoding.DecodeString(EncodingAESKey + "=")
  183. if err != nil {
  184. utils.LogError("DecodeString失败:", err)
  185. c.ResponseRaw([]byte("success"))
  186. }
  187. EncryptVal, err := base64.StdEncoding.DecodeString(encrypt)
  188. if err != nil {
  189. utils.LogError("密文base64解析", err)
  190. c.ResponseRaw([]byte("success"))
  191. }
  192. msgbyte, err := utils.AesDecrypt(EncryptVal, AESKey)
  193. if err != nil {
  194. utils.LogError("解密失败:", err)
  195. c.ResponseRaw([]byte("success"))
  196. }
  197. utils.LogError("解密成功")
  198. // 解析xml
  199. val, err := xp.Parse(string(msgbyte))
  200. if err != nil {
  201. utils.LogError("xml解析失败:", err)
  202. c.ResponseRaw([]byte("success"))
  203. }
  204. utils.LogError("xml解析成功:", val)
  205. var replay = new(model.TaAutoReply)
  206. switch val["MsgType"] {
  207. case "text":
  208. content := val["Content"]
  209. // 获取数据库存储返回类型
  210. replay, err = c.serv.GetAutoReplayByAppID(appid, content)
  211. break
  212. case "event":
  213. if val["Event"] == "subscribe" {
  214. replay, err = c.serv.GetSubscribeByAppID(appid)
  215. }
  216. break
  217. }
  218. if err != nil {
  219. utils.LogError("获取微信自动回复信息失败: " + err.Error())
  220. c.ResponseRaw([]byte(""))
  221. }
  222. if replay == nil {
  223. c.ResponseRaw([]byte(""))
  224. }
  225. openID := val["FromUserName"]
  226. signature := c.GetString("msg_signature")
  227. nonce := c.GetString("nonce")
  228. timestamp, _ := strconv.Atoi(c.GetString("timestamp"))
  229. beego.Error("signature:", signature, ",nonce:", nonce, ",timestamp:", timestamp)
  230. message, err := c.getReplayMessage(replay, openID, AESKey, wechat)
  231. if err != nil {
  232. utils.LogError("转换回复信息失败: " + err.Error())
  233. c.ResponseRaw([]byte(""))
  234. }
  235. // message, err = utils.AesEncrypt(message, AESKey)
  236. // if err != nil {
  237. // utils.LogError("加密失败:", err)
  238. // c.ResponseRaw([]byte(""))
  239. // }
  240. // beego.Error(string(message))
  241. // data := PassiveMessage{
  242. // Encrypt: component.CDATA{string(message)},
  243. // MsgSignature: component.CDATA{signature},
  244. // TimeStamp: int64(timestamp),
  245. // Nonce: component.CDATA{nonce},
  246. // }
  247. // beego.Error(data)
  248. // res, err := xml.Marshal(data)
  249. // beego.Error(err)
  250. // beego.Error(string(res))
  251. c.ResponseRaw(message)
  252. c.DestroyContext()
  253. c.StopRun()
  254. }
  255. // PassiveMessage 加密后的返回信息
  256. type PassiveMessage struct {
  257. XMLName xml.Name `xml:"xml"`
  258. Encrypt component.CDATA `xml:"Encrypt"`
  259. MsgSignature component.CDATA `xml:"MsgSignature"`
  260. TimeStamp int64 `xml:"TimeStamp"`
  261. Nonce component.CDATA `xml:"Nonce"`
  262. }
  263. func (c *WechatController) getReplayMessage(replay *model.TaAutoReply, openid string, Aeskey []byte, wx *component.WxClient) ([]byte, error) {
  264. switch replay.MessageType {
  265. case models.MESSAGE_TYPE_PARAGRAPH:
  266. msg, err := wx.ResponseMessageText(openid, replay.MessageParagraph)
  267. return msg, err
  268. case models.MESSAGE_TYPE_IMG:
  269. msg, err := wx.ResponseMessageImage(openid, replay.MessageImg)
  270. return msg, err
  271. // case models.MESSAGE_TYPE_PARAGRAPH:
  272. // msg, err := wx.ResponseMessageNews(openid, replay.MessageImg)
  273. // return msg, err
  274. }
  275. return nil, nil
  276. }
  277. // GetPreAuthCode 获取预授权码
  278. func (c *WechatController) GetPreAuthCode() {
  279. code, err := utils.Component.GetPreAuthCode()
  280. if err != nil {
  281. utils.LogError("获取预授权码错误: " + err.Error())
  282. c.ResponseError(err)
  283. }
  284. appid := utils.Component.GetCertificate()["appid"]
  285. c.ResponseJSON(map[string]string{
  286. "appid": appid,
  287. "code": code,
  288. })
  289. }
  290. // GetWechatMenuByAppID 根据appid获取微信详情
  291. func (c *WechatController) GetWechatInfoByAppID() {
  292. appid := c.GetString(":appid")
  293. wxclient, err := utils.Component.GetWxClient(appid)
  294. if err != nil {
  295. utils.LogError("获取微信信息失败: " + err.Error())
  296. c.ResponseError(err)
  297. }
  298. info, err := wxclient.GetWechatInfo()
  299. if err != nil {
  300. utils.LogError("获取微信详情失败: " + err.Error())
  301. c.ResponseError(err)
  302. }
  303. c.ResponseJSON(info)
  304. }
  305. // GetWechatMenuByAppID 获取菜单
  306. func (c *WechatController) GetWechatMenuByAppID() {
  307. appid := c.GetString(":appid")
  308. wxclient, err := utils.Component.GetWxClient(appid)
  309. if err != nil {
  310. utils.LogError("获取微信信息失败: " + err.Error())
  311. c.ResponseError(err)
  312. }
  313. menus, err := wxclient.GetMenu()
  314. if err != nil {
  315. utils.LogError("获取微信详情失败: " + err.Error())
  316. c.ResponseError(err)
  317. }
  318. c.ResponseJSON(menus)
  319. }
  320. // GetWechatByCode 根据code获取微信信息
  321. func (c *WechatController) GetWechatByCode() {
  322. code := c.GetString(":code")
  323. beego.Error(code)
  324. conf, err := c.wechatServ.GetWechatByCode(code)
  325. if err != nil {
  326. utils.LogError("获取微信详情失败: " + err.Error())
  327. c.ResponseError(err)
  328. }
  329. beego.Error(conf)
  330. if conf == nil || conf.ConfId == "" || conf.Status == models.STATUS_NORMAL {
  331. c.ResponseJSON("")
  332. }
  333. c.ResponseJSON(map[string]string{
  334. "ConfId": conf.ConfId,
  335. "NickName": conf.WxNikeName,
  336. "HeadImg": conf.HeadImg,
  337. })
  338. }