dingtalk_oa.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. package xnet
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "gcore/core"
  6. "gcore/xnet"
  7. "log"
  8. "net/http"
  9. "strings"
  10. )
  11. type DevConf struct {
  12. AppKey string
  13. AppSecret string
  14. GetTokenUrl string
  15. GetDeptListUrl string
  16. GetDeptUserListUrl string
  17. GetAttendanceGroupUrl string
  18. GetAttendanceGroupUserIdsUrl string
  19. GetAttendanceClockDataUrl string
  20. GetAttendanceGroupDetailsUrl string
  21. ListAttendanceGroupMenberListByIdsUrl string
  22. Token string
  23. Params map[string]string
  24. Headers map[string]string
  25. Cookie []*http.Cookie
  26. DeptId int64
  27. OpUserId int64
  28. ManageGroupId int64
  29. EmployeeGroupId int64
  30. }
  31. // @title GetToken
  32. // @description 获取access token
  33. // @param
  34. // @return
  35. func (m *DevConf) GetToken() error {
  36. params := map[string]string{"appkey": m.AppKey, "appsecret": m.AppSecret}
  37. content, err := xnet.GetX(m.GetTokenUrl, params, m.Headers, m.Cookie)
  38. if err != nil {
  39. log.Printf("GetToken error : %v", err)
  40. }
  41. //fmt.Printf("%v\n", content)
  42. ret := map[string]interface{}{}
  43. err = json.Unmarshal([]byte(content), &ret)
  44. if err != nil {
  45. log.Printf("Unmarshal error : %v", err)
  46. return err
  47. }
  48. m.Token = ret["access_token"].(string)
  49. m.Params["access_token"] = ret["access_token"].(string)
  50. m.Headers["Content-Type"] = "application/json"
  51. return nil
  52. }
  53. // @title GetDeptList
  54. // @description 获取部门列表,只支持查询下一级子部门 https://developers.dingtalk.com/document/app/obtain-the-department-list-v2
  55. // @param
  56. // @return
  57. func (m *DevConf) GetDeptList(deptId int64) ([]interface{}, error) {
  58. result := []interface{}{}
  59. PostData := make(map[string]interface{})
  60. PostData["dept_id"] = deptId
  61. content, err := xnet.PostJson(m.GetDeptListUrl, m.Params, m.Headers, PostData, m.Cookie)
  62. if err != nil {
  63. log.Printf("GetDeptUserList PostJson error : %v", err)
  64. return result, err
  65. }
  66. ret := map[string]interface{}{}
  67. err = json.Unmarshal([]byte(content), &ret)
  68. if err != nil {
  69. log.Printf("Unmarshal error : %v", err)
  70. return result, err
  71. }
  72. //fmt.Printf("ret===>%v\n", ret)
  73. result = ret["result"].([]interface{})
  74. /*
  75. {
  76. "errcode": 0,
  77. "errmsg":"ok",
  78. "result": [
  79. {
  80. "auto_add_user": true,
  81. "create_dept_group": true,
  82. "dept_id": 37xxxx95,
  83. "name": "市场部",
  84. "parent_id": 1
  85. },
  86. {
  87. "auto_add_user": true,
  88. "create_dept_group": true,
  89. "dept_id": 399xxxx96,
  90. "name": "财务部",
  91. "parent_id": 1
  92. }
  93. ],
  94. "request_id": "5um7ykyaalsj"
  95. }
  96. */
  97. return result, nil
  98. }
  99. // @title GetDeptUserList
  100. // @description 获取部门成员的姓名和userid https://developers.dingtalk.com/document/app/queries-the-simple-information-of-a-department-user
  101. // @param
  102. // @return
  103. func (m *DevConf) GetDeptUserList(deptId int64) (map[string]string, error) {
  104. cursor := 0.0
  105. size := 100
  106. PostData := make(map[string]interface{})
  107. PostData["dept_id"] = deptId
  108. PostData["size"] = size
  109. deptUserList := make(map[string]string)
  110. //外层循环,翻页
  111. for {
  112. PostData["cursor"] = cursor
  113. //fmt.Printf("%v\n", cursor)
  114. //请求APi
  115. content, err := xnet.PostJson(m.GetDeptUserListUrl, m.Params, m.Headers, PostData, m.Cookie)
  116. if err != nil {
  117. log.Printf("GetDeptUserList PostJson error : %v", err)
  118. }
  119. ret := map[string]interface{}{}
  120. err = json.Unmarshal([]byte(content), &ret)
  121. if err != nil {
  122. log.Printf("Unmarshal error : %v", err)
  123. }
  124. /*
  125. {
  126. "errcode": 0,
  127. "errmsg": "ok",
  128. "result": {
  129. "has_more": false,
  130. "list": [
  131. {
  132. "name": "测试用户2",
  133. "userid": "user100"
  134. },
  135. {
  136. "name": "李思",
  137. "userid": "user1"
  138. }
  139. ]
  140. },
  141. "request_id": "x4p6arvi0fzj"
  142. }
  143. */
  144. result := ret["result"]
  145. //遍历用户信息list
  146. for _, i := range result.(map[string]interface{})["list"].([]interface{}) {
  147. deptUserList[i.(map[string]interface{})["userid"].(string)] = i.(map[string]interface{})["name"].(string)
  148. }
  149. //当前请求返回数据量小于size,跳出循环
  150. if len(result.(map[string]interface{})["list"].([]interface{})) < size {
  151. break
  152. }
  153. if result.(map[string]interface{})["next_cursor"] == nil {
  154. break
  155. }
  156. cursor = result.(map[string]interface{})["next_cursor"].(float64)
  157. }
  158. return deptUserList, nil
  159. }
  160. // @title GetAttendanceGroup
  161. // @description 批量获取考勤组摘要 https://developers.dingtalk.com/document/app/batch-query-of-simple-information-of-the-attendance-group
  162. // @param
  163. // @return
  164. func (m *DevConf) GetAttendanceGroup() ([]map[string]interface{}, error) {
  165. groupData := []map[string]interface{}{}
  166. PostData := make(map[string]interface{})
  167. cursor := 1
  168. PostData["op_user_id"] = m.OpUserId
  169. PostData["cursor"] = cursor
  170. content, err := xnet.PostJson(m.GetAttendanceGroupUrl, m.Params, m.Headers, PostData, m.Cookie)
  171. if err != nil {
  172. log.Printf("GetAttendanceClockData PostJson error : %v", err)
  173. return groupData, err
  174. }
  175. ret := map[string]interface{}{}
  176. err = json.Unmarshal([]byte(content), &ret)
  177. if err != nil {
  178. log.Printf("Unmarshal error : %v", err)
  179. return groupData, err
  180. }
  181. /*
  182. {
  183. "errcode": 0,
  184. "result": {
  185. "cursor": 685935028,
  186. "has_more": false,
  187. "result": [
  188. {
  189. "id": 677765054,
  190. "name": "周末加班"
  191. },
  192. {
  193. "id": 685935028,
  194. "name": "考勤"
  195. }
  196. ]
  197. },
  198. "success": true,
  199. "request_id": "wv9973jntamw"
  200. }
  201. */
  202. //fmt.Printf("%v\n", ret)
  203. result := ret["result"]
  204. for _, group := range result.(map[string]interface{})["result"].([]interface{}) {
  205. group_id := int64(group.(map[string]interface{})["id"].(float64))
  206. group_name := group.(map[string]interface{})["name"].(string)
  207. groupData = append(groupData, map[string]interface{}{"group_id": group_id, "group_name": group_name})
  208. }
  209. return groupData, err
  210. }
  211. // @title GetAttendanceClockData
  212. // @description 获取7天内的指定时间段成员的打卡记录, https://developers.dingtalk.com/document/app/open-attendance-clock-in-data
  213. // @param days获取多少天内的考勤数据
  214. // @return
  215. func (m *DevConf) GetAttendanceClockData(days int, userIdList []string) (map[string][]int, error) {
  216. limit := 50 //表示获取考勤数据的条数,最大不能超过50条。
  217. userIdStep := 50 //单次请求传入的userId数量
  218. //最近30天日期数组
  219. workData, _ := core.GetWorkDate(days)
  220. fmt.Printf("workData lenght %v\n", len(workData))
  221. //post请求的body
  222. PostData := make(map[string]interface{})
  223. PostData["dept_id"] = m.DeptId
  224. PostData["limit"] = limit
  225. //当前部门每个人的考勤数据
  226. attendanceData := make(map[string][]int)
  227. userIdIndex := 0
  228. //userId的遍历
  229. for {
  230. if userIdIndex+1 > len(userIdList) {
  231. break
  232. }
  233. fmt.Printf("=================第%v位至第%v位user开始遍历\n", userIdIndex+1, userIdIndex+userIdStep)
  234. if userIdIndex+userIdStep > len(userIdList) {
  235. PostData["userIdList"] = userIdList[userIdIndex+1:]
  236. } else {
  237. PostData["userIdList"] = userIdList[userIdIndex+1 : userIdIndex+userIdStep]
  238. }
  239. //外面的for是日期遍历,间隔6天
  240. date := 0
  241. dateStep := 6
  242. for {
  243. if date >= len(workData) {
  244. break
  245. }
  246. fmt.Printf("---------------%v开始的考勤\n", workData[date+1])
  247. fmt.Printf("date==>%v\n", date+1)
  248. splits := strings.Split(workData[date+1], "/")
  249. PostData["workDateFrom"] = fmt.Sprintf("%s-%s-%s 00:00:00", splits[0], splits[1], splits[2])
  250. if date+1+dateStep < len(workData) {
  251. splits = strings.Split(workData[date+1+dateStep], "/")
  252. } else {
  253. splits = strings.Split(workData[len(workData)-1], "/")
  254. }
  255. PostData["workDateTo"] = fmt.Sprintf("%s-%s-%s 00:00:00", splits[0], splits[1], splits[2])
  256. //分页遍历
  257. offset := 0 //获取考勤数据的起始点。第一次传0,如果还有多余数据,下次获取传的offset值为之前的offset+limit,
  258. for {
  259. fmt.Printf("---------------从%v条到%v条的数据\n", offset, offset+limit)
  260. PostData["offset"] = offset
  261. //fmt.Printf("offset %v\n", offset)
  262. //fmt.Printf("data %v\n", data)
  263. content, err := xnet.PostJson(m.GetAttendanceClockDataUrl, m.Params, m.Headers, PostData, m.Cookie)
  264. if err != nil {
  265. log.Printf("GetAttendanceClockData PostJson error : %v", err)
  266. }
  267. ret := map[string]interface{}{}
  268. err = json.Unmarshal([]byte(content), &ret)
  269. if err != nil {
  270. log.Printf("Unmarshal error : %v", err)
  271. }
  272. //fmt.Printf("%v\n", ret)
  273. //开始解析本次请求的考勤数据,添加到attendanceData
  274. for _, i := range ret["recordresult"].([]interface{}) {
  275. userId := i.(map[string]interface{})["userId"].(string)
  276. userCheckTime := i.(map[string]interface{})["userCheckTime"].(float64)
  277. //把考勤数据加到个人的slice里
  278. attendanceData[userId] = append(attendanceData[userId], int(userCheckTime))
  279. }
  280. //当前请求返回数据量小于size,跳出循环
  281. if len(ret["recordresult"].([]interface{})) < limit {
  282. break
  283. }
  284. offset += limit
  285. //time.Sleep(1*time.Second)
  286. }
  287. date += dateStep
  288. }
  289. userIdIndex += userIdStep
  290. }
  291. return attendanceData, nil
  292. }
  293. // @title GetAttendanceGroupDetails
  294. // @description 获取考勤组列表, https://developers.dingtalk.com/document/app/queries-attendance-group-list-details
  295. // @param
  296. // @return map[5.5天制管理人员:753150009 5天制:761355305 6天制员工:667040040 合肥1:721640063 合肥6天制:795345194 清洁:854690013 音乐:761855162]
  297. func (m *DevConf) GetAttendanceGroupDetails() (map[int64]string, error) {
  298. PostData := make(map[string]interface{})
  299. PostData["offset"] = 0
  300. PostData["size"] = 10
  301. content, err := xnet.PostJson(m.GetAttendanceGroupDetailsUrl, m.Params, m.Headers, PostData, m.Cookie)
  302. if err != nil {
  303. log.Printf("GetAttendanceClockData PostJson error : %v", err)
  304. }
  305. ret := map[string]interface{}{}
  306. err = json.Unmarshal([]byte(content), &ret)
  307. if err != nil {
  308. log.Printf("Unmarshal error : %v", err)
  309. }
  310. attendaceGroups := make(map[int64]string)
  311. groups := ret["result"].(map[string]interface{})["groups"]
  312. for _, i := range groups.([]interface{}) {
  313. attendaceGroups[int64(i.(map[string]interface{})["group_id"].(float64))] = i.(map[string]interface{})["group_name"].(string)
  314. }
  315. return attendaceGroups, nil
  316. }
  317. // @title ListAttendanceGroupMenberListByIds
  318. // @description 考勤组成员校验 , https://developers.dingtalk.com/document/app/query-members-by-id
  319. // @param
  320. // @return
  321. func (m *DevConf) ListAttendanceGroupMenberListByIds(groupId int64, userIdList []string) ([]string, error) {
  322. PostData := make(map[string]interface{})
  323. PostData["op_user_id"] = m.OpUserId
  324. PostData["group_id"] = groupId
  325. userids := strings.Join(userIdList, ",")
  326. //fmt.Printf("userids=======>%v\n", userids)
  327. PostData["member_ids"] = userids
  328. PostData["member_type"] = 0
  329. content, err := xnet.PostJson(m.ListAttendanceGroupMenberListByIdsUrl, m.Params, m.Headers, PostData, m.Cookie)
  330. if err != nil {
  331. log.Printf("GetAttendanceClockData PostJson error : %v", err)
  332. }
  333. ret := map[string]interface{}{}
  334. err = json.Unmarshal([]byte(content), &ret)
  335. if err != nil {
  336. log.Printf("Unmarshal error : %v", err)
  337. }
  338. //fmt.Printf("%v\n", ret)
  339. userIds := []string{}
  340. for _, i := range ret["result"].([]interface{}) {
  341. userIds = append(userIds, i.(string))
  342. }
  343. return userIds, nil
  344. }