From 36f7a21a15b77a7b320acef0ef59bbac853444be Mon Sep 17 00:00:00 2001 From: weiyunlong Date: Wed, 4 Sep 2024 15:27:07 +0800 Subject: [PATCH] =?UTF-8?q?1.e=E7=AD=BE=E5=AE=9D=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=B5=8B=E8=AF=95=202.=E4=BB=98=E6=AC=BE=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=E5=8D=95=E8=A1=A8=E5=8D=95=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/SignTechnologCallbackController.java | 82 +++++++++ .../formplugin/ReconPayreqFormPlugin.java | 146 ++++++++++++++++ .../repc/recon/opplugin/TestOPPlugin.java | 157 ++++++++++++++---- 3 files changed, 351 insertions(+), 34 deletions(-) create mode 100644 fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/api/SignTechnologCallbackController.java create mode 100644 fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/formplugin/ReconPayreqFormPlugin.java diff --git a/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/api/SignTechnologCallbackController.java b/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/api/SignTechnologCallbackController.java new file mode 100644 index 0000000..487cb96 --- /dev/null +++ b/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/api/SignTechnologCallbackController.java @@ -0,0 +1,82 @@ +package shkd.repc.recon.api; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.openapi.common.custom.annotation.ApiController; + +import com.drew.lang.annotations.NotNull; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.openapi.common.custom.annotation.ApiParam; +import kd.bos.openapi.common.custom.annotation.ApiPostMapping; +import kd.bos.openapi.common.result.CustomApiResult; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.operation.SaveServiceHelper; +import kd.bos.util.StringUtils; + +import java.io.Serializable; +/** + * @author :weiyunlong + * @date :Created 2024/8/30 14:22 + * @description:合同签署流程回调接口(e签宝接口文档 3.6.2.1) + */ + + +@ApiController(value = "SignTechnologCallbackController",desc = "合同签署流程回调api接口,自定义插件") +public class SignTechnologCallbackController implements Serializable { + + @ApiPostMapping(value = "/eqb_signcallback", desc = "合同签署流程回调接口") + public CustomApiResult eqb_signcallback + (@NotNull @ApiParam(value = "入参", example = "") String str) { + + CustomApiResult customApiResult = new CustomApiResult(); + JSONObject jsonObject = JSONObject.parseObject(str); + //回调通知数据体 + JSONObject callBackProcessVO = (JSONObject)jsonObject.get("callBackProcessVO"); + if (null != callBackProcessVO) { + //获取合同id + String businessNo = (String) callBackProcessVO.get("businessNo"); + if (StringUtils.isNotEmpty(businessNo)) { + DynamicObject recon_contractbill = BusinessDataServiceHelper.loadSingle("recon_contractbill", + "id,billno,qeug_theothersignstatus",new QFilter[]{new QFilter("billno", QCP.equals, businessNo)}); + if (null != recon_contractbill) { + + + + //待签署方列表 + JSONArray nextSignerList = callBackProcessVO.getJSONArray("nextSignerList"); + if (null != nextSignerList) { + JSONObject jsonobject = (JSONObject)nextSignerList.get(0); + String signStatus = jsonobject.getString("signStatus"); + recon_contractbill.set("qeug_theothersignstatus",signStatus);//状态 + SaveServiceHelper.save(new DynamicObject[]{recon_contractbill}); + return customApiResult ; + } + + //签署方列表 + JSONArray signerList = callBackProcessVO.getJSONArray("signerList"); + if (null != signerList) { + JSONObject jsonobject = (JSONObject)nextSignerList.get(0); + String signStatus = jsonobject.getString("signStatus"); + recon_contractbill.set("qeug_theothersignstatus",signStatus); + SaveServiceHelper.save(new DynamicObject[]{recon_contractbill}); + return customApiResult ; + } + + //拒签人信息 + JSONObject refuseSigner = (JSONObject)callBackProcessVO.get("refuseSigner"); + if (null != refuseSigner) { + String signStatus = refuseSigner.getString("signStatus"); + recon_contractbill.set("qeug_theothersignstatus",signStatus); + SaveServiceHelper.save(new DynamicObject[]{recon_contractbill}); + return customApiResult ; + } + } + } + } + + return customApiResult; + } +} diff --git a/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/formplugin/ReconPayreqFormPlugin.java b/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/formplugin/ReconPayreqFormPlugin.java new file mode 100644 index 0000000..47caecf --- /dev/null +++ b/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/formplugin/ReconPayreqFormPlugin.java @@ -0,0 +1,146 @@ +package shkd.repc.recon.formplugin; + +import com.grapecity.documents.excel.D; +import kd.bos.bill.BillShowParameter; +import kd.bos.bill.OperationStatus; +import kd.bos.coderule.api.CodeRuleInfo; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.dataentity.entity.DynamicObjectCollection; +import kd.bos.form.CloseCallBack; +import kd.bos.form.ShowType; +import kd.bos.form.events.AfterDoOperationEventArgs; +import kd.bos.form.plugin.AbstractFormPlugin; +import kd.bos.orm.query.QCP; +import kd.bos.orm.query.QFilter; +import kd.bos.servicehelper.AttachmentServiceHelper; +import kd.bos.servicehelper.BusinessDataServiceHelper; +import kd.bos.servicehelper.coderule.CodeRuleServiceHelper; +import kd.bos.servicehelper.operation.SaveServiceHelper; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * 付款申请单表单插件 + * qeug_recon_payreqbill_ext + */ +public class ReconPayreqFormPlugin extends AbstractFormPlugin { + + @Override + public void afterDoOperation(AfterDoOperationEventArgs args) { + super.afterDoOperation(args); + + String operateKey = args.getOperateKey(); + switch (operateKey){ + //发票识别 + case "qeug_invoicedistinguish": + + DynamicObject dataEntity = this.getView().getModel().getDataEntity(); + List> attachments = AttachmentServiceHelper.getAttachments("recon_payreqbill", + dataEntity.getPkValue(), "qeug_attachmentpanelap"); + if (attachments.size() <= 0) { + this.getView().showTipNotification("请先上传发票附件"); + return; + } + //发票信息分录 + DynamicObjectCollection invoiceentry = this.getView().getModel().getEntryEntity("invoiceentry"); + if (invoiceentry.size() > 0) { + this.getView().showTipNotification("请先删除发票信息数据后,再进行发票识别"); + return; + } + // TODO: 调取OA发票识别接口 + boolean b = true; + //成功--新增分录行 + if (b) { + //发票信息分录 + for (int i = 0; i < attachments.size(); i++) { + invoiceentry.addNew(); + //todo:模仿标品新增字段,为接口返回数据反写分录做准备 + this.getModel().setValue("qeug_invoicecode", "FKHM-0904-0001",i);//发票代码 + this.getModel().setValue("qeug_invoiceno", "FKHM-0904-0001",i);//发票号码 + this.getModel().setValue("qeug_amount", 10000,i);//价税合计 + this.getModel().setValue("qeug_attainformation", "发票识别:"+attachments.get(i).get("name"),i); + this.getModel().setValue("qeug_invoicestatus", 0,i);//发票验真/重状态 + } + this.getView().updateView("invoiceentry"); + this.getView().showSuccessNotification("发票识别成功"); + }else { + //失败--提示失败信息 + this.getView().showTipNotification("发票识别失败:请上传有效发票"); + } + + break; + //发票验真验重 + case "qeug_invoicecheck": + //todo: 发票验真验重接口 + // 根据接口情况打包分录数据去OA验真验重---遍历调取接口还是汇总集合调取接口 + boolean bb = true; + //成功--新增分录行 + if (bb) { + this.getView().showSuccessNotification("发票验真验重接口"); + //验真验重接口调通--生成发票登记单据(recon_invoicebill) + DynamicObject recon_invoicebill1 = BusinessDataServiceHelper.newDynamicObject("recon_invoicebill"); + DynamicObject recon_invoicebill = BusinessDataServiceHelper.loadSingle("2031274535679975424", "recon_invoicebill"); + recon_invoicebill.set("billstatus","A");//单据状态 + //所属组织 + DynamicObject org = BusinessDataServiceHelper.loadSingle("bos_org", new QFilter[]{new QFilter("number", QCP.equals, "DOBE")}); + if (null != org) { + recon_invoicebill.set("org",org); + } + //发票号码 invoiceno +// recon_invoicebill.set("invoiceno",System.currentTimeMillis());//----编码规则待维护 + recon_invoicebill.set("invoiceno","FKHM-0904-0001");//----编码规则待维护 + //发票编码 + recon_invoicebill.set("billno","测试数据勿删!!");//----编码规则待维护 + + //付款申请单 payreqentrys + DynamicObjectCollection payreqentrys = recon_invoicebill.getDynamicObjectCollection("payreqentrys"); + payreqentrys.clear(); + DynamicObject payreqentry = payreqentrys.addNew(); + payreqentry.set("fbasedataid", this.getView().getModel().getDataEntity()); + + //todo:若接口返回汇总 + //发票_明细 + DynamicObjectCollection invoiceentrs = recon_invoicebill.getDynamicObjectCollection("invoiceentry"); + invoiceentrs.clear(); + DynamicObject invoiceentr = invoiceentrs.addNew(); + invoiceentr.set("entry_notaxamt",100000); + //todo:若接口返回明细--遍历新增发票明细分录 + + Object[] save = SaveServiceHelper.save(new DynamicObject[]{recon_invoicebill}); + //如果 成功生成发票登记的单子,反写分录状态为完成 + if (save.length > 0) { + //发票信息分录 + DynamicObjectCollection invoiceentrys = this.getView().getModel().getEntryEntity("invoiceentry"); + if (invoiceentrys.size() > 0) { + for (DynamicObject invoiceent : invoiceentrys) { + //根据发票号码进行过滤 + String qeug_invoiceno = invoiceent.getString("qeug_invoiceno");//分录中的发票号码 + //todo:付款申请单发票信息分录行的发票号码 == 发票登记单头发票号码 + if (qeug_invoiceno.equals(recon_invoicebill.getString("invoiceno"))) { + System.out.println(); + invoiceent.set("qeug_invoicestatus",1);//发票状态(验真/重)--------已完成 + } + } + this.getView().updateView("invoiceentry"); +// SaveServiceHelper.save(new DynamicObject[]{this.getView().getModel().getDataEntity()}); + } + } + System.out.println(""); + }else { + //失败--提示失败信息 + this.getView().showTipNotification("发票验真验重失败:请检查发票明细信息是否正确"); + } + break; + case "deleteinvoiceentry": + //用户在删除发票明细时,如果当前发票已经生成发票登记单,一并删除掉 + // + break; + default: + break; + } + + } +} +// CodeRuleInfo codeRule = CodeRuleServiceHelper.getCodeRule("recon_invoicebill", recon_invoicebill, null); \ No newline at end of file diff --git a/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/opplugin/TestOPPlugin.java b/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/opplugin/TestOPPlugin.java index 32d158e..f381015 100644 --- a/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/opplugin/TestOPPlugin.java +++ b/fi/fi/shkd-fi-fi-plugin/src/main/java/shkd/repc/recon/opplugin/TestOPPlugin.java @@ -1,19 +1,23 @@ package shkd.repc.recon.opplugin; import com.alibaba.fastjson.JSONObject; +import kd.bos.dataentity.entity.DynamicObject; +import kd.bos.entity.operate.result.OperateErrorInfo; import kd.bos.entity.plugin.AbstractOperationServicePlugIn; import kd.bos.entity.plugin.args.AfterOperationArgs; +import kd.bos.entity.validate.ErrorLevel; import kd.bos.logging.Log; import kd.bos.logging.LogFactory; -import kd.bos.mvc.list.AttachmentModel; import kd.bos.util.HttpClientUtils; import kd.bos.util.StringUtils; - -import java.io.IOException; +import org.apache.commons.net.util.Base64; +//import java.util.Base64; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import java.nio.charset.StandardCharsets; import java.util.*; /** - * @description: */ public class TestOPPlugin extends AbstractOperationServicePlugIn { @@ -25,43 +29,128 @@ public class TestOPPlugin extends AbstractOperationServicePlugIn { String operationKey = e.getOperationKey(); if ("submit".equals(operationKey)) { + + for (DynamicObject dataEntity : e.getDataEntities()) { + // String url = System.getProperty("efms.infcompany.url.ip"); // logger.info("url"); - /** - * ---------------------生成上传文件链接---------------------------- + /* + ---------------------生成上传文件链接---------------------------- */ - String linkUrl = "http://172.31.254.241:8869/file/v1/generateUploadUrl"; - //TODO:请求头 2.2.1 - Map linkHeader = new HashMap<>(); - linkHeader.put("Content-Type", "application/json"); - //生成上传文件链接接口请求体 - JSONObject linkBody = new JSONObject(); - linkBody.put("expire",5); - linkBody.put("requestID", "550E8400E29B11D4A716446655440000"); - linkBody.put("type", 0); - //获取上传链接类型,0-上传文件并分割,适用于100M以内的pdf文件。1-上传文件,适用于大于100M的pdf文件,以及其他类型的文件:ofd、doc、docx、xls、xlsx、jpg、jpeg、png、zip、rar。 - try { - String linkPostjson = HttpClientUtils.postjson(linkUrl, linkHeader,linkBody.toJSONString()); - if (StringUtils.isNotEmpty(linkPostjson)) { - /** - * ---------------------上传文件---------------------------- - */ - String uploadUrl = linkPostjson; - //TODO:请求头 2.2.1 - Map uploadHeader = new HashMap<>(); - linkHeader.put("Content-Type", "application/json"); - //生成上传文件链接接口请求体 - JSONObject uploadBody = new JSONObject(); - linkBody.put("file",new AttachmentModel());//附件 + try { + String linkUrl = "http://172.31.254.241:8869/file/v1/generateUploadUrl"; + //TODO: 一.请求头(2.2.1) 二.requestID - String uploadPostjson = HttpClientUtils.postjson(uploadUrl, uploadHeader,uploadBody.toJSONString()); - if ("success".equals(uploadPostjson)) { - //上传成功 + //生成上传文件链接接口请求体 + JSONObject linkBody = new JSONObject(); + linkBody.put("expire",5); + linkBody.put("requestID", "4A6F3B4E5C2D1A9F8E7B6C5D4A3B2C1E"); + linkBody.put("type", 1); + + //获取上传链接类型,0-上传文件并分割,适用于100M以内的pdf文件。1-上传文件,适用于大于100M的pdf文件,以及其他类型的文件:ofd、doc、docx、xls、xlsx、jpg、jpeg、png、zip、rar。 + Map linkHeader = new HashMap<>(); + //body,项目密钥进行加密(HmacSHA256进行数据加密) + String secret = linkBody.toJSONString(); + String message ="B69RSfJJ5yJ6gizo"; + +// //import org.apache.commons.net.util.Base64; +// Mac sha256_HMAC = Mac.getInstance("HmacSHA256"); +// SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(),"HmacSHA256"); +// sha256_HMAC.init(secretKey); +// byte[] hash = sha256_HMAC.doFinal(message.getBytes()); +// String encodeStr = Base64.encodeBase64String(hash);//Ew6TnQg1i+e6GomCPBSoXfX+UFqmKy1AnP6gVKJrrQM=\r\n + + //import java.util.Base64; +// SecretKeySpec secretKey = new SecretKeySpec(message.getBytes(),"HmacSHA256"); +// sha256_HMAC.init(secretKey); +// byte[] hash = sha256_HMAC.doFinal(secret.getBytes()); +// String encodeStr = Base64.getEncoder().encodeToString(hash);//a7FxNRJsu5q0quFSF84R0eOhAiXYXoKvrrPw2o/JwbM= + + +// String encodestr16 = byte2Hex(hash);//130e939d08358be7ba1a89823c14a85df5fe505aa62b2d409cfea054a26bad03 //6bb17135126cbb9ab4aae15217ce11d1e3a10225d85e82afaeb3f0da8fc9c1b3 + + String HMACsha256 = calculateHMACSHA256(secret, message);//130e939d08358be7ba1a89823c14a85df5fe505aa62b2d409cfea054a26bad03 + String HMACsha256s = calculateHMACSHA256(message,secret );//6bb17135126cbb9ab4aae15217ce11d1e3a10225d85e82afaeb3f0da8fc9c1b3 + + + linkHeader.put("Content-Type", "application/json"); + linkHeader.put("x-timevale-project-id", "1000000"); + linkHeader.put("x-timevale-signature", "4c45b39ebe42818aa90001849dffda622c9894454bc6d68c03aff67c55730661"); + + + + String linkPostjson = HttpClientUtils.postjson(linkUrl, linkHeader,linkBody.toJSONString()); + if (StringUtils.isNotEmpty(linkPostjson)) { + + JSONObject jsonObject = JSONObject.parseObject(linkPostjson); + String messages = jsonObject.getString("message"); + + OperateErrorInfo operateErrorInfo = new OperateErrorInfo(); + operateErrorInfo.setMessage(messages); + operateErrorInfo.setErrorLevel(ErrorLevel.Error.name()); + operateErrorInfo.setPkValue(dataEntity.getPkValue()); + this.operationResult.addErrorInfo(operateErrorInfo); +// /* +// ---------------------上传文件---------------------------- +// */ +// //TODO:请求头 2.2.1 +// Map uploadHeader = new HashMap<>(); +// linkHeader.put("Content-Type", "multipart/form-data"); +// //生成上传文件链接接口请求体 +// JSONObject uploadBody = new JSONObject(); +// linkBody.put("file",new AttachmentModel());//附件 +// +// String uploadPostjson = HttpClientUtils.postjson(linkPostjson, uploadHeader,uploadBody.toJSONString()); +// switch (uploadPostjson) { +// case "success": +// //上传成功 +// break; +// default: +// break; +// } } + } catch (Exception ex) { + OperateErrorInfo operateErrorInfo = new OperateErrorInfo(); + operateErrorInfo.setMessage(ex.getMessage()); + operateErrorInfo.setErrorLevel(ErrorLevel.Error.name()); + operateErrorInfo.setPkValue(dataEntity.getPkValue()); + this.operationResult.addErrorInfo(operateErrorInfo); } - } catch (IOException ex) { - throw new RuntimeException(ex); } } } + + private static String byte2Hex(byte[] bytes){ + StringBuffer stringBuffer = new StringBuffer(); + String temp = null; + for(int i=0 ; i < bytes.length; i++) { + temp = Integer.toHexString(bytes[i] & 0xFF); + //1得到一位的进行补0操作 + if (temp.length() == 1) { + stringBuffer.append("0"); + } + stringBuffer.append(temp); + } + return stringBuffer.toString(); + } + + public static String calculateHMACSHA256(String key, String message) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + mac.init(secretKeySpec); + byte[] hmac = mac.doFinal(message.getBytes(StandardCharsets.UTF_8)); + StringBuilder sb = new StringBuilder(); + for (byte b : hmac) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + }catch(Exception e){ + e.printStackTrace(); + } + return null; + + } } +// String[] split = encodeStr.split("=", 4); +// String s = split[0]; \ No newline at end of file