This commit is contained in:
邹宗楠
2022-05-25 16:44:01 +08:00
parent 8e8d03c5fa
commit 8b1f8c79d6
5 changed files with 325 additions and 26 deletions

View File

@@ -1,18 +1,101 @@
package enterprise_wechat
type CreateGroup struct {
AccessToken string `json:"access_token"` // 调用接口凭证 [必填]
Scene int `json:"scene"` // 1 - 群的小程序插件, 2 - 群的二维码插件 [必填]
ChatIDList []string `json:"chat_id_list"` // 使用该配置的客户群ID列表支持5个 [必填]
import (
"errors"
"git.rosy.net.cn/baseapi/utils"
"net/http"
)
Remark string `json:"remark"` // 联系方式的备注信息用于助记超过30个字符将被截断
AutoCreateRoom int `json:"auto_create_room"` // 当群满了后是否自动新建群。0-否1-是。 默认为1
RoomBaseName string `json:"room_base_name"` // 自动建群的群名前缀
RoomBaseID int `json:"room_base_id"` // 自动建群的群起始序号
State string `json:"state"` // 企业自定义的state参数用于区分不同的入群渠道。
// 创建成员,将门店老板创建为京西员工
func (a *API) CreateBoss2JxStaff(param *CreateBoos2JXStaffReq) error {
a.CheckAccessTokenExpiresIn()
result, err := a.AccessAPI(WeChatBaseApi, CreateBoosToJxStaff, http.MethodPost, utils.Struct2FlatMap(param))
if err != nil {
return err
}
errResult := &Err{}
if err := utils.Map2StructByJson(result, errResult, false); err != nil {
return err
}
if errResult.ErrCode != 0 {
return errors.New(errResult.ErrMsg)
}
return nil
}
// 创建客户入群方式
func (a *API) CreateUserGroup() {
// 创建会话群聊
// 只允许企业自建应用调用,且应用的可见范围必须是根部门;
// 群成员人数不可超过管理端配置的“群成员人数上限”且最大不可超过2000人
// 每企业创建群数不可超过1000/天;
func (a *API) CreateAppChat(param *CreateAppChatParamReq) error {
a.CheckAccessTokenExpiresIn()
data, err := a.AccessAPI(WeChatBaseApi, CreateAppChat, http.MethodPost, utils.Struct2FlatMap(param))
if err != nil {
return err
}
errResult := &Err{}
if err := utils.Map2StructByJson(data, errResult, false); err != nil {
return err
}
if errResult.ErrCode != 0 {
return errors.New(errResult.ErrMsg)
}
return nil
}
// 获取所有的部门列表
func (a *API) GetAllDepartmentList() ([]*Department, error) {
a.CheckAccessTokenExpiresIn()
data, err := a.AccessAPI(WeChatBaseApi, GetAllDepartmentListById, http.MethodGet, map[string]interface{}{"access_token": a.accessToken})
if err != nil {
return nil, err
}
result := &GetAllDepartmentListRes{}
if err := utils.Map2StructByJson(data, result, false); err != nil {
return nil, err
}
if result.ErrCode != 0 {
return nil, errors.New(result.ErrMsg)
}
return result.Department, nil
}
// 获取企业部门用户详细情况
func (a *API) GetEnterpriseStaffInfo(department int) ([]*UserList, error) {
a.CheckAccessTokenExpiresIn()
departmentUserDetail, err := a.AccessAPI(WeChatBaseApi, GetDepartmentUserDetail, http.MethodGet, map[string]interface{}{"department_id": department, "fetch_child": 0})
if err != nil {
return nil, err
}
result := &GetEnterpriseStaffInfoRes{}
if err := utils.Map2StructByJson(departmentUserDetail, result, false); err != nil {
return nil, err
}
if result.ErrCode != 0 {
return nil, errors.New(result.ErrMsg)
}
return result.UserList, nil
}
// 通过手机号获取用户消息
func (a *API) GetUserIdByMobile(mobile string) (string, error) {
a.CheckAccessTokenExpiresIn()
data, err := a.AccessAPI(WeChatBaseApi, GetUserByMobileUrl, http.MethodPost, map[string]interface{}{"mobile": mobile})
if err != nil {
return "", err
}
result := &GetUserByMobileRes{}
if err := utils.Map2StructByJson(data, result, false); err != nil {
return "", err
}
if result.ErrCode != 0 {
return "", errors.New(result.ErrMsg)
}
return result.UserId, nil
}

View File

@@ -0,0 +1,66 @@
package enterprise_wechat
type CreateBoos2JXStaffReq struct {
Userid string `json:"userid"` // y 用户id 成员UserID。对应管理端的帐号企业内必须唯一。长度为1~64个字节。只能由数字、字母和“_-@.”四种字符组成,且第一个字符必须是数字或字母。系统进行唯一性检查时会忽略大小写
Name string `json:"name"` // y 成员名称。长度为1~64个utf8字符
Alias string `json:"alias"` // n 成员别名。长度1~64个utf8字符
Mobile string `json:"mobile"` // y 手机号码。企业内必须唯一mobile/email二者不能同时为空
Department []int `json:"department"` // y 成员所属部门id列表不超过100个
Order []int `json:"order"` // n 部门内的排序值默认为0
Position string `json:"position"` // n 职务信息。
Gender string `json:"gender"` // n 性别。1表示男性2表示女性性别。1表示男性2表示女性
Email string `json:"email"` // y 邮箱
IsLeaderInDept []int `json:"is_leader_in_dept"` // n 个数必须和参数department的个数一致表示在所在的部门内是否为部门负责人。1表示为部门负责人0表示非部门负责人
Enable int `json:"enable"` // n 直属上级UserID
AvatarMediaid string `json:"avatar_mediaid"` // n 成员头像的mediaid
Telephone string `json:"telephone"` // n 座机
Address string `json:"address"` // n 地址
Extattr Extattr `json:"extattr"` // n 自定义字段。自定义字段需要先在WEB管理端添加见扩展属性添加方法否则忽略未知属性的赋值。
MainDepartment int `json:"main_department"` // n 主部门
ToInvite bool `json:"to_invite"` // n 是否邀请该成员使用企业微信将通过微信服务通知或短信或邮件下发邀请每天自动下发一次最多持续3个工作日默认值为true
ExternalPosition string `json:"external_position"` // n 对外职务如果设置了该值则以此作为对外展示的职务否则以position来展示。长度12个汉字内
ExternalProfile ExternalProfile `json:"external_profile"` // n 成员对外属性,字段详情见对外属性
}
type Extattr struct {
Attrs []Attrs `json:"attrs"`
}
type ExternalAttr struct {
Type int `json:"type"`
Name string `json:"name"`
Text Text `json:"text,omitempty"`
Web Web `json:"web,omitempty"`
Miniprogram Miniprogram `json:"miniprogram,omitempty"`
}
type ExternalProfile struct {
ExternalCorpName string `json:"external_corp_name"`
ExternalAttr []ExternalAttr `json:"external_attr"`
}
type Attrs struct {
Type int `json:"type"`
Name string `json:"name"`
Text Text `json:"text,omitempty"`
Web Web `json:"web,omitempty"`
}
type Text struct {
Value string `json:"value"`
}
type Web struct {
URL string `json:"url"`
Title string `json:"title"`
}
type Miniprogram struct {
Appid string `json:"appid"`
Pagepath string `json:"pagepath"`
Title string `json:"title"`
}
/*获取部门列表*/
type GetAllDepartmentList struct {
}

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"git.rosy.net.cn/baseapi"
"go.uber.org/zap"
"strconv"
"testing"
)
@@ -16,7 +17,9 @@ func init() {
logger, _ := zap.NewDevelopment()
sugarLogger = logger.Sugar()
baseapi.Init(sugarLogger)
api = New("ww9a156bfa070e1857", "JQsEmSTltHhNgdPIT320YJFphiYmRs-YZa-rCBwplss")
//api = New("ww9a156bfa070e1857", "JQsEmSTltHhNgdPIT320YJFphiYmRs-YZa-rCBwplss") // 小程序
api = New("ww9a156bfa070e1857", "0jBdCjSmoFiOoHIXyeCK9VbGQ82fVNJZ8uMl6JNN7X4") // 通讯录
api = New("ww9a156bfa070e1857", "JQsEmSTltHhNgdPIT320YJFphiYmRs-YZa-rCBwplss") // 小程序
//api = New("6705486294797503379", "c1e6c280-e618-4103-9d0a-673bc54fb22e", "5375691", "cabrXQf9eFMVWVYg4hNlwu")
//token, _ := api.GetAccessToken()
//api.accessToken = token.BusinessDataObj.AccessToken
@@ -36,5 +39,66 @@ func TestGetToken(t *testing.T) {
}
func TestAPI_GetDepartmentList(t *testing.T) {
var aa int = 10004
fmt.Println(aa)
cc := strconv.Itoa(int(aa))
bb := string(aa)
fmt.Println(bb)
fmt.Println(cc)
ee := "四川省"
fmt.Println(ee[0:6])
}
// 获取所有的部门
func TestGetAllDepartmentList(t *testing.T) {
data, err := api.GetAllDepartmentList()
fmt.Println(err)
for _, v := range data {
fmt.Println(v.Name)
}
}
// 创建员工
func TestCreateStaff(t *testing.T) {
err := api.CreateBoss2JxStaff(&CreateBoos2JXStaffReq{
Userid: "jx2022524_668511",
Name: "门店老板",
Alias: "",
Mobile: "18981810341",
Department: []int{18}, // 四川省
Order: nil,
Position: "老板_群主",
Gender: "1",
Email: "",
IsLeaderInDept: []int{1},
Enable: 0,
AvatarMediaid: "",
Telephone: "",
Address: "",
Extattr: Extattr{},
MainDepartment: 0,
ToInvite: true,
ExternalPosition: "",
ExternalProfile: ExternalProfile{},
})
fmt.Println("err", err)
}
// 手机账号获取用户信息
func TestGetUserByMobile(t *testing.T) {
mobile, err := api.GetUserIdByMobile("18981810351")
fmt.Println(err)
fmt.Println(mobile)
}
// 创建会话群聊
func TestCreateSession(t *testing.T) {
api = New("ww9a156bfa070e1857", "JQsEmSTltHhNgdPIT320YJFphiYmRs-YZa-rCBwplss") // 小程序
err := api.CreateAppChat(&CreateAppChatParamReq{
UserList: []string{"jx2022524_668511", "LiuLei"},
Name: "test1liulei",
Owner: "LiuLei",
ChatId: "11112",
})
fmt.Println(err)
}

View File

@@ -13,6 +13,7 @@ import (
"time"
)
// 通讯录
func New(corpId, corpSecret string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
@@ -28,9 +29,26 @@ func New(corpId, corpSecret string, config ...*platformapi.APIConfig) *API {
}
}
// 会话
func NewMin(corpId, corpSecret string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
curConfig = *config[0]
}
return &API{
corpId: corpId,
corpSecret: corpSecret,
locker: sync.RWMutex{},
client: &http.Client{Timeout: curConfig.ClientTimeout},
config: &curConfig,
}
}
// 获取token
type EnterpriseToken struct {
PublicCode
ErrCode int `json:"errcode"` // 错误码
ErrMsg string `json:"errmsg"` // 错误消息
AccessToken string `json:"access_token"` // 权限说明
ExpiresIn int64 `json:"expires_in"` // 过期时间
}
@@ -72,19 +90,17 @@ func (a *API) GetAccessToken() (tokenInfo *EnterpriseToken, err error) {
// 数据发送
func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]interface{}) (retVal map[string]interface{}, err error) {
bizParams["access_token"] = a.accessToken
data, err := json.Marshal(bizParams) // 序列化
if err != nil {
return nil, err
}
// 全路径请求参数
fullURL := utils.GenerateGetURL(baseUrl, actionApi, nil)
// 发送请求
sendUrl := func() *http.Request {
var request *http.Request
if http.MethodPost == method {
// 全路径请求参数
fullURL := utils.GenerateGetURL(baseUrl, actionApi, map[string]interface{}{"access_token": a.accessToken})
request, _ = http.NewRequest(http.MethodPost, fullURL, strings.NewReader(string(data)))
} else {
request, _ = http.NewRequest(http.MethodGet, utils.GenerateGetURL(baseUrl, actionApi, bizParams), nil)
@@ -114,8 +130,9 @@ func (a *API) AccessAPI(baseUrl, actionApi, method string, bizParams map[string]
return retVal, err
}
// 检查token是否应该更新
func (a *API) CheckAccessTokenExpiresIn() {
if a.expiresIn == 0 || a.expiresIn <= time.Now().Unix() {
if a.expiresIn == 0 || a.expiresIn <= time.Now().Unix() || a.accessToken == "" {
a.GetAccessToken()
}
return

View File

@@ -10,7 +10,12 @@ const (
WeChatBaseApi = "https://qyapi.weixin.qq.com" // 企业微信基础访问链接
// api接口
GetToken = "cgi-bin/gettoken" // 获取token
GetToken = "cgi-bin/gettoken" // 获取token
CreateAppChat = "cgi-bin/appchat/create" // 创建会话群聊
GetAllDepartmentListById = "cgi-bin/department/list" // 获取所有的部门
CreateBoosToJxStaff = "cgi-bin/user/create" // 将京西老板创建为企业员工
GetDepartmentUserDetail = "cgi-bin/user/list" // 获取部门用户详细情况
GetUserByMobileUrl = "cgi-bin/user/getuserid" // 通过手机号获取用户id
)
// 注册请求api
@@ -24,9 +29,73 @@ type API struct {
config *platformapi.APIConfig
}
// 公共错误码
type PublicCode struct {
ErrCode int `json:"errcode"` // 错误码
ErrMsg string `json:"errmsg"` // 错误消息
// 创建群聊
type CreateAppChatParamReq struct {
UserList []string `json:"userlist"` // 成员列表(至少两个)
Name string `json:"name"` // 群聊名最多50个utf8字符超过将截断
Owner string `json:"owner"` // 群主id
ChatId string `json:"chatid"` // 群聊的唯一标志,不能与已有的群重复
}
// 获取所有的部门
type Department struct {
ID int `json:"id"` // id
Name string `json:"name"` // 名称
ParentId int `json:"parentid"` // 父部门id
Order int `json:"order"` // 排序
DepartmentLeader []string `json:"department_leader"` // 部门负责人的UserID第三方仅通讯录应用可获取
}
type GetAllDepartmentListRes struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
Department []*Department `json:"department"`
}
// 错误消息
type Err struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
ChatId string `json:"chatid"` // 群聊的唯一标志,不能与已有的群重复
}
// 获取部门全部用户详细信息
type GetEnterpriseStaffInfoRes struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
UserList []*UserList `json:"userlist"`
}
type UserList struct {
Userid string `json:"userid"`
Name string `json:"name"`
Department []int `json:"department"`
Position string `json:"position"`
Mobile string `json:"mobile"`
Gender string `json:"gender"`
Email string `json:"email"`
Avatar string `json:"avatar"`
Status int `json:"status"`
Enable int `json:"enable"`
IsLeader int `json:"isleader"`
ExtAttr Extattr `json:"extattr"`
HideMobile int `json:"hide_mobile"`
Telephone string `json:"telephone"`
Order []int `json:"order"`
ExternalProfile ExternalProfile `json:"external_profile"`
MainDepartment int `json:"main_department"`
QrCode string `json:"qr_code"`
Alias string `json:"alias"`
IsLeaderInDept []int `json:"is_leader_in_dept"`
Address string `json:"address"`
ThumbAvatar string `json:"thumb_avatar"`
DirectLeader []string `json:"direct_leader"`
BizMail string `json:"biz_mail"`
}
// 手机号获取用户信息
type GetUserByMobileRes struct {
ErrCode int `json:"errcode"`
ErrMsg string `json:"errmsg"`
UserId string `json:"userid"`
}