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
}