diff --git a/README.md b/README.md
index 5729183..1debab9 100644
--- a/README.md
+++ b/README.md
@@ -119,11 +119,23 @@ in at least 2 of Qiniu's internal systems.
客户联系 API
* [x] 成员对外信息
+* [x] 企业服务人员管理
+ - [x] 获取配置了客户联系功能的成员列表
+ - [x] 客户联系「联系我」管理
* [x] 客户管理
- [x] 获取客户列表
- [x] 获取客户详情
- [x] 批量获取客户详情
- [x] 修改客户备注信息
+* [x] 在职继承
+ - [x] 分配在职成员的客户
+ - [x] 查询客户接替状态
+ - [ ] 分配在职成员的客户群
+* [x] 离职继承
+ - [ ] 获取待分配的离职成员列表
+ - [x] 分配离职成员的客户
+ - [x] 查询客户接替状态
+ - [ ] 分配离职成员的客户群
* [x] 客户标签管理
- [x] 管理企业标签
- [x] 编辑客户企业标签
diff --git a/apis.md.go b/apis.md.go
index dd976d3..7ffccb6 100644
--- a/apis.md.go
+++ b/apis.md.go
@@ -505,3 +505,157 @@ func (c *WorkwxApp) execMsgAuditGetGroupChat(req reqMsgAuditGetGroupChat) (respM
return resp, nil
}
+
+// execListFollowUserExternalContact 获取配置了客户联系功能的成员列表
+func (c *WorkwxApp) execListFollowUserExternalContact(req reqListFollowUserExternalContact) (respListFollowUserExternalContact, error) {
+ var resp respListFollowUserExternalContact
+ err := c.executeQyapiGet("/cgi-bin/externalcontact/get_follow_user_list", req, &resp, true)
+ if err != nil {
+ return respListFollowUserExternalContact{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respListFollowUserExternalContact{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execAddContactExternalContact 配置客户联系「联系我」方式
+func (c *WorkwxApp) execAddContactExternalContact(req reqAddContactExternalContact) (respAddContactExternalContact, error) {
+ var resp respAddContactExternalContact
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/add_contact_way", req, &resp, true)
+ if err != nil {
+ return respAddContactExternalContact{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respAddContactExternalContact{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execGetContactWayExternalContact 获取企业已配置的「联系我」方式
+func (c *WorkwxApp) execGetContactWayExternalContact(req reqGetContactWayExternalContact) (respGetContactWayExternalContact, error) {
+ var resp respGetContactWayExternalContact
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/get_contact_way", req, &resp, true)
+ if err != nil {
+ return respGetContactWayExternalContact{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respGetContactWayExternalContact{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execListContactWayChatExternalContact 获取企业已配置的「联系我」列表
+func (c *WorkwxApp) execListContactWayChatExternalContact(req reqListContactWayExternalContact) (respListContactWayChatExternalContact, error) {
+ var resp respListContactWayChatExternalContact
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/list_contact_way", req, &resp, true)
+ if err != nil {
+ return respListContactWayChatExternalContact{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respListContactWayChatExternalContact{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execUpdateContactWayExternalContact 更新企业已配置的「联系我」成员配置
+func (c *WorkwxApp) execUpdateContactWayExternalContact(req reqUpdateContactWayExternalContact) (respUpdateContactWayExternalContact, error) {
+ var resp respUpdateContactWayExternalContact
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/update_contact_way", req, &resp, true)
+ if err != nil {
+ return respUpdateContactWayExternalContact{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respUpdateContactWayExternalContact{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execDelContactWayExternalContact 删除企业已配置的「联系我」方式
+func (c *WorkwxApp) execDelContactWayExternalContact(req reqDelContactWayExternalContact) (respDelContactWayExternalContact, error) {
+ var resp respDelContactWayExternalContact
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/del_contact_way", req, &resp, true)
+ if err != nil {
+ return respDelContactWayExternalContact{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respDelContactWayExternalContact{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execCloseTempChatExternalContact 结束临时会话
+func (c *WorkwxApp) execCloseTempChatExternalContact(req reqCloseTempChatExternalContact) (respCloseTempChatExternalContact, error) {
+ var resp respCloseTempChatExternalContact
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/close_temp_chat", req, &resp, true)
+ if err != nil {
+ return respCloseTempChatExternalContact{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respCloseTempChatExternalContact{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execTransferCustomer 在职继承 分配在职成员的客户
+func (c *WorkwxApp) execTransferCustomer(req reqTransferCustomer) (respTransferCustomer, error) {
+ var resp respTransferCustomer
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/transfer_customer", req, &resp, true)
+ if err != nil {
+ return respTransferCustomer{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respTransferCustomer{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execGetTransferCustomerResult 在职继承 查询客户接替状态
+func (c *WorkwxApp) execGetTransferCustomerResult(req reqGetTransferCustomerResult) (respGetTransferCustomerResult, error) {
+ var resp respGetTransferCustomerResult
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/transfer_result", req, &resp, true)
+ if err != nil {
+ return respGetTransferCustomerResult{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respGetTransferCustomerResult{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execTransferResignedCustomer 离职继承 分配离职成员的客户
+func (c *WorkwxApp) execTransferResignedCustomer(req reqTransferCustomer) (respTransferCustomer, error) {
+ var resp respTransferCustomer
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/resigned/transfer_customer", req, &resp, true)
+ if err != nil {
+ return respTransferCustomer{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respTransferCustomer{}, bizErr
+ }
+
+ return resp, nil
+}
+
+// execGetTransferResignedCustomerResult 离职继承 查询客户接替状态
+func (c *WorkwxApp) execGetTransferResignedCustomerResult(req reqGetTransferCustomerResult) (respGetTransferCustomerResult, error) {
+ var resp respGetTransferCustomerResult
+ err := c.executeQyapiJSONPost("/cgi-bin/externalcontact/resigned/transfer_result", req, &resp, true)
+ if err != nil {
+ return respGetTransferCustomerResult{}, err
+ }
+ if bizErr := resp.TryIntoErr(); bizErr != nil {
+ return respGetTransferCustomerResult{}, bizErr
+ }
+
+ return resp, nil
+}
diff --git a/docs/apis.md b/docs/apis.md
index b2cc794..66f5362 100644
--- a/docs/apis.md
+++ b/docs/apis.md
@@ -169,7 +169,6 @@ Name|Request Type|Response Type|Access Token|URL|Doc
Name|Request Type|Response Type|Access Token|URL|Doc
:---|------------|-------------|------------|:--|:--
-
# 会话内容存档
## API calls
@@ -180,3 +179,35 @@ Name|Request Type|Response Type|Access Token|URL|Doc
`execMsgAuditCheckSingleAgree`|`reqMsgAuditCheckSingleAgree`|`respMsgAuditCheckSingleAgree`|+|`POST /cgi-bin/msgaudit/check_single_agree`|[获取会话同意情况(单聊)](https://work.weixin.qq.com/api/doc/90000/90135/91782)
`execMsgAuditCheckRoomAgree`|`reqMsgAuditCheckRoomAgree`|`respMsgAuditCheckRoomAgree`|+|`POST /cgi-bin/msgaudit/check_room_agree`|[获取会话同意情况(群聊)](https://work.weixin.qq.com/api/doc/90000/90135/91782)
`execMsgAuditGetGroupChat`|`reqMsgAuditGetGroupChat`|`respMsgAuditGetGroupChat`|+|`POST /cgi-bin/msgaudit/groupchat/get`|[获取会话内容存档内部群信息](https://work.weixin.qq.com/api/doc/90000/90135/92951)
+
+# 企业服务人员管理 - 联系我
+
+## API calls
+
+Name|Request Type|Response Type|Access Token|URL|Doc
+:---|------------|-------------|------------|:--|:--
+`execListFollowUserExternalContact`|`reqListFollowUserExternalContact`|`respListFollowUserExternalContact`|+|`GET /cgi-bin/externalcontact/get_follow_user_list`|[获取配置了客户联系功能的成员列表](https://developer.work.weixin.qq.com/document/path/92571)
+`execAddContactExternalContact`|`reqAddContactExternalContact`|`respAddContactExternalContact`|+|`POST /cgi-bin/externalcontact/add_contact_way`|[配置客户联系「联系我」方式](https://developer.work.weixin.qq.com/document/path/92572#%E9%85%8D%E7%BD%AE%E5%AE%A2%E6%88%B7%E8%81%94%E7%B3%BB%E3%80%8C%E8%81%94%E7%B3%BB%E6%88%91%E3%80%8D%E6%96%B9%E5%BC%8F)
+`execGetContactWayExternalContact`|`reqGetContactWayExternalContact`|`respGetContactWayExternalContact`|+|`POST /cgi-bin/externalcontact/get_contact_way`|[获取企业已配置的「联系我」方式](https://developer.work.weixin.qq.com/document/path/92572#%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%B7%B2%E9%85%8D%E7%BD%AE%E7%9A%84%E3%80%8C%E8%81%94%E7%B3%BB%E6%88%91%E3%80%8D%E6%96%B9%E5%BC%8F)
+`execListContactWayChatExternalContact`|`reqListContactWayExternalContact`|`respListContactWayChatExternalContact`|+|`POST /cgi-bin/externalcontact/list_contact_way`|[获取企业已配置的「联系我」列表](https://developer.work.weixin.qq.com/document/path/92572#%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E5%B7%B2%E9%85%8D%E7%BD%AE%E7%9A%84%E3%80%8C%E8%81%94%E7%B3%BB%E6%88%91%E3%80%8D%E5%88%97%E8%A1%A8)
+`execUpdateContactWayExternalContact`|`reqUpdateContactWayExternalContact`|`respUpdateContactWayExternalContact`|+|`POST /cgi-bin/externalcontact/update_contact_way`|[更新企业已配置的「联系我」成员配置](https://developer.work.weixin.qq.com/document/path/92572#%E6%9B%B4%E6%96%B0%E4%BC%81%E4%B8%9A%E5%B7%B2%E9%85%8D%E7%BD%AE%E7%9A%84%E3%80%8C%E8%81%94%E7%B3%BB%E6%88%91%E3%80%8D%E6%96%B9%E5%BC%8F)
+`execDelContactWayExternalContact`|`reqDelContactWayExternalContact`|`respDelContactWayExternalContact`|+|`POST /cgi-bin/externalcontact/del_contact_way`|[删除企业已配置的「联系我」方式](https://developer.work.weixin.qq.com/document/path/92572#%E5%88%A0%E9%99%A4%E4%BC%81%E4%B8%9A%E5%B7%B2%E9%85%8D%E7%BD%AE%E7%9A%84%E3%80%8C%E8%81%94%E7%B3%BB%E6%88%91%E3%80%8D%E6%96%B9%E5%BC%8F)
+`execCloseTempChatExternalContact`|`reqCloseTempChatExternalContact`|`respCloseTempChatExternalContact`|+|`POST /cgi-bin/externalcontact/close_temp_chat`|[结束临时会话](https://developer.work.weixin.qq.com/document/path/92572#%E7%BB%93%E6%9D%9F%E4%B8%B4%E6%97%B6%E4%BC%9A%E8%AF%9D)
+
+# 在职继承
+
+## API calls
+
+Name|Request Type|Response Type|Access Token|URL|Doc
+:---|------------|-------------|------------|:--|:--
+`execTransferCustomer`|`reqTransferCustomer`|`respTransferCustomer`|+|`POST /cgi-bin/externalcontact/transfer_customer`|[在职继承 分配在职成员的客户](https://developer.work.weixin.qq.com/document/path/92125)
+`execGetTransferCustomerResult`|`reqGetTransferCustomerResult`|`respGetTransferCustomerResult`|+|`POST /cgi-bin/externalcontact/transfer_result`|[在职继承 查询客户接替状态](https://developer.work.weixin.qq.com/document/path/94088)
+
+# 离职继承
+
+## API calls
+
+Name|Request Type|Response Type|Access Token|URL|Doc
+:---|------------|-------------|------------|:--|:--
+`execTransferResignedCustomer`|`reqTransferCustomer`|`respTransferCustomer`|+|`POST /cgi-bin/externalcontact/resigned/transfer_customer`|[离职继承 分配离职成员的客户](https://developer.work.weixin.qq.com/document/path/94081)
+`execGetTransferResignedCustomerResult`|`reqGetTransferCustomerResult`|`respGetTransferCustomerResult`|+|`POST /cgi-bin/externalcontact/resigned/transfer_result`|[离职继承 查询客户接替状态](https://developer.work.weixin.qq.com/document/path/94082)
diff --git a/docs/external_contact.md b/docs/external_contact.md
index 59d1a1e..ffe2362 100644
--- a/docs/external_contact.md
+++ b/docs/external_contact.md
@@ -229,3 +229,92 @@ Name|JSON|Type|Doc
`ChatID`|`chat_id`|`string`| 没能成功继承的群ID
`ErrCode`|`errcode`|`int`| 没能成功继承的群,错误码
`ErrMsg`|`errmsg`|`string`| 没能成功继承的群,错误描述
+
+### `ExternalContactFollowUserList` 配置了客户联系功能的成员列表
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`FollowUser`|`follow_user`|`[]string`| 配置了客户联系功能的成员userid列表
+
+### `ExternalContactWay` 配置客户联系「联系我」方式
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`Type`|`type`|`int`| 联系方式类型,1-单人, 2-多人
+`Scene`|`scene`|`int`| 场景,1-在小程序中联系,2-通过二维码联系
+`Style`|`style`|`int`| 在小程序中联系时使用的控件样式,详见附表
+`Remark`|`remark`|`string`| 联系方式的备注信息,用于助记,不超过30个字符
+`SkipVerify`|`skip_verify`|`bool`| 外部客户添加时是否无需验证,默认为true
+`State`|`state`|`string`| 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情”时会返回该参数值,不超过30个字符
+`User`|`user`|`[]string`| 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个
+`Party`|`party`|`[]int`| 使用该联系方式的部门id列表,只在type为2时有效
+`IsTemp`|`is_temp`|`bool`| 是否临时会话模式,true表示使用临时会话模式,默认为false
+`ExpiresIn`|`expires_in`|`int`| 临时会话二维码有效期,以秒为单位。该参数仅在is_temp为true时有效,默认7天,最多为14天
+`ChatExpiresIn`|`chat_expires_in`|`int`| 临时会话有效期,以秒为单位。该参数仅在is_temp为true时有效,默认为添加好友后24小时,最多为14天
+`UnionID`|`unionid`|`string`| 可进行临时会话的客户UnionID,该参数仅在is_temp为true时有效,如不指定则不进行限制
+`Conclusions`|`conclusions`|`Conclusions`| 结束语,会话结束时自动发送给客户,可参考“结束语定义”,仅在is_temp为true时有效,
+
+### `Conclusions` 结束语,会话结束时自动发送给客户
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`Text`|`text`|`Text`| 文本消息
+`Image`|`image`|`Image`| 图片
+`Link`|`link`|`Link`| 链接
+`MiniProgram`|`miniprogram`|`MiniProgram`| 小程序
+
+### `Text` 结束语,会话结束时自动发送给客户
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`Content`|`content`|`string`| 消息文本内容,最长为4000字节
+
+### `Image` 结束语,会话结束时自动发送给客户
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`MediaID`|`media_id`|`string`| 图片的media_id
+`PicURL`|`pic_url`|`string`| 图片的url
+
+### `Link` 结束语,会话结束时自动发送给客户
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`Title`|`title`|`string`| 图文消息标题,最长为128字节
+`Picurl`|`picurl`|`string`| 图文消息封面的url
+`Desc`|`desc`|`string`| 图文消息的描述,最长为512字节
+`URL`|`url`|`string`| 图文消息的链接
+
+### `MiniProgram` 结束语,会话结束时自动发送给客户
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`Title`|`title`|`string`| 小程序消息标题,最长为64字节
+`PicMediaID`|`pic_media_id`|`string`| 小程序消息封面的mediaid,封面图建议尺寸为520*416
+`AppID`|`appid`|`string`| 小程序appid,必须是关联到企业的小程序应用
+`Page`|`page`|`string`| 小程序page路径
+
+### `reqListContactWayExternalContact` 获取企业已配置的「联系我」列表请求参数
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`StartTime`|`start_time`|`int`| 「联系我」创建起始时间戳, 默认为90天前
+`EndTime`|`end_time`|`int`| 「联系我」创建结束时间戳, 默认为当前时间
+`Cursor`|`cursor`|`string`| 分页查询使用的游标,为上次请求返回的 next_cursor
+`Limit`|`limit`|`int`| 每次查询的分页大小,默认为100条,最多支持1000条
+
+### `reqUpdateContactWayExternalContact` 更新企业已配置的「联系我」方式请求参数
+
+Name|JSON|Type|Doc
+:---|:---|:---|:--
+`ConfigID`|`config_id`|`string`| 企业联系方式的配置id
+`Remark`|`remark`|`string`| 联系方式的备注信息,不超过30个字符,将覆盖之前的备注
+`SkipVerify`|`skip_verify`|`bool`| 外部客户添加时是否无需验证
+`Style`|`style`|`int`| 样式,只针对“在小程序中联系”的配置生效
+`State`|`state`|`string`| 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情”时会返回该参数值,不超过30个字符
+`User`|`user`|`[]string`| 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个
+`Party`|`party`|`[]int`| 使用该联系方式的部门id列表,只在type为2时有效
+`ExpiresIn`|`expires_in`|`int`| 临时会话二维码有效期,以秒为单位。该参数仅在is_temp为true时有效,默认7天,最多为14天
+`ChatExpiresIn`|`chat_expires_in`|`int`| 临时会话有效期,以秒为单位。该参数仅在is_temp为true时有效,默认为添加好友后24小时,最多为14天
+`UnionID`|`unionid`|`string`| 可进行临时会话的客户UnionID,该参数仅在is_temp为true时有效,如不指定则不进行限制
+`Conclusions`|`conclusions`|`Conclusions`| 结束语,会话结束时自动发送给客户,可参考“结束语定义”,仅在is_temp为true时有效,
diff --git a/docs/rx_msg.md b/docs/rx_msg.md
index 5bb188b..7ef7357 100644
--- a/docs/rx_msg.md
+++ b/docs/rx_msg.md
@@ -51,6 +51,9 @@ const EventTypeChangeExternalChat EventType = "change_external_chat"
// EventTypeSysApprovalChange 审批申请状态变化回调通知
const EventTypeSysApprovalChange EventType = "sys_approval_change"
+// EventTypeChangeContact 通讯录回调通知
+const EventTypeChangeContact EventType = "change_contact"
+
// ChangeType 变更类型
type ChangeType string
@@ -72,6 +75,12 @@ const ChangeTypeDelFollowUser ChangeType = "del_follow_user"
// ChangeTypeTransferFail 客户接替失败事件
const ChangeTypeTransferFail ChangeType = "transfer_fail"
+// ChangeTypeCreateUser 新增成员事件
+const ChangeTypeCreateUser ChangeType = "create_user"
+
+// ChangeTypeUpdateUser 更新成员事件
+const ChangeTypeUpdateUser ChangeType = "update_user"
+
```
### `rxTextMessageSpecifics` 接收的文本消息,特有字段
@@ -182,3 +191,54 @@ Name|XML|Type|Doc
Name|XML|Type|Doc
:---|:--|:---|:--
`ApprovalInfo`|`ApprovalInfo`|`OAApprovalInfo`|审批信息、
+
+### `rxEventChangeTypeCreateUser` 接受的事件消息,新增成员事件
+
+Name|XML|Type|Doc
+:---|:--|:---|:--
+`UserID`|`UserID`|`string`|成员UserID
+`Name`|`Name`|`string`|成员名称
+`Department`|`Department`|`string`|成员部门列表,仅返回该应用有查看权限的部门id
+`IsLeaderInDept`|`IsLeaderInDept`|`string`|表示所在部门是否为上级,0-否,1-是,顺序与Department字段的部门逐一对应
+`Mobile`|`Mobile`|`string`|手机号
+`Position`|`Position`|`string`|职位信息。长度为0~64个字节
+`Gender`|`Gender`|`int`|性别,1表示男性,2表示女性
+`Email`|`Email`|`string`|邮箱
+`Status`|`Status`|`int`|激活状态:1=已激活 2=已禁用 4=未激活 已激活代表已激活企业微信或已关注微工作台(原企业号)5=成员退出
+`Avatar`|`Avatar`|`string`|头像url。注:如果要获取小图将url最后的”/0”改成”/100”即可。
+`Alias`|`Alias`|`string`|成员别名
+`Telephone`|`Telephone`|`string`|座机
+`Address`|`Address`|`string`|地址
+`ExtAttr`|`ExtAttr`|`string`|扩展属性
+`Type`|`Type`|`string`|扩展属性类型: 0-本文 1-网页
+`Text`|`Text`|`string`|文本属性类型,扩展属性类型为0时填写
+`Value`|`Value`|`string`|文本属性内容
+`Web`|`Web`|`string`|网页类型属性,扩展属性类型为1时填写
+`Title`|`Title`|`string`|网页的展示标题
+`Url`|`Url`|`string`|网页的url
+
+### `rxEventChangeTypeUpdateUser` 接受的事件消息,更新成员事件
+
+Name|XML|Type|Doc
+:---|:--|:---|:--
+`UserID`|`UserID`|`string`|成员UserID
+`NewUserID`|`NewUserID`|`string`|新的UserID,变更时推送(userid由系统生成时可更改一次)
+`Name`|`Name`|`string`|成员名称
+`Department`|`Department`|`string`|成员部门列表,仅返回该应用有查看权限的部门id
+`IsLeaderInDept`|`IsLeaderInDept`|`string`|表示所在部门是否为上级,0-否,1-是,顺序与Department字段的部门逐一对应
+`Mobile`|`Mobile`|`string`|手机号
+`Position`|`Position`|`string`|职位信息。长度为0~64个字节
+`Gender`|`Gender`|`int`|性别,1表示男性,2表示女性
+`Email`|`Email`|`string`|邮箱
+`Status`|`Status`|`int`|激活状态:1=已激活 2=已禁用 4=未激活 已激活代表已激活企业微信或已关注微工作台(原企业号)5=成员退出
+`Avatar`|`Avatar`|`string`|头像url。注:如果要获取小图将url最后的”/0”改成”/100”即可。
+`Alias`|`Alias`|`string`|成员别名
+`Telephone`|`Telephone`|`string`|座机
+`Address`|`Address`|`string`|地址
+`ExtAttr`|`ExtAttr`|`string`|扩展属性
+`Type`|`Type`|`string`|扩展属性类型: 0-本文 1-网页
+`Text`|`Text`|`string`|文本属性类型,扩展属性类型为0时填写
+`Value`|`Value`|`string`|文本属性内容
+`Web`|`Web`|`string`|网页类型属性,扩展属性类型为1时填写
+`Title`|`Title`|`string`|网页的展示标题
+`Url`|`Url`|`string`|网页的url
diff --git a/external_contact.go b/external_contact.go
index 37252b7..d5a2f51 100644
--- a/external_contact.go
+++ b/external_contact.go
@@ -156,8 +156,8 @@ func (c *WorkwxApp) GetTransferExternalContactResult(externalUserID, handoverUse
return &externalContactTransferResult, nil
}
-// TransferGroupChatExternalContact 离职成员的群再分配
-func (c *WorkwxApp) TransferGroupChatExternalContact(chatIDList []string, newOwner string) ([]ExternalContactGroupChatTransferFailed, error) {
+// ExternalContactTransferGroupChat 离职成员的群再分配
+func (c *WorkwxApp) ExternalContactTransferGroupChat(chatIDList []string, newOwner string) ([]ExternalContactGroupChatTransferFailed, error) {
resp, err := c.execTransferGroupChatExternalContact(reqTransferGroupChatExternalContact{
ChatIDList: chatIDList,
NewOwner: newOwner,
@@ -167,3 +167,176 @@ func (c *WorkwxApp) TransferGroupChatExternalContact(chatIDList []string, newOwn
}
return resp.FailedChatList, nil
}
+
+// TransferCustomer 在职继承 分配在职成员的客户
+// 一次最多转移100个客户
+// 为保障客户服务体验,90个自然日内,在职成员的每位客户仅可被转接2次
+func (c *WorkwxApp) TransferCustomer(handoverUserId, takeoverUserId string, externalUserIds []string) (TransferCustomerResult, error) {
+ resp, err := c.execTransferCustomer(reqTransferCustomer{
+ HandoverUserid: handoverUserId,
+ TakeoverUserid: takeoverUserId,
+ ExternalUserid: externalUserIds,
+ })
+ result := resp.intoTransferCustomerResult()
+ return result, err
+}
+
+type TransferCustomerResult []struct {
+ // ExternalUserid 转接客户的外部联系人userid
+ ExternalUserid string `json:"external_userid"`
+ // Errcode 对此客户进行分配的结果, 具体可参考全局错误码(https://work.weixin.qq.com/api/doc/90000/90135/92125#10649), 0表示成功发起接替,待24小时后自动接替,并不代表最终接替成功
+ Errcode int `json:"errcode"`
+}
+
+// GetTransferCustomerResult 在职继承 查询客户接替状态
+func (c *WorkwxApp) GetTransferCustomerResult(handoverUserId, takeoverUserId, cursor string) (*CustomerTransferResult, error) {
+ resp, err := c.execGetTransferCustomerResult(reqGetTransferCustomerResult{
+ HandoverUserid: handoverUserId,
+ TakeoverUserid: takeoverUserId,
+ Cursor: cursor,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ result := resp.intoCustomerTransferResult()
+ return &result, nil
+}
+
+type CustomerTransferResult struct {
+ Customer []struct {
+ // ExternalUserID 转接客户的外部联系人userid
+ ExternalUserID string `json:"external_userid"`
+ // Status 接替状态, 1-接替完毕 2-等待接替 3-客户拒绝 4-接替成员客户达到上限 5-无接替记录
+ Status int `json:"status"`
+ // TakeoverTime 接替客户的时间,如果是等待接替状态,则为未来的自动接替时间
+ TakeoverTime int `json:"takeover_time"`
+ } `json:"customer"`
+ // NextCursor 下个分页的起始cursor
+ NextCursor string `json:"next_cursor"`
+}
+
+// ResignedTransferCustomer 离职继承 分配离职成员的客户
+// 一次最多转移100个客户
+func (c *WorkwxApp) ResignedTransferCustomer(handoverUserId, takeoverUserId string, externalUserIds []string) (TransferCustomerResult, error) {
+ resp, err := c.execTransferResignedCustomer(reqTransferCustomer{
+ HandoverUserid: handoverUserId,
+ TakeoverUserid: takeoverUserId,
+ ExternalUserid: externalUserIds,
+ })
+ result := resp.intoTransferCustomerResult()
+ return result, err
+}
+
+// GetTransferResignedCustomerResult 离职继承 查询客户接替状态
+func (c *WorkwxApp) GetTransferResignedCustomerResult(handoverUserId, takeoverUserId, cursor string) (*CustomerTransferResult, error) {
+ resp, err := c.execGetTransferResignedCustomerResult(reqGetTransferCustomerResult{
+ HandoverUserid: handoverUserId,
+ TakeoverUserid: takeoverUserId,
+ Cursor: cursor,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ result := resp.intoCustomerTransferResult()
+ return &result, nil
+}
+
+// ExternalContactListFollowUser 获取配置了客户联系功能的成员列表
+func (c *WorkwxApp) ExternalContactListFollowUser() (*ExternalContactFollowUserList, error) {
+ resp, err := c.execListFollowUserExternalContact(reqListFollowUserExternalContact{})
+ if err != nil {
+ return nil, err
+ }
+
+ return &resp.ExternalContactFollowUserList, nil
+}
+
+// ExternalContactAddContact 配置客户联系「联系我」方式
+func (c *WorkwxApp) ExternalContactAddContact(t int, scene int, style int, remark string, skipVerify bool, state string, user []string, party []int, isTemp bool, expiresIn int, chatExpiresIn int, unionID string, conclusions Conclusions) (*ExternalContactAddContact, error) {
+ resp, err := c.execAddContactExternalContact(
+ reqAddContactExternalContact{
+ ExternalContactWay{
+ Type: t,
+ Scene: scene,
+ Style: style,
+ Remark: remark,
+ SkipVerify: skipVerify,
+ State: state,
+ User: user,
+ Party: party,
+ IsTemp: isTemp,
+ ExpiresIn: expiresIn,
+ ChatExpiresIn: chatExpiresIn,
+ UnionID: unionID,
+ Conclusions: conclusions,
+ },
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return &resp.ExternalContactAddContact, nil
+}
+
+// ExternalContactGetContactWay 获取企业已配置的「联系我」方式
+func (c *WorkwxApp) ExternalContactGetContactWay(configID string) (*ExternalContactContactWay, error) {
+ resp, err := c.execGetContactWayExternalContact(reqGetContactWayExternalContact{ConfigID: configID})
+ if err != nil {
+ return nil, err
+ }
+
+ return &resp.ContactWay, nil
+}
+
+// ExternalContactListContactWayChat 获取企业已配置的「联系我」列表
+func (c *WorkwxApp) ExternalContactListContactWayChat(startTime int, endTime int, cursor string, limit int) (*ExternalContactListContactWayChat, error) {
+ resp, err := c.execListContactWayChatExternalContact(reqListContactWayExternalContact{
+ StartTime: startTime,
+ EndTime: endTime,
+ Cursor: cursor,
+ Limit: limit,
+ })
+ if err != nil {
+ return nil, err
+ }
+
+ return &resp.ExternalContactListContactWayChat, nil
+}
+
+// ExternalContactUpdateContactWay 更新企业已配置的「联系我」成员配置
+func (c *WorkwxApp) ExternalContactUpdateContactWay(configId string, remark string, skipVerify bool, style int, state string, user []string, party []int, expiresIn int, chatExpiresIn int, unionid string, conclusions Conclusions) error {
+ _, err := c.execUpdateContactWayExternalContact(reqUpdateContactWayExternalContact{
+ ConfigID: configId,
+ Remark: remark,
+ SkipVerify: skipVerify,
+ Style: style,
+ State: state,
+ User: user,
+ Party: party,
+ ExpiresIn: expiresIn,
+ ChatExpiresIn: chatExpiresIn,
+ UnionID: unionid,
+ Conclusions: conclusions,
+ })
+
+ return err
+}
+
+// ExternalContactDelContactWay 删除企业已配置的「联系我」方式
+func (c *WorkwxApp) ExternalContactDelContactWay(configID string) error {
+ _, err := c.execDelContactWayExternalContact(reqDelContactWayExternalContact{ConfigID: configID})
+
+ return err
+}
+
+// ExternalContactCloseTempChat 结束临时会话
+func (c *WorkwxApp) ExternalContactCloseTempChat(userID, externalUserID string) error {
+ _, err := c.execCloseTempChatExternalContact(reqCloseTempChatExternalContact{
+ UserID: userID,
+ ExternalUserID: externalUserID,
+ })
+
+ return err
+}
diff --git a/external_contact.md.go b/external_contact.md.go
index 6480fd5..c89a81d 100644
--- a/external_contact.md.go
+++ b/external_contact.md.go
@@ -271,3 +271,127 @@ type ExternalContactGroupChatTransferFailed struct {
// ErrMsg 没能成功继承的群,错误描述
ErrMsg string `json:"errmsg"`
}
+
+// ExternalContactFollowUserList 配置了客户联系功能的成员列表
+type ExternalContactFollowUserList struct {
+ // FollowUser 配置了客户联系功能的成员userid列表
+ FollowUser []string `json:"follow_user"`
+}
+
+// ExternalContactWay 配置客户联系「联系我」方式
+type ExternalContactWay struct {
+ // Type 联系方式类型,1-单人, 2-多人
+ Type int `json:"type"`
+ // Scene 场景,1-在小程序中联系,2-通过二维码联系
+ Scene int `json:"scene"`
+ // Style 在小程序中联系时使用的控件样式,详见附表
+ Style int `json:"style"`
+ // Remark 联系方式的备注信息,用于助记,不超过30个字符
+ Remark string `json:"remark"`
+ // SkipVerify 外部客户添加时是否无需验证,默认为true
+ SkipVerify bool `json:"skip_verify"`
+ // State 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情”时会返回该参数值,不超过30个字符 https://developer.work.weixin.qq.com/document/path/92114
+ State string `json:"state"`
+ // User 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个
+ User []string `json:"user"`
+ // Party 使用该联系方式的部门id列表,只在type为2时有效
+ Party []int `json:"party"`
+ // IsTemp 是否临时会话模式,true表示使用临时会话模式,默认为false
+ IsTemp bool `json:"is_temp"`
+ // ExpiresIn 临时会话二维码有效期,以秒为单位。该参数仅在is_temp为true时有效,默认7天,最多为14天
+ ExpiresIn int `json:"expires_in"`
+ // ChatExpiresIn 临时会话有效期,以秒为单位。该参数仅在is_temp为true时有效,默认为添加好友后24小时,最多为14天
+ ChatExpiresIn int `json:"chat_expires_in"`
+ // UnionID 可进行临时会话的客户UnionID,该参数仅在is_temp为true时有效,如不指定则不进行限制
+ UnionID string `json:"unionid"`
+ // Conclusions 结束语,会话结束时自动发送给客户,可参考“结束语定义”,仅在is_temp为true时有效,https://developer.work.weixin.qq.com/document/path/92572#%E7%BB%93%E6%9D%9F%E8%AF%AD%E5%AE%9A%E4%B9%89
+ Conclusions Conclusions `json:"conclusions"`
+}
+
+// Conclusions 结束语,会话结束时自动发送给客户
+type Conclusions struct {
+ // Text 文本消息
+ Text Text `json:"text"`
+ // Image 图片
+ Image Image `json:"image"`
+ // Link 链接
+ Link Link `json:"link"`
+ // MiniProgram 小程序
+ MiniProgram MiniProgram `json:"miniprogram"`
+}
+
+// Text 结束语,会话结束时自动发送给客户
+type Text struct {
+ // Content 消息文本内容,最长为4000字节
+ Content string `json:"content"`
+}
+
+// Image 结束语,会话结束时自动发送给客户
+type Image struct {
+ // MediaID 图片的media_id
+ MediaID string `json:"media_id"`
+ // PicURL 图片的url
+ PicURL string `json:"pic_url"`
+}
+
+// Link 结束语,会话结束时自动发送给客户
+type Link struct {
+ // Title 图文消息标题,最长为128字节
+ Title string `json:"title"`
+ // Picurl 图文消息封面的url
+ Picurl string `json:"picurl"`
+ // Desc 图文消息的描述,最长为512字节
+ Desc string `json:"desc"`
+ // URL 图文消息的链接
+ URL string `json:"url"`
+}
+
+// MiniProgram 结束语,会话结束时自动发送给客户
+type MiniProgram struct {
+ // Title 小程序消息标题,最长为64字节
+ Title string `json:"title"`
+ // PicMediaID 小程序消息封面的mediaid,封面图建议尺寸为520*416
+ PicMediaID string `json:"pic_media_id"`
+ // AppID 小程序appid,必须是关联到企业的小程序应用
+ AppID string `json:"appid"`
+ // Page 小程序page路径
+ Page string `json:"page"`
+}
+
+// reqListContactWayExternalContact 获取企业已配置的「联系我」列表请求参数
+type reqListContactWayExternalContact struct {
+ // StartTime 「联系我」创建起始时间戳, 默认为90天前
+ StartTime int `json:"start_time"`
+ // EndTime 「联系我」创建结束时间戳, 默认为当前时间
+ EndTime int `json:"end_time"`
+ // Cursor 分页查询使用的游标,为上次请求返回的 next_cursor
+ Cursor string `json:"cursor"`
+ // Limit 每次查询的分页大小,默认为100条,最多支持1000条
+ Limit int `json:"limit"`
+}
+
+// reqUpdateContactWayExternalContact 更新企业已配置的「联系我」方式请求参数
+type reqUpdateContactWayExternalContact struct {
+ // ConfigID 企业联系方式的配置id
+ ConfigID string `json:"config_id"`
+ // Remark 联系方式的备注信息,不超过30个字符,将覆盖之前的备注
+ Remark string `json:"remark"`
+ // SkipVerify 外部客户添加时是否无需验证
+ SkipVerify bool `json:"skip_verify"`
+ // Style 样式,只针对“在小程序中联系”的配置生效
+ Style int `json:"style"`
+ // State 企业自定义的state参数,用于区分不同的添加渠道,在调用“获取外部联系人详情”时会返回该参数值,不超过30个字符 https://developer.work.weixin.qq.com/document/path/92114
+ State string `json:"state"`
+ // User 使用该联系方式的用户userID列表,在type为1时为必填,且只能有一个
+ User []string `json:"user"`
+ // Party 使用该联系方式的部门id列表,只在type为2时有效
+ Party []int `json:"party"`
+ // ExpiresIn 临时会话二维码有效期,以秒为单位。该参数仅在is_temp为true时有效,默认7天,最多为14天
+ ExpiresIn int `json:"expires_in"`
+ // ChatExpiresIn 临时会话有效期,以秒为单位。该参数仅在is_temp为true时有效,默认为添加好友后24小时,最多为14天
+ ChatExpiresIn int `json:"chat_expires_in"`
+ // UnionID 可进行临时会话的客户UnionID,该参数仅在is_temp为true时有效,如不指定则不进行限制
+ UnionID string `json:"unionid"`
+ // Conclusions 结束语,会话结束时自动发送给客户,可参考“结束语定义”,仅在is_temp为true时有效,https://developer.work.weixin.qq.com/document/path/92572#%E7%BB%93%E6%9D%9F%E8%AF%AD%E5%AE%9A%E4%B9%89
+ Conclusions Conclusions `json:"conclusions"`
+}
diff --git a/models.go b/models.go
index 2340d96..566a2e0 100644
--- a/models.go
+++ b/models.go
@@ -992,3 +992,218 @@ type TaskCardBtn struct {
// IsBold 按钮字体是否加粗,默认false
IsBold bool `json:"is_bold"`
}
+
+type reqTransferCustomer struct {
+ // HandoverUserid 原跟进成员的userid
+ HandoverUserid string `json:"handover_userid"`
+ // TakeoverUserid 接替成员的userid
+ TakeoverUserid string `json:"takeover_userid"`
+ // ExternalUserid 客户的external_userid列表,每次最多分配100个客户
+ ExternalUserid []string `json:"external_userid"`
+ // TransferSuccessMsg 转移成功后发给客户的消息,最多200个字符,不填则使用默认文案
+ TransferSuccessMsg string `json:"transfer_success_msg"`
+}
+
+var _ bodyer = reqTransferCustomer{}
+
+func (x reqTransferCustomer) intoBody() ([]byte, error) {
+ result, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+type respTransferCustomer struct {
+ respCommon
+ Customer []struct {
+ // ExternalUserid 转接客户的外部联系人userid
+ ExternalUserid string `json:"external_userid"`
+ // Errcode 对此客户进行分配的结果, 具体可参考全局错误码(https://developer.work.weixin.qq.com/document/path/90475), 0表示成功发起接替,待24小时后自动接替,并不代表最终接替成功
+ Errcode int `json:"errcode"`
+ } `json:"customer"`
+}
+
+func (x respTransferCustomer) intoTransferCustomerResult() TransferCustomerResult {
+ return x.Customer
+}
+
+type reqGetTransferCustomerResult struct {
+ // HandoverUserid 原跟进成员的userid
+ HandoverUserid string `json:"handover_userid"`
+ // TakeoverUserid 接替成员的userid
+ TakeoverUserid string `json:"takeover_userid"`
+ // Cursor 分页查询的cursor,每个分页返回的数据不会超过1000条;不填或为空表示获取第一个分页
+ Cursor string `json:"cursor"`
+}
+
+var _ bodyer = reqGetTransferCustomerResult{}
+
+func (x reqGetTransferCustomerResult) intoBody() ([]byte, error) {
+ result, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+
+ return result, nil
+}
+
+type respGetTransferCustomerResult struct {
+ respCommon
+ Customer []struct {
+ // ExternalUserID 转接客户的外部联系人userid
+ ExternalUserID string `json:"external_userid"`
+ // Status 接替状态, 1-接替完毕 2-等待接替 3-客户拒绝 4-接替成员客户达到上限 5-无接替记录
+ Status int `json:"status"`
+ // TakeoverTime 接替客户的时间,如果是等待接替状态,则为未来的自动接替时间
+ TakeoverTime int `json:"takeover_time"`
+ } `json:"customer"`
+ // NextCursor 下个分页的起始cursor
+ NextCursor string `json:"next_cursor"`
+}
+
+func (x respGetTransferCustomerResult) intoCustomerTransferResult() CustomerTransferResult {
+ return CustomerTransferResult{
+ Customer: x.Customer,
+ NextCursor: x.NextCursor,
+ }
+}
+
+type reqListFollowUserExternalContact struct {
+}
+
+var _ urlValuer = reqListFollowUserExternalContact{}
+
+func (x reqListFollowUserExternalContact) intoURLValues() url.Values {
+ return url.Values{}
+}
+
+type respListFollowUserExternalContact struct {
+ respCommon
+ ExternalContactFollowUserList
+}
+
+type reqAddContactExternalContact struct {
+ ExternalContactWay
+}
+
+var _ bodyer = reqAddContactExternalContact{}
+
+func (x reqAddContactExternalContact) intoBody() ([]byte, error) {
+ body, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
+type respAddContactExternalContact struct {
+ respCommon
+ ExternalContactAddContact
+}
+
+type ExternalContactAddContact struct {
+ ConfigID string `json:"config_id"`
+ QRCode string `json:"qr_code"`
+}
+
+type reqGetContactWayExternalContact struct {
+ ConfigID string `json:"config_id"`
+}
+
+var _ bodyer = reqGetContactWayExternalContact{}
+
+func (x reqGetContactWayExternalContact) intoBody() ([]byte, error) {
+ body, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
+type respGetContactWayExternalContact struct {
+ respCommon
+ ContactWay ExternalContactContactWay `json:"contact_way"`
+}
+
+type ExternalContactContactWay struct {
+ ConfigID string `json:"config_id"`
+ QRCode string `json:"qr_code"`
+ ExternalContactWay
+}
+
+var _ bodyer = reqListContactWayExternalContact{}
+
+func (x reqListContactWayExternalContact) intoBody() ([]byte, error) {
+ body, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
+type respListContactWayChatExternalContact struct {
+ respCommon
+ ExternalContactListContactWayChat
+}
+
+type ExternalContactListContactWayChat struct {
+ NextCursor string `json:"next_cursor"`
+ ContactWay []contactWay `json:"contact_way"`
+}
+
+type contactWay struct {
+ ConfigID string `json:"config_id"`
+}
+
+var _ bodyer = reqUpdateContactWayExternalContact{}
+
+func (x reqUpdateContactWayExternalContact) intoBody() ([]byte, error) {
+ body, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
+type respUpdateContactWayExternalContact struct {
+ respCommon
+}
+
+type reqDelContactWayExternalContact struct {
+ ConfigID string `json:"config_id"`
+}
+
+var _ bodyer = reqDelContactWayExternalContact{}
+
+func (x reqDelContactWayExternalContact) intoBody() ([]byte, error) {
+ body, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
+type respDelContactWayExternalContact struct {
+ respCommon
+}
+
+type reqCloseTempChatExternalContact struct {
+ UserID string `json:"userid"`
+ ExternalUserID string `json:"external_userid"`
+}
+
+var _ bodyer = reqCloseTempChatExternalContact{}
+
+func (x reqCloseTempChatExternalContact) intoBody() ([]byte, error) {
+ body, err := json.Marshal(x)
+ if err != nil {
+ return nil, err
+ }
+ return body, nil
+}
+
+type respCloseTempChatExternalContact struct {
+ respCommon
+}
diff --git a/rx_msg.go b/rx_msg.go
index 148e242..83d0cda 100644
--- a/rx_msg.go
+++ b/rx_msg.go
@@ -169,3 +169,15 @@ func (m *RxMessage) EventSysApprovalChange() (EventSysApprovalChange, bool) {
y, ok := m.extras.(EventSysApprovalChange)
return y, ok
}
+
+// EventChangeTypeUpdateUser 如果消息为更新成员事件通知,则拿出相应消息参数,否则返回 nil, false
+func (m *RxMessage) EventChangeTypeUpdateUser() (*rxEventChangeTypeUpdateUser, bool) {
+ y, ok := m.extras.(*rxEventChangeTypeUpdateUser)
+ return y, ok
+}
+
+// EventChangeTypeCreateUser 如果消息为创建成员事件通知,则拿出相应消息参数,否则返回 nil, false
+func (m *RxMessage) EventChangeTypeCreateUser() (*rxEventChangeTypeCreateUser, bool) {
+ y, ok := m.extras.(*rxEventChangeTypeCreateUser)
+ return y, ok
+}
diff --git a/rx_msg.md.go b/rx_msg.md.go
index b86ec21..1edc423 100644
--- a/rx_msg.md.go
+++ b/rx_msg.md.go
@@ -58,6 +58,9 @@ const EventTypeChangeExternalChat EventType = "change_external_chat"
// EventTypeSysApprovalChange 审批申请状态变化回调通知
const EventTypeSysApprovalChange EventType = "sys_approval_change"
+// EventTypeChangeContact 通讯录回调通知
+const EventTypeChangeContact EventType = "change_contact"
+
// ChangeType 变更类型
type ChangeType string
@@ -79,6 +82,12 @@ const ChangeTypeDelFollowUser ChangeType = "del_follow_user"
// ChangeTypeTransferFail 客户接替失败事件
const ChangeTypeTransferFail ChangeType = "transfer_fail"
+// ChangeTypeCreateUser 新增成员事件
+const ChangeTypeCreateUser ChangeType = "create_user"
+
+// ChangeTypeUpdateUser 更新成员事件
+const ChangeTypeUpdateUser ChangeType = "update_user"
+
// rxTextMessageSpecifics 接收的文本消息,特有字段
type rxTextMessageSpecifics struct {
// Content 文本消息内容
@@ -212,3 +221,93 @@ type rxEventSysApprovalChange struct {
// ApprovalInfo 审批信息、
ApprovalInfo OAApprovalInfo `xml:"ApprovalInfo"`
}
+
+// rxEventChangeTypeCreateUser 接受的事件消息,新增成员事件
+type rxEventChangeTypeCreateUser struct {
+ // UserID 成员UserID
+ UserID string `xml:"UserID"`
+ // Name 成员名称
+ Name string `xml:"Name"`
+ // Department 成员部门列表,仅返回该应用有查看权限的部门id
+ Department string `xml:"Department"`
+ // IsLeaderInDept 表示所在部门是否为上级,0-否,1-是,顺序与Department字段的部门逐一对应
+ IsLeaderInDept string `xml:"IsLeaderInDept"`
+ // Mobile 手机号
+ Mobile string `xml:"Mobile"`
+ // Position 职位信息。长度为0~64个字节
+ Position string `xml:"Position"`
+ // Gender 性别,1表示男性,2表示女性
+ Gender int `xml:"Gender"`
+ // Email 邮箱
+ Email string `xml:"Email"`
+ // Status 激活状态:1=已激活 2=已禁用 4=未激活 已激活代表已激活企业微信或已关注微工作台(原企业号)5=成员退出
+ Status int `xml:"Status"`
+ // Avatar 头像url。注:如果要获取小图将url最后的”/0”改成”/100”即可。
+ Avatar string `xml:"Avatar"`
+ // Alias 成员别名
+ Alias string `xml:"Alias"`
+ // Telephone 座机
+ Telephone string `xml:"Telephone"`
+ // Address 地址
+ Address string `xml:"Address"`
+ // ExtAttr 扩展属性
+ ExtAttr string `xml:"ExtAttr"`
+ // Type 扩展属性类型: 0-本文 1-网页
+ Type string `xml:"Type"`
+ // Text 文本属性类型,扩展属性类型为0时填写
+ Text string `xml:"Text"`
+ // Value 文本属性内容
+ Value string `xml:"Value"`
+ // Web 网页类型属性,扩展属性类型为1时填写
+ Web string `xml:"Web"`
+ // Title 网页的展示标题
+ Title string `xml:"Title"`
+ // Url 网页的url
+ Url string `xml:"Url"`
+}
+
+// rxEventChangeTypeUpdateUser 接受的事件消息,更新成员事件
+type rxEventChangeTypeUpdateUser struct {
+ // UserID 成员UserID
+ UserID string `xml:"UserID"`
+ // NewUserID 新的UserID,变更时推送(userid由系统生成时可更改一次)
+ NewUserID string `xml:"NewUserID"`
+ // Name 成员名称
+ Name string `xml:"Name"`
+ // Department 成员部门列表,仅返回该应用有查看权限的部门id
+ Department string `xml:"Department"`
+ // IsLeaderInDept 表示所在部门是否为上级,0-否,1-是,顺序与Department字段的部门逐一对应
+ IsLeaderInDept string `xml:"IsLeaderInDept"`
+ // Mobile 手机号
+ Mobile string `xml:"Mobile"`
+ // Position 职位信息。长度为0~64个字节
+ Position string `xml:"Position"`
+ // Gender 性别,1表示男性,2表示女性
+ Gender int `xml:"Gender"`
+ // Email 邮箱
+ Email string `xml:"Email"`
+ // Status 激活状态:1=已激活 2=已禁用 4=未激活 已激活代表已激活企业微信或已关注微工作台(原企业号)5=成员退出
+ Status int `xml:"Status"`
+ // Avatar 头像url。注:如果要获取小图将url最后的”/0”改成”/100”即可。
+ Avatar string `xml:"Avatar"`
+ // Alias 成员别名
+ Alias string `xml:"Alias"`
+ // Telephone 座机
+ Telephone string `xml:"Telephone"`
+ // Address 地址
+ Address string `xml:"Address"`
+ // ExtAttr 扩展属性
+ ExtAttr string `xml:"ExtAttr"`
+ // Type 扩展属性类型: 0-本文 1-网页
+ Type string `xml:"Type"`
+ // Text 文本属性类型,扩展属性类型为0时填写
+ Text string `xml:"Text"`
+ // Value 文本属性内容
+ Value string `xml:"Value"`
+ // Web 网页类型属性,扩展属性类型为1时填写
+ Web string `xml:"Web"`
+ // Title 网页的展示标题
+ Title string `xml:"Title"`
+ // Url 网页的url
+ Url string `xml:"Url"`
+}
diff --git a/rx_msg_extras.go b/rx_msg_extras.go
index 0732374..d432a5a 100644
--- a/rx_msg_extras.go
+++ b/rx_msg_extras.go
@@ -120,7 +120,21 @@ func extractMessageExtras(common rxMessageCommon, body []byte) (messageKind, err
return nil, err
}
return &x, nil
+ case ChangeTypeCreateUser:
+ var x rxEventChangeTypeCreateUser
+ err := xml.Unmarshal(body, &x)
+ if err != nil {
+ return nil, err
+ }
+ return &x, nil
+ case ChangeTypeUpdateUser:
+ var x rxEventChangeTypeUpdateUser
+ err := xml.Unmarshal(body, &x)
+ if err != nil {
+ return nil, err
+ }
+ return &x, nil
default:
return nil, fmt.Errorf("unknown change type '%s'", common.ChangeType)
}
@@ -131,6 +145,25 @@ func extractMessageExtras(common rxMessageCommon, body []byte) (messageKind, err
return nil, err
}
return &x, nil
+ case EventTypeChangeContact:
+ switch common.ChangeType {
+ case ChangeTypeUpdateUser:
+ var x rxEventChangeTypeUpdateUser
+ err := xml.Unmarshal(body, &x)
+ if err != nil {
+ return nil, err
+ }
+ return &x, nil
+ case ChangeTypeCreateUser:
+ var x rxEventChangeTypeCreateUser
+ err := xml.Unmarshal(body, &x)
+ if err != nil {
+ return nil, err
+ }
+ return &x, nil
+ default:
+ return nil, fmt.Errorf("unknown change type '%s'", common.ChangeType)
+ }
default:
return nil, fmt.Errorf("unknown event '%s'", common.Event)
@@ -627,3 +660,19 @@ func (r rxEventSysApprovalChange) formatInto(w io.Writer) {
func (r rxEventSysApprovalChange) GetApprovalInfo() OAApprovalInfo {
return r.ApprovalInfo
}
+
+func (r rxEventChangeTypeUpdateUser) formatInto(w io.Writer) {
+ _, _ = fmt.Fprintf(
+ w,
+ "UpdateUser: %#v",
+ r,
+ )
+}
+
+func (r rxEventChangeTypeCreateUser) formatInto(w io.Writer) {
+ _, _ = fmt.Fprintf(
+ w,
+ "CreateUser: %#v",
+ r,
+ )
+}
diff --git a/rx_msg_test.go b/rx_msg_test.go
index 694e0f4..092681d 100644
--- a/rx_msg_test.go
+++ b/rx_msg_test.go
@@ -92,3 +92,38 @@ func TestRxMessageEventEditExternalContact(t *testing.T) {
})
})
}
+
+func TestRxMessageChangeContactUpdateUser(t *testing.T) {
+ c.Convey("解析接收的 XML 消息体", t, func() {
+ c.Convey("更新成员事件", func() {
+ body := []byte(" 1403610513update_user11380000000011- 0
- 1
")
+
+ msg, err := fromEnvelope(body)
+ c.So(err, c.ShouldBeNil)
+
+ {
+ y, ok := msg.EventChangeTypeUpdateUser()
+ c.So(ok, c.ShouldBeTrue)
+ c.So(y, c.ShouldNotBeNil)
+ }
+ })
+ })
+
+}
+
+func TestRxMessageChangeContactCreateUser(t *testing.T) {
+ c.Convey("解析接收的 XML 消息体", t, func() {
+ c.Convey("更新成员事件", func() {
+ body := []byte(" 1403610513create_user11380000000011- 0
- 1
")
+
+ msg, err := fromEnvelope(body)
+ c.So(err, c.ShouldBeNil)
+
+ {
+ y, ok := msg.EventChangeTypeCreateUser()
+ c.So(ok, c.ShouldBeTrue)
+ c.So(y, c.ShouldNotBeNil)
+ }
+ })
+ })
+}