Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

254 Zeilen
7.0KB

  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. //BuildLocationMsg doesn't work for build location message
  30. func BuildLocationMsg(long, lat, precision float64, ToUserName string) (xml string) {
  31. msg := buildLocationMsg()
  32. e := Encode(msg)
  33. xml, _, _, _ = signMsg(e)
  34. return
  35. }
  36. func signMsg(content string) (xml string, timestamp int32, nonce int32, signature string) {
  37. timestamp = int32(time.Now().Unix())
  38. nonce = rand.Int31()
  39. strTimestamp := fmt.Sprintf("%d", timestamp)
  40. strNonce := fmt.Sprintf("%d", nonce)
  41. signature = getSignature(APIConfig.Token, strTimestamp, strNonce, content)
  42. xml = "<xml>" +
  43. "<Encrypt>" + content + "</Encrypt>" +
  44. "<MsgSignature>" + signature + "</MsgSignature>" +
  45. "<TimeStamp>" + strTimestamp + "</TimeStamp>" +
  46. "<Nonce>" + strNonce + "</Nonce>" +
  47. "</xml>"
  48. return
  49. }
  50. func getSignature(token string, timestamp string, nonce string, content string) (signature string) {
  51. strs := []string{token, timestamp, nonce, content}
  52. sort.Strings(strs)
  53. s := strings.Join(strs, "")
  54. h := sha1.New()
  55. h.Write([]byte(s))
  56. signature = fmt.Sprintf("%x", h.Sum(nil))
  57. return
  58. }
  59. func buildTxtMsg(ToUserName, content string) (msg string) {
  60. msg = fmt.Sprintf(txtMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), content)
  61. return
  62. }
  63. func txtMsgTemplate() string {
  64. return `<xml>
  65. <ToUserName><![CDATA[%s]]></ToUserName>
  66. <FromUserName><![CDATA[%s]]></FromUserName>
  67. <CreateTime>%d</CreateTime>
  68. <MsgType><![CDATA[text]]></MsgType>
  69. <Content><![CDATA[%s]]></Content>
  70. </xml>`
  71. }
  72. //upload image to media as temp data, get mediaid and send it out
  73. func buildUploadPicMsg(ToUserName, path string) (msg string) {
  74. mediaID := uploadImage(path)
  75. msg = buildPicMsg(ToUserName, mediaID)
  76. return
  77. }
  78. func buildPicMsg(ToUserName, mediaID string) (msg string) {
  79. msg = fmt.Sprintf(picMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID)
  80. return
  81. }
  82. func picMsgTemplate() string {
  83. return `<xml>
  84. <ToUserName><![CDATA[%s]]></ToUserName>
  85. <FromUserName><![CDATA[%s]]></FromUserName>
  86. <CreateTime>%d</CreateTime>
  87. <MsgType><![CDATA[image]]></MsgType>
  88. <Image>
  89. <MediaId><![CDATA[%s]]></MediaId>
  90. </Image>
  91. </xml>`
  92. }
  93. func buildUploadVoiceMsg(ToUserName, path string) (msg string) {
  94. mediaID := uploadVoice(path)
  95. log.Println("get media id " + mediaID)
  96. msg = buildVoiceMsg(ToUserName, mediaID)
  97. return
  98. }
  99. func buildVoiceMsg(ToUserName, mediaID string) (msg string) {
  100. msg = fmt.Sprintf(voiceMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID)
  101. return
  102. }
  103. func voiceMsgTemplate() string {
  104. return `<xml>
  105. <ToUserName><![CDATA[%s]]></ToUserName>
  106. <FromUserName><![CDATA[%s]]></FromUserName>
  107. <CreateTime>%d</CreateTime>
  108. <MsgType><![CDATA[voice]]></MsgType>
  109. <Voice>
  110. <MediaId><![CDATA[%s]]></MediaId>
  111. </Voice>
  112. </xml>`
  113. }
  114. func buildVideoMsg(ToUserName, mediaID, title, description string) (msg string) {
  115. msg = fmt.Sprintf(videoMsgTemplate(), ToUserName, APIConfig.PublicAccountID, int32(time.Now().Unix()), mediaID, title, description)
  116. return
  117. }
  118. func videoMsgTemplate() string {
  119. return `<xml>
  120. <ToUserName><![CDATA[%s]]></ToUserName>
  121. <FromUserName><![CDATA[%s]]></FromUserName>
  122. <CreateTime>%d</CreateTime>
  123. <MsgType><![CDATA[video]]></MsgType>
  124. <Video>
  125. <MediaId><![CDATA[%s]]></MediaId>
  126. <Title><![CDATA[%s]]></Title>
  127. <Description><![CDATA[%s]]></Description>
  128. </Video>
  129. </xml>`
  130. }
  131. func buildSampleMusicMsg(ToUserName string) (msg string) {
  132. thumbID := "AxEDlSNwJcs_0KnyiGnpAYiB1-sjITosWkU3VFsj62KuCyTQO-Fh1UH8d-pBmY1K"
  133. thumbID = "JZoNKZr9gzaI5ELBnFUljujiBfIwr4CtXHkZtQMjm-sLVD5PGOU_uvsaF3oNNFjp"
  134. thumbID = "5dlAsVZ8znWBuGLTjAFM8mIqapHiI0Cmazsvx4TmbsQXZk73RZz8AVnbZp6oSJZn" //jpg 200x200
  135. thumbID = "e2iNEiSxCX5TV1WbFd0TQJsw84YtISnam2Q_qEXDdT4" //永久素材的 ID
  136. url := "http://www.youtubeinmp3.com/download/get/?i=vNIuJKoAE46uz2RggRaKGFqQUVAqd0Td&e=92&progressType=button&color=008000"
  137. url = "http://agobe.yt-downloader.org/download.php?id=d7be28d3a1fafa69d7e464edb8186226"
  138. url = "http://www.sample-videos.com/audio/mp3/india-national-anthem.mp3"
  139. url = "http://google.com/"
  140. url = "http://m.creaders.net/travel/2017/05/11/1823175.html"
  141. url = "https://biukop.com.au/music.mp3" //real mp3
  142. //url = "http://mp.weixin.qq.com/s/Jo7rmlMZa_iO97eckWIzFg"
  143. msg = buildMusicMsg(ToUserName, thumbID, "音乐标杆出", "测试音乐缩略土月卡其", url, url)
  144. return
  145. }
  146. func buildMusicMsg(ToUserName, ThumbMediaID, title, description, url, hqURL string) (msg string) {
  147. msg = fmt.Sprintf(musicMsgTemplate(),
  148. ToUserName,
  149. APIConfig.PublicAccountID,
  150. int32(time.Now().Unix()),
  151. title,
  152. description,
  153. url,
  154. hqURL,
  155. ThumbMediaID)
  156. return
  157. }
  158. func musicMsgTemplate() string {
  159. return `<xml>
  160. <ToUserName><![CDATA[%s]]></ToUserName>
  161. <FromUserName><![CDATA[%s]]></FromUserName>
  162. <CreateTime>%d</CreateTime>
  163. <MsgType><![CDATA[music]]></MsgType>
  164. <Music>
  165. <Title><![CDATA[%s]]></Title>
  166. <Description><![CDATA[%s]]></Description>
  167. <MusicUrl><![CDATA%s]]></MusicUrl>
  168. <HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
  169. <ThumbMediaId><![CDATA[%s]]></ThumbMediaId>
  170. </Music>
  171. </xml>`
  172. }
  173. func buildNewsMsg(ToUserName, title, description string, articles []Article) (msg string) {
  174. count := 0
  175. items := []string{}
  176. for _, a := range articles {
  177. if count >= 8 {
  178. err := errors.New("too many articles, only take first 8")
  179. log.Println(err)
  180. break
  181. }
  182. s := buildArticleItem(a)
  183. items = append(items, s)
  184. count++
  185. }
  186. strItems := strings.Join(items, "")
  187. msg = fmt.Sprintf(newsMsgTemplate(),
  188. ToUserName,
  189. APIConfig.PublicAccountID,
  190. int32(time.Now().Unix()),
  191. count,
  192. strItems)
  193. return
  194. }
  195. func buildArticleItem(item Article) (article string) {
  196. template := `<item>
  197. <Title><![CDATA[%s]]></Title>
  198. <Description><![CDATA[%s]]></Description>
  199. <PicUrl><![CDATA[%s]]></PicUrl>
  200. <Url><![CDATA[%s]]></Url>
  201. </item>
  202. `
  203. article = fmt.Sprintf(template,
  204. item.title, item.description, item.picURL, item.url)
  205. return article
  206. }
  207. func newsMsgTemplate() string {
  208. return `<xml>
  209. <ToUserName><![CDATA[%s]]></ToUserName>
  210. <FromUserName><![CDATA[%s]]></FromUserName>
  211. <CreateTime>%d</CreateTime>
  212. <MsgType><![CDATA[news]]></MsgType>
  213. <ArticleCount>%d</ArticleCount>
  214. <Articles>
  215. %s
  216. </Articles>
  217. </xml>`
  218. }
  219. func buildLocationMsg() string {
  220. template := `<xml>
  221. <ToUserName><![CDATA[oUN420bxqFqlx0ZQHciUOesZO3PE]]></ToUserName>
  222. <FromUserName><![CDATA[gh_f09231355c68]]></FromUserName>
  223. <CreateTime>1494124221</CreateTime>
  224. <MsgType><![CDATA[location]]></MsgType>
  225. <Location_X>23.134521</Location_X>
  226. <Location_Y>113.358803</Location_Y>
  227. <Scale>20</Scale>
  228. <Label><![CDATA[位置信息]]></Label>
  229. </xml> `
  230. return template
  231. }