Quellcode durchsuchen

添加企业微信外部联系部分的 sdk (#562)

bear vor 4 Jahren
Ursprung
Commit
182339c00f

+ 3 - 0
work/externalcontact/README.md

@@ -0,0 +1,3 @@
+### 企业微信 客户联系部分
+
+相关文档正在梳理中...

+ 17 - 0
work/externalcontact/client.go

@@ -0,0 +1,17 @@
+package externalcontact
+
+import (
+	"github.com/silenceper/wechat/v2/work/context"
+)
+
+// Client 外部联系接口实例
+type Client struct {
+	*context.Context
+}
+
+// NewClient 初始化实例
+func NewClient(ctx *context.Context) *Client {
+	return &Client{
+		ctx,
+	}
+}

+ 177 - 0
work/externalcontact/external_user.go

@@ -0,0 +1,177 @@
+package externalcontact
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/silenceper/wechat/v2/util"
+)
+
+const (
+	// FetchExternalContactUserListURL 获取客户列表
+	FetchExternalContactUserListURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/list"
+	// FetchExternalContactUserDetailURL 获取客户详情
+	FetchExternalContactUserDetailURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get"
+	// FetchBatchExternalContactUserDetailURL 批量获取客户详情
+	FetchBatchExternalContactUserDetailURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user"
+	// UpdateUserRemarkURL 更新客户备注信息
+	UpdateUserRemarkURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/remark"
+)
+
+// ExternalUserListResponse 外部联系人列表响应
+type ExternalUserListResponse struct {
+	util.CommonError
+	ExternalUserID []string `json:"external_userid"`
+}
+
+// GetExternalUserList 获取客户列表
+// @see https://developer.work.weixin.qq.com/document/path/92113
+func (r *Client) GetExternalUserList(userID string) ([]string, error) {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return nil, err
+	}
+	var response []byte
+	response, err = util.HTTPGet(fmt.Sprintf("%s?access_token=%v&userid=%v", FetchExternalContactUserListURL, accessToken, userID))
+	if err != nil {
+		return nil, err
+	}
+	var result ExternalUserListResponse
+	err = util.DecodeWithError(response, &result, "GetExternalUserList")
+	if err != nil {
+		return nil, err
+	}
+	return result.ExternalUserID, nil
+}
+
+// ExternalUserDetailResponse 外部联系人详情响应
+type ExternalUserDetailResponse struct {
+	util.CommonError
+	ExternalUser
+}
+
+// ExternalUser 外部联系人
+type ExternalUser struct {
+	ExternalUserID  string       `json:"external_userid"`
+	Name            string       `json:"name"`
+	Avatar          string       `json:"avatar"`
+	Type            int64        `json:"type"`
+	Gender          int64        `json:"gender"`
+	UnionID         string       `json:"unionid"`
+	Position        string       `json:"position"`
+	CorpName        string       `json:"corp_name"`
+	CorpFullName    string       `json:"corp_full_name"`
+	ExternalProfile string       `json:"external_profile"`
+	FollowUser      []FollowUser `json:"follow_user"`
+	NextCursor      string       `json:"next_cursor"`
+}
+
+// FollowUser 跟进用户(指企业内部用户)
+type FollowUser struct {
+	UserID         string        `json:"userid"`
+	Remark         string        `json:"remark"`
+	Description    string        `json:"description"`
+	CreateTime     string        `json:"create_time"`
+	Tags           []Tag         `json:"tags"`
+	RemarkCorpName string        `json:"remark_corp_name"`
+	RemarkMobiles  []string      `json:"remark_mobiles"`
+	OperUserID     string        `json:"oper_userid"`
+	AddWay         int64         `json:"add_way"`
+	WeChatChannels WechatChannel `json:"wechat_channels"`
+	State          string        `json:"state"`
+}
+
+// Tag 已绑定在外部联系人的标签
+type Tag struct {
+	GroupName string `json:"group_name"`
+	TagName   string `json:"tag_name"`
+	Type      int64  `json:"type"`
+	TagID     string `json:"tag_id"`
+}
+
+// WechatChannel 视频号添加的场景
+type WechatChannel struct {
+	NickName string `json:"nickname"`
+	Source   string `json:"source"`
+}
+
+// GetExternalUserDetail 获取外部联系人详情
+func (r *Client) GetExternalUserDetail(externalUserID string, nextCursor ...string) (*ExternalUser, error) {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return nil, err
+	}
+	var response []byte
+	response, err = util.HTTPGet(fmt.Sprintf("%s?access_token=%v&external_userid=%v&cursor=%v", FetchExternalContactUserDetailURL, accessToken, externalUserID, nextCursor))
+	if err != nil {
+		return nil, err
+	}
+	var result ExternalUserDetailResponse
+	err = util.DecodeWithError(response, &result, "get_external_user_detail")
+	if err != nil {
+		return nil, err
+	}
+	return &result.ExternalUser, nil
+}
+
+// BatchGetExternalUserDetailsRequest 批量获取外部联系人详情请求
+type BatchGetExternalUserDetailsRequest struct {
+	UserIDList []string `json:"userid_list"`
+	Cursor     string   `json:"cursor"`
+}
+
+// ExternalUserDetailListResponse 批量获取外部联系人详情响应
+type ExternalUserDetailListResponse struct {
+	util.CommonError
+	ExternalContactList []ExternalUser `json:"external_contact_list"`
+}
+
+// BatchGetExternalUserDetails 批量获取外部联系人详情
+func (r *Client) BatchGetExternalUserDetails(request BatchGetExternalUserDetailsRequest) ([]ExternalUser, error) {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return nil, err
+	}
+	var response []byte
+	jsonData, _ := json.Marshal(request)
+	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", FetchBatchExternalContactUserDetailURL, accessToken), string(jsonData))
+	if err != nil {
+		return nil, err
+	}
+	var result ExternalUserDetailListResponse
+	err = util.DecodeWithError(response, &result, "BatchGetExternalUserDetails")
+	if err != nil {
+		return nil, err
+	}
+	return result.ExternalContactList, nil
+}
+
+// UpdateUserRemarkRequest 修改客户备注信息请求体
+type UpdateUserRemarkRequest struct {
+	UserID           string   `json:"userid"`
+	ExternalUserID   string   `json:"external_userid"`
+	Remark           string   `json:"remark"`
+	Description      string   `json:"description"`
+	RemarkCompany    string   `json:"remark_company"`
+	RemarkMobiles    []string `json:"remark_mobiles"`
+	RemarkPicMediaid string   `json:"remark_pic_mediaid"`
+}
+
+// UpdateUserRemark 修改客户备注信息
+func (r *Client) UpdateUserRemark(request UpdateUserRemarkRequest) error {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return err
+	}
+	var response []byte
+	jsonData, _ := json.Marshal(request)
+	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", UpdateUserRemarkURL, accessToken), string(jsonData))
+	if err != nil {
+		return err
+	}
+	return util.DecodeWithCommonError(response, "UpdateUserRemark")
+}

+ 39 - 0
work/externalcontact/follow_user.go

@@ -0,0 +1,39 @@
+package externalcontact
+
+import (
+	"fmt"
+
+	"github.com/silenceper/wechat/v2/util"
+)
+
+const (
+	// FetchFollowUserListURL 获取配置了客户联系功能的成员列表
+	FetchFollowUserListURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_follow_user_list"
+)
+
+// followerUserResponse 客户联系功能的成员列表响应
+type followerUserResponse struct {
+	util.CommonError
+	FollowUser []string `json:"follow_user"`
+}
+
+//GetFollowUserList 获取配置了客户联系功能的成员列表
+//@see https://developer.work.weixin.qq.com/document/path/92571
+func (r *Client) GetFollowUserList() ([]string, error) {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return nil, err
+	}
+	var response []byte
+	response, err = util.HTTPGet(fmt.Sprintf("%s?access_token=%s", FetchFollowUserListURL, accessToken))
+	if err != nil {
+		return nil, err
+	}
+	var result followerUserResponse
+	err = util.DecodeWithError(response, &result, "GetFollowUserList")
+	if err != nil {
+		return nil, err
+	}
+	return result.FollowUser, nil
+}

+ 191 - 0
work/externalcontact/tag.go

@@ -0,0 +1,191 @@
+package externalcontact
+
+import (
+	"encoding/json"
+	"fmt"
+
+	"github.com/silenceper/wechat/v2/util"
+)
+
+const (
+	// GetCropTagURL 获取标签列表
+	GetCropTagURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_corp_tag_list"
+	// AddCropTagURL 添加标签
+	AddCropTagURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/add_corp_tag"
+	// EditCropTagURL 修改标签
+	EditCropTagURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/edit_corp_tag"
+	// DelCropTagURL 删除标签
+	DelCropTagURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/del_corp_tag"
+	// MarkCropTagURL 为客户打上、删除标签
+	MarkCropTagURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/mark_tag"
+)
+
+// GetCropTagRequest 获取企业标签请求
+type GetCropTagRequest struct {
+	TagID   []string `json:"tag_id"`
+	GroupID []string `json:"group_id"`
+}
+
+// GetCropTagListResponse 获取企业标签列表响应
+type GetCropTagListResponse struct {
+	util.CommonError
+	TagGroup []TagGroup `json:"tag_group"`
+}
+
+// TagGroup 企业标签组
+type TagGroup struct {
+	GroupID    string            `json:"group_id"`
+	GroupName  string            `json:"group_name"`
+	CreateTime string            `json:"create_time"`
+	GroupOrder int               `json:"group_order"`
+	Deleted    bool              `json:"deleted"`
+	Tag        []TagGroupTagItem `json:"tag"`
+}
+
+// TagGroupTagItem 企业标签内的子项
+type TagGroupTagItem struct {
+	ID         string `json:"id"`
+	Name       string `json:"name"`
+	CreateTime int    `json:"create_time"`
+	Order      int    `json:"order"`
+	Deleted    bool   `json:"deleted"`
+}
+
+// GetCropTagList 获取企业标签库
+// @see https://developer.work.weixin.qq.com/document/path/92117
+func (r *Client) GetCropTagList(req GetCropTagRequest) ([]TagGroup, error) {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return nil, err
+	}
+	var response []byte
+	jsonData, _ := json.Marshal(req)
+	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", GetCropTagURL, accessToken), string(jsonData))
+	if err != nil {
+		return nil, err
+	}
+	var result GetCropTagListResponse
+	err = util.DecodeWithError(response, &result, "GetCropTagList")
+	if err != nil {
+		return nil, err
+	}
+	return result.TagGroup, nil
+}
+
+// AddCropTagRequest 添加企业标签请求
+type AddCropTagRequest struct {
+	GroupID   string           `json:"group_id"`
+	GroupName string           `json:"group_name"`
+	Order     int              `json:"order"`
+	Tag       []AddCropTagItem `json:"tag"`
+	AgentID   int              `json:"agentid"`
+}
+
+// AddCropTagItem 添加企业标签子项
+type AddCropTagItem struct {
+	Name  string `json:"name"`
+	Order int    `json:"order"`
+}
+
+// AddCropTagResponse 添加企业标签响应
+type AddCropTagResponse struct {
+	util.CommonError
+	TagGroup TagGroup `json:"tag_group"`
+}
+
+// AddCropTag 添加企业客户标签
+// @see https://developer.work.weixin.qq.com/document/path/92117
+func (r *Client) AddCropTag(req AddCropTagRequest) (*TagGroup, error) {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return nil, err
+	}
+	var response []byte
+	jsonData, _ := json.Marshal(req)
+	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", AddCropTagURL, accessToken), string(jsonData))
+	if err != nil {
+		return nil, err
+	}
+	var result AddCropTagResponse
+	err = util.DecodeWithError(response, &result, "AddCropTag")
+	if err != nil {
+		return nil, err
+	}
+	return &result.TagGroup, nil
+}
+
+// EditCropTagRequest 编辑客户企业标签请求
+type EditCropTagRequest struct {
+	ID      string `json:"id"`
+	Name    string `json:"name"`
+	Order   int    `json:"order"`
+	AgentID string `json:"agent_id"`
+}
+
+// EditCropTag 修改企业客户标签
+// @see https://developer.work.weixin.qq.com/document/path/92117
+func (r *Client) EditCropTag(req EditCropTagRequest) error {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return err
+	}
+	var response []byte
+	jsonData, _ := json.Marshal(req)
+	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", EditCropTagURL, accessToken), string(jsonData))
+	if err != nil {
+		return err
+	}
+	return util.DecodeWithCommonError(response, "EditCropTag")
+}
+
+// DeleteCropTagRequest 删除企业标签请求
+type DeleteCropTagRequest struct {
+	TagID   []string `json:"tag_id"`
+	GroupID []string `json:"group_id"`
+	AgentID string   `json:"agent_id"`
+}
+
+// DeleteCropTag 删除企业客户标签
+// @see https://developer.work.weixin.qq.com/document/path/92117
+func (r *Client) DeleteCropTag(req DeleteCropTagRequest) error {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return err
+	}
+	var response []byte
+	jsonData, _ := json.Marshal(req)
+	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", DelCropTagURL, accessToken), string(jsonData))
+	if err != nil {
+		return err
+	}
+	return util.DecodeWithCommonError(response, "DeleteCropTag")
+}
+
+// MarkTagRequest 给客户打标签请求
+type MarkTagRequest struct {
+	UserID         string   `json:"user_id"`
+	ExternalUserID string   `json:"external_userid"`
+	AddTag         []string `json:"add_tag"`
+	RemoveTag      []string `json:"remove_tag"`
+}
+
+// MarkTag 为客户打上标签
+// @see https://developer.work.weixin.qq.com/document/path/92118
+func (r *Client) MarkTag(request MarkTagRequest) error {
+	var accessToken string
+	accessToken, err := r.GetAccessToken()
+	if err != nil {
+		return err
+	}
+	var response []byte
+	jsonData, _ := json.Marshal(request)
+	response, err = util.HTTPPost(fmt.Sprintf("%s?access_token=%v", MarkCropTagURL, accessToken), string(jsonData))
+	if err != nil {
+		return err
+	}
+	return util.DecodeWithCommonError(response, "MarkTag")
+}

+ 6 - 0
work/work.go

@@ -4,6 +4,7 @@ import (
 	"github.com/silenceper/wechat/v2/credential"
 	"github.com/silenceper/wechat/v2/work/config"
 	"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/msgaudit"
 	"github.com/silenceper/wechat/v2/work/oauth"
@@ -43,3 +44,8 @@ func (wk *Work) GetMsgAudit() (*msgaudit.Client, error) {
 func (wk *Work) GetKF() (*kf.Client, error) {
 	return kf.NewClient(wk.ctx.Config)
 }
+
+// GetExternalContact get external_contact
+func (wk *Work) GetExternalContact() *externalcontact.Client {
+	return externalcontact.NewClient(wk.ctx)
+}