广告平台(站长使用)
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.

message.go 9.3 KiB

3 months ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. package wechat
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "encoding/xml"
  6. "errors"
  7. "strconv"
  8. "time"
  9. )
  10. var EventTicket = "component_verify_ticket" //ticket推送
  11. var EventUnauthorized = "unauthorized" //取消授权
  12. var EventUpdateAuthorized = "updateauthorized" //更新授权
  13. var EventAuthorized = "authorized" //授权成功
  14. var MsgTypeText = "text" //文本消息
  15. var MsgTypeImage = "image" //文本消息
  16. var MsgTypeVoice = "voice" //语音消息
  17. var MsgTypeVideo = "Video" //视频消息
  18. var MsgTypeMusic = "music" //音乐消息
  19. var MsgTypeNews = "news" //图文消息
  20. // EventMessageBody 事件推送
  21. type EventMessageBody struct {
  22. XMLName xml.Name `xml:"xml"`
  23. AppId string `xml:"AppId" json:"app_id"`
  24. CreateTime int `xml:"CreateTime" json:"create_time"`
  25. InfoType string `xml:"InfoType" json:"info_type"`
  26. ComponentVerifyTicket string `xml:"ComponentVerifyTicket" json:"component_verify_ticket"`
  27. AuthorizerAppid string `xml:"AuthorizerAppid" json:"authorizer_appid"`
  28. AuthorizationCode string `xml:"AuthorizationCode" json:"authorization_code"`
  29. AuthorizationCodeExpiredTime string `xml:"AuthorizationCodeExpiredTime" json:"authorization_code_expired_time"`
  30. PreAuthCode string `xml:"PreAuthCode" json:"pre_auth_code"`
  31. }
  32. // MessageBodyDecrypt 消息体
  33. type MessageBodyDecrypt struct {
  34. XMLName xml.Name `xml:"xml"`
  35. ToUserName string `xml:"ToUserName"`
  36. FromUserName string `xml:"FromUserName"`
  37. CreateTime string `xml:"CreateTime"`
  38. MsgType string `xml:"MsgType"`
  39. Url string `xml:"Url"`
  40. PicUrl string `xml:"PicUrl"`
  41. MediaId string `xml:"MediaId"`
  42. ThumbMediaId string `xml:"ThumbMediaId"`
  43. Content string `xml:"Content"`
  44. MsgId int `xml:"MsgId"`
  45. Location_X string `xml:"Location_x"`
  46. Location_Y string `xml:"Location_y"`
  47. Label string `xml:"Label"`
  48. }
  49. type MessageEncryptBody struct {
  50. XMLName xml.Name `xml:"xml"`
  51. Encrypt CDATA `xml:"Encrypt"`
  52. MsgSignature CDATA `xml:"MsgSignature"`
  53. TimeStamp string `xml:"TimeStamp"`
  54. Nonce CDATA `xml:"Nonce"`
  55. }
  56. type MessageText struct {
  57. XMLName xml.Name `xml:"xml"`
  58. ToUserName CDATA `xml:"ToUserName"`
  59. FromUserName CDATA `xml:"FromUserName"`
  60. CreateTime string `xml:"CreateTime"`
  61. MsgType CDATA `xml:"MsgType"`
  62. Content CDATA `xml:"Content"`
  63. }
  64. type MessageImage struct {
  65. XMLName xml.Name `xml:"xml"`
  66. ToUserName CDATA `xml:"ToUserName"`
  67. FromUserName CDATA `xml:"FromUserName"`
  68. CreateTime string `xml:"CreateTime"`
  69. MsgType CDATA `xml:"MsgType"`
  70. Image Media `xml:"Image"`
  71. }
  72. type MessageVoice struct {
  73. XMLName xml.Name `xml:"xml"`
  74. ToUserName CDATA `xml:"ToUserName"`
  75. FromUserName CDATA `xml:"FromUserName"`
  76. CreateTime string `xml:"CreateTime"`
  77. MsgType CDATA `xml:"MsgType"`
  78. Voice Media `xml:"Voice"`
  79. }
  80. type MessageVideo struct {
  81. XMLName xml.Name `xml:"xml"`
  82. ToUserName CDATA `xml:"ToUserName"`
  83. FromUserName CDATA `xml:"FromUserName"`
  84. CreateTime string `xml:"CreateTime"`
  85. MsgType CDATA `xml:"MsgType"`
  86. Video Video `xml:"Video"`
  87. }
  88. type MessageMusic struct {
  89. XMLName xml.Name `xml:"xml"`
  90. ToUserName CDATA `xml:"ToUserName"`
  91. FromUserName CDATA `xml:"FromUserName"`
  92. CreateTime string `xml:"CreateTime"`
  93. MsgType CDATA `xml:"MsgType"`
  94. Music Music `xml:"Music"`
  95. }
  96. type MessageArticle struct {
  97. XMLName xml.Name `xml:"xml"`
  98. ToUserName CDATA `xml:"ToUserName"`
  99. FromUserName CDATA `xml:"FromUserName"`
  100. CreateTime string `xml:"CreateTime"`
  101. MsgType CDATA `xml:"MsgType"`
  102. ArticleCount string `xml:"ArticleCount"`
  103. Articles []ArticleItem `xml:"Articles"`
  104. }
  105. type CDATA struct {
  106. Text string `xml:",innerxml"`
  107. }
  108. type Media struct {
  109. MediaId CDATA `xml:"MediaId"`
  110. }
  111. type Video struct {
  112. MediaId CDATA `xml:"MediaId"`
  113. Title CDATA `xml:"Title"`
  114. Description CDATA `xml:"Description"`
  115. }
  116. type Music struct {
  117. Title CDATA `xml:"Title"`
  118. Description CDATA `xml:"Description"`
  119. MusicUrl CDATA `xml:"MusicUrl"`
  120. HQMusicUrl CDATA `xml:"HQMusicUrl"`
  121. ThumbMediaId CDATA `xml:"ThumbMediaId"`
  122. }
  123. type ArticleItem struct {
  124. Title CDATA `xml:"Title"`
  125. Description CDATA `xml:"Description"`
  126. PicUrl CDATA `xml:"PicUrl"`
  127. Url CDATA `xml:"Url"`
  128. }
  129. func FormatMessage(plainText []byte, data interface{}) (*interface{}, error) {
  130. length := GetMessageLength(plainText)
  131. err := xml.Unmarshal(plainText[20:20+length], data)
  132. if err != nil {
  133. return nil, errors.New("格式化消息失败:format message error")
  134. }
  135. return &data, nil
  136. }
  137. func GetMessageLength(plainText []byte) int32 {
  138. // Read length
  139. buf := bytes.NewBuffer(plainText[16:20])
  140. var length int32
  141. err := binary.Read(buf, binary.BigEndian, &length)
  142. if err != nil {
  143. panic("获取消息长度失败:read message length error")
  144. }
  145. return length
  146. }
  147. func ValueToCDATA(content string) CDATA {
  148. return CDATA{"<![CDATA[" + content + "]]>"}
  149. }
  150. // FormatTextMessage 格式化文本消息
  151. func FormatTextMessage(fromUserName string, toUserName string, content string) []byte {
  152. timestamp := strconv.Itoa(int(time.Now().Unix()))
  153. textMessage := MessageText{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), Content: ValueToCDATA(content), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeText)}
  154. messageBytes, err := xml.MarshalIndent(textMessage, " ", " ")
  155. if err != nil {
  156. panic("格式化文本消息失败:xml marsha1 error;" + err.Error())
  157. }
  158. return messageBytes
  159. }
  160. // FormatImageMessage 格式化图片消息
  161. func FormatImageMessage(fromUserName string, toUserName string, mediaId string) []byte {
  162. timestamp := strconv.Itoa(int(time.Now().Unix()))
  163. imageMessage := MessageImage{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeImage), Image: Media{ValueToCDATA(mediaId)}}
  164. messageBytes, err := xml.MarshalIndent(imageMessage, " ", " ")
  165. if err != nil {
  166. panic("格式化图片消息失败:xml marsha1 error;" + err.Error())
  167. }
  168. return messageBytes
  169. }
  170. // FormatVoiceMessage 格式语音消息
  171. func FormatVoiceMessage(fromUserName string, toUserName string, mediaId string) []byte {
  172. timestamp := strconv.Itoa(int(time.Now().Unix()))
  173. voiceMessage := MessageVoice{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeVoice), Voice: Media{ValueToCDATA(mediaId)}}
  174. messageBytes, err := xml.MarshalIndent(voiceMessage, " ", " ")
  175. if err != nil {
  176. panic("格式化语音消息失败:xml marsha1 error;" + err.Error())
  177. }
  178. return messageBytes
  179. }
  180. // FormatVideoMessage 格式化视频消息
  181. func FormatVideoMessage(fromUserName string, toUserName string, mediaId string, title string, description string) []byte {
  182. timestamp := strconv.Itoa(int(time.Now().Unix()))
  183. videoMessage := MessageVideo{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeVideo), Video: Video{
  184. MediaId: ValueToCDATA(mediaId),
  185. Title: ValueToCDATA(title),
  186. Description: ValueToCDATA(description),
  187. }}
  188. messageBytes, err := xml.MarshalIndent(videoMessage, " ", " ")
  189. if err != nil {
  190. panic("格式化语音消息失败:xml marsha1 error;" + err.Error())
  191. }
  192. return messageBytes
  193. }
  194. // FormatMusicMessage 格式化音乐消息
  195. func FormatMusicMessage(fromUserName string, toUserName string, thumbMediaId string, title string, description string, musicUrl string, hQMusicUrl string) []byte {
  196. timestamp := strconv.Itoa(int(time.Now().Unix()))
  197. musicMessage := MessageMusic{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeMusic), Music: Music{
  198. Title: ValueToCDATA(title),
  199. Description: ValueToCDATA(description),
  200. MusicUrl: ValueToCDATA(musicUrl),
  201. HQMusicUrl: ValueToCDATA(hQMusicUrl),
  202. ThumbMediaId: ValueToCDATA(thumbMediaId),
  203. }}
  204. messageBytes, err := xml.MarshalIndent(musicMessage, " ", " ")
  205. if err != nil {
  206. panic("格式化音乐消息失败:xml marsha1 error;" + err.Error())
  207. }
  208. return messageBytes
  209. }
  210. // FormatArticlesMessage 格式化音乐消息
  211. func FormatArticlesMessage(fromUserName string, toUserName string, items []ArticleItem) []byte {
  212. timestamp := strconv.Itoa(int(time.Now().Unix()))
  213. articleNum := strconv.Itoa(len(items))
  214. musicMessage := MessageArticle{FromUserName: ValueToCDATA(fromUserName), ToUserName: ValueToCDATA(toUserName), CreateTime: timestamp, MsgType: ValueToCDATA(MsgTypeNews), Articles: items, ArticleCount: articleNum}
  215. messageBytes, err := xml.MarshalIndent(musicMessage, " ", " ")
  216. if err != nil {
  217. panic("格式化图文消息失败:xml marsha1 error;" + err.Error())
  218. }
  219. return messageBytes
  220. }
  221. // FormatEncryptData 格式化微信加密数据
  222. func FormatEncryptData(encrypted string, token string) MessageEncryptBody {
  223. nonce := makeRandomString(16)
  224. timestamp := strconv.Itoa(int(time.Now().Unix()))
  225. data := MessageEncryptBody{Encrypt: ValueToCDATA(encrypted), Nonce: ValueToCDATA(nonce), MsgSignature: ValueToCDATA(GetSignature(timestamp, nonce, encrypted, token)), TimeStamp: timestamp}
  226. return data
  227. }