main.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package main
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "io/ioutil"
  8. "log"
  9. "net/http"
  10. "qfw/util"
  11. "qfw/util/redis"
  12. "time"
  13. )
  14. const (
  15. RedisCode = "wxtoken"
  16. MenuButtonTypeUrl = "view"
  17. )
  18. var post_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s"
  19. var Config *config
  20. type config struct {
  21. Appid string
  22. Webdomain string
  23. Redis string
  24. }
  25. // Custom Menu
  26. type Menu struct {
  27. Buttons []MenuButton `json:"button,omitempty"`
  28. }
  29. type MenuButton struct {
  30. Name string `json:"name"`
  31. Type string `json:"type,omitempty"`
  32. Key string `json:"key,omitempty"`
  33. Url string `json:"url,omitempty"`
  34. MediaId string `json:"media_id,omitempty"`
  35. SubButtons []MenuButton `json:"sub_button,omitempty"`
  36. }
  37. type response struct {
  38. ErrorCode int `json:"errcode,omitempty"`
  39. ErrorMessage string `json:"errmsg,omitempty"`
  40. }
  41. //微信菜单数据
  42. func WXMenu() Menu {
  43. urlstr := fmt.Sprintf("https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s/wx/oauth/%s&response_type=code&scope=snsapi_base&state=1#wechat_redirect", Config.Appid, Config.Webdomain, "%s")
  44. menu := &Menu{make([]MenuButton, 3)}
  45. menu.Buttons[0].Name = "招标搜索"
  46. menu.Buttons[0].Type = MenuButtonTypeUrl
  47. menu.Buttons[0].Url = fmt.Sprintf(urlstr, "searchinfo")
  48. menu.Buttons[1].Name = "招标订阅"
  49. menu.Buttons[1].Type = MenuButtonTypeUrl
  50. menu.Buttons[1].Url = fmt.Sprintf(urlstr, "rssset")
  51. menu.Buttons[2].Name = "发现"
  52. menu.Buttons[2].SubButtons = make([]MenuButton, 5)
  53. menu.Buttons[2].SubButtons[0].Name = "\U0001F4BC百宝箱"
  54. menu.Buttons[2].SubButtons[0].Type = MenuButtonTypeUrl
  55. menu.Buttons[2].SubButtons[0].Url = fmt.Sprintf(urlstr, "treasurebox")
  56. menu.Buttons[2].SubButtons[1].Name = string(0x1F4C1) + "大会员"
  57. menu.Buttons[2].SubButtons[1].Type = MenuButtonTypeUrl
  58. menu.Buttons[2].SubButtons[1].Url = fmt.Sprintf(urlstr, "bigMember")
  59. menu.Buttons[2].SubButtons[2].Name = "\U0001F4DD结构化数据"
  60. menu.Buttons[2].SubButtons[2].Type = MenuButtonTypeUrl
  61. menu.Buttons[2].SubButtons[2].Url = fmt.Sprintf(urlstr, "structed")
  62. menu.Buttons[2].SubButtons[3].Name = string(0x1F465) + "剑鱼标讯社区"
  63. menu.Buttons[2].SubButtons[3].Type = MenuButtonTypeUrl
  64. menu.Buttons[2].SubButtons[3].Url = fmt.Sprintf(urlstr, "community")
  65. menu.Buttons[2].SubButtons[4].Name = "\U0001F464我的"
  66. menu.Buttons[2].SubButtons[4].Type = MenuButtonTypeUrl
  67. menu.Buttons[2].SubButtons[4].Url = fmt.Sprintf(urlstr, "mymenu")
  68. return *menu
  69. }
  70. //
  71. func init() {
  72. util.ReadConfig(&Config)
  73. redis.InitRedis(Config.Redis)
  74. }
  75. //
  76. func main() {
  77. tokenKey := fmt.Sprintf("WxToken_%s", Config.Appid)
  78. ret, err := redis.GetNewBytes(RedisCode, tokenKey)
  79. if err == nil {
  80. if ret != nil {
  81. var res map[string]interface{}
  82. err := json.Unmarshal(*ret, &res)
  83. if err != nil {
  84. log.Println(Config.Appid, "从redis加载token出错", err)
  85. } else if res["access_token"] != nil {
  86. post_url = fmt.Sprintf(post_url, res["access_token"].(string))
  87. data, err := marshal(WXMenu())
  88. if err != nil {
  89. log.Println("序列化菜单内容异常")
  90. } else {
  91. _, err := CreateMenu(post_url, data)
  92. if err != nil {
  93. log.Println("err:", err)
  94. } else {
  95. log.Println("create wx menu success")
  96. }
  97. }
  98. }
  99. } else {
  100. log.Println("redis 读取 token有误...")
  101. }
  102. } else {
  103. log.Println("redis 读取信息有误...")
  104. }
  105. time.Sleep(time.Second)
  106. }
  107. //创建菜单
  108. func CreateMenu(post_url string, data []byte) ([]byte, error) {
  109. // log.Println(string(data))
  110. r, err := http.Post(post_url, "application/json; charset=utf-8", bytes.NewReader(data))
  111. if err != nil {
  112. return nil, err
  113. }
  114. defer r.Body.Close()
  115. reply, err := ioutil.ReadAll(r.Body)
  116. if err != nil {
  117. return nil, err
  118. }
  119. var result response
  120. if err := json.Unmarshal(reply, &result); err != nil {
  121. return nil, err
  122. }
  123. switch result.ErrorCode {
  124. case 0:
  125. return reply, nil
  126. case 42001, 40001:
  127. log.Println("reget the tocken by ", result.ErrorCode, result.ErrorMessage)
  128. default:
  129. return nil, errors.New(fmt.Sprintf("WeiXin send post request reply[%d]: %s", result.ErrorCode, result.ErrorMessage))
  130. }
  131. return nil, errors.New("WeiXin post request error")
  132. }
  133. func marshal(v interface{}) ([]byte, error) {
  134. data, err := json.Marshal(v)
  135. if err == nil {
  136. data = bytes.Replace(data, []byte("\\u003c"), []byte("<"), -1)
  137. data = bytes.Replace(data, []byte("\\u003e"), []byte(">"), -1)
  138. data = bytes.Replace(data, []byte("\\u0026"), []byte("&"), -1)
  139. }
  140. return data, err
  141. }