JAVA 对接钉钉API(人员、部门、官方智能工作流)20210527

前言

应公司要求,公司人事HR系统需要对接钉钉考勤数据,所以需要获取钉钉的打卡记录、出差、外出、请假、调岗的数据,然后转换成HR系统数据。

对接前准备

创建应用

1、首先需要管理员登录钉钉开放平台,创建应用。

说明 只有管理员和子管理员可登录开发者后台。

钉钉开放平台:钉钉开放平台能力中心

2、在应用开发页面,选择企业内部开发,然后单击创建应用

JAVA 对接钉钉API(人员、部门、官方智能工作流)20210527_第1张图片

3、填写应用的基本信息,然后单击确定创建

JAVA 对接钉钉API(人员、部门、官方智能工作流)20210527_第2张图片

应用创建后,在基础信息页可获取AppKey和AppSecret。

如果是定制服务商创建的应用,应用的key为CustomKey。开发者需要使用应用的CustomKey和CustomSecret获取调用服务端API的授权凭证。

开发管理

在应用详情页,单击开发管理配置应用的基本信息。

JAVA 对接钉钉API(人员、部门、官方智能工作流)20210527_第3张图片

配置

是否必选

配置说明

开发模式

H5微应用必须配置

选择开发模式:

  • 开发应用:开发一个新的H5微应用。

  • 快捷链接:添加一个已有的H5微应用。企业可以将内部应用通过快捷链接的方式接入钉钉,方便内部员工在钉钉工作台中使用。

服务器出口IP

输入调用钉钉服务端API时使用的IP即企业服务器的公网IP,多个IP请以英文逗号","隔开,支持带一个*号通配符的IP格式。

应用首页地址

H5微应用必须配置

输入应用首页URL,在移动端工作台点击应用图标会跳转到此页面。

可输入后端服务部署的服务器的IP或域名。例如:http://公网IP:8080

PC端首页地址

输入在PC端钉钉工作台上打开应用的地址。链接地址必须以http或https开头。

说明 

如果未填写,在钉钉PC端工作台点击应用图标时,会提示“电脑版暂不支持显示,请用手机钉钉扫描下方二维码查看”。只能在手机钉钉客户端使用该应用。

管理后台地址

输入管理员在钉钉管理后台访问该应用的地址。

添加依赖

由于jar是在本地项目,不是中央Maven库,所以要如下引用



	com.taobao.top
	top-api-sdk-dev
	ding-open-mc-SNAPSHOT
	system
	${pom.basedir}/src/main/webapp/WEB-INF/lib/taobao-sdk-java-auto_1479188381469-20210517.jar

接口对接

公司项目使用mybatis,所以部分代码忽略。

process_code:审批流的唯一码。在审批流编辑页面的URL中获取。

DingDingUtil 与钉钉对接工具类

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 钉钉工具类
 */
@Slf4j
public class DingDingUtil {

	private final static String SYSTEM_ERROR ="SYSTEM_ERROR";

    private final static String APPKEY ="";

    private final static String APPSECRET="";

    private final static Long AGENTID = 0L;

    public final static String LEAVE_PROCESS_CODE = "PROC-70A9A9C2-BF877C09E3FE";
    public final static String PUBLIC_PROCESS_CODE = "PROC-C6B6F367-BE545F51D9E0";
    public final static String TRAVELWORK_PROCESS_CODE = "PROC-8763D6A9-A788E7CEC119";
    public final static String TRANSFER_PROCESS_CODE = "PROC-E05FD7DE-5A2B9D7CD6AC";


    //获取token
    public static String getToken (){
        Object object = LocalCacheClient.get("access_token");
        if(object != null){
            return object.toString();
        }
        DefaultDingTalkClient client = new
                DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(DingDingUtil.APPKEY);
        request.setAppsecret(DingDingUtil.APPSECRET);
        request.setHttpMethod("GET");
        try {
            OapiGettokenResponse response = client.execute(request);
            LocalCacheClient.set("access_token", response.getAccessToken(),7200*1000);
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response.getAccessToken();
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }

    //获取部门列表
    public static List getDepartment(){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/department/listsub");
        OapiV2DepartmentListsubRequest request = new OapiV2DepartmentListsubRequest();
        //获取根部门下所有部门列表  根部门的部门id为1
//        request.setDeptId(1L);
        request.setHttpMethod("GET");
        try {
            OapiV2DepartmentListsubResponse response = client.execute(request, DingDingUtil.getToken());
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response.isSuccess() ? response.getResult():null;
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }

    //获取部门下的所有用户列表
    public static List getDepartmentUserId(Long departmentId){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/listid");
        OapiUserListidRequest req = new OapiUserListidRequest();
        req.setDeptId(departmentId);

        try {
            OapiUserListidResponse response = client.execute(req, DingDingUtil.getToken());
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response.isSuccess()?response.getResult().getUseridList():null;
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }

    //获取部门下的所有用户列表
    public static OapiV2UserListResponse.PageResult getDepartmentUser(Long departmentId, long cursor, long size){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/list");
        OapiV2UserListRequest request = new OapiV2UserListRequest();
        request.setDeptId(departmentId);
        request.setCursor(cursor);
        request.setSize(size);
        request.setOrderField("modify_desc");
        request.setHttpMethod("GET");

        try {
            OapiV2UserListResponse  response = client.execute(request, DingDingUtil.getToken());
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response.isSuccess()?response.getResult():null;
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }

    //获取钉钉考勤记录
    public static List getAttendanceList(String startWorkDate, String endWorkDate, List userIdList, long offset, long limit) {
        // 通过调用接口获取考勤打卡结果
        DingTalkClient clientDingTalkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/attendance/list");
        OapiAttendanceListRequest requestAttendanceListRequest = new OapiAttendanceListRequest();
        // 查询考勤打卡记录的起始工作日
        requestAttendanceListRequest.setWorkDateFrom(startWorkDate);
        // 查询考勤打卡记录的结束工作日
        requestAttendanceListRequest.setWorkDateTo(endWorkDate);
        // 员工在企业内的userid列表,最多不能超过50个。
        requestAttendanceListRequest.setUserIdList(userIdList);
        // 表示获取考勤数据的起始点
        requestAttendanceListRequest.setOffset(offset);
        // 表示获取考勤数据的条数,最大不能超过50条。
        requestAttendanceListRequest.setLimit(limit);
        OapiAttendanceListResponse response = null;
        try {
            response = clientDingTalkClient.execute(requestAttendanceListRequest,DingDingUtil.getToken());
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response.isSuccess()?response.getRecordresult():null;
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }

    //给用户推送消息(文字消息)
    public static Object pushUser(String userIds,String content){
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2");

        OapiMessageCorpconversationAsyncsendV2Request request = new OapiMessageCorpconversationAsyncsendV2Request();
        request.setUseridList(userIds);
        request.setAgentId(AGENTID);
        request.setToAllUser(false);

        OapiMessageCorpconversationAsyncsendV2Request.Msg msg = new OapiMessageCorpconversationAsyncsendV2Request.Msg();
        msg.setMsgtype("text");
        msg.setText(new OapiMessageCorpconversationAsyncsendV2Request.Text());
        msg.getText().setContent(content);
        request.setMsg(msg);

        try {
            OapiMessageCorpconversationAsyncsendV2Response response = client.execute(request, DingDingUtil.getToken());
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response;
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }

    //获取审批实例ID列表
    public static OapiProcessinstanceListidsResponse.PageResult getProcessinstanceListid(String processCode, Long startTime, Long endTime, long cursor, long size) {
        try {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/listids");
            OapiProcessinstanceListidsRequest request = new OapiProcessinstanceListidsRequest();
            request.setProcessCode(processCode);
            request.setStartTime(startTime);
            if(endTime != null) {
                request.setEndTime(endTime);
            }
            request.setSize(size);
            request.setCursor(cursor);
            OapiProcessinstanceListidsResponse response = client.execute(request, DingDingUtil.getToken());
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response.isSuccess()?response.getResult():null;
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }

    //获取审批实例详情
    public static OapiProcessinstanceGetResponse.ProcessInstanceTopVo getProcessinstanceInfo(String processInstanceId) {
        try {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/processinstance/get");
            OapiProcessinstanceGetRequest request = new OapiProcessinstanceGetRequest();
            request.setProcessInstanceId(processInstanceId);
            OapiProcessinstanceGetResponse response = client.execute(request, DingDingUtil.getToken());
            if(!response.isSuccess()) {
                log.error("调用钉钉接口失败:"+response.getMessage()); 
            }
            return response.isSuccess()?response.getProcessInstance():null;
        } catch (ApiException e) {
            log.error(DingDingUtil.SYSTEM_ERROR, e); 
        }
        return null;
    }


}

LocalCacheClient 本地缓存工具

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 本地缓存工具
 */
public class LocalCacheClient {

    // 缓存map
    private static Map cacheMap = new HashMap();
    // 缓存有效期map
    private static Map expireTimeMap = new HashMap();


    /**
     * 获取指定的value,如果key不存在或者已过期,则返回null
     * @param key
     * @return
     */
    public static Object get(String key) {
        if (!cacheMap.containsKey(key)) {
            return null;
        }
        if (expireTimeMap.containsKey(key)) {
            if (expireTimeMap.get(key) < System.currentTimeMillis()) { // 缓存失效,已过期
                return null;
            }
        }
        return cacheMap.get(key);
    }

    /**
     * @param key
     * @param 
     * @return
     */
    public static  T getT(String key) {
        Object obj = get(key);
        return obj == null ? null : (T) obj;
    }

    /**
     * 设置value(不过期)
     * @param key
     * @param value
     */
    public static void set(String key, Object value) {
        cacheMap.put(key, value);
    }

    /**
     * 设置value
     * @param key
     * @param value
     * @param millSeconds 过期时间(毫秒)
     */
    public static void set(final String key, Object value, int millSeconds) {
        final long expireTime = System.currentTimeMillis() + millSeconds;
        cacheMap.put(key, value);
        expireTimeMap.put(key, expireTime);
        if (cacheMap.size() > 2) { // 清除过期数据
            new Thread(new Runnable() {
                public void run() {
                    // 此处若使用foreach进行循环遍历,删除过期数据,会抛出java.util.ConcurrentModificationException异常
                    Iterator> iterator = cacheMap.entrySet().iterator();
                    while (iterator.hasNext()) {
                        Map.Entry entry = iterator.next();
                        if (expireTimeMap.containsKey(entry.getKey())) {
                            long expireTime = expireTimeMap.get(key);
                            if (System.currentTimeMillis() > expireTime) {
                                iterator.remove();
                                expireTimeMap.remove(entry.getKey());
                            }
                        }
                    }
                }
            }).start();
        }
    }

    /**
     * key是否存在
     * @param key
     * @return
     */
    public static boolean isExist(String key) {
        return cacheMap.containsKey(key);
    }

}

对接钉钉业务代码

单独获取钉钉人员、部门方法

@Test
public void doBaseTask() {
	log.info("--------------------------钉钉人员部门基本任务开始-----------------------");
	Date now = new Date();

	try {
		List departmentList = DingDingUtil.getDepartment();
		if(departmentList != null && departmentList.size() > 0) {
			List userIdList = new ArrayList<>();
			List dingdingDeptList = new ArrayList<>();
			List userList = new ArrayList();
			for(OapiV2DepartmentListsubResponse.DeptBaseResponse department:departmentList) {
				long cursor = 0L;
				long size = 50L;
				OapiV2UserListResponse.PageResult userPageResult = DingDingUtil.getDepartmentUser(department.getDeptId(), cursor, size);
				while (userPageResult != null && userPageResult.getHasMore()) {
					userList.addAll(userPageResult.getList());
					cursor = userPageResult.getNextCursor();
					userPageResult = DingDingUtil.getDepartmentUser(department.getDeptId(), cursor, size);
				}
				if(userPageResult != null && userPageResult.getList() != null && userPageResult.getList().size() > 0) {
					userList.addAll(userPageResult.getList());
				}

				HrDingdingDept hrDingdingDept = new HrDingdingDept();
				hrDingdingDept.setDeptId(department.getDeptId());
				hrDingdingDept.setName(department.getName());
				hrDingdingDept.setParentId(department.getParentId());
				hrDingdingDept.setUpdateTime(now);
				dingdingDeptList.add(hrDingdingDept);
			}

			hrDingdingService.insertOrUpdateDept(dingdingDeptList);

			if(userList != null && userList.size() > 0) {
				List hrDingdingUserList = new ArrayList<>();
				for(OapiV2UserListResponse.ListUserResponse user:userList) {
					userIdList.add(user.getUserid());

					HrDingdingUser hrDingdingUser = new HrDingdingUser();
					hrDingdingUser.setUserid(user.getUserid());
					hrDingdingUser.setUnionid(user.getUnionid());
					hrDingdingUser.setName(user.getName());
					hrDingdingUser.setAvatar(user.getAvatar());
					hrDingdingUser.setStateCode(user.getStateCode());
					hrDingdingUser.setMobile(user.getMobile());
					hrDingdingUser.setHideMobile(user.getHideMobile()?"true":"false");
					hrDingdingUser.setTelephone(user.getTelephone());
					hrDingdingUser.setJobNumber(user.getJobNumber());
					hrDingdingUser.setTitle(user.getTitle());
					hrDingdingUser.setEmail(user.getEmail());
					hrDingdingUser.setOrgEmail(user.getOrgEmail());
					hrDingdingUser.setWorkPlace(user.getWorkPlace());
					hrDingdingUser.setRemark(user.getRemark());
					hrDingdingUser.setDeptIdList(JSON.toJSONString(user.getDeptIdList()));
					hrDingdingUser.setExtension(user.getExtension());
					hrDingdingUser.setAdmin(user.getAdmin()?"true":"false");
					hrDingdingUser.setBoss(user.getBoss()?"true":"false");
					hrDingdingUser.setLeader(user.getLeader()?"true":"false");
					if(user.getHiredDate() != null) {
						hrDingdingUser.setHiredDate(new Date(Long.valueOf(user.getHiredDate())));
					}
					hrDingdingUser.setExclusiveAccountType(user.getExclusiveAccountType());
					hrDingdingUser.setExclusiveAccount(user.getExclusiveAccount()?"true":"false");
					hrDingdingUser.setLoginId(user.getLoginId());
					hrDingdingUser.setUpdateTime(now);
					hrDingdingUserList.add(hrDingdingUser);
				}

				hrDingdingService.insertOrUpdateUser(hrDingdingUserList);
			}
		}
	} catch (Exception e) {
		log.error(ConstantsUtil.SYSTEM_ERROR, e);
	}

	log.info("--------------------------钉钉人员部门基本任务结束-----------------------");
}

单独获取钉钉打卡记录

@Test
public void doAttendTest() {
	System.out.println(DingDingUtil.getToken());
	Date now = new Date();

	String workDate = DateUtils.getDate(DateUtils.addDay(new Date(), -3));
	String nowDate = DateUtils.getDate(new Date());
	String startWorkDate = workDate + " 00:00:00";
	String endWorkDate = nowDate + " 23:59:59";

	List attendanceList = new ArrayList<>();

	List departmentList = DingDingUtil.getDepartment();
	if(departmentList != null && departmentList.size() > 0) {
		List userIdList = new ArrayList<>();
		for(OapiV2DepartmentListsubResponse.DeptBaseResponse department:departmentList) {
			List userIdListTmp = DingDingUtil.getDepartmentUserId(department.getDeptId());
			if(userIdListTmp != null && userIdListTmp.size() > 0) {
				userIdList.addAll(userIdListTmp);
			}
		}

		if(userIdList != null && userIdList.size() > 0) {
			List> userIds = Lists.partition(userIdList, 50);
			for(List users:userIds) {
				int count = 1;
				long offset = 0L;
				long limit = 50L;
				List attendanceListTmp = DingDingUtil.getAttendanceList(startWorkDate, endWorkDate, users, offset, limit);
				if(attendanceListTmp != null && attendanceListTmp.size() > 0) {
					attendanceList.addAll(attendanceListTmp);
					while (attendanceListTmp.size() <= 50) {
						count++;
						offset = (count - 1) * limit;
						attendanceListTmp = DingDingUtil.getAttendanceList(startWorkDate, endWorkDate, users, offset, limit);
						if(attendanceListTmp == null || attendanceListTmp.size() == 0) {
							break;
						}
						attendanceList.addAll(attendanceListTmp);
					}
				}

			}
		}

		if(attendanceList != null && attendanceList.size() > 0) {
			List hrDingdingAttendanceList = new ArrayList<>();
			for(OapiAttendanceListResponse.Recordresult attendance: attendanceList) {
				HrDingdingAttendance hrDingdingAttendance = new HrDingdingAttendance();
				hrDingdingAttendance.setAttendanceId(attendance.getId());
				hrDingdingAttendance.setSourceType(attendance.getSourceType());
				hrDingdingAttendance.setBaseCheckTime(attendance.getBaseCheckTime());
				hrDingdingAttendance.setUserCheckTime(attendance.getUserCheckTime());
				hrDingdingAttendance.setProcInstId(attendance.getProcInstId());
				hrDingdingAttendance.setApproveId(attendance.getApproveId());
				hrDingdingAttendance.setLocationResult(attendance.getLocationResult());
				hrDingdingAttendance.setTimeResult(attendance.getTimeResult());
				hrDingdingAttendance.setCheckType(attendance.getCheckType());
				hrDingdingAttendance.setUserId(attendance.getUserId());
				hrDingdingAttendance.setWorkDate(attendance.getWorkDate());
				hrDingdingAttendance.setRecordId(attendance.getRecordId());
				hrDingdingAttendance.setPlanId(attendance.getPlanId());
				hrDingdingAttendance.setGroupId(attendance.getGroupId());
				hrDingdingAttendance.setUpdateTime(now);
				hrDingdingAttendanceList.add(hrDingdingAttendance);
			}

			hrDingdingService.insertOrUpdateAttendance(hrDingdingAttendanceList);
		}
	}
}

获取工作流程数据

@Test
public void doJXProcessinstanceTest() {

	String type = "";
	//出差
	String processCode = DingDingUtil.TRAVELWORK_PROCESS_CODE;
	if(StringUtils.isNotBlank(processCode)) {
		if(DingDingUtil.TRANSFER_PROCESS_CODE.equals(processCode)) {
			type = "transfer";//调岗
		} else if(DingDingUtil.TRAVELWORK_PROCESS_CODE.equals(processCode)) {
			type = "travelwork";//出差
		} else if(DingDingUtil.PUBLIC_PROCESS_CODE.equals(processCode)) {
			type = "public";//外出
		} else if(DingDingUtil.LEAVE_PROCESS_CODE.equals(processCode)) {
			type = "leave";//请假
		}
	}
	try {

		List processinstanceList = hrDingdingService.getProcessinstanceList(processCode);
		if(processinstanceList != null && processinstanceList.size() > 0) {
			hrDingdingService.insertOrUpdateProcessInstance(type, processinstanceList);
		}
	} catch (Exception e) {
		e.printStackTrace();
	}

}

public List getProcessinstanceListid(String processCode) {
	Date now = new Date();
	//仅仅获取30天以为的工作流程
	String workDate = DateUtils.getDate(DateUtils.addDay(new Date(), -30));
	String startDate = workDate + " 00:00:00";
	long startTime = Long.valueOf(DateUtils.stringToTime(startDate, EnumDateStyle.YYYY_MM_DD_HH_MM_SS));

	List processinstanceList = new ArrayList<>();
	List processinstanceListids = new ArrayList<>();
	long cursor = 0L;
	long size = 10L;
	OapiProcessinstanceListidsResponse.PageResult processinstanceListidsResponse = DingDingUtil.getProcessinstanceListid(processCode, startTime, null, cursor, size);
	while (processinstanceListidsResponse != null && processinstanceListidsResponse.getNextCursor() != null) {
		processinstanceListids.addAll(processinstanceListidsResponse.getList());
		cursor = processinstanceListidsResponse.getNextCursor();
		processinstanceListidsResponse = DingDingUtil.getProcessinstanceListid(processCode, startTime, null, cursor, size);
	}
	if(processinstanceListidsResponse != null && processinstanceListidsResponse.getList() != null && processinstanceListidsResponse.getList().size() > 0) {
		processinstanceListids.addAll(processinstanceListidsResponse.getList());
	}
	if(processinstanceListids != null && processinstanceListids.size() > 0) {
		for(String processInstanceId:processinstanceListids) {
			OapiProcessinstanceGetResponse.ProcessInstanceTopVo processInstanceTopVo = DingDingUtil.getProcessinstanceInfo(processInstanceId);
			if(processInstanceTopVo != null) {
				HrDingdingProcessWithBLOBs hrDingdingProcess = new HrDingdingProcessWithBLOBs();
				hrDingdingProcess.setProcessInstanceId(processInstanceId);
				hrDingdingProcess.setProcessCode(processCode);
				hrDingdingProcess.setTitle(processInstanceTopVo.getTitle());
				hrDingdingProcess.setCreateTime(processInstanceTopVo.getCreateTime());
				hrDingdingProcess.setFinishTime(processInstanceTopVo.getFinishTime());
				if(StringUtils.isNotBlank(processInstanceTopVo.getOriginatorDeptId())) {
					hrDingdingProcess.setOriginatorDeptId(Long.valueOf(processInstanceTopVo.getOriginatorDeptId()));
				}
				hrDingdingProcess.setOriginatorDeptName(processInstanceTopVo.getOriginatorDeptName());
				hrDingdingProcess.setOriginatorUserid(processInstanceTopVo.getOriginatorUserid());
				hrDingdingProcess.setStatus(processInstanceTopVo.getStatus());
				hrDingdingProcess.setResult(processInstanceTopVo.getResult());
				hrDingdingProcess.setBusinessId(processInstanceTopVo.getBusinessId());
				hrDingdingProcess.setBizAction(processInstanceTopVo.getBizAction());
				hrDingdingProcess.setMainProcessInstanceId(processInstanceTopVo.getMainProcessInstanceId());
				hrDingdingProcess.setFormComponentValues(JSON.toJSONString(processInstanceTopVo.getFormComponentValues()));
				hrDingdingProcess.setOperationRecords(JSON.toJSONString(processInstanceTopVo.getOperationRecords()));
				hrDingdingProcess.setUpdateTime(now);
				processinstanceList.add(hrDingdingProcess);
			}
		}
	}
	return processinstanceList;
}

HrDingdingServiceImpl 钉钉数据转换人事HR系统业务数据,省略了部分业务代码

@Slf4j
@Service
public class HrDingdingServiceImpl implements HrDingdingService {

    @Autowired
    private HrDingdingUserMapper hrDingdingUserMapper;
    @Autowired
    private HrDingdingDeptMapper hrDingdingDeptMapper;
    @Autowired
    private HrDingdingAttendanceMapper hrDingdingAttendanceMapper;
    @Autowired
    private HrDingdingProcessMapper hrDingdingProcessMapper;
	//以下为系统其它业务类,本例不展示其详细代码
	......

    @Override
    public void insert(HrDingdingAttendance hrDingdingAttendance) {
        hrDingdingAttendanceMapper.insert(hrDingdingAttendance);
    }

    @Override
    public void insertOrUpdateAttendance(List hrDingdingAttendanceList) {
        if(hrDingdingAttendanceList != null && hrDingdingAttendanceList.size() > 0) {
            for(HrDingdingAttendance hrDingdingAttendance:hrDingdingAttendanceList) {
                HrDingdingAttendanceExample hrDingdingAttendanceExample = new HrDingdingAttendanceExample();
                hrDingdingAttendanceExample.createCriteria().andAttendanceIdEqualTo(hrDingdingAttendance.getAttendanceId());
                List list = hrDingdingAttendanceMapper.selectByExample(hrDingdingAttendanceExample);
                if(list != null && list.size() > 0) {
                    hrDingdingAttendanceMapper.updateByExampleSelective(hrDingdingAttendance, hrDingdingAttendanceExample);
                }else {
                    hrDingdingAttendanceMapper.insert(hrDingdingAttendance);
                }
                if(hrDingdingAttendance.getUserCheckTime() != null) {
                    HrDingdingUser hrDingdingUser = getDingdingUserByUserId(hrDingdingAttendance.getUserId());
                    if(hrDingdingUser != null) {
                        //根据手机号获取档案用户
                        CMUser cmUser = getHrUserByPhone(hrDingdingUser.getMobile());
                        if(cmUser != null) {
                            //保存HR系统打卡记录
                            HrAttendPunchRecord hapr = new HrAttendPunchRecord();
                            hapr.setHrUserId(cmUser.getHrUserId());
                            hapr.setUserNumber(cmUser.getUserName());
                            hapr.setNameCn(cmUser.getRealName());
							hapr.setAttendanceTime(String.valueOf(hrDingdingAttendance.getUserCheckTime().getTime()/1000));
                            ......
							
                        }else {
                            log.warn("HR系统不存在手机号["+hrDingdingUser.getMobile()+"]的用户");
                        }
                    }
                }

            }
        }
    }

    private CMUser getHrUserByPhone(String phone) {
        //根据手机号获取HR系统人员信息
    }

	/**
	*	根据userid获取钉钉人员详细信息
	*/
    private HrDingdingUser getDingdingUserByUserId(String userId) {
        HrDingdingUserExample hrDingdingUserExample = new HrDingdingUserExample();
        hrDingdingUserExample.createCriteria().andUseridEqualTo(userId);
        List hrDingdingUserList = hrDingdingUserMapper.selectByExample(hrDingdingUserExample);
        if(hrDingdingUserList != null && hrDingdingUserList.size() > 0) {
            return hrDingdingUserList.get(0);
        }
        return null;
    }

	/**
	*	根据名称获取钉钉人员详细信息
	*/
    private HrDingdingUser getDingdingUserByName(String userName) {
        HrDingdingUserExample hrDingdingUserExample = new HrDingdingUserExample();
        hrDingdingUserExample.createCriteria().andNameEqualTo(userName);
        List hrDingdingUserList = hrDingdingUserMapper.selectByExample(hrDingdingUserExample);
        if(hrDingdingUserList != null && hrDingdingUserList.size() > 0) {
            return hrDingdingUserList.get(0);
        }
        return null;
    }

    @Override
    public void insertOrUpdateUser(List hrDingdingUserList) {
        if(hrDingdingUserList != null && hrDingdingUserList.size() > 0) {
            for(HrDingdingUser hrDingdingUser:hrDingdingUserList) {
                HrDingdingUserExample hrDingdingUserExample = new HrDingdingUserExample();
                hrDingdingUserExample.createCriteria().andUseridEqualTo(hrDingdingUser.getUserid());
                List list = hrDingdingUserMapper.selectByExample(hrDingdingUserExample);
                if(list != null && list.size() > 0) {
                    hrDingdingUserMapper.updateByExampleSelective(hrDingdingUser, hrDingdingUserExample);
                }else {
                    hrDingdingUserMapper.insert(hrDingdingUser);
                }
            }
        }
    }

    @Override
    public void insertOrUpdateDept(List dingdingDeptList) {
        if(dingdingDeptList != null && dingdingDeptList.size() > 0) {
            for(HrDingdingDept hrDingdingDept:dingdingDeptList) {
                HrDingdingDeptExample hrDingdingDeptExample = new HrDingdingDeptExample();
                hrDingdingDeptExample.createCriteria().andDeptIdEqualTo(hrDingdingDept.getDeptId());
                List list = hrDingdingDeptMapper.selectByExample(hrDingdingDeptExample);
                if(list != null && list.size() > 0) {
                    hrDingdingDeptMapper.updateByExampleSelective(hrDingdingDept, hrDingdingDeptExample);
                }else {
                    hrDingdingDeptMapper.insert(hrDingdingDept);
                }
            }
        }
    }

    @Override
    public void insertOrUpdateProcessInstance(String type, List processinstanceList) {
        if(processinstanceList != null && processinstanceList.size() > 0) {
            for(HrDingdingProcessWithBLOBs hrDingdingProcess:processinstanceList) {
                HrDingdingProcessExample hrDingdingProcessExample = new HrDingdingProcessExample();
                hrDingdingProcessExample.createCriteria().andProcessInstanceIdEqualTo(hrDingdingProcess.getProcessInstanceId());
                List list = hrDingdingProcessMapper.selectByExample(hrDingdingProcessExample);
                if(list != null && list.size() > 0) {
                    hrDingdingProcessMapper.updateByExampleSelective(hrDingdingProcess, hrDingdingProcessExample);
                }else {
                    hrDingdingProcessMapper.insert(hrDingdingProcess);
                }

                try {
                    if("leave".equals(type)) {
                        convertHrLeave(hrDingdingProcess);
                    }else if("public".equals(type)) {
                        convertHrPublic(hrDingdingProcess);
                    }else if("travelwork".equals(type)) {
                        convertHrTravelwork(hrDingdingProcess);
                    }else if("transfer".equals(type)) {
                        convertHrTransfer(hrDingdingProcess);
                    }
                } catch (Exception e) {
                    log.error(ConstantsUtil.SYSTEM_ERROR, e);
                }
            }
        }
    }

    private void convertHrTransfer(HrDingdingProcessWithBLOBs hrDingdingProcess) {
        if("COMPLETED".equals(hrDingdingProcess.getStatus()) && "agree".equals(hrDingdingProcess.getResult())) {
            HrDingdingUser hrDingdingUser = getDingdingUserByUserId(hrDingdingProcess.getOriginatorUserid());
            if(hrDingdingUser != null) {
                //根据手机号获取档案用户
                CMUser cmUser = getHrUserByPhone(hrDingdingUser.getMobile());
                if (cmUser != null) {
                    ExtOaPeopleDataModel oaModel = new ExtOaPeopleDataModel();
					//保存人员信息
					......
                    if(StringUtils.isNotBlank(hrDingdingProcess.getFormComponentValues())) {
                        JSONArray jsonArray = JSONArray.parseArray(hrDingdingProcess.getFormComponentValues());
                        if(jsonArray != null && jsonArray.size() > 0) {
                            JSONObject jsonObject = jsonArray.getJSONObject(0);
                            String value = jsonObject.getString("value");
                            JSONArray valueArr = JSONArray.parseArray(value);
                            for(int i=0;i result = hrUserEditService.updateOaPeopleData(oaModel);
                    if (result != null && !result.getSuccess()) {
                        log.warn("保存转岗信息失败:"+result.getMessage());
                    }
                }else {
                    log.warn("HR系统不存在手机号["+hrDingdingUser.getMobile()+"]的用户");
                }
            }
        }
    }

    private void convertHrTravelwork(HrDingdingProcessWithBLOBs hrDingdingProcess) {
        if("COMPLETED".equals(hrDingdingProcess.getStatus()) && "agree".equals(hrDingdingProcess.getResult())) {
            HrDingdingUser hrDingdingUser = getDingdingUserByUserId(hrDingdingProcess.getOriginatorUserid());
            if(hrDingdingUser != null) {
                //根据手机号获取档案用户
                CMUser cmUser = getHrUserByPhone(hrDingdingUser.getMobile());
                if (cmUser != null) {
                    HrOaAttendTravelwork hrOaAttendTravelwork = new HrOaAttendTravelwork();
                    List hrOaAttendTravelworkList = new ArrayList<>();
                    //保存人员信息
					......

                    hrOaAttendTravelwork.setSqrq(DateUtils.DateToString(hrDingdingProcess.getCreateTime(), EnumDateStyle.YYYY_MM_DD));
                    hrOaAttendTravelwork.setZw(String.valueOf(oaMapTableService.getPositionOaId(cmUser.getHrUserId()).getResult()));
                    hrOaAttendTravelwork.setSfjk("0");

                    if(StringUtils.isNotBlank(hrDingdingProcess.getFormComponentValues())) {
                        JSONArray jsonArray = JSONArray.parseArray(hrDingdingProcess.getFormComponentValues());
                        if(jsonArray != null && jsonArray.size() > 0) {
                            JSONObject formObj = jsonArray.getJSONObject(0);
                            JSONArray propsArr = JSONArray.parseArray(formObj.getString("value"));
                            if(propsArr != null && propsArr.size() > 0) {
                                if(propsArr != null && propsArr.size() > 0) {
                                    for(int i=0;i 0) {
                                                for(int j=0; j 0) {
                        for(HrOaAttendTravelwork travelwork:hrOaAttendTravelworkList) {

                            hrOaAttendTravelwork.setCcmdd(travelwork.getCcmdd());
                            hrOaAttendTravelwork.setCcrq(travelwork.getCcrq());
                            hrOaAttendTravelwork.setCcrqa(travelwork.getCcrqa());
                            ServiceResult result = attendTravelworkService.saveTravelworkData(hrOaAttendTravelwork);
                            if (result != null && !result.getSuccess()) {
                                log.warn("保存出差信息失败:"+result.getMessage());
                            }
                        }
                    }

                }else {
                    log.warn("HR系统不存在手机号["+hrDingdingUser.getMobile()+"]的用户");
                }
            }
        }
    }

    private void convertHrPublic(HrDingdingProcessWithBLOBs hrDingdingProcess) {
        if("COMPLETED".equals(hrDingdingProcess.getStatus()) && "agree".equals(hrDingdingProcess.getResult())) {
            HrDingdingUser hrDingdingUser = getDingdingUserByUserId(hrDingdingProcess.getOriginatorUserid());
            if(hrDingdingUser != null) {
                //根据手机号获取档案用户
                CMUser cmUser = getHrUserByPhone(hrDingdingUser.getMobile());
                if (cmUser != null) {
                    //实体类
                    HrOaAttendPublicLeave hrOaAttendPublicLeave = new HrOaAttendPublicLeave();
                    hrOaAttendPublicLeave.setUserName(cmUser.getUserName());
                    hrOaAttendPublicLeave.setHrUserId(cmUser.getHrUserId());
                    //保存人员信息
					......
					
                    hrOaAttendPublicLeave.setApplyDate(String.valueOf(hrDingdingProcess.getCreateTime().getTime()/1000));

                    hrOaAttendPublicLeave.setBorrowMoney("0");

                    if(StringUtils.isNotBlank(hrDingdingProcess.getFormComponentValues())) {
                        JSONArray jsonArray = JSONArray.parseArray(hrDingdingProcess.getFormComponentValues());
                        if(jsonArray != null && jsonArray.size() > 0) {
                            for(int i = 0; i result = attendLeaveListService.insertLeaveDetail(model);
                    if (result != null && !result.getSuccess()) {
                        log.warn("保存请假信息失败:"+result.getMessage());
                    }
                }else {
                    log.warn("HR系统不存在手机号["+hrDingdingUser.getMobile()+"]的用户");
                }
            }
        }
    }

}

实体类

import com.lxhr.mybatis.bean.BaseBean;
import java.io.Serializable;
import java.util.Date;

//钉钉人员表
public class HrDingdingUser extends BaseBean implements Serializable {
    private Long id;

    private String userid;

    private String unionid;

    private String name;

    private String avatar;

    private String stateCode;

    private String mobile;

    private String hideMobile;

    private String telephone;

    private String jobNumber;

    private String title;

    private String email;

    private String orgEmail;

    private String workPlace;

    private String remark;

    private String deptIdList;

    private String extension;

    private String admin;

    private String boss;

    private String leader;

    private Date hiredDate;

    private String exclusiveAccount;

    private String loginId;

    private String exclusiveAccountType;

    private Date updateTime;

    private static final long serialVersionUID = 1L;

	//get set ...
}
import com.lxhr.mybatis.bean.BaseBean;
import java.io.Serializable;
import java.util.Date;

//钉钉部门表
public class HrDingdingDept extends BaseBean implements Serializable {
    private Long id;

    private Long deptId;

    private String name;

    private Long parentId;

    private Date updateTime;

    private static final long serialVersionUID = 1L;

    //get set ...
}
import com.lxhr.mybatis.bean.BaseBean;
import java.io.Serializable;
import java.util.Date;

//打卡记录表
public class HrDingdingAttendance extends BaseBean implements Serializable {
    private Long id;

    private Long attendanceId;

    private String sourceType;

    private Date baseCheckTime;

    private Date userCheckTime;

    private String procInstId;

    private Long approveId;

    private String locationResult;

    private String timeResult;

    private String checkType;

    private String userId;

    private Date workDate;

    private Long recordId;

    private Long planId;

    private Long groupId;

    private Date updateTime;

    private static final long serialVersionUID = 1L;

    //get set ...
}
import com.lxhr.mybatis.bean.BaseBean;
import java.io.Serializable;
import java.util.Date;

//流程表
public class HrDingdingProcess extends BaseBean implements Serializable {
    private Long id;

    private String processInstanceId;

    private String processCode;

    private String title;

    private Date createTime;

    private Date finishTime;

    private String originatorUserid;

    private Long originatorDeptId;

    private String originatorDeptName;

    private String status;

    private String result;

    private String businessId;

    private String bizAction;

    private String mainProcessInstanceId;

    private Date updateTime;

    private static final long serialVersionUID = 1L;

    //get set ...
}

实体类对应表结构

CREATE TABLE `hr_dingding_attendance` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `attendance_id` bigint(11) NOT NULL COMMENT '打卡ID',
  `source_type` varchar(20) DEFAULT '' COMMENT '数据来源:ATM:考勤机打卡(指纹/人脸打卡)BEACON:IBeacon DING_ATM:钉钉考勤机(考勤机蓝牙打卡) USER:用户打卡 BOSS:老板改签 APPROVE:审批系统 SYSTEM:考勤系统 AUTO_CHECK:自动打卡',
  `base_check_time` datetime DEFAULT NULL COMMENT '计算迟到和早退,基准时间。',
  `user_check_time` datetime DEFAULT NULL COMMENT '实际打卡时间, 用户打卡时间的毫秒数。',
  `proc_inst_id` varchar(36) DEFAULT NULL COMMENT '关联的审批实例ID,当该字段非空时,表示打卡记录与请假、加班等审批有关。',
  `approve_id` bigint(11) DEFAULT NULL COMMENT '关联的审批ID,当该字段非空时,表示打卡记录与请假、加班等审批有关。',
  `location_result` varchar(20) DEFAULT NULL COMMENT '位置结果: Normal:范围内 Outside:范围外 NotSigned:未打卡',
  `time_result` varchar(20) DEFAULT NULL COMMENT '打卡结果: Normal:正常 Early:早退 Late:迟到 SeriousLate:严重迟到 Absenteeism:旷工迟到 NotSigned:未打卡',
  `check_type` varchar(20) DEFAULT NULL COMMENT '考勤类型: OnDuty:上班 OffDuty:下班',
  `user_id` varchar(36) DEFAULT NULL COMMENT '打卡人的UserID。',
  `work_date` datetime DEFAULT NULL COMMENT '工作日。',
  `record_id` bigint(11) DEFAULT NULL COMMENT '打卡记录ID。',
  `plan_id` bigint(11) DEFAULT NULL COMMENT '排班ID。',
  `group_id` bigint(11) DEFAULT NULL COMMENT '考勤组ID。',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`)
) COMMENT='钉钉打开记录';


CREATE TABLE `hr_dingding_user` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `userid` varchar(36) DEFAULT NULL COMMENT '用户的userid。',
  `unionid` varchar(36) DEFAULT NULL COMMENT '用户在当前开发者企业账号范围内的唯一标识。',
  `name` varchar(50) DEFAULT NULL COMMENT '用户姓名。',
  `avatar` varchar(255) DEFAULT NULL COMMENT '头像地址。',
  `state_code` varchar(10) DEFAULT NULL COMMENT '国际电话区号。',
  `mobile` varchar(20) DEFAULT NULL COMMENT '手机号码。',
  `hide_mobile` varchar(10) DEFAULT NULL COMMENT '是否号码隐藏:true:隐藏  false:不隐藏',
  `telephone` varchar(20) DEFAULT NULL COMMENT '分机号。',
  `job_number` varchar(10) DEFAULT NULL COMMENT '员工工号。',
  `title` varchar(20) DEFAULT NULL COMMENT '职位。',
  `email` varchar(50) DEFAULT NULL COMMENT '员工邮箱。',
  `org_email` varchar(50) DEFAULT NULL COMMENT '员工的企业邮箱。',
  `work_place` varchar(255) DEFAULT NULL COMMENT '办公地点。',
  `remark` varchar(255) DEFAULT NULL COMMENT '备注。',
  `dept_id_list` varchar(200) DEFAULT NULL COMMENT '所属部门ID列表。',
  `extension` varchar(255) DEFAULT NULL COMMENT '扩展属性。',
  `admin` varchar(10) DEFAULT NULL COMMENT '是否为企业的管理员:true:是  false:不是',
  `boss` varchar(10) DEFAULT NULL COMMENT '是否为企业的老板:true:是  false:不是',
  `leader` varchar(10) DEFAULT NULL COMMENT '是否是部门的主管:true:是  false:不是',
  `hired_date` datetime DEFAULT NULL COMMENT '入职时间,单位毫秒。',
  `exclusive_account` varchar(10) DEFAULT NULL COMMENT '是否专属帐号:true:是 false:不是',
  `login_id` varchar(50) DEFAULT NULL COMMENT '专属帐号登录名。',
  `exclusive_account_type` varchar(10) DEFAULT NULL COMMENT '专属帐号类型:sso:企业自建专属帐号  dingtalk:钉钉自建专属帐号',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`)
) COMMENT='钉钉用户信息';



CREATE TABLE `hr_dingding_dept` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `dept_id` bigint(11) DEFAULT NULL COMMENT '部门ID。',
  `name` varchar(50) DEFAULT NULL COMMENT '部门名称。',
  `parent_id` bigint(11) DEFAULT NULL COMMENT '父部门ID。',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`)
) COMMENT='钉钉部门表';



CREATE TABLE `hr_dingding_process` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `process_instance_id` varchar(50) DEFAULT NULL COMMENT '流程实例标识。',
  `process_code` varchar(100) DEFAULT NULL COMMENT '审批流的唯一码。',
  `title` varchar(200) DEFAULT NULL COMMENT '审批实例标题。',
  `create_time` datetime DEFAULT NULL COMMENT '开始时间',
  `finish_time` datetime DEFAULT NULL COMMENT '结束时间。',
  `originator_userid` varchar(36) DEFAULT NULL COMMENT '发起人的userid。',
  `originator_dept_id` bigint(11) DEFAULT NULL COMMENT '发起人的部门。-1表示根部门。',
  `originator_dept_name` varchar(50) DEFAULT NULL COMMENT '发起部门。',
  `status` varchar(20) DEFAULT NULL COMMENT '审批状态:NEW:新创建 RUNNING:审批中 TERMINATED:被终止 COMPLETED:完成 CANCELED:取消',
  `result` varchar(10) DEFAULT NULL COMMENT '审批结果:agree:同意 refuse:拒绝',
  `business_id` varchar(36) DEFAULT NULL COMMENT '审批实例业务编号。',
  `biz_action` varchar(10) DEFAULT NULL COMMENT '审批实例业务动作:MODIFY:表示该审批实例是基于原来的实例修改而来  REVOKE:表示该审批实例是由原来的实例撤销后重新发起的  NONE表示正常发起',
  `main_process_instance_id` varchar(50) DEFAULT NULL COMMENT '主流程实例标识。',
  `form_component_values` text COMMENT '表单详情列表。',
  `operation_records` text COMMENT '操作记录列表。',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`)
) COMMENT='钉钉流程表';

最新sdk下载地址:服务端SDK下载 - 钉钉开放平台

我项目使用sdk地址:JAVA版钉钉开发SDK包dingtalk-sdk-java.zip_OapiV2DepartmentListsubResponse-互联网文档类资源-CSDN下载

你可能感兴趣的:(Java,java)