subscribe.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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. if err != nil {
  83. return
  84. }
  85. templateList = res.SubscriptionList
  86. return
  87. }
  88. type resSubscribeAdd struct {
  89. util.CommonError
  90. TemplateID string `json:"priTmplId"`
  91. }
  92. // Add 添加订阅消息模板
  93. func (tpl *Subscribe) Add(ShortID string, kidList []int, sceneDesc string) (templateID string, err error) {
  94. var accessToken string
  95. accessToken, err = tpl.GetAccessToken()
  96. if err != nil {
  97. return
  98. }
  99. var msg = struct {
  100. TemplateIDShort string `json:"tid"`
  101. SceneDesc string `json:"sceneDesc"`
  102. KidList []int `json:"kidList"`
  103. }{TemplateIDShort: ShortID, SceneDesc: sceneDesc, KidList: kidList}
  104. uri := fmt.Sprintf("%s?access_token=%s", subscribeTemplateAddURL, accessToken)
  105. var response []byte
  106. response, err = util.PostJSON(uri, msg)
  107. if err != nil {
  108. return
  109. }
  110. var result resSubscribeAdd
  111. err = util.DecodeWithError(response, &result, "AddSubscribe")
  112. if err != nil {
  113. return
  114. }
  115. templateID = result.TemplateID
  116. return
  117. }
  118. // Delete 删除私有模板
  119. func (tpl *Subscribe) Delete(templateID string) (err error) {
  120. var accessToken string
  121. accessToken, err = tpl.GetAccessToken()
  122. if err != nil {
  123. return
  124. }
  125. var msg = struct {
  126. TemplateID string `json:"priTmplId"`
  127. }{TemplateID: templateID}
  128. uri := fmt.Sprintf("%s?access_token=%s", subscribeTemplateDelURL, accessToken)
  129. var response []byte
  130. response, err = util.PostJSON(uri, msg)
  131. if err != nil {
  132. return
  133. }
  134. return util.DecodeWithCommonError(response, "DeleteSubscribe")
  135. }
  136. // PublicTemplateCategory 公众号类目
  137. type PublicTemplateCategory struct {
  138. ID int `json:"id"` // 类目ID
  139. Name string `json:"name"` // 类目的中文名
  140. }
  141. type resSubscribeCategoryList struct {
  142. util.CommonError
  143. CategoryList []*PublicTemplateCategory `json:"data"`
  144. }
  145. // GetCategory 获取公众号类目
  146. func (tpl *Subscribe) GetCategory() (categoryList []*PublicTemplateCategory, err error) {
  147. var accessToken string
  148. accessToken, err = tpl.GetAccessToken()
  149. if err != nil {
  150. return
  151. }
  152. uri := fmt.Sprintf("%s?access_token=%s", subscribeTemplateGetCategoryURL, accessToken)
  153. var response []byte
  154. response, err = util.HTTPGet(uri)
  155. if err != nil {
  156. return
  157. }
  158. var result resSubscribeCategoryList
  159. err = util.DecodeWithError(response, &result, "GetCategory")
  160. if err != nil {
  161. return
  162. }
  163. categoryList = result.CategoryList
  164. return
  165. }
  166. // PublicTemplateKeyWords 模板中的关键词
  167. type PublicTemplateKeyWords struct {
  168. KeyWordsID int `json:"kid"` // 关键词 id
  169. Name string `json:"name"` // 关键词内容
  170. Example string `json:"example"` // 关键词内容对应的示例
  171. Rule string `json:"rule"` // 参数类型
  172. }
  173. type resPublicTemplateKeyWordsList struct {
  174. util.CommonError
  175. KeyWordsList []*PublicTemplateKeyWords `json:"data"` // 关键词列表
  176. }
  177. // GetPubTplKeyWordsByID 获取模板中的关键词
  178. func (tpl *Subscribe) GetPubTplKeyWordsByID(titleID string) (keyWordsList []*PublicTemplateKeyWords, err error) {
  179. var accessToken string
  180. accessToken, err = tpl.GetAccessToken()
  181. if err != nil {
  182. return
  183. }
  184. uri := fmt.Sprintf("%s?access_token=%s&tid=%s", subscribeTemplateGetPubTplKeyWorksURL, accessToken, titleID)
  185. var response []byte
  186. response, err = util.HTTPGet(uri)
  187. if err != nil {
  188. return
  189. }
  190. var result resPublicTemplateKeyWordsList
  191. err = util.DecodeWithError(response, &result, "GetPublicTemplateKeyWords")
  192. if err != nil {
  193. return
  194. }
  195. keyWordsList = result.KeyWordsList
  196. return
  197. }
  198. // PublicTemplateTitle 类目下的公共模板
  199. type PublicTemplateTitle struct {
  200. TitleID int `json:"tid"` // 模版标题 id
  201. Title string `json:"title"` // 模版标题
  202. Type int `json:"type"` // 模版类型,2 为一次性订阅,3 为长期订阅
  203. CategoryID string `json:"categoryId"` // 模版所属类目 id
  204. }
  205. type resPublicTemplateTitleList struct {
  206. util.CommonError
  207. Count int `json:"count"` // 公共模板列表总数
  208. TemplateTitleList []*PublicTemplateTitle `json:"data"` // 模板标题列表
  209. }
  210. // GetPublicTemplateTitleList 获取类目下的公共模板
  211. func (tpl *Subscribe) GetPublicTemplateTitleList(ids string, start int, limit int) (count int, templateTitleList []*PublicTemplateTitle, err error) {
  212. var accessToken string
  213. accessToken, err = tpl.GetAccessToken()
  214. if err != nil {
  215. return
  216. }
  217. uri := fmt.Sprintf("%s?access_token=%s&ids=%s&start=%d&limit=%d", subscribeTemplateGetPubTplTitles, accessToken, ids, start, limit)
  218. var response []byte
  219. response, err = util.HTTPGet(uri)
  220. if err != nil {
  221. return
  222. }
  223. var result resPublicTemplateTitleList
  224. err = util.DecodeWithError(response, &result, "GetPublicTemplateTitle")
  225. if err != nil {
  226. return
  227. }
  228. count = result.Count
  229. templateTitleList = result.TemplateTitleList
  230. return
  231. }