package weixinapi import "git.rosy.net.cn/baseapi/utils" const ( MaxRemarkByteCount = 30 ticketType = "wx_card" authType = 0 //Int 是 授权类型,0:开票授权,1:填写字段开票授权,2:领票授权 //图片(image)、视频(video)、语音 (voice)、图文(news) MaterialTypeImage = "image" MaterialTypeVideo = "video" MaterialTypeVoice = "voice" MaterialTypeNews = "news" MaterialTypeThumb = "thumb" SNSCutLine = `


` ) type CBUserInfo struct { Subscribe int `json:"subscribe"` OpenID string `json:"openid"` Nickname string `json:"nickname"` Sex int `json:"sex"` Language string `json:"language"` City string `json:"city"` Province string `json:"province"` Country string `json:"country"` HeadImgURL string `json:"headimgurl"` SubscribeTime int64 `json:"subscribe_time"` UnionID string `json:"unionid"` Remark string `json:"remark"` TagIDList []int `json:"tagid_list"` SubscribeScene string `json:"subscribe_scene"` QRScene int `json:"qr_scene"` QRSceneStr string `json:"qr_scene_str"` } type CBTicketInfo struct { Errcode int `json:"errcode"` Errmsg string `json:"errmsg"` Ticket string `json:"ticket"` ExpiresIn int `json:"expires_in"` } func (a *API) CBSetToken(newToken string) bool { curToken := a.CBGetToken() if curToken != newToken { a.locker.Lock() defer a.locker.Unlock() a.token = newToken return true } return false } func (a *API) CBGetToken() string { a.locker.RLock() defer a.locker.RUnlock() return a.token } func (a *API) CBRetrieveToken() (tokenInfo *TokenInfo, err error) { result, err := a.AccessAPI("cgi-bin/token", utils.Params2Map("grant_type", "client_credential"), "") if err != nil { return nil, err } tokenInfo = &TokenInfo{ AccessToken: utils.Interface2String(result["access_token"]), ExpiresIn: int(utils.MustInterface2Int64(result["expires_in"])), } a.CBSetToken(tokenInfo.AccessToken) return tokenInfo, nil } func (a *API) CBMessageTemplateSend(userOpenID, templateID, downloadURL string, miniProgram, data interface{}) (err error) { bodyJson := map[string]interface{}{ "touser": userOpenID, "template_id": templateID, "url": downloadURL, "data": data, } if downloadURL != "" { bodyJson["url"] = downloadURL } if miniProgram != nil { bodyJson["miniprogram"] = miniProgram } _, err = a.AccessAPI("cgi-bin/message/template/send", nil, string(utils.MustMarshal(bodyJson))) return err } // remark的字节数不超过30个字节 func (a *API) CBUpdateRemark(userOpenID, remark string) (err error) { bodyJson := map[string]interface{}{ "openid": userOpenID, "remark": utils.LimitMixedStringLen(remark, MaxRemarkByteCount), } _, err = a.AccessAPI("cgi-bin/user/info/updateremark", nil, string(utils.MustMarshal(bodyJson))) return err } func (a *API) CBGetUserInfo(userOpenID string) (userInfo *CBUserInfo, err error) { bodyJson := map[string]interface{}{ "openid": userOpenID, "lang": "zh_CN", } result, err := a.AccessAPI("cgi-bin/user/info", bodyJson, "") if err == nil { err = utils.Map2StructByJson(result, &userInfo, false) } return userInfo, err } //获取授权页ticket func (a *API) CBGetTicketInfo() (ticketInfo *CBTicketInfo, err error) { bodyJson := map[string]interface{}{ "type": ticketType, } result, err := a.AccessAPI("cgi-bin/ticket/getticket", bodyJson, "") if err == nil { err = utils.Map2StructByJson(result, &ticketInfo, false) } return ticketInfo, err } type CBBatchgetMaterialResult struct { Item []struct { MediaID string `json:"media_id"` Content struct { NewsItem []struct { Title string `json:"title"` Author string `json:"author"` Digest string `json:"digest"` Content string `json:"content"` ContentSourceURL string `json:"content_source_url"` ThumbMediaID string `json:"thumb_media_id"` ShowCoverPic int `json:"show_cover_pic"` URL string `json:"url"` ThumbURL string `json:"thumb_url"` NeedOpenComment int `json:"need_open_comment"` OnlyFansCanComment int `json:"only_fans_can_comment"` } `json:"news_item"` CreateTime int `json:"create_time"` UpdateTime int `json:"update_time"` } `json:"content"` UpdateTime int `json:"update_time"` } `json:"item"` TotalCount int `json:"total_count"` ItemCount int `json:"item_count"` } //获取素材列表 func (a *API) CBBatchgetMaterial(mediaType string, offset, count int) (ticketInfo *CBBatchgetMaterialResult, err error) { bodyJson := map[string]interface{}{ "type": mediaType, "offset": offset, "count": count, } result, err := a.AccessAPI("cgi-bin/material/batchget_material", nil, string(utils.MustMarshal(bodyJson))) if err == nil { err = utils.Map2StructByJson(result, &ticketInfo, false) } return ticketInfo, err } //上传图片 func (a *API) CBUploadImg(data []byte, fileName, contentType string) (url string, err error) { result, err := a.AccessAPIUpload("cgi-bin/media/uploadimg", data, fileName, contentType, "") if err == nil { return result["url"].(string), err } return url, err } //上传图片素材 func (a *API) CBUploadThumb(data []byte, fileName, contentType string) (mediaID, url string, err error) { result, err := a.AccessAPIUpload("cgi-bin/material/add_material", data, fileName, contentType, MaterialTypeThumb) if err == nil { return result["media_id"].(string), result["url"].(string), err } return mediaID, url, err } type CBAddNewsParamF struct { Articles []*CBAddNewsParam `json:"articles"` } type CBAddNewsParam struct { Title string `json:"title"` //是 标题 ThumbMediaID string `json:"thumb_media_id"` //是 图文消息的封面图片素材id(必须是永久mediaID) Author string `json:"author"` //否 作者 Digest string `json:"digest"` //否 图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空。如果本字段为没有填写,则默认抓取正文前54个字。 ShowCoverPic int `json:"show_cover_pic"` //是 是否显示封面,0为false,即不显示,1为true,即显示 Content string `json:"content"` //是 图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,且此处会去除JS,涉及图片url必须来源 "上传图文消息内的图片获取URL"接口获取。外部图片url将被过滤。 ContentSourceUrl string `json:"content_source_url"` //是 图文消息的原文地址,即点击“阅读原文”后的URL NeedOpenComment int `json:"need_open_comment"` //否 Uint32 是否打开评论,0不打开,1打开 OnlyFansCanComment int `json:"only_fans_can_comment"` //否 Uint32 是否粉丝才可评论,0所有人可评论,1粉丝才可评论 } //新增永久图文素材 func (a *API) CBAddNews(cbAddNewsParam *CBAddNewsParam) (mediaID string, err error) { params := &CBAddNewsParamF{ Articles: []*CBAddNewsParam{}, } params.Articles = append(params.Articles, cbAddNewsParam) bodyJson := utils.Struct2FlatMap(params) result, err := a.AccessAPI("cgi-bin/material/add_news", nil, string(utils.MustMarshal(bodyJson))) if err == nil { return result["media_id"].(string), err } return mediaID, err } //根据OpenID列表群发【订阅号不可用,服务号认证后可用】 func (a *API) CBMassSend(openIDs []string, mediaID string) (err error) { bodyJson := map[string]interface{}{ "touser": openIDs, "mpnews": map[string]interface{}{ "media_id": mediaID, }, "msgtype": "mpnews", } _, err = a.AccessAPI("cgi-bin/message/mass/send", nil, string(utils.MustMarshal(bodyJson))) return err }