material.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. package material
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "github.com/silenceper/wechat/v2/officialaccount/context"
  7. "github.com/silenceper/wechat/v2/util"
  8. )
  9. const (
  10. addNewsURL = "https://api.weixin.qq.com/cgi-bin/material/add_news"
  11. addMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/add_material"
  12. delMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/del_material"
  13. getMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/get_material"
  14. )
  15. //Material 素材管理
  16. type Material struct {
  17. *context.Context
  18. }
  19. //NewMaterial init
  20. func NewMaterial(context *context.Context) *Material {
  21. material := new(Material)
  22. material.Context = context
  23. return material
  24. }
  25. //Article 永久图文素材
  26. type Article struct {
  27. Title string `json:"title"`
  28. ThumbMediaID string `json:"thumb_media_id"`
  29. ThumbURL string `json:"thumb_url"`
  30. Author string `json:"author"`
  31. Digest string `json:"digest"`
  32. ShowCoverPic int `json:"show_cover_pic"`
  33. Content string `json:"content"`
  34. ContentSourceURL string `json:"content_source_url"`
  35. URL string `json:"url"`
  36. DownURL string `json:"down_url"`
  37. }
  38. // GetNews 获取/下载永久素材
  39. func (material *Material) GetNews(id string) ([]*Article, error) {
  40. accessToken, err := material.GetAccessToken()
  41. if err != nil {
  42. return nil, err
  43. }
  44. uri := fmt.Sprintf("%s?access_token=%s", getMaterialURL, accessToken)
  45. var req struct {
  46. MediaID string `json:"media_id"`
  47. }
  48. req.MediaID = id
  49. responseBytes, err := util.PostJSON(uri, req)
  50. var res struct {
  51. NewsItem []*Article `json:"news_item"`
  52. }
  53. err = json.Unmarshal(responseBytes, &res)
  54. if err != nil {
  55. return nil, err
  56. }
  57. return res.NewsItem, nil
  58. }
  59. //reqArticles 永久性图文素材请求信息
  60. type reqArticles struct {
  61. Articles []*Article `json:"articles"`
  62. }
  63. //resArticles 永久性图文素材返回结果
  64. type resArticles struct {
  65. util.CommonError
  66. MediaID string `json:"media_id"`
  67. }
  68. //AddNews 新增永久图文素材
  69. func (material *Material) AddNews(articles []*Article) (mediaID string, err error) {
  70. req := &reqArticles{articles}
  71. var accessToken string
  72. accessToken, err = material.GetAccessToken()
  73. if err != nil {
  74. return
  75. }
  76. uri := fmt.Sprintf("%s?access_token=%s", addNewsURL, accessToken)
  77. responseBytes, err := util.PostJSON(uri, req)
  78. var res resArticles
  79. err = json.Unmarshal(responseBytes, &res)
  80. if err != nil {
  81. return
  82. }
  83. mediaID = res.MediaID
  84. return
  85. }
  86. //resAddMaterial 永久性素材上传返回的结果
  87. type resAddMaterial struct {
  88. util.CommonError
  89. MediaID string `json:"media_id"`
  90. URL string `json:"url"`
  91. }
  92. //AddMaterial 上传永久性素材(处理视频需要单独上传)
  93. func (material *Material) AddMaterial(mediaType MediaType, filename string) (mediaID string, url string, err error) {
  94. if mediaType == MediaTypeVideo {
  95. err = errors.New("永久视频素材上传使用 AddVideo 方法")
  96. }
  97. var accessToken string
  98. accessToken, err = material.GetAccessToken()
  99. if err != nil {
  100. return
  101. }
  102. uri := fmt.Sprintf("%s?access_token=%s&type=%s", addMaterialURL, accessToken, mediaType)
  103. var response []byte
  104. response, err = util.PostFile("media", filename, uri)
  105. if err != nil {
  106. return
  107. }
  108. var resMaterial resAddMaterial
  109. err = json.Unmarshal(response, &resMaterial)
  110. if err != nil {
  111. return
  112. }
  113. if resMaterial.ErrCode != 0 {
  114. err = fmt.Errorf("AddMaterial error : errcode=%v , errmsg=%v", resMaterial.ErrCode, resMaterial.ErrMsg)
  115. return
  116. }
  117. mediaID = resMaterial.MediaID
  118. url = resMaterial.URL
  119. return
  120. }
  121. type reqVideo struct {
  122. Title string `json:"title"`
  123. Introduction string `json:"introduction"`
  124. }
  125. //AddVideo 永久视频素材文件上传
  126. func (material *Material) AddVideo(filename, title, introduction string) (mediaID string, url string, err error) {
  127. var accessToken string
  128. accessToken, err = material.GetAccessToken()
  129. if err != nil {
  130. return
  131. }
  132. uri := fmt.Sprintf("%s?access_token=%s&type=video", addMaterialURL, accessToken)
  133. videoDesc := &reqVideo{
  134. Title: title,
  135. Introduction: introduction,
  136. }
  137. var fieldValue []byte
  138. fieldValue, err = json.Marshal(videoDesc)
  139. if err != nil {
  140. return
  141. }
  142. fields := []util.MultipartFormField{
  143. {
  144. IsFile: true,
  145. Fieldname: "media",
  146. Filename: filename,
  147. },
  148. {
  149. IsFile: false,
  150. Fieldname: "description",
  151. Value: fieldValue,
  152. },
  153. }
  154. var response []byte
  155. response, err = util.PostMultipartForm(fields, uri)
  156. if err != nil {
  157. return
  158. }
  159. var resMaterial resAddMaterial
  160. err = json.Unmarshal(response, &resMaterial)
  161. if err != nil {
  162. return
  163. }
  164. if resMaterial.ErrCode != 0 {
  165. err = fmt.Errorf("AddMaterial error : errcode=%v , errmsg=%v", resMaterial.ErrCode, resMaterial.ErrMsg)
  166. return
  167. }
  168. mediaID = resMaterial.MediaID
  169. url = resMaterial.URL
  170. return
  171. }
  172. type reqDeleteMaterial struct {
  173. MediaID string `json:"media_id"`
  174. }
  175. //DeleteMaterial 删除永久素材
  176. func (material *Material) DeleteMaterial(mediaID string) error {
  177. accessToken, err := material.GetAccessToken()
  178. if err != nil {
  179. return err
  180. }
  181. uri := fmt.Sprintf("%s?access_token=%s", delMaterialURL, accessToken)
  182. response, err := util.PostJSON(uri, reqDeleteMaterial{mediaID})
  183. if err != nil {
  184. return err
  185. }
  186. return util.DecodeWithCommonError(response, "DeleteMaterial")
  187. }