diff --git a/doc/api/work.md b/doc/api/work.md index a188268..3a621b3 100644 --- a/doc/api/work.md +++ b/doc/api/work.md @@ -62,16 +62,20 @@ host: https://qyapi.weixin.qq.com/ ### 客户联系 [官方文档](https://developer.work.weixin.qq.com/document/path/92132/92133/92228) -| 名称 | 请求方式 | URL | 是否已实现 | 使用方法 | 贡献者 | -|:---------------:| -------- | :---------------------------------------| ---------- | ------------------------------- |----------| -| 获取「联系客户统计」数据 | POST | /cgi-bin/externalcontact/get_user_behavior_data | YES | (r *Client) GetUserBehaviorData | MARKWANG | -| 获取「群聊数据统计」数据 (按群主聚合的方式) | POST | /cgi-bin/externalcontact/groupchat/statistic | YES | (r *Client) GetGroupChatStat | MARKWANG | +| 名称 | 请求方式 | URL | 是否已实现 | 使用方法 | 贡献者 | +|:------------------------:| -------- | :---------------------------------------| ---------- | ------------------------------- |----------| +| 获取「联系客户统计」数据 | POST | /cgi-bin/externalcontact/get_user_behavior_data | YES | (r *Client) GetUserBehaviorData | MARKWANG | +| 获取「群聊数据统计」数据 (按群主聚合的方式) | POST | /cgi-bin/externalcontact/groupchat/statistic | YES | (r *Client) GetGroupChatStat | MARKWANG | | 获取「群聊数据统计」数据 (按自然日聚合的方式) | POST | /cgi-bin/externalcontact/groupchat/statistic_group_by_day | YES | (r *Client) GetGroupChatStatByDay | MARKWANG | -| 配置客户联系「联系我」方式 | POST | /cgi-bin/externalcontact/add_contact_way | YES | (r *Client) AddContactWay | MARKWANG | -| 获取企业已配置的「联系我」方式 | POST | /cgi-bin/externalcontact/get_contact_way | YES | (r *Client) GetContactWay | MARKWANG | -| 更新企业已配置的「联系我」方式 | POST | /cgi-bin/externalcontact/update_contact_way | YES | (r *Client) UpdateContactWay | MARKWANG | -| 获取企业已配置的「联系我」列表 | POST | /cgi-bin/externalcontact/list_contact_way | YES | (r *Client) ListContactWay | MARKWANG | -| 删除企业已配置的「联系我」方式 | POST | /cgi-bin/externalcontact/del_contact_way | YES | (r *Client) DelContactWay | MARKWANG | +| 配置客户联系「联系我」方式 | POST | /cgi-bin/externalcontact/add_contact_way | YES | (r *Client) AddContactWay | MARKWANG | +| 获取企业已配置的「联系我」方式 | POST | /cgi-bin/externalcontact/get_contact_way | YES | (r *Client) GetContactWay | MARKWANG | +| 更新企业已配置的「联系我」方式 | POST | /cgi-bin/externalcontact/update_contact_way | YES | (r *Client) UpdateContactWay | MARKWANG | +| 获取企业已配置的「联系我」列表 | POST | /cgi-bin/externalcontact/list_contact_way | YES | (r *Client) ListContactWay | MARKWANG | +| 删除企业已配置的「联系我」方式 | POST | /cgi-bin/externalcontact/del_contact_way | YES | (r *Client) DelContactWay | MARKWANG | +| 创建企业群发 | POST | /cgi-bin/externalcontact/add_msg_template | YES | (r *Client) AddMsgTemplate | MARKWANG | +| 获取群发成员发送任务列表 | POST | /cgi-bin/externalcontact/get_groupmsg_task | YES | (r *Client) GetGroupMsgTask | MARKWANG | +| 获取企业群发成员执行结果 | POST | /cgi-bin/externalcontact/get_groupmsg_send_result | YES | (r *Client) GetGroupMsgSendResult | MARKWANG | +| 发送新客户欢迎语 | POST | /cgi-bin/externalcontact/send_welcome_msg | YES | (r *Client) SendWelcomeMsg | MARKWANG | ## 通讯录管理 [官方文档](https://developer.work.weixin.qq.com/document/path/90193) @@ -82,7 +86,14 @@ host: https://qyapi.weixin.qq.com/ |:---------:|------|:----------------------------------------| ---------- | ------------------------------- |----------| | 获取子部门ID列表 | GET | /cgi-bin/department/simplelist | YES | (r *Client) DepartmentSimpleList| MARKWANG | | 获取部门成员 | GET | /cgi-bin/user/simplelist | YES | (r *Client) UserSimpleList | MARKWANG | -======= + + +## 素材管理 +[官方文档](https://developer.work.weixin.qq.com/document/path/91054) + +| 名称 | 请求方式 | URL | 是否已实现 | 使用方法 | 贡献者 | +|:---------:|------|:----------------------------------------| ---------- | ------------------------------- |----------| +| 上传图片 | POST | /cgi-bin/media/uploadimg | YES | (r *Client) UploadImg| MARKWANG | ### 成员管理 @@ -91,7 +102,6 @@ host: https://qyapi.weixin.qq.com/ | 读取成员 | GET | /cgi-bin/user/get | YES | (r *Client) UserGet | chcthink | - ## 群机器人 [官方文档](https://developer.work.weixin.qq.com/document/path/91770) @@ -101,5 +111,4 @@ host: https://qyapi.weixin.qq.com/ | 群机器人发送消息 | POST | /cgi-bin/webhook/send | YES | (r *Client) RobotBroadcast | chcthink | ## 应用管理 - TODO diff --git a/work/externalcontact/msg.go b/work/externalcontact/msg.go new file mode 100644 index 0000000..a34dffd --- /dev/null +++ b/work/externalcontact/msg.go @@ -0,0 +1,219 @@ +package externalcontact + +import ( + "fmt" + + "github.com/silenceper/wechat/v2/util" +) + +const ( + // AddMsgTemplateURL 创建企业群发 + AddMsgTemplateURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_msg_template?access_token=%s" + // GetGroupMsgTaskURL 获取群发成员发送任务列表 + GetGroupMsgTaskURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_groupmsg_task?access_token=%s" + // GetGroupMsgSendResultURL 获取企业群发成员执行结果 + GetGroupMsgSendResultURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_groupmsg_send_result?access_token=%s" + // SendWelcomeMsgURL 发送新客户欢迎语 + SendWelcomeMsgURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/send_welcome_msg?access_token=%s" +) + +// AddMsgTemplateRequest 创建企业群发请求 +type AddMsgTemplateRequest struct { + ChatType string `json:"chat_type"` + ExternalUserID []string `json:"external_userid"` + Sender string `json:"sender,omitempty"` + Text MsgText `json:"text"` + Attachments []*Attachment `json:"attachments"` +} + +// MsgText 文本消息 +type MsgText struct { + Content string `json:"content"` +} + +type ( + // Attachment 附件 + Attachment struct { + MsgType string `json:"msgtype"` + Image AttachmentImg `json:"image,omitempty"` + Link AttachmentLink `json:"link,omitempty"` + MiniProgram AttachmentMiniProgram `json:"miniprogram,omitempty"` + Video AttachmentVideo `json:"video,omitempty"` + File AttachmentFile `json:"file,omitempty"` + } + // AttachmentImg 图片消息 + AttachmentImg struct { + MediaID string `json:"media_id"` + PicURL string `json:"pic_url"` + } + // AttachmentLink 图文消息 + AttachmentLink struct { + Title string `json:"title"` + PicURL string `json:"picurl"` + Desc string `json:"desc"` + URL string `json:"url"` + } + // AttachmentMiniProgram 小程序消息 + AttachmentMiniProgram struct { + Title string `json:"title"` + PicMediaID string `json:"pic_media_id"` + AppID string `json:"appid"` + Page string `json:"page"` + } + // AttachmentVideo 视频消息 + AttachmentVideo struct { + MediaID string `json:"media_id"` + } + // AttachmentFile 文件消息 + AttachmentFile struct { + MediaID string `json:"media_id"` + } +) + +// AddMsgTemplateResponse 创建企业群发响应 +type AddMsgTemplateResponse struct { + util.CommonError + FailList []string `json:"fail_list"` + MsgID string `json:"msgid"` +} + +// AddMsgTemplate 创建企业群发 +// see https://developer.work.weixin.qq.com/document/path/92135 +func (r *Client) AddMsgTemplate(req *AddMsgTemplateRequest) (*AddMsgTemplateResponse, error) { + var ( + accessToken string + err error + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return nil, err + } + var response []byte + if response, err = util.PostJSON(fmt.Sprintf(AddMsgTemplateURL, accessToken), req); err != nil { + return nil, err + } + result := &AddMsgTemplateResponse{} + if err = util.DecodeWithError(response, result, "AddMsgTemplate"); err != nil { + return nil, err + } + return result, nil +} + +// GetGroupMsgTaskRequest 获取群发成员发送任务列表请求 +type GetGroupMsgTaskRequest struct { + MsgID string `json:"msgid"` + Limit int `json:"limit"` + Cursor string `json:"cursor"` +} + +// GetGroupMsgTaskResponse 获取群发成员发送任务列表响应 +type GetGroupMsgTaskResponse struct { + util.CommonError + NextCursor string `json:"next_cursor"` + TaskList []*Task `json:"task_list"` +} + +// Task 获取群发成员发送任务列表任务 +type Task struct { + UserID string `json:"userid"` + Status int `json:"status"` + SendTime int `json:"send_time"` +} + +// GetGroupMsgTask 获取群发成员发送任务列表 +// see https://developer.work.weixin.qq.com/document/path/93338 +func (r *Client) GetGroupMsgTask(req *GetGroupMsgTaskRequest) (*GetGroupMsgTaskResponse, error) { + var ( + accessToken string + err error + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return nil, err + } + var response []byte + if response, err = util.PostJSON(fmt.Sprintf(GetGroupMsgTaskURL, accessToken), req); err != nil { + return nil, err + } + result := &GetGroupMsgTaskResponse{} + if err = util.DecodeWithError(response, result, "GetGroupMsgTask"); err != nil { + return nil, err + } + return result, nil +} + +// GetGroupMsgSendResultRequest 获取企业群发成员执行结果请求 +type GetGroupMsgSendResultRequest struct { + MsgID string `json:"msgid"` + UserID string `json:"userid"` + Limit int `json:"limit"` + Cursor string `json:"cursor"` +} + +// GetGroupMsgSendResultResponse 获取企业群发成员执行结果响应 +type GetGroupMsgSendResultResponse struct { + util.CommonError + NextCursor string `json:"next_cursor"` + SendList []*Send `json:"send_list"` +} + +// Send 企业群发成员执行结果 +type Send struct { + ExternalUserID string `json:"external_userid"` + ChatID string `json:"chat_id"` + UserID string `json:"userid"` + Status int `json:"status"` + SendTime int `json:"send_time"` +} + +// GetGroupMsgSendResult 获取企业群发成员执行结果 +// see https://developer.work.weixin.qq.com/document/path/93338 +func (r *Client) GetGroupMsgSendResult(req *GetGroupMsgSendResultRequest) (*GetGroupMsgSendResultResponse, error) { + var ( + accessToken string + err error + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return nil, err + } + var response []byte + if response, err = util.PostJSON(fmt.Sprintf(GetGroupMsgSendResultURL, accessToken), req); err != nil { + return nil, err + } + result := &GetGroupMsgSendResultResponse{} + if err = util.DecodeWithError(response, result, "GetGroupMsgSendResult"); err != nil { + return nil, err + } + return result, nil +} + +// SendWelcomeMsgRequest 发送新客户欢迎语请求 +type SendWelcomeMsgRequest struct { + WelcomeCode string `json:"welcome_code"` + Text MsgText `json:"text"` + Attachments []*Attachment `json:"attachments"` +} + +// SendWelcomeMsgResponse 发送新客户欢迎语响应 +type SendWelcomeMsgResponse struct { + util.CommonError +} + +// SendWelcomeMsg 发送新客户欢迎语 +// see https://developer.work.weixin.qq.com/document/path/92137 +func (r *Client) SendWelcomeMsg(req *SendWelcomeMsgRequest) error { + var ( + accessToken string + err error + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return err + } + var response []byte + if response, err = util.PostJSON(fmt.Sprintf(SendWelcomeMsgURL, accessToken), req); err != nil { + return err + } + result := &SendWelcomeMsgResponse{} + if err = util.DecodeWithError(response, result, "SendWelcomeMsg"); err != nil { + return err + } + return nil +} diff --git a/work/material/client.go b/work/material/client.go new file mode 100644 index 0000000..d10f980 --- /dev/null +++ b/work/material/client.go @@ -0,0 +1,17 @@ +package material + +import ( + "github.com/silenceper/wechat/v2/work/context" +) + +// Client 素材管理接口实例 +type Client struct { + *context.Context +} + +// NewClient 初始化实例 +func NewClient(ctx *context.Context) *Client { + return &Client{ + ctx, + } +} diff --git a/work/material/media.go b/work/material/media.go new file mode 100644 index 0000000..0d2ac8d --- /dev/null +++ b/work/material/media.go @@ -0,0 +1,39 @@ +package material + +import ( + "fmt" + + "github.com/silenceper/wechat/v2/util" +) + +const ( + // UploadImgURL 上传图片 + UploadImgURL = "https://qyapi.weixin.qq.com/cgi-bin/media/uploadimg?access_token=%s" +) + +// UploadImgResponse 上传图片响应 +type UploadImgResponse struct { + util.CommonError + URL string `json:"url"` +} + +// UploadImg 上传图片 +// @see https://developer.work.weixin.qq.com/document/path/90256 +func (r *Client) UploadImg(filename string) (*UploadImgResponse, error) { + var ( + accessToken string + err error + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return nil, err + } + var response []byte + if response, err = util.PostFile("media", filename, fmt.Sprintf(UploadImgURL, accessToken)); err != nil { + return nil, err + } + result := &UploadImgResponse{} + if err = util.DecodeWithError(response, result, "UploadImg"); err != nil { + return nil, err + } + return result, nil +} diff --git a/work/work.go b/work/work.go index 2921db3..6e4e98e 100644 --- a/work/work.go +++ b/work/work.go @@ -7,6 +7,7 @@ import ( "github.com/silenceper/wechat/v2/work/context" "github.com/silenceper/wechat/v2/work/externalcontact" "github.com/silenceper/wechat/v2/work/kf" + "github.com/silenceper/wechat/v2/work/material" "github.com/silenceper/wechat/v2/work/msgaudit" "github.com/silenceper/wechat/v2/work/oauth" "github.com/silenceper/wechat/v2/work/robot" @@ -57,6 +58,11 @@ func (wk *Work) GetAddressList() *addresslist.Client { return addresslist.NewClient(wk.ctx) } +// GetMaterial get material +func (wk *Work) GetMaterial() *material.Client { + return material.NewClient(wk.ctx) +} + // GetRobot get robot func (wk *Work) GetRobot() *robot.Client { return robot.NewClient(wk.ctx)