subscribe.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package subscribe
  2. import (
  3. "fmt"
  4. "github.com/silenceper/wechat/v2/miniprogram/context"
  5. "github.com/silenceper/wechat/v2/util"
  6. )
  7. const (
  8. // 发送订阅消息
  9. // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
  10. subscribeSendURL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send"
  11. // 获取当前帐号下的个人模板列表
  12. // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.getTemplateList.html
  13. getTemplateURL = "https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate"
  14. // 添加订阅模板
  15. // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html
  16. addTemplateURL = "https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate"
  17. // 删除私有模板
  18. // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.deleteTemplate.html
  19. delTemplateURL = "https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate"
  20. // 统一服务消息
  21. // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/uniform-message/uniformMessage.send.html
  22. uniformMessageSend = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/uniform_send"
  23. )
  24. // Subscribe 订阅消息
  25. type Subscribe struct {
  26. *context.Context
  27. }
  28. // NewSubscribe 实例化
  29. func NewSubscribe(ctx *context.Context) *Subscribe {
  30. return &Subscribe{Context: ctx}
  31. }
  32. // Message 订阅消息请求参数
  33. type Message struct {
  34. ToUser string `json:"touser"` // 必选,接收者(用户)的 openid
  35. TemplateID string `json:"template_id"` // 必选,所需下发的订阅模板id
  36. Page string `json:"page"` // 可选,点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。
  37. Data map[string]*DataItem `json:"data"` // 必选, 模板内容
  38. MiniprogramState string `json:"miniprogram_state"` // 可选,跳转小程序类型:developer为开发版;trial为体验版;formal为正式版;默认为正式版
  39. Lang string `json:"lang"` // 入小程序查看”的语言类型,支持zh_CN(简体中文)、en_US(英文)、zh_HK(繁体中文)、zh_TW(繁体中文),默认为zh_CN
  40. }
  41. // DataItem 模版内某个 .DATA 的值
  42. type DataItem struct {
  43. Value interface{} `json:"value"`
  44. Color string `json:"color"`
  45. }
  46. // TemplateItem template item
  47. type TemplateItem struct {
  48. PriTmplID string `json:"priTmplId"`
  49. Title string `json:"title"`
  50. Content string `json:"content"`
  51. Example string `json:"example"`
  52. Type int64 `json:"type"`
  53. }
  54. // TemplateList template list
  55. type TemplateList struct {
  56. util.CommonError
  57. Data []TemplateItem `json:"data"`
  58. }
  59. // Send 发送订阅消息
  60. func (s *Subscribe) Send(msg *Message) (err error) {
  61. var accessToken string
  62. accessToken, err = s.GetAccessToken()
  63. if err != nil {
  64. return
  65. }
  66. uri := fmt.Sprintf("%s?access_token=%s", subscribeSendURL, accessToken)
  67. response, err := util.PostJSON(uri, msg)
  68. if err != nil {
  69. return
  70. }
  71. return util.DecodeWithCommonError(response, "Send")
  72. }
  73. // ListTemplates 获取当前帐号下的个人模板列表
  74. // https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.getTemplateList.html
  75. func (s *Subscribe) ListTemplates() (*TemplateList, error) {
  76. accessToken, err := s.GetAccessToken()
  77. if err != nil {
  78. return nil, err
  79. }
  80. uri := fmt.Sprintf("%s?access_token=%s", getTemplateURL, accessToken)
  81. response, err := util.HTTPGet(uri)
  82. if err != nil {
  83. return nil, err
  84. }
  85. templateList := TemplateList{}
  86. err = util.DecodeWithError(response, &templateList, "ListTemplates")
  87. if err != nil {
  88. return nil, err
  89. }
  90. return &templateList, nil
  91. }
  92. // UniformMessage 统一服务消息
  93. type UniformMessage struct {
  94. ToUser string `json:"touser"`
  95. WeappTemplateMsg struct {
  96. TemplateID string `json:"template_id"`
  97. Page string `json:"page"`
  98. FormID string `json:"form_id"`
  99. Data map[string]*DataItem `json:"data"`
  100. EmphasisKeyword string `json:"emphasis_keyword"`
  101. } `json:"weapp_template_msg"`
  102. MpTemplateMsg struct {
  103. Appid string `json:"appid"`
  104. TemplateID string `json:"template_id"`
  105. URL string `json:"url"`
  106. Miniprogram struct {
  107. Appid string `json:"appid"`
  108. Pagepath string `json:"page"`
  109. } `json:"miniprogram"`
  110. Data map[string]*DataItem `json:"data"`
  111. } `json:"mp_template_msg"`
  112. }
  113. // UniformSend 发送统一服务消息
  114. func (s *Subscribe) UniformSend(msg *UniformMessage) (err error) {
  115. var accessToken string
  116. accessToken, err = s.GetAccessToken()
  117. if err != nil {
  118. return
  119. }
  120. uri := fmt.Sprintf("%s?access_token=%s", uniformMessageSend, accessToken)
  121. response, err := util.PostJSON(uri, msg)
  122. if err != nil {
  123. return
  124. }
  125. return util.DecodeWithCommonError(response, "UniformSend")
  126. }
  127. type resSubscribeAdd struct {
  128. util.CommonError
  129. TemplateID string `json:"priTmplId"`
  130. }
  131. // Add 添加订阅消息模板
  132. func (s *Subscribe) Add(ShortID string, kidList []int, sceneDesc string) (templateID string, err error) {
  133. var accessToken string
  134. accessToken, err = s.GetAccessToken()
  135. if err != nil {
  136. return
  137. }
  138. var msg = struct {
  139. TemplateIDShort string `json:"tid"`
  140. SceneDesc string `json:"sceneDesc"`
  141. KidList []int `json:"kidList"`
  142. }{TemplateIDShort: ShortID, SceneDesc: sceneDesc, KidList: kidList}
  143. uri := fmt.Sprintf("%s?access_token=%s", addTemplateURL, accessToken)
  144. var response []byte
  145. response, err = util.PostJSON(uri, msg)
  146. if err != nil {
  147. return
  148. }
  149. var result resSubscribeAdd
  150. err = util.DecodeWithError(response, &result, "AddSubscribe")
  151. if err != nil {
  152. return
  153. }
  154. templateID = result.TemplateID
  155. return
  156. }
  157. // Delete 删除私有模板
  158. func (s *Subscribe) Delete(templateID string) (err error) {
  159. var accessToken string
  160. accessToken, err = s.GetAccessToken()
  161. if err != nil {
  162. return
  163. }
  164. var msg = struct {
  165. TemplateID string `json:"priTmplId"`
  166. }{TemplateID: templateID}
  167. uri := fmt.Sprintf("%s?access_token=%s", delTemplateURL, accessToken)
  168. var response []byte
  169. response, err = util.PostJSON(uri, msg)
  170. if err != nil {
  171. return
  172. }
  173. return util.DecodeWithCommonError(response, "DeleteSubscribe")
  174. }