Ver código fonte

Merge branch 'master' of http://111.75.220.136:10030/turborao/jyyy

Tyx 1 semana atrás
pai
commit
8b446cd932

+ 170 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/FanWeiSSOAuthtication.java

@@ -0,0 +1,170 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dc.api.model.Account;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.login.thirdauth.app.AppAuthResult;
+import kd.bos.login.thirdauth.app.ThirdAppAuthtication;
+import kd.bos.login.thirdauth.app.UserType;
+import kd.bos.orm.query.QCP;
+import kd.bos.orm.query.QFilter;
+import kd.bos.sdk.util.KHttpClientUtils;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 泛微OA:E10单点登录拦截,验证token用户
+ * @author wanghaiwu_kd
+ * @date 2025/04/16
+ */
+public class FanWeiSSOAuthtication extends ThirdAppAuthtication {
+    private static Log logger = LogFactory.getLog(FanWeiSSOAuthtication.class);
+    /**
+     * 判断该接口请求是否需要通过此插件认证
+     */
+    @Override
+    public boolean isNeedHandle(HttpServletRequest request, Account account) {
+        //加密的数据信息
+        String token = request.getParameter("eteams_token");
+        if(StringUtils.isNotBlank(token)){
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     *用户身份解析
+     */
+    @Override
+    public AppAuthResult appAuthtication(HttpServletRequest request, Account account) {
+        AppAuthResult result = new AppAuthResult();
+        result.setSucceed(false);
+        try{
+            //获取请求连接中的token
+            String token = request.getParameter("eteams_token");
+            if(StringUtils.isBlank(token)){
+                logger.info("FanWeiSSOAuthtication:eteams_token is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:eteams_token is null");
+                return result;
+            }
+
+            String selectField = "nckd_entryentity.nckd_key, nckd_entryentity.nckd_value";
+
+            QFilter qFilter = new QFilter("number", QCP.equals, "fanwei");
+            DynamicObject commonParam = BusinessDataServiceHelper.loadSingle("nckd_commonparams", selectField, qFilter.toArray());
+            if (ObjectUtils.isEmpty(commonParam)) {
+                logger.info("FanWeiSSOAuthtication:nckd_commonparams is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数nckd_commonparams");
+                return result;
+            }
+
+            DynamicObjectCollection entryentity = commonParam.getDynamicObjectCollection("nckd_entryentity");
+            Map<String, String> mapentity = entryentity.stream().collect(Collectors.toMap(k -> k.getString("nckd_key"), v -> v.getString("nckd_value")));
+
+            if(mapentity == null ){
+                logger.info("FanWeiSSOAuthtication:nckd_entryentity is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数");
+                return result;
+            }
+
+            String userUrl = mapentity.get("getuserinfo");
+            if(StringUtils.isEmpty(userUrl)){
+                logger.info("FanWeiSSOAuthtication:getuserinfo is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数getuserinfo");
+                return result;
+            }
+
+            String privateKey = mapentity.get("privatekey");
+            if(StringUtils.isEmpty(userUrl)){
+                logger.info("FanWeiSSOAuthtication:privatekey is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数privatekey");
+                return result;
+            }
+
+            String syscode = mapentity.get("syscode");
+            if(StringUtils.isEmpty(syscode)){
+                logger.info("FanWeiSSOAuthtication:syscode is null");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:未配置泛微相关参数syscode");
+                return result;
+            }
+
+            String isDecode = mapentity.get("isdecode");
+
+            String ssouser_dev = mapentity.get("ssouser_dev");
+            String user = "";
+
+            String apiResult = "";
+
+            Map<String, String> header = new HashMap<>();
+            header.put("Content-Type", "application/json; charset=UTF-8");
+
+            //获取token
+            try {
+                userUrl = userUrl + "?eteam_token=" + token + "&xybs=" + syscode;
+
+                logger.info("获取泛微用户url:" + userUrl);
+
+                apiResult = KHttpClientUtils.postjson(userUrl, header, "{}");
+            } catch (IOException e) {
+                logger.info(e.getMessage());
+
+                logger.info("FanWeiSSOAuthtication:getuserinfo fail");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:获取用户异常" + e.getMessage());
+                return result;
+            }
+
+            if(kd.bos.util.StringUtils.isEmpty(apiResult)){
+                logger.info("FanWeiSSOAuthtication:getuserinfo fail");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:获取用户异常");
+                return result;
+            }
+
+            String userJSONString = "";
+            if(isDecode != null && "true".equals(isDecode)) {
+                userJSONString = new String(RSAUtils.decryptByKey(RSAUtils.getPrivateKey(Base64.decodeBase64(privateKey))
+                        , Base64.decodeBase64(apiResult.getBytes("UTF-8"))));
+            }
+
+            userJSONString = userJSONString.substring(1, userJSONString.length() - 1).replace("\\", "");
+
+            JSONObject userInfo = JSONObject.parseObject(userJSONString);
+            if(userInfo.get("jobNum") == null){
+                logger.info("FanWeiSSOAuthtication:getuserinfo fail");
+
+                result.setErrorMessage("FanWeiSSOAuthtication:获取用户异常");
+                return result;
+            }
+
+            user = userInfo.getString("jobNum");
+
+            if(StringUtils.isNotEmpty(ssouser_dev)){
+                user = ssouser_dev;
+
+            }
+            result.setUserFlag(user);
+            result.setUserType(UserType.USER_NAME);
+            result.setSucceed(true);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return result;
+    }
+}

+ 143 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/RSAUtils.java

@@ -0,0 +1,143 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import org.apache.commons.codec.binary.Base64;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.ByteArrayOutputStream;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+public class RSAUtils {
+
+    private static Provider provider;
+
+    static {
+        provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();
+        Security.addProvider(provider);
+    }
+
+    /**
+     * 产生key pair,提供provider和random
+     * @return
+     * @throws NoSuchAlgorithmException
+     */
+    public static KeyPair generateKeyPair() throws NoSuchAlgorithmException {
+        // 产生用于安全加密的随机数
+        SecureRandom random = new SecureRandom();
+
+        KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
+        Integer length = 1024;//加密算法位数
+        generator.initialize(length, random);
+        return generator.generateKeyPair();
+    }
+
+    /**
+     * 返回一个keyBytes生成的PublicKey对象
+     * @param keyBytes
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PublicKey getPublicKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PublicKey publicKey = keyFactory.generatePublic(keySpec);
+        return publicKey;
+    }
+
+    public static byte[] encryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        // Cipher: 提供加密和解密功能的实例
+        // transformation: "algorithm/mode/padding"
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
+        // PrivateKey privateKey = keyPair.getPrivate();
+        // 初始化
+        cipher.init(Cipher.ENCRYPT_MODE, keys);
+        // doFinal(): 加密或者解密数据
+        byte[] plainText = cipher.doFinal(byteArray);
+        return plainText;
+    }
+
+    /**
+     * 返回一个keyBytes生成的privateKey对象
+     * @param keyBytes
+     * @return
+     * @throws NoSuchAlgorithmException
+     * @throws InvalidKeySpecException
+     */
+    public static PrivateKey getPrivateKey(byte[] keyBytes) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
+        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
+        return privateKey;
+    }
+
+    /**
+     * 用相应的key解密对应加密的问题
+     *
+     * @param keys
+     * @param byteArray
+     * @return
+     */
+    public static byte[] decryptByKey(Key keys, byte[] byteArray) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
+        // Cipher: 提供加密和解密功能的实例
+        // transformation: "algorithm/mode/padding"
+        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", provider);
+
+        // 初始化
+        cipher.init(Cipher.DECRYPT_MODE, keys);
+        // doFinal(): 加密或者解密数据
+//        byte[] plainText = cipher.doFinal(byteArray);
+
+        byte[] bytes = processData(cipher, byteArray, 1024 / 8);
+
+        return bytes;
+    }
+
+    /**
+     * 分段处理数据.
+     *
+     * @param cipher      密码算法
+     * @param dataes      数据
+     * @param segmentSize 分段大小(小于等于0不分段)
+     * @return
+     */
+    private static byte[] processData(Cipher cipher, byte[] dataes, int segmentSize) {
+        byte[] decBytes = null;
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            int inputLength = dataes.length;
+            int offSet = 0;
+            for (int i = 0; inputLength - offSet > 0; offSet = i * segmentSize) {
+                byte[] cache;
+                if (inputLength - offSet > segmentSize) {
+                    cache = cipher.doFinal(dataes, offSet, segmentSize);
+                } else {
+                    cache = cipher.doFinal(dataes, offSet, inputLength - offSet);
+                }
+                out.write(cache, 0, cache.length);
+                ++i;
+            }
+            decBytes = out.toByteArray();
+            out.close();
+        } catch (Exception e) {
+        }
+        return decBytes;
+    }
+
+    /**
+     * 产生public key
+     *
+     * @return public key字符串
+     */
+    public static String generateBase64Key(byte[] keys) {
+        // encodeBase64(): Encodes binary data using the base64
+        // algorithm but does not chunk the output.
+        // getEncoded():返回key的原始编码形式
+        return new String(Base64.encodeBase64(keys));
+    }
+}

+ 47 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/common/oauth/SHAUtils.java

@@ -0,0 +1,47 @@
+package nckd.jimin.jyyy.bd.common.oauth;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class SHAUtils {
+
+
+    public static String getSHA256Hex(String input) {
+        try {
+            // 创建一个 MessageDigest 实例,并指定算法为 SHA-256
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+
+            // 将输入字符串转换为字节数组
+            byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
+
+            // 将字节数组转换为十六进制字符串
+            StringBuilder hexString = new StringBuilder();
+            for (byte b : hash) {
+                String hex = Integer.toHexString(0xff & b);
+                if (hex.length() == 1) hexString.append('0');
+                hexString.append(hex);
+            }
+
+            return hexString.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * 检查时间戳是否一致,默认允许5分钟误差
+     * @param timeStamp
+     * @return
+     */
+    public static boolean checkDateTime(String timeStamp){
+        long now = System.currentTimeMillis();
+        if(StringUtils.isEmpty(timeStamp) || (StringUtils.isNotEmpty(timeStamp) && StringUtils.isNumeric(timeStamp) && Math.abs(now - Long.parseLong(timeStamp)) / 1000 > 5 * 60)){
+            return false;
+        }
+        return true;
+    }
+
+}

+ 38 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/EcologyListPlugin.java

@@ -0,0 +1,38 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import com.alibaba.druid.util.StringUtils;
+import kd.bos.bill.AbstractBillPlugIn;
+import kd.bos.entity.operate.result.IOperateInfo;
+import kd.bos.entity.operate.result.OperationResult;
+import kd.bos.form.events.AfterDoOperationEventArgs;
+
+import java.util.List;
+
+public class EcologyListPlugin extends AbstractBillPlugIn {
+    @Override
+    public void afterDoOperation(AfterDoOperationEventArgs afterDoOperationEventArgs) {
+        super.afterDoOperation(afterDoOperationEventArgs);
+
+        if(StringUtils.equals("sendmsg",afterDoOperationEventArgs.getOperateKey())){
+            OperationResult operationResult = afterDoOperationEventArgs.getOperationResult();
+            operationResult.setShowMessage(false);
+            String message = operationResult.getMessage();
+
+            List<IOperateInfo> errorInfos = operationResult.getAllErrorOrValidateInfo();
+            boolean isSuccess = operationResult.isSuccess();
+            if(errorInfos.size() > 0){
+                operationResult.setSuccess(false);
+                StringBuffer msg = new StringBuffer();
+                for (IOperateInfo errInfo: errorInfos) {
+                    msg.append(errInfo.getMessage()).append("\r\n");
+                }
+                message = message + "\r\n" + msg.toString();
+            }
+            if(!StringUtils.isEmpty(message)) {
+                this.getView().showErrorNotification(message);
+            } else {
+                this.getView().showTipNotification("所选记录不需要重发!");
+            }
+        }
+    }
+}

+ 171 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/EcologyOpPlugin.java

@@ -0,0 +1,171 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import com.alibaba.druid.util.StringUtils;
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.entity.plugin.AbstractOperationServicePlugIn;
+import kd.bos.entity.plugin.args.BeforeOperationArgs;
+import kd.bos.exception.KDException;
+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.servicehelper.operation.SaveServiceHelper;
+import kd.bos.workflow.exception.WFErrorCode;
+import kd.bos.workflow.exception.WFMessageServiceException;
+import kd.sdk.plugin.Plugin;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+public class EcologyOpPlugin extends AbstractOperationServicePlugIn implements Plugin {
+    private static Log logger = LogFactory.getLog(EcologyOpPlugin.class);
+    private static final String KEY_ENTITY_LOG = "nckd_ecology";
+    @Override
+    public void beforeExecuteOperationTransaction(BeforeOperationArgs e) {
+        super.beforeExecuteOperationTransaction(e);
+
+        StringBuffer errMsg = new StringBuffer();
+
+        //获取选中行
+        DynamicObject[] dynamicObjects = e.getDataEntities();
+
+        //获取操作按钮操作编码
+        String operationKey = e.getOperationKey();
+        if (StringUtils.equals( "sendmsg",operationKey)){
+            List<DynamicObject> listObj = new ArrayList<>();
+
+            String selectField = "nckd_entryentity.nckd_key, nckd_entryentity.nckd_value";
+
+            QFilter qFilter = new QFilter("number", QCP.equals, "fanwei");
+            DynamicObject commonParam = BusinessDataServiceHelper.loadSingle("nckd_commonparams", selectField, qFilter.toArray());
+            if (ObjectUtils.isEmpty(commonParam)) {
+                errMsg.append("未配置泛微相关参数nckd_commonparams");
+                return;
+            }
+
+            DynamicObjectCollection entryentity = commonParam.getDynamicObjectCollection("nckd_entryentity");
+            Map<String, String> mapentity = entryentity.stream().collect(Collectors.toMap(k -> k.getString("nckd_key"), v -> v.getString("nckd_value")));
+
+            if(mapentity == null ){
+                errMsg.append("未配置泛微相关参数nckd_entryentity");
+                return;
+            }
+
+            String sendFlowUrl = mapentity.get("sendflow");
+            String secretkey = mapentity.get("secret_key");
+
+            if(StringUtils.isEmpty(sendFlowUrl) || StringUtils.isEmpty(secretkey)){
+                return;
+            }
+
+            String token = FanweiCommonUtil.getFanWeiToken(true);
+
+            for(int i = 0; i < dynamicObjects.length; i++) {
+                String id = dynamicObjects[i].getPkValue().toString();
+                DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(id, KEY_ENTITY_LOG);
+                Boolean needSend = false;
+                if(dynamicObject.getString("nckd_logtype").matches("1|5")
+                    && "fail".equals(dynamicObject.getString("nckd_sendstatus"))){
+                    needSend = true;
+                }
+
+                if(!needSend){
+                    continue;
+                }
+
+                JSONObject fanweiBodyData = JSONObject.parseObject(dynamicObject.getString("nckd_senddata_tag"));
+
+                String url = sendFlowUrl + "?access_token=" + token + "&secret_key=" + secretkey;
+
+                JSONObject returnObj = doPostByHttpClient(url, fanweiBodyData);
+                if (returnObj == null) {
+                    throw new KDException(WFErrorCode.httpRequestWrongResponse(), new Object[]{returnObj != null ? returnObj.toJSONString() : "return value is null!"});
+                }
+
+                String result = returnObj.toJSONString();
+
+                if(kd.bos.util.StringUtils.isEmpty(result)){
+                    logger.info("重发待办异常: 接口返回为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject msgObj = JSONObject.parseObject(result);
+                if(msgObj.get("message") == null){
+                    logger.info("重发待办异常: 接口返回message为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject message = msgObj.getJSONObject("message");
+
+                if(message.get("errcode") == null){
+                    logger.info("重发待办异常: 接口返回errorcode为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                String sendStatus = "fail";
+                String code = message.getString("errcode");
+                if(!"200".equals(code)) {
+                    String errCode = message.getString("errcode") == null ? "" : message.getString("errcode");
+                    String msg = message.getString("errmsg") == null ? "" : message.getString("errmsg");
+
+                    logger.info("EcologyOpPlugin:待办(" + dynamicObject.getString("number") + ")重发失败" + msg);
+                    errMsg.append(dynamicObject.getString("number")).append(":").append("重发失败!").append(msg).append("\r\n");
+                } else {
+                    sendStatus = "success";
+                    logger.info("EcologyOpPlugin:待办(" + dynamicObject.getString("number") + ")重发成功!");
+                    errMsg.append(dynamicObject.getString("number")).append(":").append("重发成功!").append("\r\n");
+                }
+
+                if (result.length() < 200) {
+                    dynamicObject.set("nckd_resultdata", result);
+                } else {
+                    dynamicObject.set("nckd_resultdata", result.substring(0, 200) + "...");
+                }
+                dynamicObject.set("nckd_resultdata_tag", result);
+                dynamicObject.set("nckd_sendstatus", sendStatus);
+                dynamicObject.set("nckd_sendurl", sendFlowUrl);
+
+                listObj.add(dynamicObject);
+
+                if(listObj.size() == 500) {
+                    SaveServiceHelper.update(listObj.toArray(new DynamicObject[]{}));
+                    listObj.clear();
+                }
+            }
+            if(listObj.size() > 0) {
+                SaveServiceHelper.update(listObj.toArray(new DynamicObject[]{}));
+            }
+        }
+
+        if(errMsg != null && errMsg.length() > 0) {
+            ////将错误信息返回到前端
+            e.setCancelMessage(errMsg.toString());
+            e.setCancel(true);
+            System.out.println("EcologyOpPlugin 错误信息:" + errMsg.toString());
+        }
+    }
+
+    public static JSONObject doPostByHttpClient(String url, JSONObject bodyData) {
+        try {
+            Map<String, String> headers = new HashMap();
+            headers.put("Content-Type", "application/json; charset=utf-8");
+            headers.put("Accept", "application/json");
+            logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
+            System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
+
+            String responseEntify = HttpUtils.postjson(url, headers, bodyData.toJSONString());
+            JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
+            return result;
+        } catch (IOException var5) {
+            throw new KDException(var5, WFErrorCode.httpRequestException(), new Object[]{var5.getMessage()});
+        }
+    }
+}

+ 1276 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/FanweiCommonUtil.java

@@ -0,0 +1,1276 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.entity.DynamicObjectCollection;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.exception.ErrorCode;
+import kd.bos.exception.KDException;
+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.sdk.util.KHttpClientUtils;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.bos.util.StringUtils;
+import kd.bos.workflow.engine.WfConfigurationUtil;
+import kd.bos.workflow.engine.msg.MessageServiceUtil;
+import kd.bos.workflow.engine.msg.ctx.MessageContext;
+import kd.bos.workflow.engine.msg.info.MessageInfo;
+import kd.bos.workflow.engine.msg.info.ToDoInfo;
+import kd.bos.workflow.exception.WFErrorCode;
+import kd.bos.workflow.exception.WFMessageServiceException;
+import org.apache.commons.lang3.ObjectUtils;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+/**
+ * 消息待办实现工具类
+ * @author wanghaiwu_kd
+ * @date 2025/04/16
+ */
+public final class FanweiCommonUtil {
+    private static Log logger = LogFactory.getLog(FanweiCommonUtil.class);
+    private static String KEY_ENTITY_LOG = "nckd_ecology";
+    //
+    private static String param_url = "";
+    private static String param_msgurl = "";
+    //注册企业id
+    private static String param_cropid = "";
+    private static String param_responsetype = "";
+    private static String param_state = "";
+    private static String param_appkey = "";
+    private static String param_appsecret = "";
+    private static String param_granttype = "";
+    private static String param_secretkey = "";
+    private static String param_syscode = "";
+    private static String param_getcode = "";
+    private static String param_gettoken = "";
+    private static String param_sendflow = "";
+    private static String param_receiver_dev = "";
+
+    /**
+     * 获取公共参数中的泛微相关参数配置
+     */
+    private static void setParmamValue(){
+        String selectField = "nckd_entryentity.nckd_key, nckd_entryentity.nckd_value";
+
+        QFilter qFilter = new QFilter("number", QCP.equals, "fanwei");
+        DynamicObject commonParam = BusinessDataServiceHelper.loadSingle("nckd_commonparams", selectField, qFilter.toArray());
+        if (ObjectUtils.isEmpty(commonParam)) {
+            return;
+        }
+
+        DynamicObjectCollection entryentity = commonParam.getDynamicObjectCollection("nckd_entryentity");
+        Map<String, String> mapentity = entryentity.stream().collect(Collectors.toMap(k -> k.getString("nckd_key"), v -> v.getString("nckd_value")));
+        if(mapentity != null ){
+            param_url = mapentity.get("url");
+            param_msgurl = mapentity.get("msgurl");
+            param_cropid = mapentity.get("corpid");
+            param_responsetype = mapentity.get("response_type");
+            param_state = mapentity.get("state");
+            param_appkey = mapentity.get("app_key");
+            param_appsecret = mapentity.get("app_secret");
+            param_granttype = mapentity.get("grant_type");
+            param_secretkey = mapentity.get("secret_key");
+            param_syscode = mapentity.get("syscode");
+            param_getcode = mapentity.get("getcode");
+
+            param_gettoken = mapentity.get("gettoken");
+            param_sendflow = mapentity.get("sendflow");
+            param_receiver_dev = mapentity.get("receiver_dev");
+        }
+    }
+
+    /**
+     * 创建待办
+     * @param ctx
+     * @param info
+     * @param params
+     */
+    public static void createUserToDo(MessageContext ctx, ToDoInfo info, Map<String, String> params) {
+        if (WfConfigurationUtil.isEnabled("fanwei")) {
+            setParmamValue();
+            if(StringUtils.isEmpty(param_sendflow)){
+                logger.info("泛微createToDo is fail :未配置泛微参数sendflow!");
+                return;
+            }
+
+            try {
+                JSONObject fanweiBodyData = buildToDoBodyData(ctx, info, params);
+
+                logger.info("待办发送消息:" + fanweiBodyData.toString());
+
+                String receiverLong = fanweiBodyData.getString("receiverLong");
+                String title = fanweiBodyData.getString("requestname");
+                String oaId = fanweiBodyData.getString("flowid");
+                String uuid = saveLogData(receiverLong, title, oaId, info.getContent(), fanweiBodyData.toString(), "1", param_sendflow);
+
+                logger.info("泛微推送数据日志保存成功");
+
+                String token = getFanWeiToken(false);
+                String url = "";
+                String result = "";
+
+                Map<String, String> header = new HashMap<>();
+                header.put("Content-Type", "application/json; charset=UTF-8");
+
+                //获取token
+                try {
+                    url = param_sendflow + "?access_token=" + token + "&secret_key=" + param_secretkey;
+                    logger.info("泛微发送消息接口地址:" + url);
+
+                    result = KHttpClientUtils.postjson(url, header, JSON.toJSONString(fanweiBodyData));
+                } catch (IOException e) {
+                    logger.info(e.getMessage());
+
+                    String message = ResManager.loadKDString("创建泛微待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                    ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                    throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
+                }
+
+                if(StringUtils.isEmpty(result)){
+                    logger.info("创建泛微待办异常: 接口返回为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject msgObj = JSONObject.parseObject(result);
+                if(msgObj.get("message") == null){
+                    logger.info("创建泛微待办异常: 接口返回message为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject message = msgObj.getJSONObject("message");
+
+                if(message.get("errcode") == null){
+                    logger.info("创建泛微待办异常: 接口返回errorcode为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                String sendStatus = "fail";
+                String code = message.getString("errcode");
+                if(!"200".equals(code)) {
+                    String errCode = message.getString("errcode") == null ? "" : message.getString("errcode");
+                    String errMsg = message.getString("errmsg") == null ? "" : message.getString("errmsg");
+
+                    throw new WFMessageServiceException("创建泛微待办异常: " + errMsg + "(" + errCode + ")");
+                }
+                sendStatus = "success";
+
+                updateLogData(uuid, result, sendStatus);
+
+                logger.info("泛微门户消息发送成功,发送消息:{}, 结果:{}", fanweiBodyData.toJSONString(), result);
+            } catch (Exception var15) {
+                logger.info(var15.getMessage());
+                String message = ResManager.loadKDString("泛微创建待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var15, error, new Object[]{var15.getMessage()});
+            } finally {
+            }
+        }
+    }
+
+
+
+    /**
+     * 处理待办
+     * @param ctx
+     * @param info
+     * @param params
+     */
+    public static void dealUserToDo(MessageContext ctx, ToDoInfo info, Map<String, String> params) {
+        if (WfConfigurationUtil.isEnabled("fanwei")) {
+            setParmamValue();
+            if(StringUtils.isEmpty(param_sendflow)){
+                logger.info("泛微dealToDo is fail :未配置泛微参数sendflow!");
+                return;
+            }
+            try {
+                JSONObject fanweiBodyData = buildToDoBodyData(ctx, info, params);
+
+                logger.info("待办发送消息:" + fanweiBodyData.toString());
+
+                String receiverLong = fanweiBodyData.getString("receiverLong");
+                String title = fanweiBodyData.getString("requestname");
+                String oaId = fanweiBodyData.getString("flowid");
+                String uuid = saveLogData(receiverLong, title, oaId, info.getContent(), fanweiBodyData.toString(), "5", param_sendflow);
+                logger.info("泛微推送数据日志保存成功");
+
+                String token = getFanWeiToken(false);
+                String url = "";
+                String result = "";
+
+                Map<String, String> header = new HashMap<>();
+                header.put("Content-Type", "application/json; charset=UTF-8");
+
+                //获取token
+                try {
+                    url = param_sendflow + "?access_token=" + token + "&secret_key=" + param_secretkey;
+                    logger.info("泛微发送消息接口地址:" + url);
+
+                    result = KHttpClientUtils.postjson(url, header, JSON.toJSONString(fanweiBodyData));
+                } catch (IOException e) {
+                    logger.info(e.getMessage());
+
+                    String message = ResManager.loadKDString("创建泛微待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                    ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                    throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
+                }
+
+                if(StringUtils.isEmpty(result)){
+                    logger.info("创建泛微待办异常: 接口返回为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject msgObj = JSONObject.parseObject(result);
+                if(msgObj.get("message") == null){
+                    logger.info("创建泛微待办异常: 接口返回message为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject message = msgObj.getJSONObject("message");
+                if(message.get("errcode") == null){
+                    logger.info("创建泛微待办异常: 接口返回errorcode为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                String sendStatus = "fail";
+                String code = message.getString("errcode");
+                if(!"200".equals(code)) {
+                    String errCode = message.getString("errcode") == null ? "" : message.getString("errcode");
+                    String errMsg = message.getString("errmsg") == null ? "" : message.getString("errmsg");
+
+                    throw new WFMessageServiceException("创建泛微待办异常: " + errMsg + "(" + errCode + ")");
+                }
+                sendStatus = "success";
+
+                updateLogData(uuid, result, sendStatus);
+
+                logger.info("泛微门户消息发送成功,发送消息:{}, 结果:{}", fanweiBodyData.toJSONString(), result);
+            } catch (Exception var15) {
+                logger.info(var15.getMessage());
+                String message = ResManager.loadKDString("泛微处理待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var15, error, new Object[]{var15.getMessage()});
+            } finally {
+            }
+        }
+    }
+
+    /**
+     * 撤销待办、转交、加签等
+     * @param ctx
+     * @param info
+     * @param params
+     */
+    public static void deleteUserToDo(MessageContext ctx, ToDoInfo info, Map<String, String> params) {
+        if (WfConfigurationUtil.isEnabled("fanwei")) {
+            setParmamValue();
+            if(StringUtils.isEmpty(param_sendflow)){
+                logger.info("泛微dealToDo is fail :未配置泛微参数sendflow!");
+                return;
+            }
+            try {
+                JSONObject fanweiBodyData = buildToDoBodyData(ctx, info, params);
+
+                logger.info("待办发送消息:" + fanweiBodyData.toString());
+
+                String receiverLong = fanweiBodyData.getString("receiverLong");
+                String title = fanweiBodyData.getString("requestname");
+                String oaId = fanweiBodyData.getString("flowid");
+                String uuid = saveLogData(receiverLong, title, oaId, info.getContent(), fanweiBodyData.toString(), "5", param_sendflow);
+                logger.info("泛微推送数据日志保存成功");
+
+                String token = getFanWeiToken(false);
+                String url = "";
+                String result = "";
+
+                Map<String, String> header = new HashMap<>();
+                header.put("Content-Type", "application/json; charset=UTF-8");
+
+                //获取token
+                try {
+                    url = param_sendflow + "?access_token=" + token + "&secret_key=" + param_secretkey;
+                    logger.info("泛微发送消息接口地址:" + url);
+
+                    result = KHttpClientUtils.postjson(url, header, JSON.toJSONString(fanweiBodyData));
+                } catch (IOException e) {
+                    logger.info(e.getMessage());
+
+                    String message = ResManager.loadKDString("创建泛微待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                    ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                    throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
+                }
+
+                if(StringUtils.isEmpty(result)){
+                    logger.info("创建泛微待办异常: 接口返回为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject msgObj = JSONObject.parseObject(result);
+                if(msgObj.get("message") == null){
+                    logger.info("创建泛微待办异常: 接口返回message为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject message = msgObj.getJSONObject("message");
+                if(message.get("errcode") == null){
+                    logger.info("创建泛微待办异常: 接口返回errorcode为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                String sendStatus = "fail";
+                String code = message.getString("errcode");
+                if(!"200".equals(code)) {
+                    String errCode = message.getString("errcode") == null ? "" : message.getString("errcode");
+                    String errMsg = message.getString("errmsg") == null ? "" : message.getString("errmsg");
+
+                    throw new WFMessageServiceException("创建泛微待办异常: " + errMsg + "(" + errCode + ")");
+                }
+                sendStatus = "success";
+
+                updateLogData(uuid, result, sendStatus);
+
+                logger.info("泛微门户消息发送成功,发送消息:{}, 结果:{}", fanweiBodyData.toJSONString(), result);
+            } catch (Exception var15) {
+                logger.info(var15.getMessage());
+                String message = ResManager.loadKDString("泛微处理待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var15, error, new Object[]{var15.getMessage()});
+            } finally {
+            }
+        }
+    }
+
+    /**
+     * 发送消息
+     * @param ctx
+     * @param info
+     * @param params
+     */
+    public static void sendMessage(MessageContext ctx, MessageInfo info, Map<String, String> params) {
+        if (WfConfigurationUtil.isEnabled("fanwei")) {
+            setParmamValue();
+            if(StringUtils.isEmpty(param_sendflow)){
+                logger.info("泛微createToDo is fail :未配置泛微服务器地址!");
+                return;
+            }
+            //发送传阅消息
+            if("circulation".equals(info.getTplScene())) {
+                sendFlowMessage(ctx, info, params);
+            } else {
+                sendCustomMessage(ctx, info, params);
+            }
+        }
+    }
+
+    /**
+     * 发送传阅消息
+     * @param ctx
+     * @param info
+     * @param params
+     */
+    private static void sendFlowMessage(MessageContext ctx, MessageInfo info, Map<String, String> params){
+        if (WfConfigurationUtil.isEnabled("fanwei")) {
+            setParmamValue();
+            if (StringUtils.isEmpty(param_sendflow)) {
+                logger.info("泛微dealToDo is fail :未配置泛微参数sendflow!");
+                return;
+            }
+            try {
+                JSONObject fanweiBodyData = buildMessageBodyData(ctx, info, params);
+
+                logger.info("发送传阅消息到泛微:" + fanweiBodyData.toString());
+
+                String receiverLong = fanweiBodyData.getString("receiverLong");
+                String title = fanweiBodyData.getString("requestname");
+                String oaId = fanweiBodyData.getString("flowid");
+                String uuid = saveLogData(receiverLong, title, oaId, info.getContent(), fanweiBodyData.toString(), "2", param_sendflow);
+                logger.info("泛微推送数据日志保存成功");
+
+                String token = getFanWeiToken(false);
+                String url = "";
+                String result = "";
+
+                Map<String, String> header = new HashMap<>();
+                header.put("Content-Type", "application/json; charset=UTF-8");
+
+                //获取token
+                try {
+                    url = param_sendflow + "?access_token=" + token + "&secret_key=" + param_secretkey;
+                    logger.info("泛微发送消息接口地址:" + url);
+
+                    result = KHttpClientUtils.postjson(url, header, JSON.toJSONString(fanweiBodyData));
+                } catch (IOException e) {
+                    logger.info(e.getMessage());
+
+                    String message = ResManager.loadKDString("创建泛微待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                    ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                    throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
+                }
+
+                if(StringUtils.isEmpty(result)){
+                    logger.info("创建泛微待办异常: 接口返回为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject msgObj = JSONObject.parseObject(result);
+                if(msgObj.get("message") == null){
+                    logger.info("创建泛微待办异常: 接口返回message为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                JSONObject message = msgObj.getJSONObject("message");
+                if(message.get("errcode") == null){
+                    logger.info("创建泛微待办异常: 接口返回errorcode为空");
+                    throw new WFMessageServiceException("创建泛微待办异常: 接口返回为空");
+                }
+
+                String sendStatus = "fail";
+                String code = message.getString("errcode");
+                if(!"200".equals(code)) {
+                    String errCode = message.getString("errcode") == null ? "" : message.getString("errcode");
+                    String errMsg = message.getString("errmsg") == null ? "" : message.getString("errmsg");
+
+                    throw new WFMessageServiceException("创建泛微待办异常: " + errMsg + "(" + errCode + ")");
+                }
+                sendStatus = "success";
+
+                updateLogData(uuid, result, sendStatus);
+
+                logger.info("泛微门户消息发送成功,发送消息:{}, 结果:{}", fanweiBodyData.toJSONString(), result);
+            } catch (Exception var15) {
+                logger.info(var15.getMessage());
+                String message = ResManager.loadKDString("泛微创建待办失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var15, error, new Object[]{var15.getMessage()});
+            } finally {
+            }
+        }
+    }
+
+    /**
+     * 发送消息
+     */
+    private static void sendCustomMessage(MessageContext ctx, MessageInfo info, Map<String, String> params){
+//        try {
+//            Map<String,String> fanweiBodyData = buildCustomMessageBodyData(ctx, info, params);
+//
+//            logger.info("发送传阅消息到泛微:" + fanweiBodyData.toString());
+//
+//            String receiverLong = fanweiBodyData.get("createrLong");
+//            String title = fanweiBodyData.get("title");
+//            String context = fanweiBodyData.get("context");
+//            String oaId = fanweiBodyData.get("targetId");
+//            String uuid = saveLogData(receiverLong, title, oaId, context, fanweiBodyData.toString(), "3", param_msgurl);
+//            logger.info("泛微推送数据日志保存成功");
+//
+//            String url = param_msgurl + "/api/ec/dev/message/sendCustomMessageSingle";
+//            Map<String, String> heads = getHttpHeads();
+//
+//            String data = doPostByHttpClient(url, fanweiBodyData, heads);
+//
+//            if (data != null && data.contains("消息发送至OA异常")) {
+//                updateLogData(uuid, data, "fail");
+//                return;
+//            }
+//
+//            JSONObject result = JSONObject.parseObject(data);
+//            if (result == null) {
+//                throw new KDException(WFErrorCode.httpRequestWrongResponse(), new Object[]{result != null ? result.toJSONString() : "result is null!"});
+//            }
+//
+//            //失败
+//            if("true".equals(result.getString("status"))){
+//                logger.info("泛微createToDo is ok , url is:" + info.getContentUrl() + ",mobileurl:" + info.getMobContentUrl());
+//            } else {
+//                logger.info("泛微createToDo is fail :" + result.getString("message"));
+//            }
+//
+//            updateLogData(uuid, result.toJSONString(), "success");
+//
+//            logger.info("泛微门户消息发送成功,发送消息:{}, 结果:{}", fanweiBodyData.toString(), result.toJSONString());
+//        } catch (Exception var15) {
+//            logger.info(var15.getMessage());
+//            String message = ResManager.loadKDString("泛微发送消息失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+//            ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+//            throw new WFMessageServiceException(var15, error, new Object[]{var15.getMessage()});
+//        } finally {
+//        }
+    }
+
+    /**
+     * 组装消息发送
+     * @param ctx
+     * @param info
+     * @param params
+     * @return
+     */
+    public static Map<String,String> buildCustomMessageBodyData(MessageContext ctx, MessageInfo info, Map<String, String> params) {
+        Map<String, String> map = new HashMap<>();
+
+//        DynamicObject msgInfo = BusinessDataServiceHelper.loadSingleFromCache(info.getId(), "wf_msg_message");
+//
+//        //发送人员
+//        Long createUserId = 0L;
+////        if(taskInfo != null){
+////            createUserId = taskInfo.getLong("starterid");
+////        }
+//        if(ctx != null){
+//            createUserId = ctx.getStartUserId();
+//        }
+//
+//        DynamicObject createUser = BusinessDataServiceHelper.loadSingleFromCache(createUserId, "bos_user");
+//        String creator = createUser == null ? "admin" : createUser.getString("number");
+//
+//        Long userId = Long.valueOf(params.get("userId"));
+//        //接收人员
+//        DynamicObject user = BusinessDataServiceHelper.loadSingleFromCache(userId, "bos_user");
+//        String personNo = user.getString("number");
+//        String personNoLong = user.getString("name") + "(" + user.getString("number") + ")";
+//        String title = info.getTitle() == null ? "" : info.getTitle();
+//        String content = info.getContent() == null ? "" : info.getContent();
+//
+//        String linkUrl = info.getContentUrl();
+//        String linkMobileUrl = info.getMobContentUrl();
+//
+//        if(msgInfo != null) {
+//            if(StringUtils.isNotEmpty(msgInfo.getString("contenturl"))){
+//                linkUrl = msgInfo.getString("contenturl");
+//            }
+//            if(StringUtils.isNotEmpty(msgInfo.getString("contenturl"))){
+//                linkMobileUrl = msgInfo.getString("mobcontenturl");
+//            }
+//            if(StringUtils.isNotEmpty(linkMobileUrl)){
+//                linkMobileUrl = linkUrl;
+//            }
+//        }
+//
+//        logger.info("消息pcurl:" + linkUrl + ", moburl" + linkMobileUrl);
+//
+//        String targetId = FANWEI_MSGCODE + "|KD-" + info.getChannelMsgId().toString() + "-" + personNo;
+//
+//        if(StringUtils.isNotEmpty(linkMobileUrl)){
+//            //移动端需要走外网,将地址替换成外网地址
+//            String curUrl = "";//ParamsUtil.getCommonParamsField("nckd_url");
+//            String mobileUrl = "";//ParamsUtil.getCommonParamsField("nckd_mobileurl");
+//
+//            linkUrl = linkUrl.replace(mobileUrl, curUrl);
+//            linkMobileUrl = linkMobileUrl.replace(curUrl, mobileUrl);
+//        }
+//
+//        try {
+//            linkUrl = URLEncoder.encode(linkUrl, "utf-8");
+//            linkMobileUrl = URLEncoder.encode(linkMobileUrl, "utf-8");
+//        } catch (UnsupportedEncodingException e) {
+//            throw new RuntimeException(e);
+//        }
+//
+//        map.put("code", FANWEI_MSGCODE); // 消息来源,新建消息来源获取code 请查看文档第四大点补充
+//        map.put("workCodeList", personNo);
+//        map.put("creater", creator);
+//        map.put("createrLong", personNoLong);
+//        map.put("title", title);
+//        map.put("context", content);
+//        map.put("linkUrl", linkUrl);
+//        map.put("linkMobileUrl", linkMobileUrl);
+//        map.put("targetId", targetId); //消息来源code +“|”+业务id  消息需要打上已处理标记
+////        map.put("bizState","0"); //0 表示消息初始状态是待处理  消息需要打上已处理标记
+        return map;
+    }
+
+
+    /**
+     * 组装传阅消息
+     * @param ctx
+     * @param info
+     * @param params
+     * @return
+     */
+    public static JSONObject buildMessageBodyData(MessageContext ctx, MessageInfo info, Map<String, String> params) {
+        JSONObject bodyData = new JSONObject();
+        Long userId = Long.valueOf(params.get("userId"));
+        String isremark = params.get("isremark").toString();
+        String viewtype = params.get("viewtype").toString();
+        String content = info.getContent() == null ? "" : info.getContent();
+
+        //发送人员
+        Long createUserId = 0L;
+        if(info != null && info.getSenderId() != null){
+            createUserId = info.getSenderId();
+        }
+
+        DynamicObject createUser = BusinessDataServiceHelper.loadSingleFromCache(createUserId, "bos_user");
+        String creator = createUser == null ? "" : createUser.getString("number");
+
+        String requestname = info.getTitle() + ", 发送人:" + creator + ", " + content;
+        String nodename = info.getOperation() == null ? "circulation" : info.getOperation();
+        String workflowname = "财务系统审批流";
+        String workflowcode = "nobill";
+
+        if(info.getParams() != null){
+            Map<String, Object> config = info.getParams();
+            if(config != null) {
+                if(config.get("messageContext") != null){
+                    JSONObject messageContext = JSONObject.parseObject(config.get("messageContext").toString());
+                    if(messageContext.get("taskId") != null){
+                        DynamicObject taskInfo = BusinessDataServiceHelper.loadSingleFromCache(Long.valueOf(messageContext.getString("taskId")), "wf_task");
+                        if(taskInfo != null){
+                            nodename = taskInfo.getString("name");
+
+                            if(taskInfo.getLong("processdefinitionid") > 0){
+                                QFilter qFilter = new QFilter("id", QCP.equals, taskInfo.getLong("processdefinitionid"));
+                                DynamicObject processdef = BusinessDataServiceHelper.loadSingle("wf_processdefinition", qFilter.toArray());
+                                if(processdef != null){
+                                    workflowcode = processdef.getString("key");
+                                    workflowname = processdef.getString("name");
+                                }
+                            }
+
+                            if("财务系统审批流".equals(workflowname) && taskInfo.getString("entityname") != null){
+                                workflowcode = taskInfo.getString("entityname");
+                                workflowname = taskInfo.getString("entityname") + "审批流程";
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        //接收人员
+        DynamicObject user = BusinessDataServiceHelper.loadSingleFromCache(userId, "bos_user");
+        String personNo = user.getString("number");
+        String receiverLong = user.getString("name") + "(" + user.getString("number") + ")";
+
+        //创建时间
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String createTime = sdf.format(new Date());
+        String curTimestamp = String.valueOf(System.currentTimeMillis());
+        String flowid = "KD-" + info.getChannelMsgId().toString() + "-" + personNo;
+
+        String pcUrl = info.getContentUrl() == null ? "" : info.getContentUrl();
+        String mobUrl = info.getMobContentUrl() == null ? pcUrl : info.getMobContentUrl();
+
+        String contextUrl = System.getProperty("domain.contextUrl").replace("/ierp", "");
+        pcUrl = pcUrl.replace("http://127.0.0.1:8080", "").replace(contextUrl, "");
+        mobUrl = mobUrl.replace("http://127.0.0.1:8080", "").replace(contextUrl, "");
+
+        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";
+        }
+
+        try {
+            pcUrl = URLEncoder.encode(pcUrl, "utf-8");
+            mobUrl = URLEncoder.encode(mobUrl, "utf-8");
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException(e);
+        }
+
+        //异构系统标识
+        bodyData.put("syscode", param_syscode);
+        //流程实例id
+        bodyData.put("flowid", flowid);
+        //标题
+        bodyData.put("requestname", requestname);
+        //流程类型编码
+        bodyData.put("workflowcode", workflowcode);
+        //流程类型名称
+        bodyData.put("workflowname", workflowname);
+        //接收人所属节点
+        bodyData.put("receivenodename", "");
+        //节点名称
+        bodyData.put("nodename", nodename);
+        //PC地址
+        bodyData.put("pcurl", pcUrl);
+        //APP地址
+        bodyData.put("appurl", mobUrl);
+        //创建人
+        bodyData.put("creator", creator);
+        //创建时间
+        bodyData.put("createdatetime", createTime);
+        //接收人
+        bodyData.put("receiver", personNo);
+
+        //测试人员
+        if(StringUtils.isNotEmpty(param_receiver_dev)) {
+            bodyData.put("receiver", param_receiver_dev);
+        }
+
+        //接收时间
+        bodyData.put("receivedatetime", createTime);
+        //流程处理状态:0:待办,2:已办,4:办结,8:抄送(待阅)
+        bodyData.put("isremark", isremark);
+        //流程查看状态:0:未读,1:已读
+        bodyData.put("viewtype", viewtype);
+        //接收时间戳
+        bodyData.put("receivets", curTimestamp);
+        //接收人+编码,保存日志使用,oa接口不需要此字段。
+        bodyData.put("receiverLong", receiverLong);
+
+        return bodyData;
+    }
+
+    /**
+     * 组装待办
+     * @param todoInfo
+     * @return
+     */
+    public static JSONObject buildToDoBodyData(MessageContext ctx, ToDoInfo todoInfo, Map<String, String> params) {
+
+        DynamicObject taskInfo =  BusinessDataServiceHelper.loadSingleFromCache(todoInfo.getTaskId() ,"wf_task");
+
+        //add by wnaghaiwu_kd 2024/04/28
+        //如果任务中找不到,就找历史任务
+        if(taskInfo == null){
+            taskInfo =  BusinessDataServiceHelper.loadSingleFromCache(todoInfo.getTaskId() ,"wf_hitaskinst");
+        }
+
+        JSONObject bodyData = new JSONObject();
+        Long userId = Long.valueOf(params.get("userId"));
+        String isremark = params.get("isremark").toString();
+        String viewtype = params.get("viewtype").toString();
+
+        //发送人员
+        Long createUserId = 0L;
+        if(taskInfo != null){
+            createUserId = taskInfo.getLong("starterid");
+        }
+        if(createUserId.compareTo(0L) == 0){
+            createUserId = ctx.getStartUserId();
+        }
+
+        DynamicObject createUser = BusinessDataServiceHelper.loadSingleFromCache(createUserId, "bos_user");
+        String creator = createUser == null ? "" : createUser.getString("number");
+
+        String title = todoInfo.getTitle();
+        if(todoInfo.getParams() != null && todoInfo.getParams().get("subject") != null){
+            JSONObject subject = JSONObject.parseObject(todoInfo.getParams().get("subject").toString());
+            title = subject.getString("zh_CN");
+        }
+
+        if(StringUtils.isEmpty(title) && taskInfo != null){
+            title = "请处理" + taskInfo.getString("startname")
+                    + "提交的" + taskInfo.getString("entityname") + taskInfo.getString("billno");
+        }
+        String requestname = title;
+        String nodename = todoInfo.getCategory();
+        String workflowname = "财务系统审批流";
+        String workflowcode = "nobill";
+
+        if(taskInfo != null){
+            nodename = taskInfo.getString("name");
+
+            if(taskInfo.getLong("processdefinitionid") > 0) {
+                QFilter qFilter = new QFilter("id", QCP.equals, taskInfo.getLong("processdefinitionid"));
+                DynamicObject processdef = BusinessDataServiceHelper.loadSingle("wf_processdefinition", qFilter.toArray());
+                if (processdef != null) {
+                    workflowcode = processdef.getString("key");
+                    workflowname = processdef.getString("name");
+                }
+            }
+
+            if("财务系统审批流".equals(workflowname) && taskInfo.getString("entityname") != null){
+                workflowcode = taskInfo.getString("entityname");
+                workflowname = taskInfo.getString("entityname") + "审批流程";
+            }
+        }
+
+        //接收人员
+        DynamicObject user = BusinessDataServiceHelper.loadSingleFromCache(userId, "bos_user");
+        String personNo = user.getString("number");
+        String receiverLong = user.getString("name") + "(" + user.getString("number") + ")";
+
+        //创建时间
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String createTime = sdf.format(new Date());
+        String curTimestamp = String.valueOf(System.currentTimeMillis());
+        String flowid = "KD-" + todoInfo.getTaskId().toString() + "-" + personNo;
+
+        //add by wanghaiw_kd 2024/04/28
+        //如果获取的任务对象为空,则获取flowid相同的待办消息中的发送参数,修改状态、接收时间,做为待办处理的发送参数
+        if(taskInfo == null){
+            QFilter qFilter = new QFilter("nckd_oaid", QCP.equals, flowid);
+            qFilter.and(new QFilter("nckd_logtype", QCP.equals, "1"));
+
+            DynamicObject ecologyLog = BusinessDataServiceHelper.loadSingle("nckd_ecology", qFilter.toArray());
+
+            if(ecologyLog != null && StringUtils.isEmpty(ecologyLog.getString("nckd_senddata_tag"))){
+                JSONObject fanweiBodyData = JSONObject.parseObject(ecologyLog.getString("nckd_senddata_tag"));
+
+                //流程处理状态:0:待办,2:已办,4:办结,8:抄送(待阅)
+                fanweiBodyData.put("isremark", "2");
+                //流程查看状态:0:未读,1:已读
+                fanweiBodyData.put("viewtype", "1");
+                //接收时间
+                fanweiBodyData.put("receivedatetime", createTime);
+                //接收时间戳
+                fanweiBodyData.put("receivets", curTimestamp);
+
+                return fanweiBodyData;
+            }
+        }
+
+        String url = MessageServiceUtil.buildWebPageUrlForMyApplyed(ctx.getProcessInstanceId());
+        logger.info("消息url:" + url);
+
+        String pcUrl = "";
+        String mobUrl = "";
+
+        if(StringUtils.isNotEmpty(url)){
+            String contextUrl = System.getProperty("domain.contextUrl").replace("/ierp", "");
+            url = url.replace("http://127.0.0.1:8080", "").replace(contextUrl, "");
+            pcUrl = url;
+            mobUrl = url;
+
+            //移动端需要走外网,将地址替换成外网地址
+            String curUrl = "";//ParamsUtil.getCommonParamsField("nckd_url");
+            String mobileUrl = "";//ParamsUtil.getCommonParamsField("nckd_mobileurl");
+            pcUrl = pcUrl.replace(mobileUrl, curUrl);
+            mobUrl = mobUrl.replace(curUrl, mobileUrl);
+
+            try {
+                pcUrl = URLEncoder.encode(pcUrl, "utf-8");
+                mobUrl = URLEncoder.encode(mobUrl, "utf-8");
+            } catch (UnsupportedEncodingException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        //异构系统标识
+        bodyData.put("syscode", param_syscode);
+        //流程实例id
+        bodyData.put("flowid", flowid);
+        //标题
+        bodyData.put("requestname", requestname);
+        //流程类型编码
+        bodyData.put("workflowcode", workflowcode);
+        //流程类型名称
+        bodyData.put("workflowname", workflowname);
+        //接收人所属节点
+        bodyData.put("receivenodename", "");
+        //节点名称
+        bodyData.put("nodename", nodename);
+        //PC地址
+        bodyData.put("pcurl", pcUrl);
+        //APP地址
+        bodyData.put("appurl", mobUrl);
+        //创建人
+        bodyData.put("creator", creator);
+        //创建时间
+        bodyData.put("createdatetime", createTime);
+        //接收人
+        bodyData.put("receiver", personNo);
+
+        if(StringUtils.isNotEmpty(param_receiver_dev)) {
+            //测试人员
+            bodyData.put("receiver", param_receiver_dev);
+        }
+
+        //接收时间
+        bodyData.put("receivedatetime", createTime);
+        //流程处理状态:0:待办,2:已办,4:办结,8:抄送(待阅)
+        bodyData.put("isremark", isremark);
+        //流程查看状态:0:未读,1:已读
+        bodyData.put("viewtype", viewtype);
+        //接收时间戳
+        bodyData.put("receivets", curTimestamp);
+        //接收人+编码,保存日志使用,oa接口不需要此字段。
+        bodyData.put("receiverLong", receiverLong);
+
+        return bodyData;
+    }
+
+
+    /**
+     * 获取泛微OA的accesstoken
+     * @return
+     */
+    public static String getFanWeiToken(boolean isSerchParam) {
+        if(isSerchParam){
+            setParmamValue();
+        }
+
+        String token = "";
+
+        String result = "";
+        String url = "";
+        try {
+            url = param_getcode + "?corpid=" + param_cropid + "&response_type=" + param_responsetype + "&state=" + param_state;
+
+            logger.info("获取泛微code接口地址:" + url);
+            //获取code
+            result = KHttpClientUtils.get(url);
+        } catch (Exception e) {
+            logger.info(e.getMessage());
+
+            String message = ResManager.loadKDString("获取泛微code失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+            ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+            throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
+        }
+
+        if(StringUtils.isEmpty(result)){
+            throw new WFMessageServiceException("获取泛微code异常: 接口返回为空");
+        }
+
+        JSONObject codeObj = JSONObject.parseObject(result);
+        String errcode = codeObj.getString("errcode");
+
+        if(!"0".equals(errcode)) {
+            String errCode = codeObj.getString("errcode") == null ? "" : codeObj.getString("errcode");
+            String errMsg = codeObj.getString("errmsg") == null ? "" : codeObj.getString("errmsg");
+
+            throw new WFMessageServiceException("获取泛微code异常: " + errMsg + "(" + errCode + ")");
+        }
+        String code = codeObj.getString("code");
+
+        Map<String, String> header = new HashMap<>();
+        header.put("Content-Type", "application/json; charset=UTF-8");
+
+        Map<String, Object> params = new HashMap<>();
+//        Map<String, Object> body = new HashMap<>();
+
+        params.put("app_key", param_appkey);
+        params.put("app_secret", param_appsecret);
+        params.put("grant_type", param_granttype);
+        params.put("code", code);
+
+        //获取token
+        try {
+            url = param_gettoken;
+            logger.info("获取泛微token接口地址:" + url);
+
+            result = KHttpClientUtils.postjson(url, header, JSON.toJSONString(params));
+
+
+        } catch (IOException e) {
+            logger.info(e.getMessage());
+
+            String message = ResManager.loadKDString("获取泛微token失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+            ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+            throw new WFMessageServiceException(e, error, new Object[]{e.getMessage()});
+        }
+
+        if(StringUtils.isEmpty(result)){
+            throw new WFMessageServiceException("获取泛微token异常: 接口返回为空");
+        }
+
+        JSONObject tokenObj = JSONObject.parseObject(result);
+        errcode = tokenObj.getString("errcode");
+
+        if(!"0".equals(errcode)) {
+            String errCode = codeObj.getString("errcode") == null ? "" : codeObj.getString("errcode");
+            String errMsg = codeObj.getString("errmsg") == null ? "" : codeObj.getString("errmsg");
+
+            throw new WFMessageServiceException("获取泛微code异常: " + errMsg + "(" + errCode + ")");
+        }
+        token = tokenObj.getString("accessToken");
+
+        return token;
+    }
+
+    /**
+     * 保存日志
+     * @param userid
+     * @param title
+     * @param msgContent
+     * @param sendData
+     * @return
+     */
+    private static String saveLogData(String userid, String title, String oaId, String msgContent, String sendData, String logType, String url) {
+        try {
+            logger.info("记录新增泛微推送数据日志");
+
+            msgContent = msgContent == null ? "" : msgContent;
+            sendData = sendData == null ? "" : sendData;
+
+            String uuid = UUID.randomUUID().toString().replace("-", "");
+
+            uuid = uuid == null ? "uuid" + String.valueOf(System.currentTimeMillis()) : uuid;
+            DynamicObject dynamicObject = BusinessDataServiceHelper.newDynamicObject(KEY_ENTITY_LOG);
+
+            dynamicObject.set("enable", "1");
+            dynamicObject.set("status", "C");
+            dynamicObject.set("number", uuid);
+            dynamicObject.set("nckd_logtype", logType);
+            dynamicObject.set("nckd_sendurl", url);
+            dynamicObject.set("nckd_receiver", userid);
+            dynamicObject.set("nckd_title", title);
+            dynamicObject.set("nckd_oaid", oaId);
+
+            dynamicObject.set("nckd_sendtime", new Date());
+            if (sendData.length() < 200) {
+                dynamicObject.set("nckd_senddata", sendData);
+            } else {
+                dynamicObject.set("nckd_senddata", sendData.substring(0, 200) + "...");
+            }
+            dynamicObject.set("nckd_senddata_tag", sendData);
+
+            if (msgContent.length() < 200) {
+                dynamicObject.set("nckd_msgcontent", msgContent);
+            } else {
+                dynamicObject.set("nckd_msgcontent", msgContent.substring(0, 200) + "...");
+            }
+            dynamicObject.set("nckd_msgcontent_tag", msgContent);
+
+            SaveServiceHelper.save(new DynamicObject[]{dynamicObject});
+            logger.info("记录新增泛微推送数据日志成功:{}", uuid);
+            return uuid;
+        } catch (Exception e) {
+            logger.info("记录新增泛微推送数据日志异常:" + e.getMessage());
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /**
+     * 更新日志
+     * @param uuid
+     * @param response
+     */
+    private static void updateLogData(String uuid, String response, String sendStatus) {
+        try {
+            logger.info("记录更新泛微推送结果数据日志");
+            response = response == null ? "" : response;
+
+            QFilter qFilterCas = new QFilter("number", QCP.equals, uuid);
+            DynamicObject[] dynamicObjects = BusinessDataServiceHelper.load(KEY_ENTITY_LOG, "id", new QFilter[]{qFilterCas});
+            if (dynamicObjects != null && dynamicObjects.length > 0) {
+                String id = dynamicObjects[0].getPkValue().toString();
+                DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(id, KEY_ENTITY_LOG);
+                if (response.length() < 200) {
+                    dynamicObject.set("nckd_resultdata", response);
+                } else {
+                    dynamicObject.set("nckd_resultdata", response.substring(0, 200) + "...");
+                }
+                dynamicObject.set("nckd_resultdata_tag", response);
+                dynamicObject.set("nckd_sendstatus", sendStatus);
+
+                SaveServiceHelper.update(dynamicObject);
+
+                logger.info("记录更新泛微推送结果数据日志成功");
+            }
+        } catch (Exception e) {
+            logger.info("记录更新泛微推送结果数据日志异常:" + e.getMessage());
+            e.printStackTrace();
+        }
+
+    }
+
+    /**
+     *
+     * @param url
+     * @param bodyData
+     * @return
+     */
+    public static JSONObject doPostByHttpClient(String url, JSONObject bodyData) {
+        try {
+            Map<String, String> headers = new HashMap();
+            headers.put("Content-Type", "application/json; charset=utf-8");
+            headers.put("Accept", "application/json");
+            logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
+            System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
+
+            String responseEntify = HttpUtils.postjson(url, headers, bodyData.toJSONString());
+            JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
+            return result;
+        } catch (IOException var5) {
+            throw new KDException(var5, WFErrorCode.httpRequestException(), new Object[]{var5.getMessage()});
+        }
+    }
+
+    /**
+     * 发送普通消息到泛微OA
+     * @param path
+     * @param params
+     * @param data
+     * @return
+     */
+    public static String doPostByHttpClient(String path, Map<String, String> params, Map<String, String> data) {
+        if(path.toLowerCase().startsWith("https")){
+            return doPostByHttps(path, params, data);
+        }
+        return doPostByHttp(path, params, data);
+    }
+
+    /**
+     * http服务
+     * @param path
+     * @param params
+     * @param data
+     * @return
+     */
+    public static String doPostByHttp(String path, Map<String, String> params, Map<String, String> data) {
+        String errMsg = "";
+        try {
+            String str = "";
+            URL url = new URL(path);
+            //打开和url之间的连接
+            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+            // 请求参数 编码为 utf-8
+            //请求方式
+            conn.setRequestMethod("POST");
+            //设置通用的请求属性
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
+            if (data != null) {
+                for (Map.Entry<String, String> entry : data.entrySet()) {
+                    conn.setRequestProperty(entry.getKey(), entry.getValue());
+                }
+            }
+            //设置是否向httpUrlConnection输出,设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个
+            //最常用的Http请求无非是get和post,get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
+            //post与get的 不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
+            if (params != null) {
+                out.write(mapToStr(params));
+            }
+            //缓冲数据
+            out.flush();
+            out.close();
+            //获取URLConnection对象对应的输入流
+            InputStream is = conn.getInputStream();
+            //构造一个字符流缓存
+            BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));
+            String result = "";
+            while ((str = br.readLine()) != null) {
+                result = str;
+            }
+            //关闭流
+            is.close();
+            //断开连接,最好写上,disconnect是在底层tcp socket链接空闲时才切断。如果正在被其他线程使用就不切断。
+            //固定多线程的话,如果不disconnect,链接会增多,直到收发不出信息。写上disconnect后正常一些。
+            conn.disconnect();
+            return result;
+        } catch (Exception e) {
+            errMsg = "消息发送至OA异常:" + e;
+            logger.warn("消息发送至OA异常:", e);
+            //e.printStackTrace();
+//            return errMsg;
+        }
+        return errMsg;
+    }
+
+    /**
+     * htts服务
+     * @param path
+     * @param params
+     * @param data
+     * @return
+     */
+    public static String doPostByHttps(String path, Map<String, String> params, Map<String, String> data) {
+        String errMsg = "";
+        try {
+            String str = "";
+            TrustManager[] tm = { new MyX509TrustManager() };
+            SSLContext sslContext = SSLContext.getInstance("TLS");
+            sslContext.init(null, tm, new java.security.SecureRandom());
+            // 从上述SSLContext对象中得到SSLSocketFactory对象
+            SSLSocketFactory ssf = sslContext.getSocketFactory();
+            HttpsURLConnection.setDefaultSSLSocketFactory(ssf);
+            // 打开和URL之间的连接
+            URL realUrl = new URL(path);
+            HttpsURLConnection conn = (HttpsURLConnection) realUrl.openConnection();
+            // 避免只要域名提交
+            conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+            // 请求参数 编码为 utf-8
+            //请求方式
+            conn.setRequestMethod("POST");
+            //设置通用的请求属性
+            conn.setRequestProperty("accept", "*/*");
+            conn.setRequestProperty("connection", "Keep-Alive");
+            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
+            if (data != null) {
+                for (Map.Entry<String, String> entry : data.entrySet()) {
+                    conn.setRequestProperty(entry.getKey(), entry.getValue());
+                }
+            }
+            //设置是否向httpUrlConnection输出,设置是否从httpUrlConnection读入,此外发送post请求必须设置这两个
+            //最常用的Http请求无非是get和post,get请求可以获取静态页面,也可以把参数放在URL字串后面,传递给servlet,
+            //post与get的 不同之处在于post的参数不是放在URL字串里面,而是放在http请求的正文内。
+            conn.setDoOutput(true);
+            conn.setDoInput(true);
+            OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), "utf-8");
+            if (params != null) {
+                out.write(mapToStr(params));
+            }
+            //缓冲数据
+            out.flush();
+            out.close();
+            //获取URLConnection对象对应的输入流
+            InputStream is = conn.getInputStream();
+            //构造一个字符流缓存
+            BufferedReader br = new BufferedReader(new InputStreamReader(is,"utf-8"));
+            String result = "";
+            while ((str = br.readLine()) != null) {
+                result = str;
+            }
+            //关闭流
+            is.close();
+            //断开连接,最好写上,disconnect是在底层tcp socket链接空闲时才切断。如果正在被其他线程使用就不切断。
+            //固定多线程的话,如果不disconnect,链接会增多,直到收发不出信息。写上disconnect后正常一些。
+            conn.disconnect();
+            return result;
+        } catch (Exception e) {
+            errMsg = "消息发送至OA异常:" + e;
+            logger.warn("消息发送至OA异常:", e);
+            //e.printStackTrace();
+//            return errMsg;
+        }
+        return errMsg;
+    }
+
+    /**
+     * 将Map转换成字符串参数,用于POST GET 请求
+     * @param map
+     * @return
+     */
+    public static String mapToStr(Map<String, String> map) {
+        StringBuilder stringBuilder = new StringBuilder();
+        if (map != null) {
+            for (Map.Entry<String, String> entry : map.entrySet()) {
+                stringBuilder.append(entry.getKey());
+                if (entry.getValue() != null) {
+                    stringBuilder.append("=").append(entry.getValue());
+                }
+                stringBuilder.append("&");
+            }
+        }
+        if (stringBuilder.length() > 0) {
+            return stringBuilder.substring(0, stringBuilder.length() - 1);
+        }
+        return null;
+    }
+}

+ 195 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/FanweiServiceHelper.java

@@ -0,0 +1,195 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.dataentity.resource.ResManager;
+import kd.bos.exception.ErrorCode;
+import kd.bos.logging.Log;
+import kd.bos.logging.LogFactory;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.workflow.engine.msg.AbstractMessageServiceHandler;
+import kd.bos.workflow.engine.msg.ctx.MessageContext;
+import kd.bos.workflow.engine.msg.info.MessageInfo;
+import kd.bos.workflow.engine.msg.info.ToDoInfo;
+import kd.bos.workflow.exception.WFMessageServiceException;
+import org.apache.commons.collections.CollectionUtils;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 插件说明:消息渠道插件,泛微消息处理
+ * @author wanghaiwu_kd
+ * @date 2025/04/15
+ */
+public class FanweiServiceHelper extends AbstractMessageServiceHandler {
+    private static Log logger = LogFactory.getLog(FanweiServiceHelper.class);
+
+    public FanweiServiceHelper() {
+    }
+
+    /**
+     * 待办创建
+     * @param ctx
+     * @param info
+     */
+    @Override
+    public void createToDo(MessageContext ctx, ToDoInfo info) {
+        logger.info("泛微待办创建开始 ctx: " + ctx.toString() + ",taskId:" + ctx.getTaskId() + ", taskId:" + info.getTaskId());
+
+        DynamicObject taskInfo = BusinessDataServiceHelper.loadSingleFromCache(info.getTaskId(), "wf_task");
+        //获取到的taskInfo可能是空的
+        String handlestate = taskInfo == null ? "" : taskInfo.getString("handlestate");
+
+        List<Long> userIds = info.getUserIds();
+        if (CollectionUtils.isEmpty(userIds)) {
+            logger.info("人员为空,推送失败!");
+            return;
+        }
+
+        Map<String, String> params = new HashMap<>(3);
+        params.put("isremark", "0");
+        params.put("viewtype", "0");
+
+        for(int i = 0; i < userIds.size(); i++){
+            Long userId = userIds.get(i);
+            params.put("userId", userId.toString());
+
+            try {
+                FanweiCommonUtil.createUserToDo(ctx, info, params);
+                logger.info("create todo content=" + info.getTaskId());
+            } catch (Exception var8) {
+                String message = ResManager.loadKDString("泛微待办创建失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var8, error, new Object[]{var8.getMessage()});
+            }
+        }
+    }
+
+    /**
+     * 待办处理
+     * @param ctx
+     * @param info
+     */
+    @Override
+    public void dealToDo(MessageContext ctx, ToDoInfo info) {
+        logger.info("泛微待办处理开始 ctx: " + ctx.toString() + ",taskId:" + ctx.getTaskId() + ", taskId:" + info.getTaskId());
+
+//        DynamicObject taskInfo = BusinessDataServiceHelper.loadSingleFromCache(info.getTaskId(), "wf_task");
+//        //获取到的taskInfo可能是空的
+//        String handlestate = taskInfo == null ? "" : taskInfo.getString("handlestate");
+
+        //驳回状态的任务做提交处理时不做待办更新推送。
+//        if("dismissed".equals(handlestate)){
+//            return;
+//        }
+
+        List<Long> userIds = info.getUserIds();
+        if (CollectionUtils.isEmpty(userIds)) {
+            logger.info("人员为空,推送失败!");
+            return;
+        }
+
+        Map<String, String> params = new HashMap<>(3);
+        params.put("isremark", "2");
+        params.put("viewtype", "1");
+
+        for(int i = 0; i < userIds.size(); i++){
+            Long userId = userIds.get(i);
+            params.put("userId", userId.toString());
+
+            try {
+                FanweiCommonUtil.dealUserToDo(ctx, info, params);
+                logger.info("deal todo content=" + info.getTaskId());
+            } catch (Exception var8) {
+                String message = ResManager.loadKDString("泛微待办处理失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var8, error, new Object[]{var8.getMessage()});
+            }
+        }
+    }
+
+    /**
+     * 待办删除
+     * @param ctx
+     * @param info
+     */
+    @Override
+    public void deleteToDo(MessageContext ctx, ToDoInfo info) {
+        logger.info("泛微待删除办开始 ctx: " + ctx.toString() + ",taskId:" + ctx.getTaskId() + ", taskId:" + info.getTaskId());
+
+        List<Long> userIds = info.getUserIds();
+        if (CollectionUtils.isEmpty(userIds)) {
+            logger.info("人员为空,删除失败!");
+            return;
+        }
+
+        Map<String, String> params = new HashMap<>(3);
+        params.put("isremark", "-1");
+        params.put("viewtype", "1");
+
+        for(int i = 0; i < userIds.size(); i++){
+            Long userId = userIds.get(i);
+
+            params.put("userId", userId.toString());
+
+            try {
+                FanweiCommonUtil.deleteUserToDo(ctx, info, params);
+                logger.info("delete todo content=" + info.getTaskId());
+            } catch (Exception var8) {
+                String message = ResManager.loadKDString("泛微待办删除失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var8, error, new Object[]{var8.getMessage()});
+            }
+        }
+    }
+
+    /**
+     * 发送消息
+     * @param ctx
+     * @param info
+     */
+    @Override
+    public void sendMessage(MessageContext ctx, MessageInfo info) {
+        //消息渠道
+        String channel = info.getNotifyType();
+        if(!"fanwei".equals(channel)){
+            return;
+        }
+
+//        String type = info.getType();
+//        //只发送传阅的消息
+//        if(!"circulation".equals(info.getTplScene())){
+//            return;
+//        }
+
+        if (ctx != null){
+            logger.info("泛微消息url:" + info.getContentUrl() + ",mobileurl:" + info.getMobContentUrl()+ ", pk:" + ctx.getBusinessKey());
+        }else {
+            logger.info("泛微消息url:" + info.getContentUrl() + ",mobileurl:" + info.getMobContentUrl());
+        }
+        List<Long> userIds = info.getUserIds();
+        if (CollectionUtils.isEmpty(userIds)) {
+            logger.info("人员为空,删除失败!");
+            return;
+        }
+
+        Map<String, String> params = new HashMap<>(3);
+        params.put("isremark", "8");
+        params.put("viewtype", "0");
+
+        for(int i = 0; i < userIds.size(); i++){
+            Long userId = userIds.get(i);
+            params.put("userId", userId.toString());
+
+            try {
+                FanweiCommonUtil.sendMessage(ctx, info, params);
+                logger.info("create todo content=" + info.getChannelMsgId());
+            } catch (Exception var8) {
+                String message = ResManager.loadKDString("泛微消息创建失败,原因:%s", "WFErrorCode_10001", "bos-wf-engine", new Object[0]);
+                ErrorCode error = new ErrorCode("bos.wf.rpa.", message);
+                throw new WFMessageServiceException(var8, error, new Object[]{var8.getMessage()});
+            }
+        }
+    }
+}

+ 187 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/HttpUtils.java

@@ -0,0 +1,187 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.entity.GzipDecompressingEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
+import org.apache.http.params.HttpConnectionParams;
+import org.apache.http.params.HttpParams;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.security.cert.CertificateException;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URI;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+
+public class HttpUtils {
+    private static Logger logger = LoggerFactory.getLogger(HttpUtils.class);
+    private static int default_connectionTimeout = Integer.getInteger("httpclient.connectionTimeout", 3000);
+    private static int default_readTimeout = Integer.getInteger("httpclient.readTimeout", 5000);
+    private static String SCHEME_HTTPS = "https";
+
+    public static String postjson(String url, Map<String, String> header, String json) throws IOException {
+        return postjson(url, header, json, default_connectionTimeout, default_readTimeout);
+    }
+
+
+
+    public static String postjson(String url, Map<String, String> header, String json, int connectionTimeout, int readTimeout) throws IOException {
+        String CONTENT_TYPE_TEXT_JSON = "text/json;";
+        String data = "";
+        HttpClient client = null;
+        HttpPost post = new HttpPost(url);
+        URI uri = post.getURI();
+        if (SCHEME_HTTPS.equals(uri.getScheme())) {
+            client = wrapperHttpClient(connectionTimeout, readTimeout);
+            if (client == null) {
+                return data;
+            }
+        } else {
+            client = createHttpClient(connectionTimeout, readTimeout);
+            HttpParams httpParams = client.getParams();
+            HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeout);
+            HttpConnectionParams.setSoTimeout(httpParams, readTimeout);
+        }
+
+        try {
+            if (header != null && header.size() != 0) {
+                Iterator<String> iterator = header.keySet().iterator();
+
+                while(iterator.hasNext()) {
+                    String key = (String)iterator.next();
+                    post.setHeader(key, (String)header.get(key));
+                }
+            }
+
+            StringEntity se = new StringEntity(json, ContentType.APPLICATION_JSON);
+            se.setContentType("text/json;");
+            post.setEntity(se);
+            HttpResponse response = client.execute(post);
+            if (response.getStatusLine().getStatusCode() == 200) {
+                HttpEntity resEntity = response.getEntity();
+                Header respHeader = resEntity.getContentEncoding();
+                if (respHeader == null || !"gzip".equalsIgnoreCase(respHeader.getValue()) && !"x-gzip".equalsIgnoreCase(respHeader.getValue())) {
+                    data = EntityUtils.toString(resEntity);
+                } else {
+                    GzipDecompressingEntity gzipEntity = new GzipDecompressingEntity(resEntity);
+                    InputStream in = gzipEntity.getContent();
+                    data = getHTMLContent(in);
+                }
+            }
+        } catch (IOException var19) {
+            logger.warn("消息发送至OA异常:", var19);
+            JSONObject errObj = new JSONObject();
+            errObj.put("operResult", "0");
+            errObj.put("message", "消息发送至OA异常:" + var19);
+            data = errObj.toJSONString();
+//            throw var19;
+        } catch (Exception e){
+            logger.warn("消息发送至OA异常:", e);
+            JSONObject errObj = new JSONObject();
+            errObj.put("operResult", "0");
+            errObj.put("message", "消息发送至OA异常:" + e);
+            data = errObj.toJSONString();
+        } finally {
+            post.releaseConnection();
+        }
+
+        return data;
+    }
+
+    private static String getHTMLContent(InputStream in) {
+        StringBuffer sb = new StringBuffer();
+        BufferedReader br = new BufferedReader(new InputStreamReader(in));
+
+        try {
+            String line = null;
+
+            while((line = br.readLine()) != null) {
+                sb.append(line);
+            }
+        } catch (IOException var12) {
+            logger.error("getHTMLContent error", var12);
+        } finally {
+            try {
+                br.close();
+            } catch (IOException var11) {
+                logger.error("getHTMLContent error", var11);
+            }
+
+        }
+
+        return sb.toString();
+    }
+
+    private static HttpClient createHttpClient(int connectionTimeout, int readTimeout) {
+        HttpClient client = new DefaultHttpClient();
+        HttpParams httpParams = client.getParams();
+        HttpConnectionParams.setConnectionTimeout(httpParams, connectionTimeout);
+        HttpConnectionParams.setSoTimeout(httpParams, readTimeout);
+        return client;
+    }
+
+    public static HttpClient wrapperHttpClient(int connectionTimeout, int readTimeout) {
+        try {
+            final X509TrustManager trustManager = new X509TrustManager() {
+                @Override
+                public X509Certificate[] getAcceptedIssuers() {
+                    return null;
+                }
+
+                public void checkClientTrusted(final javax.security.cert.X509Certificate[] arg0, final String arg1) throws CertificateException {
+                }
+
+                public void checkServerTrusted(final javax.security.cert.X509Certificate[] arg0, final String arg1) throws CertificateException {
+                }
+
+                @Override
+                public void checkClientTrusted(final X509Certificate[] chain, final String authType) throws java.security.cert.CertificateException {
+                }
+
+                @Override
+                public void checkServerTrusted(final X509Certificate[] chain, final String authType) throws java.security.cert.CertificateException {
+                }
+            };
+            SSLContext ctx = SSLContext.getInstance("TLS");
+            ctx.init((KeyManager[])null, new TrustManager[]{trustManager}, (SecureRandom)null);
+            SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(ctx, NoopHostnameVerifier.INSTANCE);
+            RequestConfig requestConfig = RequestConfig.custom().setCookieSpec("standard-strict").setConnectTimeout(connectionTimeout).setConnectionRequestTimeout(connectionTimeout).setSocketTimeout(readTimeout).setExpectContinueEnabled(Boolean.TRUE).setTargetPreferredAuthSchemes(Arrays.asList("NTLM", "Digest")).setProxyPreferredAuthSchemes(Arrays.asList("Basic")).build();
+            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.INSTANCE).register("https", socketFactory).build();
+            PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
+            CloseableHttpClient closeableHttpClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).build();
+            return closeableHttpClient;
+        } catch (Exception var9) {
+            logger.error("包装无证书校验客户端失败:" + var9.getMessage());
+            return null;
+        }
+    }
+}

+ 20 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/MyX509TrustManager.java

@@ -0,0 +1,20 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+public class MyX509TrustManager implements X509TrustManager {
+    @Override
+    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+
+    }
+    @Override
+    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+
+    }
+    @Override
+    public X509Certificate[] getAcceptedIssuers() {
+        return null;
+    }
+}

+ 106 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/RefreshFanWeiMsgStatusTask.java

@@ -0,0 +1,106 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import com.alibaba.fastjson.JSONObject;
+import kd.bos.context.RequestContext;
+import kd.bos.dataentity.entity.DynamicObject;
+import kd.bos.exception.KDException;
+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.schedule.executor.AbstractTask;
+import kd.bos.servicehelper.BusinessDataServiceHelper;
+import kd.bos.servicehelper.operation.SaveServiceHelper;
+import kd.bos.workflow.exception.WFErrorCode;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RefreshFanWeiMsgStatusTask extends AbstractTask {
+    private static Log logger = LogFactory.getLog(RefreshFanWeiMsgStatusTask.class);
+    private static String KEY_ENTITY_LOG = "nckd_ecology";
+
+    @Override
+    public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
+        String selectField = "nckd_ecologyurl, nckd_ecologycode, nckd_ecologmsgcode, nckd_ecologappid, nckd_ecologsecret, nckd_ecologspk, nckd_ecologyurlmsg";
+        DynamicObject[] commonParams = BusinessDataServiceHelper.load("nckd_commonparams", selectField, null);
+        String FANWEI_URL = "";
+        if(commonParams.length > 0){
+            FANWEI_URL = commonParams[0].getString("nckd_ecologyurl");
+        } else {
+            return;
+        }
+
+        QFilter qFilter = new QFilter("nckd_logtype", QCP.in, new String[]{"1", "5"});
+        qFilter.and(new QFilter("nckd_sendstatus", QCP.equals, "fail"));
+
+        DynamicObject[] dynamicObjects = BusinessDataServiceHelper.load(KEY_ENTITY_LOG, "id", new QFilter[]{qFilter});
+        logger.info("RefreshFanWeiMsgStatusTask:同步待办状态start");
+        if (dynamicObjects != null && dynamicObjects.length > 0) {
+            logger.info("RefreshFanWeiMsgStatusTask:共【" + dynamicObjects.length + "】条记录!");
+
+            List<DynamicObject> listObj = new ArrayList<>();
+            for(int i = 0; i < dynamicObjects.length; i++) {
+                String id = dynamicObjects[i].getPkValue().toString();
+                DynamicObject dynamicObject = BusinessDataServiceHelper.loadSingle(id, KEY_ENTITY_LOG);
+
+                JSONObject fanweiBodyData = JSONObject.parseObject(dynamicObject.getString("nckd_senddata_tag"));
+//                FANWEI_URL = dynamicObject.getString("nckd_sendurl");
+                String url = FANWEI_URL + "/rest/ofs/ReceiveRequestInfoByJson";
+                JSONObject result = doPostByHttpClient(url, fanweiBodyData);
+                if (result == null) {
+                    throw new KDException(WFErrorCode.httpRequestWrongResponse(), new Object[]{result != null ? result.toJSONString() : "result is null!"});
+                }
+
+                String sendStatus = "fail";
+                //失败
+                if ("1".equals(result.getString("operResult"))) {
+                    sendStatus = "success";
+                    logger.info("RefreshFanWeiMsgStatusTask:待办(" + dynamicObject.getString("number") + ")重发成功!");
+                } else {
+                    logger.info("RefreshFanWeiMsgStatusTask:待办(" + dynamicObject.getString("number") + ")重发失败" + result.getString("message"));
+                }
+
+                String response = result.toJSONString();
+                if (response.length() < 200) {
+                    dynamicObject.set("nckd_resultdata", response);
+                } else {
+                    dynamicObject.set("nckd_resultdata", response.substring(0, 200) + "...");
+                }
+                dynamicObject.set("nckd_resultdata_tag", response);
+                dynamicObject.set("nckd_sendstatus", sendStatus);
+                dynamicObject.set("nckd_sendurl", FANWEI_URL);
+
+                listObj.add(dynamicObject);
+
+                if(listObj.size() == 500) {
+                    SaveServiceHelper.update(listObj.toArray(new DynamicObject[]{}));
+                    listObj.clear();
+                }
+            }
+            if(listObj.size() > 0) {
+                SaveServiceHelper.update(listObj.toArray(new DynamicObject[]{}));
+            }
+        }
+        logger.info("RefreshFanWeiMsgStatusTask:同步待办状态end");
+    }
+
+    public static JSONObject doPostByHttpClient(String url, JSONObject bodyData) {
+        try {
+            Map<String, String> headers = new HashMap();
+            headers.put("Content-Type", "application/json; charset=utf-8");
+            headers.put("Accept", "application/json");
+            logger.info(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
+            System.out.println(String.format("url[%s],data[%s]", url, bodyData.toJSONString()));
+
+            String responseEntify = HttpUtils.postjson(url, headers, bodyData.toJSONString());
+            JSONObject result = (JSONObject)JSONObject.parse(responseEntify);
+            return result;
+        } catch (IOException var5) {
+            throw new KDException(var5, WFErrorCode.httpRequestException(), new Object[]{var5.getMessage()});
+        }
+    }
+}

+ 13 - 0
code/jyyy/nckd-jimin-jyyy-bd/src/main/java/nckd/jimin/jyyy/bd/plugin/msg/ecology/TrustAnyHostnameVerifier.java

@@ -0,0 +1,13 @@
+package nckd.jimin.jyyy.bd.plugin.msg.ecology;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+public class TrustAnyHostnameVerifier implements HostnameVerifier {
+
+    @Override
+    public boolean verify(String arg0, SSLSession arg1) {
+        // TODO Auto-generated method stub
+        return true;//访问域名更改,可使用IP访问
+    }
+
+}

+ 2 - 0
code/nckd-cosmic-debug/src/main/java/kd/cosmic/debug/tools/CosmicLauncher.java

@@ -110,6 +110,8 @@ public final class CosmicLauncher {
 //			setEnableLightWeightDeploy(false);
 			setMqConsumerRegister(true, localHostName);
 		}
+
+		set("mq.consumer.register", "true");
 		
 		setStartWithQing(false);
         

+ 10 - 8
code/nckd-cosmic-debug/src/main/java/nckd/cosmic/debug/DebugApplication.java

@@ -22,19 +22,21 @@ public class DebugApplication {
     	
         CosmicLauncher cosmic = new CosmicLauncher(false);
 
-        cosmic.setClusterNumber("jmkx-uat");
-        cosmic.setTenantNumber("jmkx-uat");
+        cosmic.setClusterNumber("jmkd-dev");
+        cosmic.setTenantNumber("jmkd-dev");
 
-        cosmic.setConfigUrl("172.16.51.125:2181?user=zookeeper&password=d@f*g:SGVsbG8==855QCU/CYX432khLmGVPXD67TE4faNQfn2Ku1r1fVGpwa2RwYXNzd29yZA==");
-        cosmic.setMcServerUrl("http://172.16.51.125:8090/");
+        cosmic.setConfigUrl("172.16.51.127:2181?user=zookeeper&password=d@f*g:SGVsbG8==ks1LiwKd/S7nGdJNoDTBJDXUCSlnkc/6ELhd8lK10IEYa2RwYXNzd29yZA==");
+        cosmic.setMcServerUrl("http://172.16.51.127:8090/");
 
-        cosmic.setFsServerUrl("172.16.51.125", 8100);
-        cosmic.setImageServerUrl("172.16.51.125", 8100);
+        cosmic.setFsServerUrl("172.16.51.127", 8100);
+        cosmic.setImageServerUrl("172.16.51.127", 8100);
         //自定义本地苍穹调试服务的端口
         cosmic.setCosmicWebPort(8080);
 //        cosmic.setDubboConfig(false, true, true);
+
+        cosmic.setStartWithQing(true);
+
+
         cosmic.start();
-        
-        
     }
 }