diff --git a/work/message/app.go b/work/message/app.go new file mode 100644 index 0000000..3aa59f0 --- /dev/null +++ b/work/message/app.go @@ -0,0 +1,165 @@ +package message + +import ( + "encoding/json" + "fmt" + "github.com/silenceper/wechat/v2/util" + "github.com/silenceper/wechat/v2/work/context" +) + +const ( + messageSendURL = "https://qyapi.weixin.qq.com/cgi-bin/message/send" + messageUpdateTemplateCardURL = "https://api.weixin.qq.com/cgi-bin/message/update_template_card" + messageDelURL = "https://api.weixin.qq.com/cgi-bin/message/recall" +) + +//App 应用消息 +type App struct { + *context.Context +} + +//NewApp 实例化 +func NewApp(context *context.Context) *App { + tpl := new(App) + tpl.Context = context + return tpl +} + +//AppMessage 发送的模板消息内容 +type AppMessage struct { + ToUser string `json:"touser"` // 必须, 成员ID列表(多个接收者用‘|’分隔,最多支持1000个 ,指定为”@all”,则向该企业应用的全部成员发送 + Toparty string `json:"toparty"` //部门ID列表,当touser为”@all”时忽略本参数 + Totag string `json:"totag"` //标签ID列表,当touser为”@all”时忽略本参数 + Msgtype string `json:"msgtype"` + Agentid int `json:"agentid"` + Safe int `json:"safe"` + EnableIdTrans int `json:"enable_id_trans"` + EnableDuplicateCheck int `json:"enable_duplicate_check"` + DuplicateCheckInterval int `json:"duplicate_check_interval"` + Text *Text + *Image + *Voice + *Video + File *PushFile `json:"file"` + TextCard *PushTextCard `json:"textcard"` + News *News `json:"news"` + MpNews *MpNews `json:"mpnews"` + Markdown *Text `json:"markdown"` + //todo(hb1707) 可能会发生变化的字段直接用interface{}了 + MiniprogramNotice interface{} `json:"miniprogram_notice"` + TemplateCard interface{} `json:"template_card"` +} + +type PushFile struct { + MediaID string `json:"media_id"` +} +type PushTextCard struct { + Title string `json:"title"` + Description string `json:"description"` + Url string `json:"url"` + Btntxt string `json:"btntxt"` +} + +type resTemplateSend struct { + util.CommonError + Invaliduser string `json:"invaliduser"` //不合法的userid,不区分大小写,统一转为小写 + Invalidparty string `json:"invalidparty"` //不合法的partyid + Invalidtag string `json:"invalidtag"` //不合法的标签id + MsgID int64 `json:"msgid"` //消息id,用于撤回应用消息 + ResponseCode string `json:"response_code"` //仅消息类型为“按钮交互型”,“投票选择型”和“多项选择型”的模板卡片消息返回,应用可使用response_code调用更新模版卡片消息接口,24小时内有效,且只能使用一次 +} + +//Send 发送应用消息 +func (tpl *App) Send(msg *AppMessage) (msgID int64, err error) { + var accessToken string + accessToken, err = tpl.GetAccessToken() + if err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", messageSendURL, accessToken) + var response []byte + response, err = util.PostJSON(uri, msg) + if err != nil { + return + } + var result resTemplateSend + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("template msg send error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg) + return + } + msgID = result.MsgID + return +} + +//TemplateUpdate 更新模版卡片消息内容 +type TemplateUpdate struct { + Userids []string `json:"userids"` + Partyids []int `json:"partyids"` + Tagids []int `json:"tagids"` + Atall int `json:"atall"` + Agentid int `json:"agentid"` + ResponseCode string `json:"response_code"` + *UpdateButton + *TemplateCard +} + +//UpdateTemplate 更新模版卡片消息 +func (tpl *App) UpdateTemplate(msg *TemplateUpdate) (msgID int64, err error) { + var accessToken string + accessToken, err = tpl.GetAccessToken() + if err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", messageUpdateTemplateCardURL, accessToken) + var response []byte + response, err = util.PostJSON(uri, msg) + if err != nil { + return + } + var result resTemplateSend + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("template msg send error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg) + return + } + msgID = result.MsgID + return +} + +type ReqRecall struct { + MsgID int64 `json:"msgid"` +} + +//Recall 撤回应用消息 +func (tpl *App) Recall(msgID int64) (err error) { + var accessToken string + accessToken, err = tpl.GetAccessToken() + if err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", messageDelURL, accessToken) + var response []byte + response, err = util.PostJSON(uri, &ReqRecall{ + MsgID: msgID, + }) + if err != nil { + return + } + var result util.CommonError + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("template msg send error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg) + return + } + return +} diff --git a/work/message/image.go b/work/message/image.go new file mode 100644 index 0000000..b877042 --- /dev/null +++ b/work/message/image.go @@ -0,0 +1,16 @@ +package message + +//Image 图片消息 +type Image struct { + CommonToken `json:"-"` + Image struct { + MediaID string `xml:"MediaId" json:"media_id"` + } `xml:"Image" json:"image"` +} + +//NewImage 回复图片消息 +func NewImage(mediaID string) *Image { + image := new(Image) + image.Image.MediaID = mediaID + return image +} diff --git a/work/message/message.go b/work/message/message.go index ecbe12a..82ee26b 100644 --- a/work/message/message.go +++ b/work/message/message.go @@ -6,16 +6,19 @@ import ( "github.com/silenceper/wechat/v2/officialaccount/device" ) -// MsgType 基本消息类型 +// MsgType 企业微信普通消息类型 type MsgType string -// EventType 事件类型 +// EventType 企业微信事件消息类型 type EventType string // InfoType 第三方平台授权事件类型 type InfoType string const ( + //MsgTypeEvent 表示事件推送消息 [限接收] + MsgTypeEvent = "event" + //MsgTypeText 表示文本消息 MsgTypeText MsgType = "text" //MsgTypeImage 表示图片消息 @@ -24,37 +27,48 @@ const ( MsgTypeVoice = "voice" //MsgTypeVideo 表示视频消息 MsgTypeVideo = "video" - //MsgTypeMiniprogrampage 表示小程序卡片消息 - MsgTypeMiniprogrampage = "miniprogrampage" - //MsgTypeShortVideo 表示短视频消息[限接收] - MsgTypeShortVideo = "shortvideo" - //MsgTypeLocation 表示坐标消息[限接收] - MsgTypeLocation = "location" + //MsgTypeNews 表示图文消息[限回复与发送应用消息] + MsgTypeNews = "news" + //MsgTypeLink 表示链接消息[限接收] MsgTypeLink = "link" - //MsgTypeMusic 表示音乐消息[限回复] - MsgTypeMusic = "music" - //MsgTypeNews 表示图文消息[限回复] - MsgTypeNews = "news" - //MsgTypeTransfer 表示消息消息转发到客服 - MsgTypeTransfer = "transfer_customer_service" - //MsgTypeEvent 表示事件推送消息 - MsgTypeEvent = "event" + //MsgTypeLocation 表示坐标消息[限接收] + MsgTypeLocation = "location" + + //MsgTypeUpdateButton 更新点击用户的按钮文案[限回复应用消息] + MsgTypeUpdateButton = "update_button" + //MsgTypeUpdateTemplateCard 更新点击用户的整张卡片[限回复应用消息] + MsgTypeUpdateTemplateCard = "update_template_card" + + //MsgTypeFile 文件消息[限发送应用消息] + MsgTypeFile = "file" + //MsgTypeTextCard 文本卡片消息[限发送应用消息] + MsgTypeTextCard = "textcard" + //MsgTypeMpNews 图文消息[限发送应用消息] 跟普通的图文消息一致,唯一的差异是图文内容存储在企业微信 + MsgTypeMpNews = "mpnews" + //MsgTypeMarkdown markdown消息[限发送应用消息] + MsgTypeMarkdown = "markdown" + //MsgTypeMiniprogramNotice 小程序通知消息[限发送应用消息] + MsgTypeMiniprogramNotice = "miniprogram_notice" + //MsgTypeTemplateCard 模板卡片消息[限发送应用消息] + MsgTypeTemplateCard = "template_card" ) const ( - //EventSubscribe 订阅 + //EventSubscribe 成员关注,成员已经加入企业,管理员添加成员到应用可见范围(或移除可见范围)时 EventSubscribe EventType = "subscribe" - //EventUnsubscribe 取消订阅 + //EventUnsubscribe 成员取消关注,成员已经在应用可见范围,成员加入(或退出)企业时 EventUnsubscribe = "unsubscribe" - //EventScan 用户已经关注公众号,则微信会将带场景值扫描事件推送给开发者 - EventScan = "SCAN" + //EventEnterAgent 本事件在成员进入企业微信的应用时触发 + EventEnterAgent = "enter_agent" //EventLocation 上报地理位置事件 EventLocation = "LOCATION" + //EventBatchJobResult 异步任务完成事件推送 + EventBatchJobResult = "batch_job_result" //EventClick 点击菜单拉取消息时的事件推送 - EventClick = "CLICK" + EventClick = "click" //EventView 点击菜单跳转链接时的事件推送 - EventView = "VIEW" + EventView = "view" //EventScancodePush 扫码推事件的事件推送 EventScancodePush = "scancode_push" //EventScancodeWaitmsg 扫码推事件且弹出“消息接收中”提示框的事件推送 @@ -67,106 +81,119 @@ const ( EventPicWeixin = "pic_weixin" //EventLocationSelect 弹出地理位置选择器的事件推送 EventLocationSelect = "location_select" - //EventTemplateSendJobFinish 发送模板消息推送通知 - EventTemplateSendJobFinish = "TEMPLATESENDJOBFINISH" - //EventMassSendJobFinish 群发消息推送通知 - EventMassSendJobFinish = "MASSSENDJOBFINISH" - //EventWxaMediaCheck 异步校验图片/音频是否含有违法违规内容推送事件 - EventWxaMediaCheck = "wxa_media_check" + + //EventOpenApprovalChange 审批状态通知事件推送 + EventOpenApprovalChange = "open_approval_change" + + //EventShareAgentChange 共享应用事件回调 + EventShareAgentChange = "share_agent_change" + + //EventTemplateCard 模板卡片事件推送 + EventTemplateCard = "template_card_event" + + //EventTemplateCardMenu 通用模板卡片右上角菜单事件推送 + EventTemplateCardMenu = "template_card_menu_event" + + //EventChangeExternalContact 企业客户事件推送 + //add_external_contact 添加 + //edit_external_contact 编辑 + //add_half_external_contact 免验证添加 + //del_external_contact 员工删除客户 + //del_follow_user 客户删除跟进员工 + //transfer_fail 企业将客户分配给新的成员接替后,客户添加失败 + //change_external_chat 客户群创建事件 + EventChangeExternalContact = "change_external_contact" + + //EventChangeExternalChat 企业客户群变更事件推送 + //create 客户群创建 + //update 客户群变更 + //dismiss 客户群解散 + EventChangeExternalChat = "change_external_chat" + + //EventChangeExternalTag 企业客户标签创建事件推送 + //create 创建标签 + //update 变更标签 + //delete 删除标签 + //shuffle 重新排序 + EventChangeExternalTag = "change_external_tag" + + //EventKfMsg 企业微信客服回调事件 + EventKfMsg = "kf_msg_or_event" + //EventLivingStatusChange 直播回调事件 + EventLivingStatusChange = "living_status_change" + + //EventMsgauditNotify 会话内容存档开启后,产生会话回调事件 + EventMsgauditNotify = "msgaudit_notify" ) -const ( - //微信开放平台需要用到 +//todo 第三方应用开发 +/*const ( + //微信开放平台需要用到 - // InfoTypeVerifyTicket 返回ticket - InfoTypeVerifyTicket InfoType = "component_verify_ticket" - // InfoTypeAuthorized 授权 - InfoTypeAuthorized = "authorized" - // InfoTypeUnauthorized 取消授权 - InfoTypeUnauthorized = "unauthorized" - // InfoTypeUpdateAuthorized 更新授权 - InfoTypeUpdateAuthorized = "updateauthorized" -) + // InfoTypeVerifyTicket 返回ticket + InfoTypeVerifyTicket InfoType = "component_verify_ticket" + // InfoTypeAuthorized 授权 + InfoTypeAuthorized = "authorized" + // InfoTypeUnauthorized 取消授权 + InfoTypeUnauthorized = "unauthorized" + // InfoTypeUpdateAuthorized 更新授权 + InfoTypeUpdateAuthorized = "updateauthorized" +)*/ -//MixMessage 存放所有微信发送过来的消息和事件 +//MixMessage 存放所有企业微信官方发送过来的消息和事件 type MixMessage struct { CommonToken - //基本消息 - MsgID int64 `xml:"MsgId"` //其他消息推送过来是MsgId - TemplateMsgID int64 `xml:"MsgID"` //模板消息推送成功的消息是MsgID - Content string `xml:"Content"` - Recognition string `xml:"Recognition"` - PicURL string `xml:"PicUrl"` - MediaID string `xml:"MediaId"` - Format string `xml:"Format"` - ThumbMediaID string `xml:"ThumbMediaId"` - LocationX float64 `xml:"Location_X"` - LocationY float64 `xml:"Location_Y"` - Scale float64 `xml:"Scale"` - Label string `xml:"Label"` - Title string `xml:"Title"` - Description string `xml:"Description"` - URL string `xml:"Url"` + //接收普通消息 + MsgID int64 `xml:"MsgId"` //其他消息推送过来是MsgId + AgentID int `xml:"AgentID"` //企业应用的id,整型。可在应用的设置页面查看 + + Content string `xml:"Content"` //文本消息内容 + Format string `xml:"Format"` //语音消息格式,如amr,speex等 + ThumbMediaID string `xml:"ThumbMediaId"` //视频消息缩略图的媒体id,可以调用获取媒体文件接口拉取数据,仅三天内有效 + + Title string `xml:"Title"` //链接消息,标题 + Description string `xml:"Description"` //链接消息,描述 + URL string `xml:"Url"` //链接消息,链接跳转的url + + PicURL string `xml:"PicUrl"` ////图片消息或者链接消息,封面缩略图的url + MediaID string `xml:"MediaId"` //图片媒体文件id//语音媒体文件id//视频消息缩略图的媒体id,可以调用获取媒体文件接口拉取,仅三天内有效 + + LocationX float64 `xml:"Location_X"` //位置消息,地理位置纬度 + LocationY float64 `xml:"Location_Y"` //位置消息,地理位置经度 + Scale float64 `xml:"Scale"` //位置消息,地图缩放大小 + Label string `xml:"Label"` //位置消息,地理位置信息 + + AppType string `xml:"AppType"` //接收地理位置时存在,app类型,在企业微信固定返回wxwork,在微信不返回该字段 + + //TemplateMsgID int64 `xml:"MsgID"` //模板消息推送成功的消息是MsgID + ///Recognition string `xml:"Recognition"` //事件相关 - Event EventType `xml:"Event"` - EventKey string `xml:"EventKey"` - Ticket string `xml:"Ticket"` - Latitude string `xml:"Latitude"` - Longitude string `xml:"Longitude"` - Precision string `xml:"Precision"` - MenuID string `xml:"MenuId"` - Status string `xml:"Status"` - SessionFrom string `xml:"SessionFrom"` - TotalCount int64 `xml:"TotalCount"` - FilterCount int64 `xml:"FilterCount"` - SentCount int64 `xml:"SentCount"` - ErrorCount int64 `xml:"ErrorCount"` + Event EventType `xml:"Event"` + EventKey string `xml:"EventKey"` - ScanCodeInfo struct { - ScanType string `xml:"ScanType"` - ScanResult string `xml:"ScanResult"` - } `xml:"ScanCodeInfo"` + //仅上报地理位置事件 + Latitude string `xml:"Latitude"` //地理位置纬度 + Longitude string `xml:"Longitude"` //地理位置经度 + Precision string `xml:"Precision"` //地理位置精度 - SendPicsInfo struct { - Count int32 `xml:"Count"` - PicList []EventPic `xml:"PicList>item"` - } `xml:"SendPicsInfo"` + //仅异步任务完成事件 + JobId string `xml:"JobId"` //异步任务id,最大长度为64字符 + JobType string `xml:"JobType"` //异步任务,操作类型,字符串,目前分别有:sync_user(增量更新成员)、 replace_user(全量覆盖成员)、invite_user(邀请成员关注)、replace_party(全量覆盖部门) + ErrCode int `xml:"ErrCode"` //异步任务,返回码 + ErrMsg string `xml:"ErrMsg"` //异步任务,对返回码的文本描述内容 - SendLocationInfo struct { - LocationX float64 `xml:"Location_X"` - LocationY float64 `xml:"Location_Y"` - Scale float64 `xml:"Scale"` - Label string `xml:"Label"` - Poiname string `xml:"Poiname"` - } + //开启通讯录回调通知 https://open.work.weixin.qq.com/api/doc/90000/90135/90967 - // 第三方平台相关 - InfoType InfoType `xml:"InfoType"` - AppID string `xml:"AppId"` - ComponentVerifyTicket string `xml:"ComponentVerifyTicket"` - AuthorizerAppid string `xml:"AuthorizerAppid"` - AuthorizationCode string `xml:"AuthorizationCode"` - AuthorizationCodeExpiredTime int64 `xml:"AuthorizationCodeExpiredTime"` - PreAuthCode string `xml:"PreAuthCode"` - - // 卡券相关 - CardID string `xml:"CardId"` - RefuseReason string `xml:"RefuseReason"` - IsGiveByFriend int32 `xml:"IsGiveByFriend"` - FriendUserName string `xml:"FriendUserName"` - UserCardCode string `xml:"UserCardCode"` - OldUserCardCode string `xml:"OldUserCardCode"` - OuterStr string `xml:"OuterStr"` - IsRestoreMemberCard int32 `xml:"IsRestoreMemberCard"` - UnionID string `xml:"UnionId"` - - // 内容审核相关 - IsRisky bool `xml:"isrisky"` - ExtraInfoJSON string `xml:"extra_info_json"` - TraceID string `xml:"trace_id"` - StatusCode int `xml:"status_code"` + // todo 第三方平台相关 字段名可能不准确 + /*InfoType InfoType `xml:"InfoType"` + AppID string `xml:"AppId"` + ComponentVerifyTicket string `xml:"ComponentVerifyTicket"` + AuthorizerAppid string `xml:"AuthorizerAppid"` + AuthorizationCode string `xml:"AuthorizationCode"``````````````````````````````````````` + AuthorizationCodeExpiredTime int64 `xml:"AuthorizationCodeExpiredTime"` + PreAuthCode string `xml:"PreAuthCode"`*/ //设备相关 device.MsgDevice @@ -181,6 +208,7 @@ type EventPic struct { type EncryptedXMLMsg struct { XMLName struct{} `xml:"xml" json:"-"` ToUserName string `xml:"ToUserName" json:"ToUserName"` + AgentID string `xml:"AgentID" json:"AgentID"` EncryptedMsg string `xml:"Encrypt" json:"Encrypt"` } diff --git a/work/message/news.go b/work/message/news.go new file mode 100644 index 0000000..b4cd16e --- /dev/null +++ b/work/message/news.go @@ -0,0 +1,41 @@ +package message + +//News 图文消息 +type News struct { + CommonToken `json:"-"` + ArticleCount int `xml:"ArticleCount" json:"-"` + Articles []*Article `xml:"Articles>item,omitempty" json:"articles"` +} + +//NewNews 初始化图文消息 +func NewNews(articles []*Article) *News { + news := new(News) + news.ArticleCount = len(articles) + news.Articles = articles + return news +} + +//Article 单篇文章 +type Article struct { + Title string `xml:"Title,omitempty" json:"title"` + Description string `xml:"Description,omitempty" json:"description"` + PicURL string `xml:"PicUrl,omitempty" json:"picurl"` + URL string `xml:"Url,omitempty" json:"url"` + Appid string `xml:"-" json:"appid"` //仅在发送应用消息时需要 + Pagepath string `xml:"-" json:"pagepath"` //仅在发送应用消息时需要 +} + +//MpNews 图文消息 +type MpNews struct { + Articles []*MpNewsArticle `xml:"-" json:"articles"` +} + +//MpNewsArticle mpnews类型的图文消息,跟普通的图文消息一致,唯一的差异是图文内容存储在企业微信 +type MpNewsArticle struct { + Title string `json:"title"` + ThumbMediaId string `json:"thumb_media_id"` + Author string `json:"author"` + ContentSourceUrl string `json:"content_source_url"` + Content string `json:"content"` + Digest string `json:"digest"` +} diff --git a/work/message/reply.go b/work/message/reply.go index 53592f0..8f53903 100644 --- a/work/message/reply.go +++ b/work/message/reply.go @@ -6,7 +6,7 @@ import "errors" var ErrInvalidReply = errors.New("无效的回复消息") //ErrUnsupportReply 不支持的回复类型 -var ErrUnsupportReply = errors.New("不支持的回复消息") +var ErrUnsupportReply = errors.New("无需回复消息") //Reply 消息回复 type Reply struct { diff --git a/work/message/template_card.go b/work/message/template_card.go new file mode 100644 index 0000000..29d3bef --- /dev/null +++ b/work/message/template_card.go @@ -0,0 +1,30 @@ +package message + +//UpdateButton 模板卡片按钮 +type UpdateButton struct { + CommonToken `json:"-"` + Button struct { + ReplaceName string `xml:"ReplaceName" json:"replace_name"` + } `xml:"Button" json:"button"` +} + +//NewUpdateButton 更新点击用户的按钮文案 +func NewUpdateButton(replaceName string) *UpdateButton { + btn := new(UpdateButton) + btn.Button.ReplaceName = replaceName + return btn +} + +//TemplateCard 被动回复模板卡片 +//https://open.work.weixin.qq.com/api/doc/90000/90135/90241 +type TemplateCard struct { + CommonToken `json:"-"` + TemplateCard interface{} `xml:"TemplateCard" json:"template_card"` +} + +// NewTemplateCard 更新点击用户的整张卡片 +func NewTemplateCard(cardXml interface{}) *TemplateCard { + card := new(TemplateCard) + card.TemplateCard = cardXml + return card +} diff --git a/work/message/text.go b/work/message/text.go new file mode 100644 index 0000000..46d3bf4 --- /dev/null +++ b/work/message/text.go @@ -0,0 +1,14 @@ +package message + +//Text 文本消息 +type Text struct { + CommonToken `json:"-"` + Content CDATA `json:"content" xml:"Content"` +} + +//NewText 初始化文本消息 +func NewText(content string) *Text { + text := new(Text) + text.Content = CDATA(content) + return text +} diff --git a/work/message/video.go b/work/message/video.go new file mode 100644 index 0000000..4a60307 --- /dev/null +++ b/work/message/video.go @@ -0,0 +1,20 @@ +package message + +//Video 视频消息 +type Video struct { + CommonToken `json:"-"` + Video struct { + MediaID string `xml:"MediaId" json:"media_id"` + Title string `xml:"Title,omitempty" json:"title"` + Description string `xml:"Description,omitempty" json:"description"` + } `xml:"Video" json:"video"` +} + +//NewVideo 回复图片消息 +func NewVideo(mediaID, title, description string) *Video { + video := new(Video) + video.Video.MediaID = mediaID + video.Video.Title = title + video.Video.Description = description + return video +} diff --git a/work/message/voice.go b/work/message/voice.go new file mode 100644 index 0000000..4a389c0 --- /dev/null +++ b/work/message/voice.go @@ -0,0 +1,16 @@ +package message + +//Voice 语音消息 +type Voice struct { + CommonToken `json:"-"` + Voice struct { + MediaID string `xml:"MediaId" json:"media_id"` + } `xml:"Voice" json:"voice"` +} + +//NewVoice 回复语音消息 +func NewVoice(mediaID string) *Voice { + voice := new(Voice) + voice.Voice.MediaID = mediaID + return voice +} diff --git a/work/server/server.go b/work/server/server.go index b1a32aa..5f0298a 100644 --- a/work/server/server.go +++ b/work/server/server.go @@ -64,7 +64,7 @@ func (srv *Server) SkipValidate(skip bool) { srv.skipValidate = skip } -//Serve 处理微信的请求消息 +//Serve 处理企业微信的请求消息 func (srv *Server) Serve() error { response, err := srv.handleRequest() if err != nil { @@ -88,7 +88,7 @@ func (srv *Server) Validate() bool { return signature == util.Signature(srv.Token, timestamp, nonce) } -//HandleRequest 处理微信的请求 +//HandleRequest 处理企业微信的请求 func (srv *Server) handleRequest() (reply *message.Reply, err error) { var msg interface{} @@ -105,7 +105,7 @@ func (srv *Server) handleRequest() (reply *message.Reply, err error) { return } -//getMessage 解析微信返回的消息 +//getMessage 解析企业微信返回的消息 func (srv *Server) getMessage() (interface{}, error) { var rawXMLMsgBytes []byte var err error @@ -136,7 +136,6 @@ func (srv *Server) getMessage() (interface{}, error) { } srv.RequestRawXMLMsg = rawXMLMsgBytes - return srv.parseRequestMessage(rawXMLMsgBytes) } @@ -167,9 +166,9 @@ func (srv *Server) buildResponse(reply *message.Reply) (err error) { case message.MsgTypeImage: case message.MsgTypeVoice: case message.MsgTypeVideo: - case message.MsgTypeMusic: case message.MsgTypeNews: - case message.MsgTypeTransfer: + case message.MsgTypeUpdateButton: + case message.MsgTypeUpdateTemplateCard: default: err = message.ErrUnsupportReply return @@ -195,7 +194,6 @@ func (srv *Server) buildResponse(reply *message.Reply) (err error) { params[0] = reflect.ValueOf(util.GetCurrTS()) value.MethodByName("SetCreateTime").Call(params) - srv.ResponseMsg = msgData srv.ResponseRawXMLMsg, err = xml.Marshal(msgData) return