总结:
应用场景:公司ERP里看到钉钉的考勤记录
一共建了4个实体 ,如果只有单个公司又想简化的话可以只建实体2和4
- 公司ID和公司密匙表(我需要涉及多个公司)
- 钉钉用户与ERP系统用户的对照表
- 钉钉的考勤记录
- 系统的考勤记录
其中踩了个坑,通过接口传入userIdList 获取考勤记录时,老是不全,后来发现这个用户ID属性不能为Long,改为String就好了,有什么问题大家可以多看看文档,里面啥都有,就是有点不友好,我以前开发完之后现在钉钉改了接口参数 ,正好以前写的也不是很好于是重新改了一版,不要再问我要代码,主要代码和思路已经写好分享了,其余基础代码还要问我要你觉得合适吗?
获取钉钉的accessToken
/**
* 获取钉钉的accessToken
*/
public String getAccessToken(String corpid, String secret) {
String requestUrl = "https://oapi.dingtalk.com/gettoken?corpid=" + corpid + "&corpsecret=" + secret;
RequestResult result = SendHttpRequestUtil.doGet(requestUrl);
String accessToken = null;
JSONObject jsonObject = JSON.parseObject(result.getResult());
String msg = jsonObject.get("errmsg").toString();
if ("ok".equals(msg)) {
accessToken = (String) jsonObject.get("access_token");
}
return accessToken;
}
获取钉钉的用户并与自己系统相关联,人事在上工号的时候需要在钉钉那边填一下该员工在系统里的工号(当然,钉钉也有接口你可以自己直接加)
Controller
/**
* 获取钉钉用户并保存
*/
@ResponseBody
@RequestMapping(value = "getDingUser")
public ActionResult<Map<String, Object>> getDingUser() {
return dingUserService.getDingUser();
}
Service
/**
* 获取钉钉的用户信息
*/
@Transactional(readOnly = false)
public ActionResult<Map<String, Object>> getDingUser() {
//清空表数据
dao.deleteTable();
//两个公司遍历
List<HrmDingCompany> companyList = companyService.findList(new HrmDingCompany());
for (HrmDingCompany companyEach : companyList) {
//获取token
String accessToken = recordsService.getAccessToken(companyEach.getCorpId(), companyEach.getCorpSecret());
//获取子部门ID列表
String requestUrl = "https://oapi.dingtalk.com/department/list_ids?access_token=" + accessToken + "&id=1";
RequestResult result = SendHttpRequestUtil.doGet(requestUrl);
JSONObject jsonObject = JSON.parseObject(result.getResult());
String msg = (String) jsonObject.get("errmsg");
List<Integer> departIds = new ArrayList<>();
if ("ok".equals(msg)) {
departIds = (List<Integer>) jsonObject.get("sub_dept_id_list");
} else {
logger.error(jsonObject.toString());
}
//获取部门用户userid列表
List<String> userIds = new ArrayList<>();
for (Integer departId : departIds) {
requestUrl = "https://oapi.dingtalk.com/user/getDeptMember?access_token=" + accessToken + "&deptId=" + departId;
result = SendHttpRequestUtil.doGet(requestUrl);
jsonObject = JSON.parseObject(result.getResult());
msg = (String) jsonObject.get("errmsg");
if ("ok".equals(msg)) {
List<String> tempList = new ArrayList<>();
tempList = (List<String>) jsonObject.get("userIds");
userIds.addAll(tempList);
} else {
logger.error(jsonObject.toString());
}
}
//保存用户对照
for (String userId : userIds) {
HrmDingUser dingUser = getSingleDingUser(userId, accessToken);
dingUser.setCorpId(companyEach.getCorpId());
dingUser.setUserId(userId);
save(dingUser);
}
}
return new ActionResult<Map<String, Object>>(ErpStatusCode.SUCCESS, "操作成功", null);
}
/**
* 获取单个钉钉的用户信息
*/
private HrmDingUser getSingleDingUser(String userId, String accessToken) {
String requestUrl = "https://oapi.dingtalk.com/user/get?access_token=" + accessToken + "&userid=" + userId;
RequestResult result = SendHttpRequestUtil.doGet(requestUrl);
HrmDingUser dingUser = new HrmDingUser();
JSONObject jsonObject = JSON.parseObject(result.getResult());
String msg = (String) jsonObject.get("errmsg");
if ("ok".equals(msg)) {
dingUser.setStaffName(jsonObject.get("name").toString());
dingUser.setStaffNo(jsonObject.get("jobnumber").toString());
}
return dingUser;
}
获取钉钉的考勤记录并保存
Controller
@RequestMapping(value = "syncByDays")
public ActionResult<Map<String, Object>> syncByDays(int days) {
String offset = "0";//分页获取数据,0表示第一页
String limit = "50";//每页50条数据
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");//需要的时间的格式
String workDateFrom = DateUtils.formatDate(DateUtils.getDestDate(new Date(), -days)) + " 00:00:00";
String workDateTo = sdf.format(new Date()) + " 23:59:59";
//多个公司数据合并
List<HrmDingCompany> companyList = companyService.findList(new HrmDingCompany());
for (HrmDingCompany companyEach : companyList) {
String accessToken = recordsService.getAccessToken(companyEach.getCorpId(), companyEach.getCorpSecret());
recordsService.getUserId(accessToken, workDateFrom, workDateTo, offset, limit, companyEach.getCorpId());
}
return new ActionResult<Map<String, Object>>(ErpStatusCode.SUCCESS, "操作成功", null);
}
Service
/**
* 获取钉钉用户的userid
*/
public void getUserId(String accessToken, String workDateFrom, String workDateTo, String offset, String limit, String corpId) {
List<String> userIdList = dingUserDao.findUserIdList(corpId);
List<String> userIdListResult = new ArrayList<>();
if (userIdList.size() > 50) {
for (int i = 0; 50 * i < userIdList.size(); i++) {
userIdListResult = userIdList.subList(50 * i, userIdList.size() > 50 * (i + 1) ? 50 * (i + 1) : userIdList.size());
getDingRecords(accessToken, workDateFrom, workDateTo, offset, limit, corpId, userIdListResult);
}
} else {
userIdListResult = userIdList;
getDingRecords(accessToken, workDateFrom, workDateTo, offset, limit, corpId, userIdListResult);
}
}
/**
* 获取钉钉的考勤记录
*/
@Transactional(readOnly = false)
public void getDingRecords(String accessToken, String workDateFrom, String workDateTo, String offset, String limit, String corpId, List<String> userIdList) {
String requestUrl = "https://oapi.dingtalk.com/attendance/list?access_token=" + accessToken;
JSONObject jsonObject = new JSONObject();
jsonObject.put("workDateFrom", workDateFrom);
jsonObject.put("workDateTo", workDateTo);
jsonObject.put("offset", offset);
jsonObject.put("limit", limit);
jsonObject.put("userIdList", userIdList);
RequestResult result = SendHttpRequestUtil.doPost(requestUrl, "", jsonObject);
JSONObject resultJSON = JSONObject.parseObject(result.getResult());
String msg = (String) resultJSON.get("errmsg");
String hasMore = resultJSON.get("hasMore").toString();
List<HrmDingRecords> resultList = new ArrayList<HrmDingRecords>();
if ("ok".equals(msg)) {
resultList = JSONObject.parseArray(resultJSON.get("recordresult").toString(), HrmDingRecords.class);
}
//保存钉钉的考勤记录
saveDingList(resultList);
//如果还有继续获取
if (resultList.size() == 50) {
//表示获取考勤数据的起始点,第一次传0,如果还有多余数据,下次获取传的offset值为之前的offset+limit
offset = String.valueOf(Integer.parseInt(offset) + Integer.parseInt(limit));
getDingRecords(accessToken, workDateFrom, workDateTo, offset, limit, corpId, userIdList);
}
}
private void saveDingList(List<HrmStaffDingRecords> list) {
//保存钉钉数据
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//需要的时间的格式
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");//需要的时间的格式
for (HrmStaffDingRecords hrmStaffDingRecords : list) {
//如果数据库里已经有了就不插入数据
HrmStaffDingRecords hrmStaffDingRecordsCheck = new HrmStaffDingRecords();
hrmStaffDingRecordsCheck.setId(hrmStaffDingRecords.getId());
List<HrmStaffDingRecords> hrmStaffDingRecordsCheckList = findList(hrmStaffDingRecordsCheck);
if (hrmStaffDingRecordsCheckList.size() > 0) {
hrmStaffDingRecords.setIsNewRecord(false);
} else {
hrmStaffDingRecords.setIsNewRecord(true);
}
//转换获取到的时间格式
hrmStaffDingRecords.setBaseCheckTime(sdf.format(new Date(Long.parseLong(String.valueOf(hrmStaffDingRecords.getBaseCheckTime())))));
hrmStaffDingRecords.setUserCheckTime(sdf.format(new Date(Long.parseLong(String.valueOf(hrmStaffDingRecords.getUserCheckTime())))));
hrmStaffDingRecords.setWorkDate(sdf2.format(new Date(Long.parseLong(String.valueOf(hrmStaffDingRecords.getWorkDate())))));
save(hrmStaffDingRecords);
//保存页面展示数据
HrmStaffAttendanceRecords hrmStaffAttendanceRecords = new HrmStaffAttendanceRecords();
//上班数据保存
if (hrmStaffDingRecords.getCheckType().equals("OnDuty")) {
try {
hrmStaffAttendanceRecords.setAttendanceBeginTime(sdf.parse(hrmStaffDingRecords.getUserCheckTime()));
} catch (ParseException e) {
e.printStackTrace();
}
hrmStaffAttendanceRecords.setUserId(hrmStaffDingRecords.getUserId());
hrmStaffAttendanceRecords.setWorkDate(hrmStaffDingRecords.getWorkDate());
if (hrmStaffDingRecords.getTimeResult().equals("Normal")) {
hrmStaffAttendanceRecords.setAttendanceStatus("0");
} else if (hrmStaffDingRecords.getTimeResult().equals("Late")) {
hrmStaffAttendanceRecords.setAttendanceStatus("5");
} else if (hrmStaffDingRecords.getTimeResult().equals("SeriousLate")) {
hrmStaffAttendanceRecords.setAttendanceStatus("5");
} else if (hrmStaffDingRecords.getTimeResult().equals("Absenteeism")) {
hrmStaffAttendanceRecords.setAttendanceStatus("2");
} else if (hrmStaffDingRecords.getTimeResult().equals("NotSigned")) {
hrmStaffAttendanceRecords.setAttendanceStatus("2");
}
//如果数据库里有记录了则更新上班时间
HrmStaffAttendanceRecords hrmStaffAttendanceRecordsCheck = new HrmStaffAttendanceRecords();
hrmStaffAttendanceRecordsCheck.setUserId(hrmStaffAttendanceRecords.getUserId());
hrmStaffAttendanceRecordsCheck.setWorkDate(hrmStaffAttendanceRecords.getWorkDate());
List<HrmStaffAttendanceRecords> hrmStaffAttendanceRecordsCheckList = hrmStaffAttendanceRecordsService.findList(hrmStaffAttendanceRecordsCheck);
if (hrmStaffAttendanceRecordsCheckList.size() != 0) {
hrmStaffAttendanceRecordsCheck = hrmStaffAttendanceRecordsCheckList.get(0);
hrmStaffAttendanceRecordsCheck.setAttendanceBeginTime(hrmStaffAttendanceRecords.getAttendanceBeginTime());
hrmStaffAttendanceRecordsService.save(hrmStaffAttendanceRecordsCheck);
} else {
hrmStaffAttendanceRecordsService.save(hrmStaffAttendanceRecords);
}
}
//下班数据保存,找到上班记录并更新
if (hrmStaffDingRecords.getCheckType().equals("OffDuty")) {
HrmStaffAttendanceRecords hrmStaffAttendanceRecordsFind = new HrmStaffAttendanceRecords();
hrmStaffAttendanceRecordsFind.setUserId(hrmStaffDingRecords.getUserId());
hrmStaffAttendanceRecordsFind.setWorkDate(hrmStaffDingRecords.getWorkDate());
List<HrmStaffAttendanceRecords> hrmStaffAttendanceRecordsCheckList = hrmStaffAttendanceRecordsService.findList(hrmStaffAttendanceRecordsFind);
if (hrmStaffAttendanceRecordsCheckList.size() != 0) {
hrmStaffAttendanceRecordsFind = hrmStaffAttendanceRecordsCheckList.get(0);
try {
hrmStaffAttendanceRecordsFind.setAttendanceEndTime(sdf.parse(hrmStaffDingRecords.getUserCheckTime()));
if (StringUtils.isNotBlank(hrmStaffAttendanceRecordsFind.getAttendanceBeginTime().toString()) && StringUtils.isNotBlank(hrmStaffAttendanceRecordsFind.getAttendanceEndTime().toString())) {
//午休一个半小时逻辑判断
String restTime = hrmStaffAttendanceRecordsFind.getWorkDate() + " 13:30:00";
Date checkDate = DateUtils.parseDate(restTime);
long between;
if (checkDate.getTime() < hrmStaffAttendanceRecordsFind.getAttendanceEndTime().getTime()) {
between = hrmStaffAttendanceRecordsFind.getAttendanceEndTime().getTime() - hrmStaffAttendanceRecordsFind.getAttendanceBeginTime().getTime() - 1000 * 60 * 90;
} else {
between = hrmStaffAttendanceRecordsFind.getAttendanceEndTime().getTime() - hrmStaffAttendanceRecordsFind.getAttendanceBeginTime().getTime();
}
hrmStaffAttendanceRecordsFind.setWorkHours(TimeUtils.toTimeString(between));
}
} catch (ParseException e) {
e.printStackTrace();
}
hrmStaffAttendanceRecordsService.save(hrmStaffAttendanceRecordsFind);
}
}
}
}
实体
HrmDingCompany
private String corpId; // 企业ID
private String corpSecret; // 企业密匙
HrmDingUser
private String corpId; // 企业ID
private String groupId; // 考勤组ID
private String userId; // 用户ID
private String staffNo; // 员工工号
private String staffName; // 员工姓名
private String officeName; // 部门名称
HrmDingRecords
private String baseCheckTime; // 计算迟到和早退,基准时间
private String checkType; // 考勤类型(OnDuty:上班,OffDuty:下班)
private String corpId; // 企业ID
private String groupId; // 考勤组ID
private String locationResult; // 上班打卡时间
private String planId; // 排班ID
private String recordId; // 打卡记录ID
private String timeResult; // 时间结果(Normal:正常;Early:早退; Late:迟到;SeriousLate:严重迟到;Absenteeism:旷工迟到; NotSigned:未打卡)
private String userCheckTime; // 实际打卡时间
private String userId; // 用户ID
private String workDate; // 工作日
private String procInstId; // 关联的审批实例id
//用于页面展示
private String staffNo; // 员工工号
private String staffName; // 员工姓名
private String officeName; // 部门名称
HrmDingAttendance
private String userId; // 钉钉用户ID
private String corpId; // 企业ID
private String staffNo; // 员工工号
private String staffName; // 员工姓名
private String officeName; // 部门名称
private String attendanceStatus; // 考勤状态0正常1补勤2缺勤3请假4放假5迟到
private String workDate; // 考勤日期
private Date attendanceBeginTime; // 上班打卡时间
private Date attendanceEndTime; // 下班打卡时间
private String workHours; // 当日上班时长
private String zhengChangDays; // 正常天数
private String queQinDays; // 缺勤天数
private String qingJiaDays; // 请假天数
private String fangJiaDays; // 放假天数
private String beginDate; // 时间查询
private String endDate; // 时间查询
private String time; // 统计用