package broadcast import ( "fmt" "github.com/silenceper/wechat/v2/officialaccount/context" "github.com/silenceper/wechat/v2/util" ) const ( sendURLByTag = "https://api.weixin.qq.com/cgi-bin/message/mass/sendall" sendURLByOpenID = "https://api.weixin.qq.com/cgi-bin/message/mass/send" deleteSendURL ="https://api.weixin.qq.com/cgi-bin/message/mass/delete" ) //MsgType 发送消息类型 type MsgType string const ( //MsgTypeNews 图文消息 MsgTypeNews MsgType = "mpnews" //MsgTypeText 文本 MsgTypeText MsgType = "text" //MsgTypeVoice 语音/音频 MsgTypeVoice MsgType = "voice" //MsgTypeImage 图片 MsgTypeImage MsgType = "image" //MsgTypeVideo 视频 MsgTypeVideo MsgType = "mpvideo" //MsgTypeWxCard 卡券 MsgTypeWxCard MsgType = "wxcard" ) //Broadcast 群发消息 type Broadcast struct { *context.Context } //NewBroadcast new func NewBroadcast(ctx *context.Context) *Broadcast { return &Broadcast{ctx} } //User 发送的用户 type User struct { TagID int64 OpenID []string } //Result 群发返回结果 type Result struct { util.CommonError MsgID int64 `json:"msg_id"` MsgDataID int64 `json:"msg_data_id"` } //sendRequest 发送请求的数据 type sendRequest struct { //根据tag获全部发送 Filter map[string]interface{} `json:"filter,omitempty"` //根据OpenID发送 ToUser interface{} `json:"touser,omitempty"` //发送文本 Text map[string]interface{} `json:"text,omitempty"` //发送图文消息 Mpnews map[string]interface{} `json:"mpnews,omitempty"` //发送语音 Voice map[string]interface{} `json:"voice,omitempty"` //发送图片 Images *Image `json:"images,omitempty"` //发送卡券 WxCard map[string]interface{} `json:"wxcard,omitempty"` MsgType MsgType `json:"msgtype"` SendIgnoreReprint int32 `json:"send_ignore_reprint,omitempty"` } //Image 发送图片 type Image struct{ MediaIDs []string `json:"media_ids"` Recommend string `json:"recommend"` NeedOpenComment int32 `json:"need_open_comment"` OnlyFansCanComment int32 `json:"only_fans_can_comment"` } //SendText 群发文本 //user 为nil,表示全员发送 //&User{TagID:2} 根据tag发送 //&User{OpenID:[]string("xxx","xxx")} 根据openid发送 func (broadcast *Broadcast) SendText(user *User, content string) (*Result, error) { ak, err := broadcast.GetAccessToken() if err != nil { return nil, err } req := &sendRequest{ ToUser: nil, MsgType: MsgTypeText, } req.Text=map[string]interface{}{ "content":content, } req,sendURL:=broadcast.chooseTagOrOpenID(user,req) url := fmt.Sprintf("%s?access_token=%s", sendURL, ak) data, err := util.PostJSON(url, req) if err != nil { return nil, err } res := &Result{} err = util.DecodeWithError(data, res, "SendText") return res, err } //SendNews 发送图文 func (broadcast *Broadcast) SendNews(user *User, mediaID string,ignoreReprint bool) (*Result, error) { ak, err := broadcast.GetAccessToken() if err != nil { return nil, err } req := &sendRequest{ ToUser: nil, MsgType: MsgTypeNews, } if ignoreReprint{ req.SendIgnoreReprint=1 } req.Mpnews=map[string]interface{}{ "media_id":mediaID, } req,sendURL:=broadcast.chooseTagOrOpenID(user,req) url := fmt.Sprintf("%s?access_token=%s", sendURL, ak) data, err := util.PostJSON(url, req) if err != nil { return nil, err } res := &Result{} err = util.DecodeWithError(data, res, "SendNews") return res, err } //SendVoice 发送语音 func (broadcast *Broadcast) SendVoice(user *User, mediaID string) (*Result, error) { ak, err := broadcast.GetAccessToken() if err != nil { return nil, err } req := &sendRequest{ ToUser: nil, MsgType: MsgTypeVoice, } req.Voice=map[string]interface{}{ "media_id":mediaID, } req,sendURL:=broadcast.chooseTagOrOpenID(user,req) url := fmt.Sprintf("%s?access_token=%s", sendURL, ak) data, err := util.PostJSON(url, req) if err != nil { return nil, err } res := &Result{} err = util.DecodeWithError(data, res, "SendVoice") return res, err } //SendImage 发送图片 func (broadcast *Broadcast) SendImage(user *User, images *Image) (*Result, error) { ak, err := broadcast.GetAccessToken() if err != nil { return nil, err } req := &sendRequest{ ToUser: nil, MsgType: MsgTypeImage, } req.Images=images req,sendURL:=broadcast.chooseTagOrOpenID(user,req) url := fmt.Sprintf("%s?access_token=%s", sendURL, ak) data, err := util.PostJSON(url, req) if err != nil { return nil, err } res := &Result{} err = util.DecodeWithError(data, res, "SendImage") return res, err } //SendVideo 发送视频 func (broadcast *Broadcast) SendVideo(user *User, mediaID string,title,description string) (*Result, error) { ak, err := broadcast.GetAccessToken() if err != nil { return nil, err } req := &sendRequest{ ToUser: nil, MsgType: MsgTypeVideo, } req.Voice=map[string]interface{}{ "media_id":mediaID, "title":title, "description":description, } req,sendURL:=broadcast.chooseTagOrOpenID(user,req) url := fmt.Sprintf("%s?access_token=%s", sendURL, ak) data, err := util.PostJSON(url, req) if err != nil { return nil, err } res := &Result{} err = util.DecodeWithError(data, res, "SendVideo") return res, err } //SendWxCard 发送卡券 func (broadcast *Broadcast) SendWxCard(user *User, cardID string) (*Result, error) { ak, err := broadcast.GetAccessToken() if err != nil { return nil, err } req := &sendRequest{ ToUser: nil, MsgType: MsgTypeWxCard, } req.WxCard=map[string]interface{}{ "card_id":cardID, } req,sendURL:=broadcast.chooseTagOrOpenID(user,req) url := fmt.Sprintf("%s?access_token=%s", sendURL, ak) data, err := util.PostJSON(url, req) if err != nil { return nil, err } res := &Result{} err = util.DecodeWithError(data, res, "SendWxCard") return res, err } //Delete 删除群发消息 func (broadcast *Broadcast) Delete(msgID int64 ,articleIDx int64) error { ak, err := broadcast.GetAccessToken() if err != nil { return err } req := map[string]interface{}{ "msg_id": msgID, "article_idx": articleIDx, } url := fmt.Sprintf("%s?access_token=%s", deleteSendURL, ak) data, err := util.PostJSON(url, req) if err != nil { return err } return util.DecodeWithCommonError(data, "Delete") } //TODO 发送预览,群发消息状态,发送速度 func (broadcast *Broadcast) chooseTagOrOpenID(user *User,req *sendRequest)(ret *sendRequest,url string){ sendURL:="" if user == nil { req.Filter=map[string]interface{}{ "is_to_all":true, } sendURL=sendURLByTag } else { if user.TagID != 0 { req.Filter=map[string]interface{}{ "is_to_all":false, "tag_id":user.TagID, } sendURL=sendURLByTag } if len(user.OpenID) != 0 { req.ToUser = user.OpenID sendURL=sendURLByOpenID } } return req,sendURL }