material.go 4.4 KB

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