1
0

wechat-test-account.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package channel
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "message-pusher/common"
  8. "message-pusher/model"
  9. "net/http"
  10. "time"
  11. )
  12. type wechatTestAccountResponse struct {
  13. ErrorCode int `json:"errcode"`
  14. ErrorMessage string `json:"errmsg"`
  15. AccessToken string `json:"access_token"`
  16. ExpiresIn int `json:"expires_in"`
  17. }
  18. type WeChatTestAccountTokenStoreItem struct {
  19. AppID string
  20. AppSecret string
  21. AccessToken string
  22. }
  23. func (i *WeChatTestAccountTokenStoreItem) Key() string {
  24. return i.AppID + i.AppSecret
  25. }
  26. func (i *WeChatTestAccountTokenStoreItem) IsShared() bool {
  27. return model.DB.Where("wechat_test_account_id = ? and wechat_test_account_secret = ?",
  28. i.AppID, i.AppSecret).Find(&model.User{}).RowsAffected != 1
  29. }
  30. func (i *WeChatTestAccountTokenStoreItem) IsFilled() bool {
  31. return i.AppID != "" && i.AppSecret != ""
  32. }
  33. func (i *WeChatTestAccountTokenStoreItem) Token() string {
  34. return i.AccessToken
  35. }
  36. func (i *WeChatTestAccountTokenStoreItem) Refresh() {
  37. // https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
  38. client := http.Client{
  39. Timeout: 5 * time.Second,
  40. }
  41. req, err := http.NewRequest("GET", fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
  42. i.AppID, i.AppSecret), nil)
  43. if err != nil {
  44. common.SysError(err.Error())
  45. return
  46. }
  47. responseData, err := client.Do(req)
  48. if err != nil {
  49. common.SysError("failed to refresh access token: " + err.Error())
  50. return
  51. }
  52. defer responseData.Body.Close()
  53. var res wechatTestAccountResponse
  54. err = json.NewDecoder(responseData.Body).Decode(&res)
  55. if err != nil {
  56. common.SysError("failed to decode wechatTestAccountResponse: " + err.Error())
  57. return
  58. }
  59. if res.ErrorCode != 0 {
  60. common.SysError(res.ErrorMessage)
  61. return
  62. }
  63. i.AccessToken = res.AccessToken
  64. common.SysLog("access token refreshed")
  65. }
  66. type wechatTestMessageRequest struct {
  67. ToUser string `json:"touser"`
  68. TemplateId string `json:"template_id"`
  69. URL string `json:"url"`
  70. Data struct {
  71. Text struct {
  72. Value string `json:"value"`
  73. } `json:"text"`
  74. } `json:"data"`
  75. }
  76. type wechatTestMessageResponse struct {
  77. ErrorCode int `json:"errcode"`
  78. ErrorMessage string `json:"errmsg"`
  79. }
  80. func SendWeChatTestMessage(message *model.Message, user *model.User) error {
  81. if user.WeChatTestAccountId == "" {
  82. return errors.New("未配置微信测试号消息推送方式")
  83. }
  84. values := wechatTestMessageRequest{
  85. ToUser: user.WeChatTestAccountOpenId,
  86. TemplateId: user.WeChatTestAccountTemplateId,
  87. URL: "",
  88. }
  89. values.Data.Text.Value = message.Description
  90. values.URL = message.URL
  91. jsonData, err := json.Marshal(values)
  92. if err != nil {
  93. return err
  94. }
  95. key := fmt.Sprintf("%s%s", user.WeChatTestAccountId, user.WeChatTestAccountSecret)
  96. accessToken := TokenStoreGetToken(key)
  97. resp, err := http.Post(fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s", accessToken), "application/json",
  98. bytes.NewBuffer(jsonData))
  99. if err != nil {
  100. return err
  101. }
  102. var res wechatTestMessageResponse
  103. err = json.NewDecoder(resp.Body).Decode(&res)
  104. if err != nil {
  105. return err
  106. }
  107. if res.ErrorCode != 0 {
  108. return errors.New(res.ErrorMessage)
  109. }
  110. return nil
  111. }