diff --git a/work/externalcontact/groupchat.go b/work/externalcontact/groupchat.go new file mode 100644 index 0000000..0aa9ccd --- /dev/null +++ b/work/externalcontact/groupchat.go @@ -0,0 +1,143 @@ +package externalcontact + +import ( + "fmt" + + "github.com/silenceper/wechat/v2/util" +) + +// OpengIDToChatIDURL 客户群opengid转换URL +const OpengIDToChatIDURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/opengid_to_chatid" + +type ( + //GroupChatListRequest 获取客户群列表的请求参数 + GroupChatListRequest struct { + StatusFilter int `json:"status_filter"` // 非必填 客户群跟进状态过滤。0 - 所有列表(即不过滤) 1 - 离职待继承 2 - 离职继承中 3 - 离职继承完成 + OwnerFilter OwnerFilter `json:"owner_filter"` //非必填 群主过滤。如果不填,表示获取应用可见范围内全部群主的数据(但是不建议这么用,如果可见范围人数超过1000人,为了防止数据包过大,会报错 81017) + Cursor string `json:"cursor"` //非必填 用于分页查询的游标,字符串类型,由上一次调用返回,首次调用不填 + Limit int `json:"limit"` //必填 分页,预期请求的数据量,取值范围 1 ~ 1000 + } + + //GroupChatList 客户群列表 + GroupChatList struct { + ChatID string `json:"chat_id"` + Status int `json:"status"` + } + //GroupChatListResponse 获取客户群列表的返回值 + GroupChatListResponse struct { + util.CommonError + GroupChatList []GroupChatList `json:"group_chat_list"` + NextCursor string `json:"next_cursor"` //游标 + } +) + +// GetGroupChatList 获取客户群列表 +// @see https://developer.work.weixin.qq.com/document/path/92120 +func (r *Client) GetGroupChatList(req *GroupChatListRequest) (*GroupChatListResponse, error) { + accessToken, err := r.GetAccessToken() + if err != nil { + return nil, err + } + var response []byte + response, err = util.PostJSON(fmt.Sprintf("%s/list?access_token=%s", GroupChatURL, accessToken), req) + if err != nil { + return nil, err + } + result := &GroupChatListResponse{} + if err = util.DecodeWithError(response, result, "GetGroupChatList"); err != nil { + return nil, err + } + return result, nil +} + +type ( + //GroupChatDetailRequest 客户群详情 请求参数 + GroupChatDetailRequest struct { + ChatID string `json:"chat_id"` + NeedName int `json:"need_name"` + } + //Invitor 邀请者 + Invitor struct { + UserID string `json:"userid"` //邀请者的userid + } + //GroupChatMember 群成员 + GroupChatMember struct { + UserID string `json:"userid"` //群成员id + Type int `json:"type"` //成员类型。 1 - 企业成员 2 - 外部联系人 + JoinTime int `json:"join_time"` //入群时间 + JoinScene int `json:"join_scene"` //入群方式 1 - 由群成员邀请入群(直接邀请入群) 2 - 由群成员邀请入群(通过邀请链接入群) 3 - 通过扫描群二维码入群 + Invitor Invitor `json:"invitor,omitempty"` //邀请者。目前仅当是由本企业内部成员邀请入群时会返回该值 + GroupNickname string `json:"group_nickname"` //在群里的昵称 + Name string `json:"name"` //名字。仅当 need_name = 1 时返回 如果是微信用户,则返回其在微信中设置的名字 如果是企业微信联系人,则返回其设置对外展示的别名或实名 + UnionID string `json:"unionid,omitempty"` //外部联系人在微信开放平台的唯一身份标识(微信unionid),通过此字段企业可将外部联系人与公众号/小程序用户关联起来。仅当群成员类型是微信用户(包括企业成员未添加好友),且企业绑定了微信开发者ID有此字段(查看绑定方法)。第三方不可获取,上游企业不可获取下游企业客户的unionid字段 + } + //GroupChatAdmin 群管理员 + GroupChatAdmin struct { + UserID string `json:"userid"` //群管理员userid + } + //GroupChat 客户群详情 + GroupChat struct { + ChatID string `json:"chat_id"` //客户群ID + Name string `json:"name"` //群名 + Owner string `json:"owner"` //群主ID + CreateTime int `json:"create_time"` //群的创建时间 + Notice string `json:"notice"` //群公告 + MemberList []GroupChatMember `json:"member_list"` //群成员列表 + AdminList []GroupChatAdmin `json:"admin_list"` //群管理员列表 + } + //GroupChatDetailResponse 客户群详情 返回值 + GroupChatDetailResponse struct { + util.CommonError + GroupChat GroupChat `json:"group_chat"` //客户群详情 + } +) + +// GetGroupChatDetail 获取客户群详情 +// @see https://developer.work.weixin.qq.com/document/path/92122 +func (r *Client) GetGroupChatDetail(req *GroupChatDetailRequest) (*GroupChatDetailResponse, error) { + accessToken, err := r.GetAccessToken() + if err != nil { + return nil, err + } + var response []byte + response, err = util.PostJSON(fmt.Sprintf("%s/get?access_token=%s", GroupChatURL, accessToken), req) + if err != nil { + return nil, err + } + result := &GroupChatDetailResponse{} + if err = util.DecodeWithError(response, result, "GetGroupChatDetail"); err != nil { + return nil, err + } + return result, nil +} + +type ( + //OpengIDToChatIDRequest 客户群opengid转换 请求参数 + OpengIDToChatIDRequest struct { + OpengID string `json:"opengid"` + } + //OpengIDToChatIDResponse 客户群opengid转换 返回值 + OpengIDToChatIDResponse struct { + util.CommonError + ChatID string `json:"chat_id"` //客户群ID + } +) + +// OpengIDToChatID 客户群opengid转换 +// @see https://developer.work.weixin.qq.com/document/path/94828 +func (r *Client) OpengIDToChatID(req *OpengIDToChatIDRequest) (*OpengIDToChatIDResponse, error) { + accessToken, err := r.GetAccessToken() + if err != nil { + return nil, err + } + var response []byte + response, err = util.PostJSON(fmt.Sprintf("%s?access_token=%s", OpengIDToChatIDURL, accessToken), req) + if err != nil { + return nil, err + } + result := &OpengIDToChatIDResponse{} + if err = util.DecodeWithError(response, result, "GetGroupChatDetail"); err != nil { + return nil, err + } + return result, nil +} diff --git a/work/externalcontact/join_way.go b/work/externalcontact/join_way.go new file mode 100644 index 0000000..2396103 --- /dev/null +++ b/work/externalcontact/join_way.go @@ -0,0 +1,146 @@ +package externalcontact + +import ( + "fmt" + + "github.com/silenceper/wechat/v2/util" +) + +// GroupChatURL 客户群 +const GroupChatURL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat" + +type ( + // AddJoinWayRequest 添加群配置请求参数 + AddJoinWayRequest struct { + Scene int `json:"scene"` // 必填 1 - 群的小程序插件,2 - 群的二维码插件 + Remark string `json:"remark"` //非必填 联系方式的备注信息,用于助记,超过30个字符将被截断 + AutoCreateRoom int `json:"auto_create_room"` //非必填 当群满了后,是否自动新建群。0-否;1-是。 默认为1 + RoomBaseName string `json:"room_base_name"` //非必填 自动建群的群名前缀,当auto_create_room为1时有效。最长40个utf8字符 + RoomBaseID int `json:"room_base_id"` //非必填 自动建群的群起始序号,当auto_create_room为1时有效 + ChatIDList []string `json:"chat_id_list"` //必填 使用该配置的客户群ID列表,支持5个。见客户群ID获取方法 + State string `json:"state"` //非必填 企业自定义的state参数,用于区分不同的入群渠道。不超过30个UTF-8字符 + } + + // AddJoinWayResponse 添加群配置返回值 + AddJoinWayResponse struct { + util.CommonError + ConfigID string `json:"config_id"` + } +) + +// AddJoinWay 加入群聊 +// @see https://developer.work.weixin.qq.com/document/path/92229 +func (r *Client) AddJoinWay(req *AddJoinWayRequest) (*AddJoinWayResponse, error) { + var ( + accessToken string + err error + response []byte + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return nil, err + } + response, err = util.PostJSON(fmt.Sprintf("%s/add_join_way?access_token=%s", GroupChatURL, accessToken), req) + if err != nil { + return nil, err + } + result := &AddJoinWayResponse{} + if err = util.DecodeWithError(response, result, "AddJoinWay"); err != nil { + return nil, err + } + return result, nil +} + +type ( + //JoinWayConfigRequest 获取或删除群配置的请求参数 + JoinWayConfigRequest struct { + ConfigID string `json:"config_id"` + } + + //JoinWay 群配置 + JoinWay struct { + ConfigID string `json:"config_id"` + Scene int `json:"scene"` + Remark string `json:"remark"` + AutoCreateRoom int `json:"auto_create_room"` + RoomBaseName string `json:"room_base_name"` + RoomBaseID int `json:"room_base_id"` + ChatIDList []string `json:"chat_id_list"` + QrCode string `json:"qr_code"` + State string `json:"state"` + } + //GetJoinWayResponse 获取群配置的返回值 + GetJoinWayResponse struct { + util.CommonError + JoinWay JoinWay `json:"join_way"` + } +) + +// GetJoinWay 获取客户群进群方式配置 +// @see https://developer.work.weixin.qq.com/document/path/92229 +func (r *Client) GetJoinWay(req *JoinWayConfigRequest) (*GetJoinWayResponse, error) { + var ( + accessToken string + err error + response []byte + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return nil, err + } + response, err = util.PostJSON(fmt.Sprintf("%s/get_join_way?access_token=%s", GroupChatURL, accessToken), req) + if err != nil { + return nil, err + } + result := &GetJoinWayResponse{} + if err = util.DecodeWithError(response, result, "GetJoinWay"); err != nil { + return nil, err + } + return result, nil +} + +// UpdateJoinWayRequest 更新群配置的请求参数 +type UpdateJoinWayRequest struct { + ConfigID string `json:"config_id"` + Scene int `json:"scene"` // 必填 1 - 群的小程序插件,2 - 群的二维码插件 + Remark string `json:"remark"` //非必填 联系方式的备注信息,用于助记,超过30个字符将被截断 + AutoCreateRoom int `json:"auto_create_room"` //非必填 当群满了后,是否自动新建群。0-否;1-是。 默认为1 + RoomBaseName string `json:"room_base_name"` //非必填 自动建群的群名前缀,当auto_create_room为1时有效。最长40个utf8字符 + RoomBaseID int `json:"room_base_id"` //非必填 自动建群的群起始序号,当auto_create_room为1时有效 + ChatIDList []string `json:"chat_id_list"` //必填 使用该配置的客户群ID列表,支持5个。见客户群ID获取方法 + State string `json:"state"` //非必填 企业自定义的state参数,用于区分不同的入群渠道。不超过30个UTF-8字符 +} + +// UpdateJoinWay 更新客户群进群方式配置 +// @see https://developer.work.weixin.qq.com/document/path/92229 +func (r *Client) UpdateJoinWay(req *UpdateJoinWayRequest) error { + var ( + accessToken string + err error + response []byte + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return err + } + response, err = util.PostJSON(fmt.Sprintf("%s/update_join_way?access_token=%s", GroupChatURL, accessToken), req) + if err != nil { + return err + } + return util.DecodeWithCommonError(response, "UpdateJoinWay") +} + +// DelJoinWay 删除客户群进群方式配置 +// @see https://developer.work.weixin.qq.com/document/path/92229 +func (r *Client) DelJoinWay(req *JoinWayConfigRequest) error { + var ( + accessToken string + err error + response []byte + ) + if accessToken, err = r.GetAccessToken(); err != nil { + return err + } + response, err = util.PostJSON(fmt.Sprintf("%s/del_join_way?access_token=%s", GroupChatURL, accessToken), req) + if err != nil { + return err + } + return util.DecodeWithCommonError(response, "DelJoinWay") +}