main.go 4.5 KB

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