subscribe.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. package message
  2. import (
  3. "fmt"
  4. "github.com/silenceper/wechat/v2/officialaccount/context"
  5. "github.com/silenceper/wechat/v2/util"
  6. )
  7. const (
  8. subscribeSendURL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend"
  9. subscribeTemplateListURL = "https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate"
  10. subscribeTemplateAddURL = "https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate"
  11. subscribeTemplateDelURL = "https://api.weixin.qq.com/wxaapi/newtmpl/deltemplate"
  12. subscribeTemplateGetCategoryURL = "https://api.weixin.qq.com/wxaapi/newtmpl/getcategory"
  13. subscribeTemplateGetPubTplKeyWorksURL = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatekeywords"
  14. subscribeTemplateGetPubTplTitles = "https://api.weixin.qq.com/wxaapi/newtmpl/getpubtemplatetitles"
  15. )
  16. // Subscribe 订阅消息
  17. type Subscribe struct {
  18. *context.Context
  19. }
  20. // NewSubscribe 实例化
  21. func NewSubscribe(context *context.Context) *Subscribe {
  22. tpl := new(Subscribe)
  23. tpl.Context = context
  24. return tpl
  25. }
  26. // SubscribeMessage 发送的订阅消息内容
  27. type SubscribeMessage struct {
  28. ToUser string `json:"touser"` // 必须,接受者 OpenID
  29. TemplateID string `json:"template_id"` // 必须,模版 ID
  30. Page string `json:"page,omitempty"` // 可选,跳转网页时填写
  31. Data map[string]*SubscribeDataItem `json:"data"` // 必须,模板数据
  32. MiniProgram struct {
  33. AppID string `json:"appid"` // 所需跳转到的小程序 appid(该小程序 appid 必须与发模板消息的公众号是绑定关联关系)
  34. PagePath string `json:"pagepath"` // 所需跳转到小程序的具体页面路径,支持带参数,(示例 index?foo=bar)
  35. } `json:"miniprogram"` // 可选,跳转至小程序地址
  36. }
  37. // SubscribeDataItem 模版内某个 .DATA 的值
  38. type SubscribeDataItem struct {
  39. Value string `json:"value"`
  40. }
  41. // Send 发送订阅消息
  42. func (tpl *Subscribe) Send(msg *SubscribeMessage) (err error) {
  43. var accessToken string
  44. accessToken, err = tpl.GetAccessToken()
  45. if err != nil {
  46. return
  47. }
  48. uri := fmt.Sprintf("%s?access_token=%s", subscribeSendURL, accessToken)
  49. response, err := util.PostJSON(uri, msg)
  50. if err != nil {
  51. return
  52. }
  53. return util.DecodeWithCommonError(response, "SendSubscribeMessage")
  54. }
  55. // PrivateSubscribeItem 私有订阅消息模板
  56. type PrivateSubscribeItem struct {
  57. PriTmplID string `json:"priTmplId"` // 添加至帐号下的模板 id,发送订阅通知时所需
  58. Title string `json:"title"` // 模版标题
  59. Content string `json:"content"` // 模版内容
  60. Example string `json:"example"` // 模板内容示例
  61. SubType int `json:"type"` // 模版类型,2 为一次性订阅,3 为长期订阅
  62. }
  63. type resPrivateSubscribeList struct {
  64. util.CommonError
  65. SubscriptionList []*PrivateSubscribeItem `json:"data"`
  66. }
  67. // List 获取私有订阅消息模板列表
  68. func (tpl *Subscribe) List() (templateList []*PrivateSubscribeItem, err error) {
  69. var accessToken string
  70. accessToken, err = tpl.GetAccessToken()
  71. if err != nil {
  72. return
  73. }
  74. uri := fmt.Sprintf("%s?access_token=%s", subscribeTemplateListURL, accessToken)
  75. var response []byte
  76. response, err = util.HTTPGet(uri)
  77. if err != nil {
  78. return
  79. }
  80. var res resPrivateSubscribeList
  81. err = util.DecodeWithError(response, &res, "ListSubscribe")
  82. return res.SubscriptionList, err
  83. }
  84. type resSubscribeAdd struct {
  85. util.CommonError
  86. TemplateID string `json:"priTmplId"`
  87. }
  88. // Add 添加订阅消息模板
  89. func (tpl *Subscribe) Add(ShortID string, kidList []int, sceneDesc string) (templateID string, err error) {
  90. var accessToken string
  91. accessToken, err = tpl.GetAccessToken()
  92. if err != nil {
  93. return
  94. }
  95. var msg = struct {
  96. TemplateIDShort string `json:"tid"`
  97. SceneDesc string `json:"sceneDesc"`
  98. KidList []int `json:"kidList"`
  99. }{TemplateIDShort: ShortID, SceneDesc: sceneDesc, KidList: kidList}
  100. uri := fmt.Sprintf("%s?access_token=%s", subscribeTemplateAddURL, accessToken)
  101. var response []byte
  102. response, err = util.PostJSON(uri, msg)
  103. if err != nil {
  104. return
  105. }
  106. var result resSubscribeAdd
  107. err = util.DecodeWithError(response, &result, "AddSubscribe")
  108. return result.TemplateID, err
  109. }
  110. // Delete 删除私有模板
  111. func (tpl *Subscribe) Delete(templateID string) (err error) {
  112. var accessToken string
  113. accessToken, err = tpl.GetAccessToken()
  114. if err != nil {
  115. return
  116. }
  117. var msg = struct {
  118. TemplateID string `json:"priTmplId"`
  119. }{TemplateID: templateID}
  120. uri := fmt.Sprintf("%s?access_token=%s", subscribeTemplateDelURL, accessToken)
  121. var response []byte
  122. response, err = util.PostJSON(uri, msg)
  123. if err != nil {
  124. return
  125. }
  126. return util.DecodeWithCommonError(response, "DeleteSubscribe")
  127. }
  128. // PublicTemplateCategory 公众号类目
  129. type PublicTemplateCategory struct {
  130. ID int `json:"id"` // 类目 ID
  131. Name string `json:"name"` // 类目的中文名
  132. }
  133. type resSubscribeCategoryList struct {
  134. util.CommonError
  135. CategoryList []*PublicTemplateCategory `json:"data"`
  136. }
  137. // GetCategory 获取公众号类目
  138. func (tpl *Subscribe) GetCategory() (categoryList []*PublicTemplateCategory, err error) {
  139. var accessToken string
  140. accessToken, err = tpl.GetAccessToken()
  141. if err != nil {
  142. return
  143. }
  144. uri := fmt.Sprintf("%s?access_token=%s", subscribeTemplateGetCategoryURL, accessToken)
  145. var response []byte
  146. response, err = util.HTTPGet(uri)
  147. if err != nil {
  148. return
  149. }
  150. var result resSubscribeCategoryList
  151. err = util.DecodeWithError(response, &result, "GetCategory")
  152. return result.CategoryList, err
  153. }
  154. // PublicTemplateKeyWords 模板中的关键词
  155. type PublicTemplateKeyWords struct {
  156. KeyWordsID int `json:"kid"` // 关键词 id
  157. Name string `json:"name"` // 关键词内容
  158. Example string `json:"example"` // 关键词内容对应的示例
  159. Rule string `json:"rule"` // 参数类型
  160. }
  161. type resPublicTemplateKeyWordsList struct {
  162. util.CommonError
  163. KeyWordsList []*PublicTemplateKeyWords `json:"data"` // 关键词列表
  164. }
  165. // GetPubTplKeyWordsByID 获取模板中的关键词
  166. func (tpl *Subscribe) GetPubTplKeyWordsByID(titleID string) (keyWordsList []*PublicTemplateKeyWords, err error) {
  167. var accessToken string
  168. accessToken, err = tpl.GetAccessToken()
  169. if err != nil {
  170. return
  171. }
  172. uri := fmt.Sprintf("%s?access_token=%s&tid=%s", subscribeTemplateGetPubTplKeyWorksURL, accessToken, titleID)
  173. var response []byte
  174. response, err = util.HTTPGet(uri)
  175. if err != nil {
  176. return
  177. }
  178. var result resPublicTemplateKeyWordsList
  179. err = util.DecodeWithError(response, &result, "GetPublicTemplateKeyWords")
  180. return result.KeyWordsList, err
  181. }
  182. // PublicTemplateTitle 类目下的公共模板
  183. type PublicTemplateTitle struct {
  184. TitleID int `json:"tid"` // 模版标题 id
  185. Title string `json:"title"` // 模版标题
  186. Type int `json:"type"` // 模版类型,2 为一次性订阅,3 为长期订阅
  187. CategoryID string `json:"categoryId"` // 模版所属类目 id
  188. }
  189. type resPublicTemplateTitleList struct {
  190. util.CommonError
  191. Count int `json:"count"` // 公共模板列表总数
  192. TemplateTitleList []*PublicTemplateTitle `json:"data"` // 模板标题列表
  193. }
  194. // GetPublicTemplateTitleList 获取类目下的公共模板
  195. func (tpl *Subscribe) GetPublicTemplateTitleList(ids string, start int, limit int) (count int, templateTitleList []*PublicTemplateTitle, err error) {
  196. var accessToken string
  197. accessToken, err = tpl.GetAccessToken()
  198. if err != nil {
  199. return
  200. }
  201. uri := fmt.Sprintf("%s?access_token=%s&ids=%s&start=%d&limit=%d", subscribeTemplateGetPubTplTitles, accessToken, ids, start, limit)
  202. var response []byte
  203. response, err = util.HTTPGet(uri)
  204. if err != nil {
  205. return
  206. }
  207. var result resPublicTemplateTitleList
  208. err = util.DecodeWithError(response, &result, "GetPublicTemplateTitle")
  209. return result.Count, result.TemplateTitleList, err
  210. }