event.go 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /**
  2. * Copyright (c) 2022 Yansen Zhang
  3. * wxcomponent is licensed under Mulan PSL v2.
  4. * You can use this software according to the terms and conditions of the Mulan PSL v2.
  5. * You may obtain a copy of Mulan PSL v2 at:
  6. * http://license.coscl.org.cn/MulanPSL2
  7. * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
  8. * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
  9. * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
  10. * See the Mulan PSL v2 for more details.
  11. **/
  12. package wxcomponent
  13. import (
  14. "crypto/sha1"
  15. "encoding/base64"
  16. "encoding/binary"
  17. "encoding/xml"
  18. "fmt"
  19. "sort"
  20. "strconv"
  21. "strings"
  22. "time"
  23. "gitee.com/yansen_zh/wxcomponent/api/authorization"
  24. "gitee.com/yansen_zh/wxcomponent/api/event"
  25. "gitee.com/yansen_zh/wxcomponent/config"
  26. "gitee.com/yansen_zh/wxcomponent/utils"
  27. "gitee.com/yansen_zh/wxcomponent/utils/encrypt"
  28. "gitee.com/yansen_zh/wxcomponent/utils/log"
  29. )
  30. // DecodeMessage 解密消息
  31. func DecodeMessage(src []byte) ([]byte, error) {
  32. log.Info("解码 xml 数据: ", string(src))
  33. msg := event.ReceivedEncryptMessage{}
  34. if err := xml.Unmarshal(src, &msg); err != nil {
  35. log.Error("解码 xml 数据失败: ", err.Error())
  36. return nil, err
  37. }
  38. bt1, e1 := base64.StdEncoding.DecodeString(msg.Encrypt)
  39. if e1 != nil {
  40. log.Error("解码 base 数据失败: ", e1.Error())
  41. log.Error("原始 base64 数据: ", msg.Encrypt)
  42. return nil, e1
  43. }
  44. bt2, e2 := encrypt.AESDecode(bt1, aesKey)
  45. if e2 != nil {
  46. log.Error("解码加密数据失败: ", e2.Error())
  47. log.Error("待解密数据: ", string(bt1))
  48. return nil, e2
  49. }
  50. return bt2, nil
  51. }
  52. // toBigEndian 转换为网络大端序
  53. func toBigEndian(i int) []byte {
  54. bt := make([]byte, 4)
  55. binary.BigEndian.PutUint32(bt, uint32(i))
  56. return bt
  57. }
  58. // EncodeMessage 加密消息
  59. func EncodeMessage(appID string, src []byte) ([]byte, error) {
  60. log.Info("待加密数据APPID: ", appID)
  61. log.Info("待加密数据: ", string(src))
  62. rand16 := []byte(utils.RandStr(16))
  63. msgLen := toBigEndian(len(src))
  64. // 待加密数据 = random(16B)+ msg_len(4B) + msg + appid
  65. data := append(rand16, msgLen...)
  66. data = append(data, msgLen...)
  67. data = append(data, src...)
  68. data = append(data, []byte(appID)...)
  69. bt1, e1 := encrypt.AESEncode(data, aesKey)
  70. if e1 != nil {
  71. log.Error("加密数据失败: ", e1.Error())
  72. log.Error("待加密数据: ", string(bt1))
  73. return nil, e1
  74. }
  75. encryptStr := base64.StdEncoding.EncodeToString(bt1)
  76. timestamp := time.Now().Unix()
  77. timestampStr := strconv.FormatInt(timestamp, 10)
  78. nonceStr := utils.RandStr(16)
  79. strs := []string{
  80. timestampStr,
  81. nonceStr,
  82. config.GetAccessToken(),
  83. encryptStr,
  84. }
  85. sort.Strings(strs)
  86. signature := fmt.Sprintf("%x", sha1.Sum([]byte(strings.Join(strs, ""))))
  87. evt := event.SendEncryptMessage{
  88. Encrypt: event.CDATA{Value: encryptStr},
  89. MsgSignature: signature,
  90. TimeStamp: timestamp,
  91. Nonce: nonceStr,
  92. }
  93. res, err := xml.Marshal(&evt)
  94. if err != nil {
  95. log.Error("转换 xml 数据失败: ", err.Error())
  96. log.Error("待转换 xml 数据: ", evt)
  97. return nil, e1
  98. }
  99. return res, nil
  100. }
  101. // DecodeAuthEvent 解密事件
  102. func DecodeAuthEvent(src []byte) (*event.AuthEvent, []byte, error) {
  103. log.Info("待解密数据: ", string(src))
  104. bt, e1 := DecodeMessage(src)
  105. if e1 != nil {
  106. return nil, nil, e1
  107. }
  108. evt := event.AuthEvent{}
  109. if err := xml.Unmarshal(bt, evt); err != nil {
  110. log.Error("解码 xml 数据失败: ", err.Error())
  111. log.Error("待解码数据: ", string(bt))
  112. }
  113. // 如果是授权成功或者刷新授权, 则更新相关内容
  114. if evt.InfoType == event.INFO_TYPE_AUTHORIZED || evt.InfoType == event.INFO_TYPE_UPDATEAUTHORIZED {
  115. if err := handleAuthorized(bt); err != nil {
  116. return nil, nil, err
  117. }
  118. }
  119. // 如果是取消授权
  120. if evt.InfoType == event.INFO_TYPE_UNAUTHORIZED {
  121. handleUnauthorized(bt)
  122. }
  123. // 如果是刷新票据
  124. if evt.InfoType == event.INFO_TYPE_COMPONENT_VERIFY_TICKET {
  125. if err := handleComponentVerifyTicket(bt); err != nil {
  126. return nil, nil, err
  127. }
  128. }
  129. return &evt, bt, nil
  130. }
  131. // DecodeAuthorizerEvent 解密授权业务方的消息与事件
  132. func DecodeAuthorizerEvent(appID string, src []byte) (*event.AuthorizerEvent, []byte, error) {
  133. log.Info("待解密数据APPID: ", appID)
  134. log.Info("待解密数据: ", string(src))
  135. bt, e1 := DecodeMessage(src)
  136. if e1 != nil {
  137. return nil, nil, e1
  138. }
  139. evt := event.AuthorizerEvent{}
  140. if err := xml.Unmarshal(bt, evt); err != nil {
  141. log.Error("解码 xml 数据失败: ", err.Error())
  142. log.Error("待解码数据: ", string(bt))
  143. }
  144. authorizer := config.GetAuthorizer()
  145. e2 := authorizer.ProcessMessage(appID, evt.MsgType.Value, evt.Event.Value, bt)
  146. if e2 != nil {
  147. log.Error("处理事件或者消息失败: ", e2.Error())
  148. log.Error("待处理消息: ", string(bt))
  149. }
  150. return &evt, bt, nil
  151. }
  152. // handleAuthorized 授权成功或刷新授权
  153. func handleAuthorized(data []byte) error {
  154. authorizer := config.GetAuthorizer()
  155. evtData := event.AuthorizedEvent{}
  156. xml.Unmarshal(data, &evtData)
  157. // 获取授权信息
  158. queryAuth, e1 := authorization.GetQueryAuth(evtData.AuthorizationCode)
  159. if e1 != nil {
  160. log.Error("获取授权信息失败: ", e1.Error())
  161. return e1
  162. }
  163. appID := evtData.AuthorizerAppID
  164. authInfo := queryAuth.AuthorizationInfo
  165. expire := utils.GetExpireTime(authInfo.ExpiresIn)
  166. funcLst := make([]int, 0)
  167. if nil != authInfo.FuncInfo && len(authInfo.FuncInfo) > 0 {
  168. for _, info := range authInfo.FuncInfo {
  169. funcLst = append(funcLst, info.FuncscopeCategory.ID)
  170. }
  171. }
  172. // 刷新平台授权状态
  173. authorizer.RefreshAuthStatus(appID, evtData.InfoType)
  174. // 刷新授权集
  175. authorizer.RefreshFuncInfo(appID, funcLst)
  176. // 刷新 token
  177. e2 := authorizer.RefreshToken(appID, authInfo.AuthorizerAccessToken, authInfo.AuthorizerRefreshToken, expire)
  178. if e2 != nil {
  179. log.Error("刷新公众号或者小程序 Token 失败: ", e2.Error())
  180. return e2
  181. }
  182. return nil
  183. }
  184. // handleUnauthorized 取消授权
  185. func handleUnauthorized(data []byte) error {
  186. authorizer := config.GetAuthorizer()
  187. evtData := event.UnauthorizedEvent{}
  188. xml.Unmarshal(data, &evtData)
  189. appID := evtData.AuthorizerAppID
  190. // 刷新平台授权状态
  191. authorizer.RefreshAuthStatus(appID, evtData.InfoType)
  192. return nil
  193. }
  194. // handleComponentVerifyTicket 验证票据
  195. func handleComponentVerifyTicket(data []byte) error {
  196. evtData := event.ComponentVerifyTicketEvent{}
  197. xml.Unmarshal(data, &evtData)
  198. expire := utils.GetExpireTime(12 * 3600) // component_verify_ticket 的有效时间为12小时
  199. err := config.RefreshVerifyTicket(evtData.ComponentVerifyTicket, expire)
  200. if err != nil {
  201. log.Error("刷新票据信息失败: ", err.Error())
  202. return err
  203. }
  204. return nil
  205. }