| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- package material
- import (
- "encoding/json"
- "errors"
- "fmt"
- "github.com/silenceper/wechat/context"
- "github.com/silenceper/wechat/util"
- )
- const (
- addNewsURL = "https://api.weixin.qq.com/cgi-bin/material/add_news"
- addMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/add_material"
- delMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/del_material"
- getMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/get_material"
- batchGetMaterialURL = "https://api.weixin.qq.com/cgi-bin/material/batchget_material"
- )
- //PermanentMaterialType 永久素材类型
- type PermanentMaterialType string
- const (
- //PermanentMaterialTypeImage 永久素材图片类型(image)
- PermanentMaterialTypeImage PermanentMaterialType = "image"
- //PermanentMaterialTypeVideo 永久素材视频类型(video)
- PermanentMaterialTypeVideo PermanentMaterialType = "video"
- //PermanentMaterialTypeVoice 永久素材语音类型 (voice)
- PermanentMaterialTypeVoice PermanentMaterialType = "voice"
- //PermanentMaterialTypeNews 永久素材图文类型(news)
- PermanentMaterialTypeNews PermanentMaterialType = "news"
- )
- //Material 素材管理
- type Material struct {
- *context.Context
- }
- //NewMaterial init
- func NewMaterial(context *context.Context) *Material {
- material := new(Material)
- material.Context = context
- return material
- }
- //Article 永久图文素材
- type Article struct {
- Title string `json:"title"`
- ThumbMediaID string `json:"thumb_media_id"`
- ThumbURL string `json:"thumb_url"`
- Author string `json:"author"`
- Digest string `json:"digest"`
- ShowCoverPic int `json:"show_cover_pic"`
- Content string `json:"content"`
- ContentSourceURL string `json:"content_source_url"`
- URL string `json:"url"`
- DownURL string `json:"down_url"`
- }
- // GetNews 获取/下载永久素材
- func (material *Material) GetNews(id string) ([]*Article, error) {
- accessToken, err := material.GetAccessToken()
- if err != nil {
- return nil, err
- }
- uri := fmt.Sprintf("%s?access_token=%s", getMaterialURL, accessToken)
- var req struct {
- MediaID string `json:"media_id"`
- }
- req.MediaID = id
- responseBytes, err := util.PostJSON(uri, req)
- if err != nil {
- return nil, err
- }
- var res struct {
- NewsItem []*Article `json:"news_item"`
- }
- err = json.Unmarshal(responseBytes, &res)
- if err != nil {
- return nil, err
- }
- return res.NewsItem, nil
- }
- //reqArticles 永久性图文素材请求信息
- type reqArticles struct {
- Articles []*Article `json:"articles"`
- }
- //resArticles 永久性图文素材返回结果
- type resArticles struct {
- util.CommonError
- MediaID string `json:"media_id"`
- }
- //AddNews 新增永久图文素材
- func (material *Material) AddNews(articles []*Article) (mediaID string, err error) {
- req := &reqArticles{articles}
- var accessToken string
- accessToken, err = material.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", addNewsURL, accessToken)
- responseBytes, err := util.PostJSON(uri, req)
- if err != nil {
- return
- }
- var res resArticles
- err = json.Unmarshal(responseBytes, &res)
- if err != nil {
- return
- }
- mediaID = res.MediaID
- return
- }
- //resAddMaterial 永久性素材上传返回的结果
- type resAddMaterial struct {
- util.CommonError
- MediaID string `json:"media_id"`
- URL string `json:"url"`
- }
- //AddMaterial 上传永久性素材(处理视频需要单独上传)
- func (material *Material) AddMaterial(mediaType MediaType, filename string) (mediaID string, url string, err error) {
- if mediaType == MediaTypeVideo {
- err = errors.New("永久视频素材上传使用 AddVideo 方法")
- return
- }
- var accessToken string
- accessToken, err = material.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s&type=%s", addMaterialURL, accessToken, mediaType)
- var response []byte
- response, err = util.PostFile("media", filename, uri)
- if err != nil {
- return
- }
- var resMaterial resAddMaterial
- err = json.Unmarshal(response, &resMaterial)
- if err != nil {
- return
- }
- if resMaterial.ErrCode != 0 {
- err = fmt.Errorf("AddMaterial error : errcode=%v , errmsg=%v", resMaterial.ErrCode, resMaterial.ErrMsg)
- return
- }
- mediaID = resMaterial.MediaID
- url = resMaterial.URL
- return
- }
- type reqVideo struct {
- Title string `json:"title"`
- Introduction string `json:"introduction"`
- }
- //AddVideo 永久视频素材文件上传
- func (material *Material) AddVideo(filename, title, introduction string) (mediaID string, url string, err error) {
- var accessToken string
- accessToken, err = material.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s&type=video", addMaterialURL, accessToken)
- videoDesc := &reqVideo{
- Title: title,
- Introduction: introduction,
- }
- var fieldValue []byte
- fieldValue, err = json.Marshal(videoDesc)
- if err != nil {
- return
- }
- fields := []util.MultipartFormField{
- {
- IsFile: true,
- Fieldname: "media",
- Filename: filename,
- },
- {
- IsFile: false,
- Fieldname: "description",
- Value: fieldValue,
- },
- }
- var response []byte
- response, err = util.PostMultipartForm(fields, uri)
- if err != nil {
- return
- }
- var resMaterial resAddMaterial
- err = json.Unmarshal(response, &resMaterial)
- if err != nil {
- return
- }
- if resMaterial.ErrCode != 0 {
- err = fmt.Errorf("AddMaterial error : errcode=%v , errmsg=%v", resMaterial.ErrCode, resMaterial.ErrMsg)
- return
- }
- mediaID = resMaterial.MediaID
- url = resMaterial.URL
- return
- }
- type reqDeleteMaterial struct {
- MediaID string `json:"media_id"`
- }
- //DeleteMaterial 删除永久素材
- func (material *Material) DeleteMaterial(mediaID string) error {
- accessToken, err := material.GetAccessToken()
- if err != nil {
- return err
- }
- uri := fmt.Sprintf("%s?access_token=%s", delMaterialURL, accessToken)
- response, err := util.PostJSON(uri, reqDeleteMaterial{mediaID})
- if err != nil {
- return err
- }
- return util.DecodeWithCommonError(response, "DeleteMaterial")
- }
- //ArticleList 永久素材列表
- type ArticleList struct {
- TotalCount int64 `json:"total_count"`
- ItemCount int64 `json:"item_count"`
- Item []ArticleListItem `json:"item"`
- }
- //ArticleListItem 用于ArticleList的item节点
- type ArticleListItem struct {
- MediaID string `json:"media_id"`
- Content ArticleListContent `json:"content"`
- Name string `json:"name"`
- URL string `json:"url"`
- UpdateTime int64 `json:"update_time"`
- }
- //ArticleListContent 用于ArticleListItem的content节点
- type ArticleListContent struct {
- NewsItem []Article `json:"news_item"`
- UpdateTime int64 `json:"update_time"`
- CreateTime int64 `json:"create_time"`
- }
- //reqBatchGetMaterial BatchGetMaterial请求参数
- type reqBatchGetMaterial struct {
- Type PermanentMaterialType `json:"type"`
- Count int64 `json:"count"`
- Offset int64 `json:"offset"`
- }
- // BatchGetMaterial 批量获取永久素材
- //reference:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_materials_list.html
- func (material *Material) BatchGetMaterial(permanentMaterialType PermanentMaterialType, offset, count int64) (list ArticleList, err error) {
- var accessToken string
- accessToken, err = material.GetAccessToken()
- if err != nil {
- return
- }
- uri := fmt.Sprintf("%s?access_token=%s", batchGetMaterialURL, accessToken)
- req := reqBatchGetMaterial{
- Type: permanentMaterialType,
- Offset: offset,
- Count: count,
- }
- var response []byte
- response, err = util.PostJSON(uri, req)
- if err != nil {
- return
- }
- err = util.DecodeWithError(response, &list, "BatchGetMaterial")
- return
- }
|