Files
baseapi/platformapi/weixinapi/cgibin.go
2025-11-21 09:09:09 +08:00

234 lines
8.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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 = `
<br>
<hr style=\"border-style: solid;border-width: 1px 0 0;border-color: rgba(0,0,0,0.1);-webkit-transform-origin: 0 0;-webkit-transform: scale(1, 0.5);transform-origin: 0 0;transform: scale(1, 0.5);\" />
<br>
`
)
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
}