package kd.cosmic.jkjt.msg.feishu; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import kd.bos.bec.api.IEventServicePlugin; import kd.bos.bec.model.EntityEvent; import kd.bos.bec.model.JsonEvent; import kd.bos.bec.model.KDBizEvent; import kd.bos.dataentity.entity.DynamicObject; import kd.bos.logging.Log; import kd.bos.logging.LogFactory; import kd.bos.orm.query.QCP; import kd.bos.orm.query.QFilter; import kd.bos.servicehelper.BusinessDataServiceHelper; import kd.bos.util.StringUtils; import kd.bos.workflow.engine.WfUtils; import kd.cosmic.jkjt.tmc.util.ParamsUtil; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.rmi.ConnectException; import java.util.Arrays; import java.util.Date; import java.util.List; /** * @author wanghaiwu_kd * @date 2024/04/22 * 插件说明:业务事件中心插件,修改飞书待办状态,测试类 * 表单标识:消息阅读状态变更事件.执行插件(wf.AfterChangeMessageStateEvent.executePlugin) */ public class TestChangeMessageStatePlugin implements IEventServicePlugin { private static Log logger = LogFactory.getLog(TestChangeMessageStatePlugin.class); private static final String USER_FORM_ID = "bos_user"; private static final String USERNAME = "username"; private List interErrCodeArr = Arrays.asList(new Integer[]{ 65001,90203,90235,90242,91201,95001,95003,95005,95010,95011, 95203,95204,95205,95206,95207,95208,95209, 105001,190003,230020,1050002,1050008,1069301,1069399 }); public static final String createInstanceUrl = "https://www.feishu.cn/approval/openapi/v2/external/instance/create"; private static final String TRAGETNAME = "云苍穹移动审批"; private static final String SPDYNUMBER = "jxjkxh";//审批定义number private static final String SPDYID = "946F4A46-2D64-4EBF-9C83-5CDBC5FEB9BD";//审批定义id-测试 private static final String APP_ID = "cli_a6f0c94f273ed00b";//个人测试 private static final String APP_SERCRET = "WmQUMiDFFSjN60kKnsayvdaEd0wvqidh"; @Override public Object handleEvent(KDBizEvent evt) { logger.info("飞书消息阅读状态变更事件" + evt.toString()); if (evt instanceof EntityEvent) {//苍穹事件 EntityEvent entityEvent = (EntityEvent) evt;//类型转换 String businesskey = entityEvent.getBusinesskeys().get(0); String entityNumber = entityEvent.getEntityNumber(); DynamicObject obj = BusinessDataServiceHelper.loadSingle(businesskey, entityNumber); Long evtID = evt.getEventId(); String source = evt.getSource();//传递的事件参数 } else {//自定义事件 JsonEvent jsonEvent = (JsonEvent) evt;//类型转换 String source = jsonEvent.getSource();//传递的事件参数 if (WfUtils.isNotEmpty(source)) { JSONArray arr = (JSONArray) JSON.parse(source); for (int i = 0; i < arr.size(); i++) { if(arr.getJSONObject(i) == null) { continue; } //消息id String msgIds = arr.getJSONObject(i).getString("msgIds"); logger.info("飞书消息阅读状态变更事件:msgIds" + msgIds); //用户id String userId = arr.getJSONObject(i).getString("userId"); if(StringUtils.isEmpty(msgIds)){ continue; } updateFeiShuMsgState(userId, msgIds); } } } return null; } private void updateFeiShuMsgState(String userId, String msgIds){ QFilter qFilter = new QFilter("id", QCP.equals, Long.valueOf(userId)); //接收人员 DynamicObject user = BusinessDataServiceHelper.loadSingle("bos_user", qFilter.toArray()); String personNo = user.getString("number"); msgIds = msgIds.replace("[", "").replace("]", ""); String[] msgIdList = msgIds.split(","); if(msgIdList.length == 0){ return; } for(String msgId : msgIdList){ logger.info("飞书消息阅读状态变更事件:替换前 msgId:" + msgId); msgId = msgId.replace("\"", ""); logger.info("飞书消息阅读状态变更事件:替换后msgId:" + msgId); qFilter = new QFilter("channel", QCP.equals, "feishu"); qFilter.and(new QFilter("messageid", QCP.equals, Long.valueOf(msgId))); DynamicObject msgFail = BusinessDataServiceHelper.loadSingle("wf_msg_failmessage", qFilter.toArray()); if(msgFail == null){ continue; } qFilter = new QFilter("id", QCP.equals, Long.valueOf(msgId)); DynamicObject msg = BusinessDataServiceHelper.loadSingle("wf_msg_message", qFilter.toArray()); if(msg == null || StringUtils.isEmpty(msg.getString("contenturl"))){ continue; } Long channelMsgId = msgFail.getLong("id"); String tplscene = msgFail.getString("tplscene"); logger.info("飞书消息阅读状态变更事件:tplscene:" + tplscene); if("circulation".equals(tplscene)){ String token = getToken(); sendFlowMessage(channelMsgId.toString(), msg, user, token); } } } public void sendFlowMessage(String channelMsgId, DynamicObject message, DynamicObject userInfo, String token){ try { JSONObject m = new JSONObject(true); JSONObject c = new JSONObject(true); c.put("approval_code", SPDYID); c.put("instance_id","cq"+ channelMsgId); c.put("status", "HIDDEN"); //url连接 JSONObject links = new JSONObject(); String pcUrl = StringUtils.isEmpty(message.getString("contenturl")) ? "" : message.getString("contenturl"); String mobUrl = StringUtils.isEmpty(message.getString("mobcontenturl")) ? pcUrl : message.getString("mobcontenturl"); logger.info("消息pcurl:" + pcUrl + ", moburl:" + mobUrl); //移动端需要走外网,将地址替换成外网地址 String curUrl = ParamsUtil.getCommonParamsField("nckd_url"); String mobileUrl = ParamsUtil.getCommonParamsField("nckd_mobileurl"); if(StringUtils.isNotEmpty(pcUrl)){ pcUrl = pcUrl.replace(mobileUrl, curUrl); } if(StringUtils.isNotEmpty(mobUrl)){ mobUrl = mobUrl.replace(curUrl, mobileUrl); } if("".equals(pcUrl)||pcUrl==null){ pcUrl = System.getProperty("domain.contextUrl")+"/index.html?formId=wf_msg_center"; } links.put("pc_link",pcSrcToFeishu(changeDanDianSrc(pcUrl+"&apptype=feishu"))); links.put("mobile_link", changeDanDianSrc(mobUrl+"&apptype=feishu")); c.put("links", links); String content = message.getString("content"); String title = message.getString("title"); //标题 c.put("title", title); Long createTime = (new Date()).getTime(); c.put("start_time", createTime); c.put("update_time", createTime); c.put("update_mode", "UPDATE"); /*************处理消息格式*****************/ // String nodename = toDoInfo.getCategory(); String workflowname = "财务系统审批流"; String nodename = ""; String createDate = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"); if(message != null && StringUtils.isNotEmpty(message.getString("config"))){ JSONObject messateContext = JSONObject.parseObject(message.getString("config")).getJSONObject("messageContext"); Long taskId = messateContext.getLong("taskId"); /*************处理消息格式*****************/ DynamicObject taskInfo = BusinessDataServiceHelper.loadSingleFromCache(taskId ,"wf_task"); //add by wnaghaiwu_kd 2024/04/28 //如果任务中找不到,就找历史任务 if(taskInfo == null){ taskInfo = BusinessDataServiceHelper.loadSingleFromCache(taskId ,"wf_hitaskinst"); } if(taskInfo != null){ QFilter qFilter; nodename = taskInfo.getString("name"); if(taskInfo.getLong("processdefinitionid") > 0) { qFilter = new QFilter("id", QCP.equals, taskInfo.getLong("processdefinitionid")); DynamicObject processdef = BusinessDataServiceHelper.loadSingle("wf_processdefinition", qFilter.toArray()); if (processdef != null) { workflowname = processdef.getString("name"); } } if("财务系统审批流".equals(workflowname) && taskInfo.getString("entityname") != null){ workflowname = taskInfo.getString("entityname") + "审批流程"; } if(StringUtils.isNotEmpty(taskInfo.getString("entitynumber")) && StringUtils.isNotEmpty(taskInfo.getString("businesskey"))){ qFilter = new QFilter("id", QCP.equals, Long.valueOf(taskInfo.getString("businesskey"))); DynamicObject bill = BusinessDataServiceHelper.loadSingle(taskInfo.getString("entitynumber"), qFilter.toArray()); if(bill != null){ if(bill.getDynamicObjectType().getProperties().contains("createtime")) { createDate = DateFormatUtils.format(bill.getDate("createtime"), "yyyy-MM-dd HH:mm:ss"); } else if(bill.getDynamicObjectType().getProperties().contains("createdate")) { createDate = DateFormatUtils.format(bill.getDate("createdate"), "yyyy-MM-dd HH:mm:ss"); } } } } } c.put("title", workflowname); JSONArray formArr = new JSONArray(); JSONObject form1 = new JSONObject(); form1.put("name", "流程标题"); form1.put("value", StringUtils.isEmpty(message.getString("title")) ? workflowname : message.getString("title")); formArr.add(form1); JSONObject form2 = new JSONObject(); form2.put("name", "提单时间"); form2.put("value", createDate); formArr.add(form2); JSONObject form3 = new JSONObject(); form3.put("name", "当前节点"); form3.put("value", nodename); formArr.add(form3); c.put("form", formArr); /*************处理消息格式*****************/ //cc_list 抄送人相关 JSONArray ccArr = new JSONArray(); JSONObject cc = new JSONObject(); cc.put("cc_id", userInfo.getPkValue()+"_"+ channelMsgId); cc.put("open_id", getUserId(userInfo.getString("phone"),token)); cc.put("read_status", "READ"); cc.put("title", title); cc.put("create_time", createTime); cc.put("update_time", createTime); cc.put("title", workflowname); JSONObject links1 = new JSONObject(); links1.put("pc_link",pcSrcToFeishu(changeDanDianSrc(pcUrl+"&apptype=feishu"))); links1.put("mobile_link",changeDanDianSrc(mobUrl+"&apptype=feishu")); cc.put("links", links1); ccArr.add(cc); c.put("cc_list", ccArr); m.put("content", c); logger.info("财务系统飞书推送传阅状态更新:"+m.toJSONString()); String response = doPostByHttpClient(createInstanceUrl, m.toJSONString(), true,token); logger.info("财务系统飞书推送传阅状态更新:"+response); } catch (ConnectException e) { logger.info("财务系统飞书,推送失败"); logger.error(e.getMessage(), e); e.printStackTrace(); } } //pc链接特殊处理 public String pcSrcToFeishu(String src){ String dandianStr=""; if(dandianStr != null) { try { String encodesrc = URLEncoder.encode(src, "utf-8"); dandianStr = "https://applink.feishu.cn/client/web_url/open?mode=window&url=" + encodesrc; } catch (UnsupportedEncodingException e) { logger.info(e.getMessage()); e.printStackTrace(); } } return dandianStr; } public static String changeDanDianSrc(String src){ String dandianStr=""; if(src != null) { try { String encodesrc = URLEncoder.encode(src, "utf-8"); dandianStr = "https://open.feishu.cn/open-apis/authen/v1/index?redirect_uri=" + encodesrc + "&app_id=" + APP_ID; } catch (UnsupportedEncodingException e) { logger.info(e.getMessage()); e.printStackTrace(); } } return dandianStr; } /** * 获取飞书token * @return */ public static String getToken(){ String returnstr = ""; String url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"; JSONObject tokenJson = new JSONObject(); tokenJson.put("app_id",APP_ID); tokenJson.put("app_secret",APP_SERCRET); try { String returnSt = doPostByHttpClient(url,tokenJson.toJSONString(),false,null); JSONObject returnJson = JSONObject.parseObject(returnSt); if("0".equals(returnJson.getString("code"))){//成功 returnstr = returnJson.getString("tenant_access_token"); } } catch (ConnectException e) { logger.info(e.getMessage()); e.printStackTrace(); } return returnstr; } /** * 根据手机号(暂定)获取userId/openId */ public static String getUserId(String cell,String token) { String user_id = ""; JSONObject m = new JSONObject(); JSONArray mobiles = new JSONArray(); mobiles.add(cell); m.put("mobiles", mobiles); String userIdUrl="https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id"; try { logger.info("获取用户json: " + m.toString()); String response = doPostByHttpClient(userIdUrl, m.toJSONString(),true,token); JSONObject userRes = JSONObject.parseObject(response); user_id = userRes.getJSONObject("data").getJSONArray("user_list").getJSONObject(0).getString("user_id"); logger.info("获取用户结束json: " + userRes.toString()); } catch (ConnectException e) { // TODO Auto-generated catch block logger.info(e.getMessage()); e.printStackTrace(); } return user_id; } public static String doPostByHttpClient(String url, String data, boolean isBearer,String token) throws ConnectException { System.out.println("url =" + url); System.out.println("data =" + data); try { // System.setProperty("javax.net.debug", "ssl"); DefaultHttpClient httpClient = null; if (url.toLowerCase().startsWith("https://")) { System.out.println("use ssl"); httpClient = new SSLClient(); } else { System.out.println("use nonssl"); httpClient = new DefaultHttpClient(); } HttpPost httpPost = new HttpPost(url); httpPost.addHeader("Content-Type", "application/json; charset=UTF-8"); if(isBearer) { httpPost.addHeader("Authorization", "Bearer" + " " + token); } StringEntity se = new StringEntity(data, "UTF-8"); se.setContentType("text/json"); se.setContentEncoding(new BasicHeader("Content-Type", "application/json; charset=UTF-8")); httpPost.setEntity(se); HttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode != 200) { throw new ConnectException("连接服务器发生错误!"); } String body = EntityUtils.toString(response.getEntity()); System.out.println(body); return body; } catch (Exception e) { e.printStackTrace(); System.out.println(" ===== doPostByHttpClient() ERROR ===== "); throw new ConnectException(e.getMessage()); } finally { System.clearProperty("javax.net.debug"); } } }