Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

201 line
5.1KB

  1. package main
  2. import (
  3. "crypto/sha1"
  4. "errors"
  5. "fmt"
  6. "log"
  7. "math/rand"
  8. "sort"
  9. "strings"
  10. "time"
  11. )
  12. //Article is one item in News Message
  13. // one such message can contains upto 10 Articles
  14. type Article struct {
  15. title, description, picURL, url string
  16. }
  17. //BuildTextMsg Given a text message send it to wechat client
  18. func BuildTextMsg(txt string, ToUserName string) (xml string, err error) {
  19. if txt == "" || ToUserName == "" {
  20. err = errors.New("Empty text body or Empty destination")
  21. xml = ""
  22. return
  23. }
  24. msg := fmt.Sprintf(txtMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), txt)
  25. e := Encode(msg)
  26. xml, _, _, _ = signMsg(e)
  27. return
  28. }
  29. func signMsg(content string) (xml string, timestamp int32, nonce int32, signature string) {
  30. timestamp = int32(time.Now().Unix())
  31. nonce = rand.Int31()
  32. strTimestamp := fmt.Sprintf("%d", timestamp)
  33. strNonce := fmt.Sprintf("%d", nonce)
  34. signature = getSignature(APIConfig.Token, strTimestamp, strNonce, content)
  35. xml = "<xml>" +
  36. "<Encrypt>" + content + "</Encrypt>" +
  37. "<MsgSignature>" + signature + "</MsgSignature>" +
  38. "<TimeStamp>" + strTimestamp + "</TimeStamp>" +
  39. "<Nonce>" + strNonce + "</Nonce>" +
  40. "</xml>"
  41. return
  42. }
  43. func getSignature(token string, timestamp string, nonce string, content string) (signature string) {
  44. strs := []string{token, timestamp, nonce, content}
  45. sort.Strings(strs)
  46. s := strings.Join(strs, "")
  47. h := sha1.New()
  48. h.Write([]byte(s))
  49. signature = fmt.Sprintf("%x", h.Sum(nil))
  50. return
  51. }
  52. func buildTxtMsg(ToUserName, content string) (msg string) {
  53. msg = fmt.Sprintf(txtMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), content)
  54. return
  55. }
  56. func txtMsgTemplate() string {
  57. return `<xml>
  58. <ToUserName><![CDATA[%s]]></ToUserName>
  59. <FromUserName><![CDATA[%s]]></FromUserName>
  60. <CreateTime>%d</CreateTime>
  61. <MsgType><![CDATA[text]]></MsgType>
  62. <Content><![CDATA[%s]]></Content>
  63. </xml>`
  64. }
  65. func buildPicMsg(ToUserName, mediaID string) (msg string) {
  66. msg = fmt.Sprintf(picMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID)
  67. return
  68. }
  69. func picMsgTemplate() string {
  70. return `<xml>
  71. <ToUserName><![CDATA[%s]]></ToUserName>
  72. <FromUserName><![CDATA[%s]]></FromUserName>
  73. <CreateTime>%d</CreateTime>
  74. <MsgType><![CDATA[image]]></MsgType>
  75. <Image>
  76. <MediaId><![CDATA[%s]]></MediaId>
  77. </Image>
  78. </xml>`
  79. }
  80. func buildVoiceMsg(ToUserName, mediaID string) (msg string) {
  81. msg = fmt.Sprintf(voiceMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID)
  82. return
  83. }
  84. func voiceMsgTemplate() string {
  85. return `<xml>
  86. <ToUserName><![CDATA[%s]]></ToUserName>
  87. <FromUserName><![CDATA[%s]]></FromUserName>
  88. <CreateTime>%d</CreateTime>
  89. <MsgType><![CDATA[voice]]></MsgType>
  90. <Voice>
  91. <MediaId><![CDATA[%s]]></MediaId>
  92. </Voice>
  93. </xml>`
  94. }
  95. func buildVideoMsg(ToUserName, mediaID, title, description string) (msg string) {
  96. msg = fmt.Sprintf(videoMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID, title, description)
  97. return
  98. }
  99. func videoMsgTemplate() string {
  100. return `<xml>
  101. <ToUserName><![CDATA[%s]]></ToUserName>
  102. <FromUserName><![CDATA[%s]]></FromUserName>
  103. <CreateTime>%d</CreateTime>
  104. <MsgType><![CDATA[video]]></MsgType>
  105. <Video>
  106. <MediaId><![CDATA[%s]]></MediaId>
  107. <Title><![CDATA[%s]]></Title>
  108. <Description><![CDATA[%s]]></Description>
  109. </Video>
  110. </xml>`
  111. }
  112. func bulidMusicMsg(ToUserName, mediaID, title, description, url, hqURL string) (msg string) {
  113. msg = fmt.Sprintf(musicMsgTemplate(),
  114. ToUserName,
  115. APIConfig.PublicAccountID,
  116. int32(time.Now().Unix()),
  117. title,
  118. description,
  119. url,
  120. hqURL,
  121. mediaID)
  122. return
  123. }
  124. func musicMsgTemplate() string {
  125. return `<xml>
  126. <ToUserName><![CDATA[toUser]]></ToUserName>
  127. <FromUserName><![CDATA[fromUser]]></FromUserName>
  128. <CreateTime>12345678</CreateTime>
  129. <MsgType><![CDATA[music]]></MsgType>
  130. <Music>
  131. <Title><![CDATA[TITLE]]></Title>
  132. <Description><![CDATA[DESCRIPTION]]></Description>
  133. <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
  134. <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
  135. <ThumbMediaId><![CDATA[media_id]]></ThumbMediaId>
  136. </Music>
  137. </xml>`
  138. }
  139. func buildNewsMsg(ToUserName, title, description string, articles []Article) (msg string) {
  140. count := 0
  141. items := []string{}
  142. for _, a := range articles {
  143. if count >= 8 {
  144. err := errors.New("too many articles, only take first 8")
  145. log.Fatal(err)
  146. break
  147. }
  148. s := buildArticleItem(a)
  149. items = append(items, s)
  150. count++
  151. }
  152. strItems := strings.Join(items, "")
  153. msg = fmt.Sprintf(newsMsgTemplate(),
  154. ToUserName,
  155. APIConfig.PublicAccountID,
  156. int32(time.Now().Unix()),
  157. count,
  158. strItems)
  159. return
  160. }
  161. func buildArticleItem(item Article) (article string) {
  162. template := `<item>
  163. <Title><![CDATA[%s]]></Title>
  164. <Description><![CDATA[%s]]></Description>
  165. <PicUrl><![CDATA[%s]]></PicUrl>
  166. <Url><![CDATA[%s]]></Url>
  167. </item>
  168. `
  169. article = fmt.Sprintf(template,
  170. item.title, item.description, item.picURL, item.url)
  171. return article
  172. }
  173. func newsMsgTemplate() string {
  174. return `<xml>
  175. <ToUserName><![CDATA[%s]]></ToUserName>
  176. <FromUserName><![CDATA[%s]]></FromUserName>
  177. <CreateTime>%d</CreateTime>
  178. <MsgType><![CDATA[news]]></MsgType>
  179. <ArticleCount>%d</ArticleCount>
  180. <Articles>
  181. %s
  182. </Articles>
  183. </xml>`
  184. }