package workWechat import ( "encoding/json" "encoding/xml" "errors" "fmt" "hr_server/grocerystore" "hr_server/models" "hr_server/overall" "hr_server/overall/overallhandle" "strconv" "time" ) /* * @ 作者: 秦东 @ 时间: 2024-01-18 14:11:11 @ 功能: 获取token @ 参数 #systemApp 系统 #key 身份KEy #isAgain 重新授权 1:否,2:是 @ 返回值 # @ 方法原型 #token token值 #err 状态 */ func GainWechatToken(systemApp, key string, isAgain int) (token string, err error) { companyId := overall.CONSTANT_CONFIG.WechatCompany.CompanyId redisFileKey := fmt.Sprintf("Wechat:Token:%v_%v_%v_%v", systemApp, companyId, key, overall.CONSTANT_CONFIG.RedisPrefixStr.Alias) var secretStr string switch systemApp { case "kpi": redisFileKey = fmt.Sprintf("%v_%v_%v", redisFileKey, systemApp, overall.CONSTANT_CONFIG.WechatKpi.Agentid) secretStr = overall.CONSTANT_CONFIG.WechatKpi.Secret case "school": redisFileKey = fmt.Sprintf("%v_%v_%v", redisFileKey, systemApp, overall.CONSTANT_CONFIG.WechatSchool.Agentid) secretStr = overall.CONSTANT_CONFIG.WechatSchool.Secret case "hr": redisFileKey = fmt.Sprintf("%v_%v_%v", redisFileKey, systemApp, overall.CONSTANT_CONFIG.EmployeeFile.Agentid) secretStr = overall.CONSTANT_CONFIG.EmployeeFile.Secret case "txl": redisFileKey = fmt.Sprintf("%v_%v_%v", redisFileKey, systemApp, overall.CONSTANT_CONFIG.AddressBook.Agentid) secretStr = overall.CONSTANT_CONFIG.AddressBook.Secret default: redisFileKey = fmt.Sprintf("%v_%v", redisFileKey, systemApp) } redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS4) //设定redis库 if isAgain != 1 { token, err = getWechatServer(companyId, secretStr) if err != nil { return } redisClient.SetRedisTime(7200) redisClient.Set(redisFileKey, token) } else { isTrue, tokens := redisClient.Get(redisFileKey) if isTrue && tokens != "" { err = nil token = tokens return } else { token, err = getWechatServer(companyId, secretStr) if err != nil { return } redisClient.SetRedisTime(7200) redisClient.Set(redisFileKey, token) } } // fmt.Printf("tokenKey: %v\n", redisFileKey) return } /* * @ 作者: 秦东 @ 时间: 2024-01-18 14:23:24 @ 功能: 获取微信Token(链接微信服务器) @ 参数 # @ 返回值 # @ 方法原型 # */ func getWechatServer(companyId, secretStr string) (token string, err error) { getTokenUrl := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%v&corpsecret=%v", companyId, secretStr) // getTokenUrl := "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + companyId + "&corpsecret=" + secretStr tokenByte := overallhandle.CurlGet(getTokenUrl) var callBackCont WeChatCallBack err = json.Unmarshal(tokenByte, &callBackCont) if err != nil { return } if callBackCont.Errcode != 0 { err = errors.New(fmt.Sprintf("未能获得到TOKEN!%v", callBackCont.Errmsg)) return } token = callBackCont.Accesstoken return } /* * @ 作者: 秦东 @ 时间: 2024-01-18 17:00:54 @ 功能: 获取企业的jsapi_ticket 或 获取应用的jsapi_ticket @ 参数 #systemApp 系统 #key 身份识别 #calss 1:应用,2:企业 @ 返回值 # @ 方法原型 # */ func GainJsapiTicket(systemApp, key string, class int) (jsApiTickerStr string, err error) { jsApiTicketRedis := fmt.Sprintf("Wechat:JsapiTicket:%v_%v_%v", systemApp, overall.CONSTANT_CONFIG.RedisPrefixStr.Alias, class) redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS4) isTrue, jsApiTickerInfo := redisClient.Get(jsApiTicketRedis) //读取redis数据 fmt.Printf("读取redis数据-2-2->%v->%v->%v\n", jsApiTicketRedis, isTrue, jsApiTickerInfo) if isTrue { jsApiTickerStr = jsApiTickerInfo err = nil return } else { var sendUrlstr string //获取token tokenStr, errs := GainWechatToken(systemApp, key, 1) if errs != nil { err = errs return } if class != 1 { sendUrlstr = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=" + tokenStr //获取企业级 } else { sendUrlstr = "https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=" + tokenStr + "&type=agent_config" //获取应用级 } //获取企业微信jsapi_ticket jsapiTickerMsg := overallhandle.CurlGet(sendUrlstr) var callBackCont WeChatCallBack err = json.Unmarshal(jsapiTickerMsg, &callBackCont) if err != nil { return } if callBackCont.Errcode != 0 { return } jsApiTickerStr = callBackCont.Ticket redisClient.SetRedisTime(7200) redisClient.Set(jsApiTicketRedis, jsApiTickerStr) } return } /* * @ 作者: 秦东 @ 时间: 2024-01-25 14:11:27 @ 功能: 获取部门列表 @ 参数 #org 行政组织 #systemApp 系统 #key 身份KEy #isAgain 重新授权 1:否,2:是 @ 返回值 #departmentAry 部门列表 #err 错误信息 @ 方法原型 #func GainWechatDepartment(org int64, systemApp, key string, isAgain int) (departmentAry []WechatDepartmentInfo, err error) */ func GainWechatDepartment(org int64, systemApp, key string, isAgain int) (departmentAry []WechatDepartmentInfo, err error) { token, err := GainWechatToken(systemApp, key, 1) if err != nil { return } sendWechatUrl := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%v&id=%v", token, org) if org == 0 { sendWechatUrl = fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token=%v", token) } // fmt.Printf("网址-->%v-->%v\n", org, sendWechatUrl) //获取企业微信取部门列表 wechatCallBack := overallhandle.CurlGet(sendWechatUrl) var deparmentsList WechatCallBackDepartment err = json.Unmarshal(wechatCallBack, &deparmentsList) if err != nil { return } if deparmentsList.Errcode != 0 { return } departmentAry = deparmentsList.Department return } /* * @ 作者: 秦东 @ 时间: 2024-01-25 15:22:28 @ 功能: 获取行政组织人员信息 @ 参数 #org 行政组织 #systemApp 系统 #key 身份KEy #isAgain 重新授权 1:否,2:是 @ 返回值 # @ 方法原型 # */ func GainOrgPeopleInfo(org int64, systemApp, key string, isAgain int) (peopleAry interface{}, err error) { token, err := GainWechatToken(systemApp, key, 1) if err != nil { return } sendWechatUrl := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/user/list?access_token=%v&department_id=%v", token, org) //获取企业微信取部门成员详情 wechatCallBack := overallhandle.CurlGet(sendWechatUrl) var orgPeopleList WechatCallBackPeople // peo := overallhandle.MapOut() err = json.Unmarshal(wechatCallBack, &orgPeopleList) if err != nil { return } if orgPeopleList.Errcode != 0 { return } peopleAry = orgPeopleList.UserList // peopleAry = peo return } /* * @ 作者: 秦东 @ 时间: 2024-01-25 16:05:08 @ 功能: 更新企业微信人员信息 @ 参数 # @ 返回值 # @ 方法原型 # */ func UpdateWechatPeopel(systemApp, key string, isAgain int, userInfo map[string]interface{}) (err error) { if _, ok := userInfo["userid"]; !ok { err = errors.New("关键信息不全userid") return } token, err := GainWechatToken(systemApp, key, 1) if err != nil { return } userJson, err := json.Marshal(userInfo) if err != nil { overallhandle.WriteLog("e", "1、更新企业微信人员信息", err, userJson) return } overallhandle.WriteLog("i", "更新企业微信人员信息", string(userJson)) sendWechatUrl := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/user/update?access_token=%v", token) //获取企业微信取部门成员详情 wechatCallBack := overallhandle.CurlPostJosn(sendWechatUrl, userJson) var orgPeopleList RevokeMsgSendCallBack err = json.Unmarshal(wechatCallBack, &orgPeopleList) // fmt.Printf("成员详情--->%v\n", orgPeopleList) if err != nil { overallhandle.WriteLog("e", "2、更新企业微信人员信息", err, string(wechatCallBack)) return } if orgPeopleList.Errcode != 0 { err = errors.New(orgPeopleList.Errmsg) overallhandle.WriteLog("e", "3、更新企业微信人员信息", orgPeopleList.Errcode, orgPeopleList.Errmsg) return } return } // 企业微信回调验证URL func (c *CallBackData) VerificationUrl() (msg string) { switch c.DataType { case "json": wxCallBackJson := WechatDecryptJson(c.SystemApp) echoStr, cryptErr := wxCallBackJson.VerifyURL(c.MsgSignature, c.Timestamp, c.Nonce, c.Echostr) msg = string(echoStr) if cryptErr != nil { fmt.Println("verifyUrl fail", cryptErr) overallhandle.WriteLog("e", "verifyUrl fail", cryptErr) } default: wxCallBackXml := WechatDecryptXml(c.SystemApp) echoStr, cryptErr := wxCallBackXml.VerifyURL(c.MsgSignature, c.Timestamp, c.Nonce, c.Echostr) msg = string(echoStr) if cryptErr != nil { fmt.Println("verifyUrl fail", cryptErr) overallhandle.WriteLog("e", "verifyUrl fail", cryptErr) } } return } // 解密文档 func (d *DecryptMsgCont) DecryptMsgInfo() (msg []byte, err error) { decryptStr := fmt.Sprintf(`{"tousername":"%v","encrypt":"%v","agentid":"%v"}`, d.ToUsername, d.Encrypt, d.Agentid) reqData := []byte(decryptStr) wxcptJson := WechatDecryptJson(d.SystemApp) msg, cryptErr := wxcptJson.DecryptMsg(d.MsgSignature, d.Timestamp, d.Nonce, reqData) if cryptErr != nil { err = fmt.Errorf("解密失败1") } overallhandle.WriteLog("write", "企业微信回调内容", string(msg)) var callbackLog CallbackLog callbackLog.MsgSignature = d.MsgSignature TimestampInt, _ := strconv.ParseInt(d.Timestamp, 10, 64) callbackLog.TimeStamp = TimestampInt callbackLog.Nonce = d.Nonce callbackLog.Echostr = d.Encrypt callbackLog.Xmlstr = string(msg) callbackLog.AddTime = time.Now().Unix() overallhandle.WriteLog("i", "企业微信回调内容", callbackLog) return } /* * @ 作者: 秦东 @ 时间: 2024-01-26 09:27:14 @ 功能: 进入应用上报地址位置 @ 参数 # @ 返回值 # @ 方法原型 # */ func GeographicalPosition(eventMsg []byte) { var msgContent GeographicalPositionType err := xml.Unmarshal(eventMsg, &msgContent) if nil != err { fmt.Println("***********Unmarshal fail") overallhandle.WriteLog("e", "上报地理位置", err) } userAddress := overallhandle.MapOut() userAddress["userid"] = msgContent.FromUsername //userID userAddress["latitude"] = msgContent.Latitude //地理位置纬度 userAddress["longitude"] = msgContent.Longitude //地理位置经度 userAddress["precision"] = msgContent.Precision //地理位置精度 userAddress["time"] = time.Now().Unix() marshal, err := json.Marshal(userAddress) if err != nil { marshal = []byte{} overallhandle.WriteLog("e", "上报地理位置,数据写入错误", marshal) } redisPrefix := fmt.Sprintf("AddressLocation:GeographicalPosition_%v:userId_%v", overall.CONSTANT_CONFIG.RedisPrefixStr.PreFix, msgContent.FromUsername) redisClient := grocerystore.RunRedis(overall.CONSTANT_REDIS4) locationJson, locationErr := redisClient.Lindex(redisPrefix, 0) if locationErr != nil { _, err := redisClient.Lpush(redisPrefix, string(marshal)) overallhandle.WriteLog("add", "1、上报地理位置,", err) } else { var geographicalPositionRedis GeographicalPositionRedis jsonErr := json.Unmarshal([]byte(locationJson), &geographicalPositionRedis) if jsonErr != nil { _, err := redisClient.Lpush(redisPrefix, string(marshal)) overallhandle.WriteLog("add", "2、上报地理位置,", err) } else { timeVal := geographicalPositionRedis.Time if time.Now().Unix()-timeVal >= 300 { _, err := redisClient.Lpush(redisPrefix, string(marshal)) overallhandle.WriteLog("add", "3、上报地理位置,", err) } } } } /* * @ 作者: 秦东 @ 时间: 2024-01-26 11:20:42 @ 功能: 指定企业微信行政组织更新其下人员信息 @ 参数 # @ 返回值 # @ 方法原型 # */ func UpdateWechatOrgPeople(org int64, systemApp, key string, isAgain int) (err error) { orgList, err := GainWechatDepartment(org, systemApp, key, isAgain) if err != nil || len(orgList) < 1 { overallhandle.WriteLog("e", "没有行政组织!", org, err) return } for _, v := range orgList { synPro.Add(1) go OrgPeopelList(int64(v.Id), systemApp, key, isAgain) } synPro.Wait() return } /* * @ 作者: 秦东 @ 时间: 2024-01-26 11:29:42 @ 功能: 协程获取人员信息 @ 参数 # @ 返回值 # @ 方法原型 # */ func OrgPeopelList(org int64, systemApp, key string, isAgain int) { defer synPro.Done() orgList, err := GainOrgPeopleInfo(org, systemApp, key, isAgain) if err != nil { overallhandle.WriteLog("e", "没有行人员!", org, err) return } var peopleAry []interface{} if val, ok := orgList.([]WechatUserList); ok { if len(val) > 0 { for _, v := range val { // fmt.Printf("org-2-->\n%T\n%v\n", v.Extattr, v.Extattr) updateWechatUserCont := overallhandle.MapOut() updateWechatUserCont["userid"] = v.Userid var userCont models.PersonArchives errUser := overall.CONSTANT_DB_HR.Model(&models.PersonArchives{}).Select("`number`,`work_wechat`,`wechat`").Where("`work_wechat` = ? OR `wechat` = ?", v.Userid, v.Userid).First(&userCont).Error //根据企业微信UserId寻找员工记录中是否存在记录 var attrsAry []interface{} isWriteUrl := true isWriteNum := true var wechatNum string dangAnIsShow := true for _, ev := range v.Extattr.Attrs { // fmt.Printf("%v档案信息%v\n", v.Userid, ev) //判断企业微信回调中是否有工号 if ev.Name == "工号" && ev.Text.Value != "" { //有工号 isWriteNum = false wechatNum = ev.Text.Value // dangAnUrl := fmt.Sprintf("http://hr.hxgk.group/#/?usernum=%v", ev.Text.Value) // if ev.Text.Value != dangAnUrl { // var dangAnInfi UpdateMyWechatURL // dangAnInfi.Name = "档案" // dangAnInfi.Type = 1 // dangAnInfi.Web.Title = "详细信息" // dangAnInfi.Web.Url = dangAnUrl // attrsAry = append(attrsAry, dangAnInfi) // isWriteUrl = false // fmt.Printf("1写档案%v\n", v.Userid) // } if errUser == nil { //数据库中存在UserId信息 if userCont.WorkWechat == "" && userCont.Wechat == "" { //如果没有绑定微信则绑定 editUserTable := overallhandle.MapOut() editUserTable["work_wechat"] = v.Userid editUserTable["eite_time"] = time.Now().Unix() var userNumInfo models.PersonArchives userNumInfo.EiteCont(map[string]interface{}{"`number`": ev.Text.Value}, editUserTable) } } else { //数据库中不存在UserId信息,则写入UserId信息 var userNumInfo models.PersonArchives errNum := userNumInfo.GetCont(map[string]interface{}{"`number`": ev.Text.Value}, "`work_wechat`", "`wechat`") if errNum == nil { //判断此工号员工是否存在,存在则写入相应数据记录中 editUserTable := overallhandle.MapOut() editUserTable["work_wechat"] = v.Userid editUserTable["eite_time"] = time.Now().Unix() userNumInfo.EiteCont(map[string]interface{}{"`number`": ev.Text.Value}, editUserTable) } } } // else { //无工号 // if errUser == nil { //数据库中存在UserId信息 // dangAnUrl := fmt.Sprintf("http://hr.hxgk.group/#/?usernum=%v", userCont.Number) // if ev.Web.Url != dangAnUrl { // var dangAnInfi UpdateMyWechatURL // dangAnInfi.Name = "档案" // dangAnInfi.Type = 1 // dangAnInfi.Web.Title = "详细信息" // dangAnInfi.Web.Url = dangAnUrl // attrsAry = append(attrsAry, dangAnInfi) // } // var gonhaoInFo UpdateMyWechatText // gonhaoInFo.Name = "工号" // gonhaoInFo.Type = 0 // gonhaoInFo.Value = userCont.Number // gonhaoInFo.Text.Value = userCont.Number // attrsAry = append(attrsAry, gonhaoInFo) // } // } if ev.Name == "档案" && ev.Web.Url != "" { dangAnIsShow = false if isWriteUrl && errUser == nil { dangAnUrl := fmt.Sprintf("http://hr.hxgk.group/#/?usernum=%v", userCont.Number) if ev.Web.Url != dangAnUrl { var dangAnInfi UpdateMyWechatURL dangAnInfi.Name = "档案" dangAnInfi.Type = 1 dangAnInfi.Web.Title = "详细信息" dangAnInfi.Web.Url = dangAnUrl attrsAry = append(attrsAry, dangAnInfi) isWriteUrl = false // fmt.Printf("2写档案%v\n", v.Userid) } else { isWriteUrl = false } } if isWriteNum && errUser == nil { var gonhaoInFo UpdateMyWechatText gonhaoInFo.Name = "工号" gonhaoInFo.Type = 0 gonhaoInFo.Value = userCont.Number gonhaoInFo.Text.Value = userCont.Number attrsAry = append(attrsAry, gonhaoInFo) isWriteNum = false } } if ev.Name == "档案" && ev.Web.Url == "" { dangAnIsShow = false if isWriteUrl && errUser == nil { dangAnUrl := fmt.Sprintf("http://hr.hxgk.group/#/?usernum=%v", userCont.Number) var dangAnInfi UpdateMyWechatURL dangAnInfi.Name = "档案" dangAnInfi.Type = 1 dangAnInfi.Web.Title = "详细信息" dangAnInfi.Web.Url = dangAnUrl attrsAry = append(attrsAry, dangAnInfi) isWriteUrl = false // fmt.Printf("3写档案%v\n", v.Userid) } if isWriteNum && errUser == nil { var gonhaoInFo UpdateMyWechatText gonhaoInFo.Name = "工号" gonhaoInFo.Type = 0 gonhaoInFo.Value = userCont.Number gonhaoInFo.Text.Value = userCont.Number attrsAry = append(attrsAry, gonhaoInFo) isWriteNum = false } } if ev.Name == "工号" && isWriteNum { if errUser == nil { wechatNum = userCont.Number } if wechatNum != "" { var gonhaoInFo UpdateMyWechatText gonhaoInFo.Name = "工号" gonhaoInFo.Type = 0 gonhaoInFo.Value = userCont.Number gonhaoInFo.Text.Value = userCont.Number attrsAry = append(attrsAry, gonhaoInFo) isWriteNum = false } } if ev.Name == "档案" && isWriteUrl { dangAnIsShow = false if errUser == nil { wechatNum = userCont.Number } if wechatNum != "" { dangAnUrl := fmt.Sprintf("http://hr.hxgk.group/#/?usernum=%v", wechatNum) var dangAnInfi UpdateMyWechatURL dangAnInfi.Name = "档案" dangAnInfi.Type = 1 dangAnInfi.Web.Title = "详细信息" dangAnInfi.Web.Url = dangAnUrl attrsAry = append(attrsAry, dangAnInfi) isWriteUrl = false // fmt.Printf("4写档案%v\n", v.Userid) } } } if dangAnIsShow { dangAnIsShow = true if errUser == nil { wechatNum = userCont.Number } if wechatNum != "" { dangAnUrl := fmt.Sprintf("http://hr.hxgk.group/#/?usernum=%v", wechatNum) var dangAnInfi UpdateMyWechatURL dangAnInfi.Name = "档案" dangAnInfi.Type = 1 dangAnInfi.Web.Title = "详细信息" dangAnInfi.Web.Url = dangAnUrl attrsAry = append(attrsAry, dangAnInfi) isWriteUrl = false // fmt.Printf("4写档案%v\n", v.Userid) } } if len(attrsAry) > 0 { extattr := overallhandle.MapOut() extattr["attrs"] = attrsAry updateWechatUserCont["extattr"] = extattr peopleAry = append(peopleAry, updateWechatUserCont) } err = UpdateWechatPeopel(systemApp, key, isAgain, updateWechatUserCont) if err != nil { overallhandle.WriteLog("e", "更新完毕!", err, updateWechatUserCont) } else { overallhandle.WriteLog("i", "更新完毕!", err, updateWechatUserCont) } } } } // errdsd := UpdateWechatPeopelAry(systemApp, key, isAgain, peopleAry) peopleJson, _ := json.Marshal(peopleAry) // fmt.Printf("集体更新---->%v\n---->%v\n", string(peopleJson), errdsd) overallhandle.WriteLog("e", "更新完毕!END", org, string(peopleJson)) } /* * @ 作者: 秦东 @ 时间: 2024-01-25 16:05:08 @ 功能: 批量更新企业微信人员信息 @ 参数 # @ 返回值 # @ 方法原型 # */ func UpdateWechatPeopelAry(systemApp, key string, isAgain int, userInfo []interface{}) (err error) { // if _, ok := userInfo["userid"]; !ok { // err = errors.New("关键信息不全userid") // return // } if len(userInfo) < 1 { err = errors.New("关键信息不全userid") return } token, err := GainWechatToken(systemApp, key, 1) if err != nil { return } userJson, err := json.Marshal(userInfo) if err != nil { overallhandle.WriteLog("e", "1、更新企业微信人员信息", err, userJson) return } overallhandle.WriteLog("i", "更新企业微信人员信息", string(userJson)) sendWechatUrl := fmt.Sprintf("https://qyapi.weixin.qq.com/cgi-bin/user/update?access_token=%v", token) //获取企业微信取部门成员详情 wechatCallBack := overallhandle.CurlPostJosn(sendWechatUrl, userJson) var orgPeopleList RevokeMsgSendCallBack err = json.Unmarshal(wechatCallBack, &orgPeopleList) // fmt.Printf("成员详情--->%v\n", orgPeopleList) if err != nil { overallhandle.WriteLog("e", "2、更新企业微信人员信息", err, string(wechatCallBack)) return } if orgPeopleList.Errcode != 0 { err = errors.New(orgPeopleList.Errmsg) overallhandle.WriteLog("e", "3、更新企业微信人员信息", orgPeopleList.Errcode, orgPeopleList.Errmsg) return } return }