|
|
@@ -0,0 +1,279 @@
|
|
|
+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
|
|
|
+}
|