package Netease import ( "context" "encoding/json" "fmt" "servicebase/pkg/common" "servicebase/pkg/common/HyTools" yunxin "servicebase/pkg/common/netease/dto" "servicebase/pkg/htools" "servicebase/pkg/log" "strings" "github.com/pkg/errors" "github.com/spf13/cast" "math/rand" "strconv" "time" "github.com/anxpp/beego/logs" "github.com/spf13/viper" ) type ImClient struct { AppKey string AppSecret string } type CreateImRes struct { Code int Desc string } type BroadcastNotificationReq struct { FromAccountId string `json:"from_account_id"` Content string `json:"content"` TargetOs []string `json:"target_os"` } func NewImClient() *ImClient { fmt.Printf("NewImClient: %s\n", viper.GetString("netease.im.key")) key := viper.GetString("netease.im.key") secret := viper.GetString("netease.im.secret") return &ImClient{AppKey: key, AppSecret: secret} } // 生成云信header func (client *ImClient) generateHeader() map[string]string { nonce := randNumber() t := time.Now() currentTime := strconv.FormatInt(t.UTC().Unix(), 10) result := make(map[string]string) result["AppKey"] = client.AppKey result["Nonce"] = nonce result["CurTime"] = currentTime result["CheckSum"] = client.generateCheckSum(nonce, currentTime) result["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8" return result } func (client *ImClient) generateJsonHeader() map[string]string { nonce := randNumber() t := time.Now() currentTime := strconv.FormatInt(t.UTC().Unix(), 10) result := make(map[string]string) result["AppKey"] = client.AppKey result["Nonce"] = nonce result["CurTime"] = currentTime result["CheckSum"] = client.generateCheckSum(nonce, currentTime) result["Content-Type"] = "application/json" return result } // 生成云信签名 func (client *ImClient) generateCheckSum(nonce, currentTime string) string { waitSignStr := client.AppSecret + nonce + currentTime result := HyTools.StringToSHA1(waitSignStr) return result } // 创建云信账户 // imService.CreateImUser(common.SYNC_DATA_USER_ID,"数据同步",common.PHOTO_DOMAIN_URL+"assets/sys/guanfanggonggao.png") func (client *ImClient) CreateImUser(userId, nickName, avatar string) error { url := "https://api.netease.im/nimserver/user/create.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := HyTools.NewStringBuilder() sb.Append("accid=" + userId) sb.Append("&") sb.Append("token=123456") sb.Append("&") sb.Append("name=" + nickName) sb.Append("&") sb.Append("icon=" + avatar) res, err := HyTools.HttpDo(httpMethod, url, header, sb.ToString()) if err != nil { // {"desc":"already register","code":414} logs.Info("YunXin_SignUp_Fail_AccID_%s:"+err.Error(), userId) return err } else { var resDTO CreateImRes json.Unmarshal([]byte(res), &resDTO) if resDTO.Code != 200 { logs.Info("YunXin_SignUp_Fail_AccID_%s:"+resDTO.Desc, userId) } else { logs.Info("YunXin_SignUp_Success_AccID_%s:"+res, userId) } } var body map[string]interface{} if errJson := json.Unmarshal([]byte(res), &body); errJson != nil { return errJson } if int(body["code"].(float64)) != 200 { return errors.New(body["desc"].(string)) } return err } // 查询用户信息 func (client *ImClient) GetImUserInfo(userId string) error { url := "https://api.netease.im/nimserver/user/getUinfos.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := HyTools.NewStringBuilder() accids := []string{userId} byteData, _ := json.Marshal(accids) sb.Append("accids=" + string(byteData)) res, err := HyTools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info("#" + "查询云信用户信息结果:" + res + "#") var body map[string]interface{} if errJson := json.Unmarshal([]byte(res), &body); errJson != nil { return errJson } if int(body["code"].(float64)) != 200 { return errors.New(body["desc"].(string)) } return err } // 更新云信信息 func (client *ImClient) UpdateImUserInfo(accid, nickName, avatar string) error { url := "https://api.netease.im/nimserver/user/updateUinfo.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() sb.Append("accid=" + accid) sb.Append("&") sb.Append("name=" + nickName) sb.Append("&") sb.Append("icon=" + avatar) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "云信更新用户信息结果:" + res + common.LOG_QUOTE_STRING) return err } // 更新云信用户扩展信息 func (client *ImClient) UpdateImUserExt(accid, ext string) error { url := "https://api.netease.im/nimserver/user/updateUinfo.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() sb.Append("accid=" + accid) sb.Append("&") sb.Append("ex=" + ext) logs.Info("update_im_user userID[%s] ext:%s", accid, ext) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING+"云信更新用户ext%s信息结果:"+res+common.LOG_QUOTE_STRING, ext) return err } // 封禁云信帐号 func (client *ImClient) BlockImUser(accid string) error { url := "https://api.netease.im/nimserver/user/block.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() sb.Append("accid=" + accid) sb.Append("&") sb.Append("needkick=true") res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "封禁云信帐号结果:" + res + common.LOG_QUOTE_STRING) return err } // 解禁云信帐号 func (client *ImClient) UnBlockImUser(accid string) error { url := "https://api.netease.im/nimserver/user/unblock.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() sb.Append("accid=" + accid) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "解禁云信帐号结果:" + res + common.LOG_QUOTE_STRING) return err } // 创建云信聊天室 func (client *ImClient) CreateChatroom(ownerUserId string, roomName string) (chatroomModel NeteaseChatroomDTO) { logs.Info("CreateChatroom ownerUserId=%s roomName=%s", ownerUserId, roomName) url := "https://api.netease.im/nimserver/chatroom/create.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() sb.Append("creator=" + ownerUserId) sb.Append("&") sb.Append("name=" + roomName) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) if err != nil { logs.Info(common.LOG_QUOTE_STRING + "云信创建聊天室请求失败:" + err.Error() + common.LOG_QUOTE_STRING) return } logs.Info(common.LOG_QUOTE_STRING + "云信创建聊天室结果:" + res + common.LOG_QUOTE_STRING) var createRes CreateChatroomResponse err1 := json.Unmarshal([]byte(res), &createRes) if err1 != nil { logs.Info(common.LOG_QUOTE_STRING + "创建聊天室失败,解析结果错误:" + res + common.LOG_QUOTE_STRING) panic(err1) } if createRes.Code != 200 { logs.Info(common.LOG_QUOTE_STRING + "创建Im聊天室失败:code= " + strconv.Itoa(createRes.Code) + common.LOG_QUOTE_STRING) panic(errors.New("创建云信Im聊天室失败")) } chatroomModel = createRes.Chatroom return } // IM发送消息 func (client *ImClient) SendMsg(parameters map[string]string) error { url := "https://api.netease.im/nimserver/msg/sendMsg.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "云信IM发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "云信IM发消息结果:" + res + common.LOG_QUOTE_STRING) return err } // 添加机器人 func (client *ImClient) AddRobot(parameters map[string]string) error { url := "https://api.netease.im/nimserver/chatroom/addRobot.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "添加机器人:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "添加机器人:" + res + common.LOG_QUOTE_STRING) return err } // 移除机器人 func (client *ImClient) RemoveRobot(parameters map[string]string) error { url := "https://api.netease.im/nimserver/chatroom/removeRobot.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "移除机器人:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "移除机器人:" + res + common.LOG_QUOTE_STRING) return err } // 发送聊天室消息 func (client *ImClient) SendChatroomMsg(parameters map[string]string) error { url := "https://api.netease.im/nimserver/chatroom/sendMsg.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "聊天室发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "聊天室发消息结果:" + res + common.LOG_QUOTE_STRING) return err } // 获取在线成员信息 func (client *ImClient) GetChatroomMembers(parameters map[string]string) (imResponse ImResponse, err error) { url := "https://api.netease.im/nimserver/chatroom/queryMembers.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() body := generateBodyData(parameters) logs.Info(common.LOG_QUOTE_STRING + "获取在线成员请求:" + body + common.LOG_QUOTE_STRING) res, err1 := htools.HttpDo(httpMethod, url, header, body) if err1 != nil { logs.Error(common.LOG_QUOTE_STRING + "获取在线成员失败:" + err1.Error() + common.LOG_QUOTE_STRING) err = err1 return } logs.Info(common.LOG_QUOTE_STRING + "获取在线成员结果:" + res + common.LOG_QUOTE_STRING) var response ImResponse if err2 := json.Unmarshal([]byte(res), &response); err2 != nil { logs.Error(common.LOG_QUOTE_STRING + "获取在线成员解析失败:" + err2.Error() + common.LOG_QUOTE_STRING) err = err2 return } imResponse = response return } // 分页获取聊天室在线用户列表 func (client *ImClient) GetChatroomOnlineUserListByPage(parameters map[string]string) (imResponse ImResponse, err error) { url := "https://api.netease.im/nimserver/chatroom/membersByPage.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() body := generateBodyData(parameters) logs.Info(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表:" + body + common.LOG_QUOTE_STRING) res, err1 := htools.HttpDo(httpMethod, url, header, body) if err1 != nil { logs.Error(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表失败:" + err1.Error() + common.LOG_QUOTE_STRING) err = err1 return } logs.Info(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表结果:" + res + common.LOG_QUOTE_STRING) var response ImResponse if err2 := json.Unmarshal([]byte(res), &response); err2 != nil { logs.Error(common.LOG_QUOTE_STRING + "分页获取聊天室在线列表失败:" + err2.Error() + common.LOG_QUOTE_STRING) err = err2 return } imResponse = response return } // 更新聊天室房间信息 func (client *ImClient) UpdateRoomInfo(request yunxin.UpdateRoomInfoRequest) (err error) { url := "https://api.netease.im/nimserver/chatroom/update.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() sb.Append("roomid=" + request.Roomid) sb.Append("&") sb.Append("name=") sb.Append("&") sb.Append("announcement=") sb.Append("&") sb.Append("ext=") sb.Append("&") sb.Append("notifyExt=" + request.NotifyExt) logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, httpErr := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息结果:" + res + common.LOG_QUOTE_STRING) if httpErr != nil { logs.Info(common.LOG_QUOTE_STRING + "更新聊天室信息失败:" + httpErr.Error() + common.LOG_QUOTE_STRING) err = httpErr return } resMap := make(map[string]interface{}) jsonErr := json.Unmarshal([]byte(res), &resMap) if jsonErr != nil { logs.Info(common.LOG_QUOTE_STRING + "解析更新房间信息结果失败:" + jsonErr.Error() + common.LOG_QUOTE_STRING) err = jsonErr return } code := resMap["code"].(float64) codeStr := htools.Float64ToString(code) if codeStr != "200" { logs.Info(common.LOG_QUOTE_STRING + "更新房间信息结果失败: code=" + codeStr + common.LOG_QUOTE_STRING) err = errors.New("更新失败 code=" + codeStr) return } return } // 聊天室临时禁言 func (client *ImClient) ChatroomMuteUser(parameters map[string]string) error { url := "https://api.netease.im/nimserver/chatroom/temporaryMute.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "聊天室临时禁言请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "聊天室临时禁言结果:" + res + common.LOG_QUOTE_STRING) return err } // 切换聊天室状态 func (client *ImClient) ChangeChatroomStat(parameters map[string]string) error { url := "https://api.netease.im/nimserver/chatroom/toggleCloseStat.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } requestId := HyTools.GetUUID() logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态请求:requestId " + requestId + " body " + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) if len(res) == 0 { logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果:失败 res为空 requestId " + requestId + common.LOG_QUOTE_STRING) return errors.New("操作失败") } if err != nil { logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果:失败 返回error requestId " + requestId + "error " + err.Error() + common.LOG_QUOTE_STRING) return err } //{"desc":"parameter roomid should be long","code":414} var resData struct { Code int `json:"code"` Desc string `json:"desc"` } _ = json.Unmarshal([]byte(res), &resData) if resData.Code != 200 { if resData.Code != 417 { // 重复操作 直接忽略 logs.Info(fmt.Sprintf(common.LOG_QUOTE_STRING+"聊天室切换聊天室开关状态结果:失败 code[%d] requestId "+requestId+" desc[%s] "+common.LOG_QUOTE_STRING, resData.Code, resData.Desc)) return errors.New("操作失败") } } logs.Info(common.LOG_QUOTE_STRING + "聊天室切换聊天室开关状态结果: requestId " + requestId + " response " + res + common.LOG_QUOTE_STRING) return err } // 设置聊天室成员角色 func (client *ImClient) SetChatroomMemberRole(parameters map[string]string) error { url := "https://api.netease.im/nimserver/chatroom/setMemberRole.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "设置聊天室成员角色请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "设置聊天室成员角色结果:" + res + common.LOG_QUOTE_STRING) return err } // 发送广播消息 func (client *ImClient) SendBroadCastMsg(parameters map[string]string) error { url := "https://api.netease.im/nimserver/msg/broadcastMsg.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "发送广播请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "发送广播结果:" + res + common.LOG_QUOTE_STRING) return err } // 发送全员广播 V2 func (client *ImClient) SendBroadCastMsgV2(req BroadcastNotificationReq) error { url := "https://open.yunxinapi.com/im/v2/broadcast_notification" httpMethod := common.HTTP_METHOD_POST header := client.generateJsonHeader() bodyStr := HyTools.JsonStr(req) logs.Info(common.LOG_QUOTE_STRING + "发送广播请求V2:" + bodyStr + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, bodyStr) logs.Info(common.LOG_QUOTE_STRING + "发送广播结果V2:" + res + common.LOG_QUOTE_STRING) return err } // 踢出用户登录 V2 https://{endpoint}/im/v2/accounts/{account_id}/actions/kick func (client *ImClient) KickOutUserV2(userId string) error { url := "https://open.yunxinapi.com/im/v2/accounts/" + userId + "/actions/kick" httpMethod := common.HTTP_METHOD_POST header := client.generateJsonHeader() req := make(map[string]any, 3) req["type"] = 1 req["device_id_list"] = []string{} req["kick_notify_extension"] = "" bodyStr := HyTools.JsonStr(req) logs.Info(common.LOG_QUOTE_STRING + "发送踢下线请求V2:" + bodyStr + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, bodyStr) logs.Info(common.LOG_QUOTE_STRING + "发送踢下线结果V2:" + res + common.LOG_QUOTE_STRING) return err } // 设置/取消 拉黑 静音 func (client *ImClient) SetSpecialRelation(parameters map[string]string) error { url := "https://api.netease.im/nimserver/user/setSpecialRelation.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "设置/取消 拉黑请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "设置/取消 拉黑结果:" + res + common.LOG_QUOTE_STRING) return err } // 发送自定义系统通知 func (client *ImClient) BatchSendMsg(parameters map[string]string) error { url := "https://api.netease.im/nimserver/msg/sendBatchMsg.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "云信IM批量发消息请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "云信IM批量发消息结果:" + res + common.LOG_QUOTE_STRING) return err } // 批量发送消息 func (client *ImClient) SendAttachMsg(parameters map[string]string) error { url := "https://api.netease.im/nimserver/msg/sendAttachMsg.action" httpMethod := common.HTTP_METHOD_POST header := client.generateHeader() sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } logs.Info(common.LOG_QUOTE_STRING + "云信IM发系统通知请求:" + sb.ToString() + common.LOG_QUOTE_STRING) res, err := htools.HttpDo(httpMethod, url, header, sb.ToString()) logs.Info(common.LOG_QUOTE_STRING + "云信IM发系统通知结果:" + res + common.LOG_QUOTE_STRING) if parameters["to"] == "b260b07ff3d1411f926e2d767cb9d6f3" { log.Info("完成给老板发接单消息") } return err } // CreateChatGroup 创建群组 func (client *ImClient) CreateChatGroup(ctx context.Context, ownerUserId string, groupName string, inviteMem []string) (string, error) { url := "https://open.yunxinapi.com/im/v2.1/teams" httpMethod := common.HTTP_METHOD_POST header := client.generateJsonHeader() reqBody := &CreateChatGroupReq{ OwnerAccountID: ownerUserId, TeamType: 1, Name: groupName, MembersLimit: 3000, InviteAccountIDs: inviteMem, InviteMsg: "管理", Configuration: &TeamConfiguration{ JoinMode: 1, }, AntispamConfiguration: nil, } bodyBytes, err := json.Marshal(reqBody) if err != nil { return "", errors.WithStack(err) } res, err := HyTools.HttpDo(httpMethod, url, header, string(bodyBytes)) if err != nil { // {"desc":"already register","code":414} logs.Info("YunXin_CreateChatGroup_Fail_AccID_%s:"+err.Error(), ownerUserId) return "", errors.WithStack(err) } log.InfoF("create group chat resp: %s", res) var body BaseRes[CreateChatGroupRsp] err = json.Unmarshal([]byte(res), &body) if err != nil { return "", errors.WithStack(err) } if body.Code != 200 { return "", errors.Errorf("YunXin_CreateChatGroup code(%d) not 200,msg: %s", body.Code, body.Msg) } if len(body.Data.FailedList) > 0 { var errInfo []string for _, member := range body.Data.FailedList { errInfo = append(errInfo, fmt.Sprintf("account: %s ,code: %d ,msg: %s", member.AccountID, member.ErrorCode, member.ErrorMsg)) } return "", errors.Errorf("YunXin_CreateChatGroup err: %s", strings.Join(errInfo, ";")) } return cast.ToString(body.Data.TeamInfo.TeamID), nil } // ================ 私有方法 ======================== func generateBodyData(parameters map[string]string) string { sb := htools.NewStringBuilder() parametersCount := len(parameters) i := 0 for k, v := range parameters { sb.Append(k + "=" + v) if i < parametersCount-1 { sb.Append("&") } i++ } return sb.ToString() } func randNumber() string { str := "0123456789" bytes := []byte(str) var result []byte r := rand.New(rand.NewSource(time.Now().UnixNano())) for i := 0; i < 4; i++ { result = append(result, bytes[r.Intn(len(bytes))]) } return string(result) }