提交 f449b9f3 authored 作者: 000516's avatar 000516

飞书部门、人员同步T100

上级 9f742eb0
......@@ -5,6 +5,15 @@ public class Constants {
* 采集数据方式
*/
public static final String SYNC_TYPE_XXL_JOB = "xxl-job";
public static final String ENCRYPT = "encrypt";
public static final String FEISHU_EVENT_CALLBACK = "event_callback";
public static final String FEISHU_APPROVAL_INSTANCE = "approval_instance";
public static final String FEISHU_EVENT_DEPT_CREATE = "corehr.department.created_v1";
public static final String FEISHU_EVENT_DEPT_PUT = "corehr.department.updated_v1";
public static final String FEISHU_EVENT_USER_CREATE = "corehr.job_data.employed_v1";
public static final String FEISHU_EVENT_USER_PUT = "corehr.job_data.changed_v1";
}
package com.sfa.job.constants;
/**
* @author : liqiulin
* @date : 2024-11-22 11
* @describe :
*/
public interface RedisKeyJob {
String FEISHU_EVENT_CREATE_DEPT = "job:feishu_event:create_dept_";
}
package com.sfa.job.consumer.feishu;
import com.alibaba.fastjson2.JSONObject;
import com.lark.oapi.ws.Constant;
import com.sfa.common.core.enums.ECode;
import com.sfa.common.core.enums.promotion.PlanStatus;
import com.sfa.common.core.exception.ServiceException;
import com.sfa.common.redis.service.RedisService;
import com.sfa.job.constants.Constants;
import com.sfa.job.constants.RedisKeyJob;
import com.sfa.job.pojo.feishu.event.EventCallBackDto;
import com.sfa.job.service.feishu.IEventCallbackService;
import lombok.extern.slf4j.Slf4j;
......@@ -21,6 +24,8 @@ import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.util.Base64;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* @author : liqiulin
......@@ -38,28 +43,31 @@ public class EventCallbackLuzx {
private String scfyCode;
@Autowired
private IEventCallbackService eventCallbackService;
@Autowired
private RedisService redisService;
@RequestMapping(method = RequestMethod.POST)
public JSONObject handleEvent(@RequestBody JSONObject eventObj) {
String encryptKey = encryptKeyP;
String encrypt = eventObj.getString(Constants.ENCRYPT);
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] keyBs = digest.digest(encryptKey.getBytes(StandardCharsets.UTF_8));
byte[] keyBs = digest.digest(encryptKeyP.getBytes(StandardCharsets.UTF_8));
String decrypt = decrypt(encrypt,keyBs);
JSONObject req = JSONObject.parseObject(decrypt);
log.info("飞书事件订阅 - 解密数据:{}",req);
log.info("飞书事件回调数据:{}\n解析:{}",eventObj,req);
EventCallBackDto eventCallBackDto = JSONObject.parseObject(decrypt, EventCallBackDto.class);
EventCallBackDto.Event event = eventCallBackDto.getEvent();
/**
* 订阅审批 - 市场推广费用申请(审批实例CODE:258B4D93-96D4-49E4-B9E1-DA6AB45740B0)
* 审批实例 状态变更 事件处理
*/
if (Constants.FEISHU_APPROVAL_INSTANCE.equals(event.getType()) && scfyCode.equals(event.getApprovalCode())){
if (!event.getStatus().equals(PlanStatus.PENDING.name())){
eventCallbackService.planCP(event);
}
String type = req.getString("type");
if (Objects.nonNull(type) && Constants.FEISHU_EVENT_CALLBACK.equals(type)){
eventCallback(decrypt);
}
/**
* 组织(部门/人员)变更 事件处理
*/
if (req.containsKey("header")){
deptOrUserEvent(req);
}
return req;
} catch (Exception e) {
......@@ -68,6 +76,56 @@ public class EventCallbackLuzx {
}
}
/**
* 部门、人员变更事件
*/
private void deptOrUserEvent(JSONObject req) {
if (!req.containsKey("event")){
return;
}
String eventType = req.getJSONObject("header").getString("event_type");
String departmentId = req.getJSONObject("event").getString("department_id");
String rk = RedisKeyJob.FEISHU_EVENT_CREATE_DEPT + (Objects.isNull(departmentId) ? "departmentId" : departmentId);
// 部门新建
if (Constants.FEISHU_EVENT_DEPT_CREATE.equals(eventType) && !redisService.hasKey(rk)){
redisService.setCacheObject(rk,departmentId,1L, TimeUnit.HOURS);
eventCallbackService.deptCreate(departmentId);
}
// 部门更新/停用
if (Constants.FEISHU_EVENT_DEPT_PUT.equals(eventType)){
eventCallbackService.deptUpdate(departmentId);
}
// 员工入职
if (Constants.FEISHU_EVENT_USER_CREATE.equals(eventType)){
eventCallbackService.userCreate(req.getJSONObject("event").getString("employment_id"));
}
// 员工信息修改
if (Constants.FEISHU_EVENT_USER_PUT.equals(eventType)){
eventCallbackService.userUpdate(req.getJSONObject("event").getString("employment_id"));
}
}
/**
* 订阅审批
*/
private void eventCallback(String decrypt){
EventCallBackDto eventCallBackDto = JSONObject.parseObject(decrypt, EventCallBackDto.class);
EventCallBackDto.Event event = eventCallBackDto.getEvent();
// 市场推广费用申请(审批实例CODE:258B4D93-96D4-49E4-B9E1-DA6AB45740B0)
if (Constants.FEISHU_APPROVAL_INSTANCE.equals(event.getType()) && scfyCode.equals(event.getApprovalCode())){
if (!event.getStatus().equals(PlanStatus.PENDING.name())){
eventCallbackService.planCP(event);
}
}
}
/**
* 解析encrypt_key加密数据
*/
......
package com.sfa.job.service.feishu;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.lark.oapi.service.corehr.v2.model.*;
import com.sfa.common.core.enums.promotion.PlanStatus;
import com.sfa.common.core.utils.DateUtils;
import com.sfa.common.core.utils.sdk.FeiShuUtil;
import com.sfa.job.domain.promotion.dao.IActivityPlanDao;
import com.sfa.job.pojo.feishu.event.EventCallBackDto;
import com.sfa.job.pojo.promotion.response.ActivityPlanApprovalDto;
import com.sfa.job.util.T100Util;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.Objects;
/**
* @author : liqiulin
* @date : 2025-06-04 17
......@@ -18,6 +28,10 @@ import org.springframework.stereotype.Service;
public class EventCallbackServiceImpl implements IEventCallbackService{
@Autowired
private IActivityPlanDao activityPlanDao;
@Autowired
private FeiShuUtil feiShuUtil;
@Autowired
private T100Util t100Util;
@Override
public void planCP(EventCallBackDto.Event event) {
......@@ -36,4 +50,180 @@ public class EventCallbackServiceImpl implements IEventCallbackService{
activityPlanDao.updateActivityPlanStatusByInstanceId(instanceId,planStatusCode);
}
@Override
public void deptCreate(String departmentId) {
JSONObject deptT100 = new JSONObject();
Department dept = feiShuUtil.getDepartmentCorehr(departmentId);
String deptCode = dept.getCode();
I18n[] departmentName = dept.getDepartmentName();
String deptName = departmentName[0].getValue();
customFields(dept.getCustomFields(),deptT100);
String parentDepartmentId = dept.getParentDepartmentId();
Department parentdept = feiShuUtil.getDepartmentCorehr(parentDepartmentId);
deptT100.put("data_status","A");
deptT100.put("enterprise_no","80");
deptT100.put("status","Y");
deptT100.put("department_no",deptCode);
deptT100.put("top_level_department_no", Objects.nonNull(parentdept.getIsRoot()) && parentdept.getIsRoot() ? "BJHQ" : parentdept.getCode());
deptT100.put("effective_date", DateUtils.datePath());
deptT100.put("expiration_date",null);
deptT100.put("corporation","ALL");
deptT100.put("department_name_name",deptName);
deptT100.put("department_shortname",deptName);
deptT100.put("top_organization_no","ALL");
deptT100.put("department_heads_employee_no","");
deptT100.put("ooeg005","Y");
createOrUpdateDept(deptT100);
}
@Override
public void deptUpdate(String departmentId) {
JSONObject deptT100 = new JSONObject();
Department dept = feiShuUtil.getDepartmentCorehr(departmentId);
// 部门启用状态,true为启用,false为停用
Boolean active = dept.getActive();
String deptCode = dept.getCode();
I18n[] departmentName = dept.getDepartmentName();
String deptName = active ? departmentName[0].getValue() : "(失效)"+departmentName[0].getValue();
customFields(dept.getCustomFields(),deptT100);
String parentDepartmentId = dept.getParentDepartmentId();
Department parentdept = feiShuUtil.getDepartmentCorehr(parentDepartmentId);
deptT100.put("data_status","AU");
deptT100.put("enterprise_no","80");
deptT100.put("status","Y");
deptT100.put("department_no",deptCode);
deptT100.put("top_level_department_no", Objects.nonNull(parentdept.getIsRoot()) && parentdept.getIsRoot() ? "BJHQ" : parentdept.getCode());
deptT100.put("effective_date", DateUtils.datePath());
deptT100.put("expiration_date",null);
deptT100.put("corporation","ALL");
deptT100.put("department_name_name",deptName);
deptT100.put("department_shortname",deptName);
deptT100.put("top_organization_no","ALL");
deptT100.put("department_heads_employee_no","");
deptT100.put("ooeg005","Y");
createOrUpdateDept(deptT100);
}
/**
* 员工入职
*/
@Override
public void userCreate(String employmentId) {
Employee emp = feiShuUtil.getEmployeeReq(employmentId);
String departmentIdV2 = emp.getDepartmentIdV2();
Department dept = feiShuUtil.getDepartmentCorehr(departmentIdV2);
String employeeNumber = emp.getEmployeeNumber();
String deptCode = dept.getCode();
BankAccount bankAccount = emp.getPersonInfo().getBankAccountList()[0];
String branchIdV2 = bankAccount.getBranchIdV2();
String bankAccountNumber = bankAccount.getBankAccountNumber();
String preferredName = emp.getPersonInfo().getPreferredName();
JSONObject userT100 = new JSONObject();
userT100.put("data_status","AU");
userT100.put("status","Y");
userT100.put("employee_no",employeeNumber);
userT100.put("department_no",deptCode);
userT100.put("site_no","ALL");
userT100.put("title","");
userT100.put("bank_no",branchIdV2);
userT100.put("account",bankAccountNumber);
userT100.put("employee_name",preferredName);
userT100.put("employee_nickname",preferredName);
userT100.put("phone","");
userT100.put("mobilephone","ALL");
userT100.put("email","");
createOrUpdateUser(userT100);
}
@Override
public void userUpdate(String employmentId) {
userCreate(employmentId);
}
private void customFields(CustomFieldData[] customFields,JSONObject deptT100){
for (CustomFieldData customField : customFields) {
String customName = customField.getName().getZhCn();
String customValue = JSONObject.parse(customField.getValue()).getString("zh-CN");
switch (customName) {
case "责任中心":
deptT100.put("responsibility_center_type",customValue.substring(0,1));
break;
case "费用类别":
deptT100.put("fee_type",customValue.substring(0,1));
break;
default:
break;
}
}
}
private void createOrUpdateDept(JSONObject deptT100){
JSONObject service = new JSONObject();
service.put("name","department.create");
JSONObject datakey = new JSONObject();
datakey.put("CompanyId","BJHQ");
datakey.put("EntId","80");
JSONObject host = new JSONObject();
host.put("acct","tiptop");
host.put("ip","192.168.100.20");
host.put("lang","zh_CN");
host.put("prod","CRM");
host.put("timestamp",DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MS_PATTERN));
JSONObject payload = new JSONObject();
payload.putObject("std_data").putObject("parameter").putArray("master_data").add(deptT100);
JSONObject deptJson = new JSONObject();
deptJson.put("service",service);
deptJson.put("datakey",datakey);
deptJson.put("host",host);
deptJson.put("payload",payload);
t100Util.createOrUpdateDept(deptJson);
}
private void createOrUpdateUser(JSONObject userT100){
JSONObject service = new JSONObject();
service.put("name","employee.create");
JSONObject datakey = new JSONObject();
datakey.put("CompanyId","BJHQ");
datakey.put("EntId","80");
JSONObject host = new JSONObject();
host.put("acct","tiptop");
host.put("ip","192.168.100.20");
host.put("lang","zh_CN");
host.put("prod","CRM");
host.put("timestamp",DateUtil.format(new Date(), DatePattern.NORM_DATETIME_MS_PATTERN));
JSONObject payload = new JSONObject();
payload.putObject("std_data").putObject("parameter").putArray("master_data").add(userT100);
JSONObject userJson = new JSONObject();
userJson.put("service",service);
userJson.put("datakey",datakey);
userJson.put("host",host);
userJson.put("payload",payload);
t100Util.createOrUpdateUser(userJson);
}
}
......@@ -9,4 +9,12 @@ import com.sfa.job.pojo.feishu.event.EventCallBackDto;
*/
public interface IEventCallbackService {
void planCP(EventCallBackDto.Event event);
void deptCreate(String departmentId);
void deptUpdate(String departmentId);
void userCreate(String employmentId);
void userUpdate(String employmentId);
}
package com.sfa.job.util;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.HashMap;
/**
* @author : liqiulin
* @date : 2025-06-19 17
* @describe : T100接口对接
*/
@Slf4j
@Component
public class T100Util {
@Value("${t100.url}")
private String url;
public void createOrUpdateDept(JSONObject deptJson){
HashMap<String,String> header = new HashMap<>();
header.put("Content-Type","application/json;charset=utf-8");
header.put("digi-protocol","raw");
header.put("digi-srvver","1.0");
header.put("digi-srvcode","000");
header.put("digi-type","sync");
header.put("digi-key","f63b06af224e90ea3f9f08e0226fc91e");
String body = HttpUtil.createPost(url).addHeaders(header).body(deptJson.toString()).execute().body();
log.info("\nT100-创建/修改部门\n参数:{}\n结果:{}",deptJson,body);
}
public void createOrUpdateUser(JSONObject userJson) {
HashMap<String,String> header = new HashMap<>();
header.put("Content-Type","application/json;charset=utf-8");
header.put("digi-protocol","raw");
header.put("digi-srvver","1.0");
header.put("digi-srvcode","000");
header.put("digi-type","sync");
header.put("digi-key","f63b06af224e90ea3f9f08e0226fc91e");
String body = HttpUtil.createPost(url).addHeaders(header).body(userJson.toString()).execute().body();
log.info("\nT100-创建/修改人员\n参数:{}\n结果:{}",userJson,body);
}
}
......@@ -40,6 +40,7 @@
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<file>${LOG_PATH}/${MODEL_NAME}-today.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
......@@ -56,6 +57,7 @@
class="ch.qos.logback.core.rolling.RollingFileAppender">
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<file>${LOG_PATH}/${MODEL_NAME}-error-today.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论