diff --git a/README.md b/README.md index 58f1308..4f9abed 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ # open-JSD-9330 -JSD-9330 第三方短信集成 \ No newline at end of file +JSD-9330 第三方短信集成\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系hugh处理。 \ No newline at end of file diff --git a/lib/finekit-10.0.jar b/lib/finekit-10.0.jar new file mode 100644 index 0000000..611c8f5 Binary files /dev/null and b/lib/finekit-10.0.jar differ diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..87f4db3 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,22 @@ + + + com.fr.plugin.third.party.jsdjdda + + yes + 0.4 + 10.0 + 2019-01-01 + fr.open + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/CustomSMSService.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/CustomSMSService.java new file mode 100644 index 0000000..4289f50 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/CustomSMSService.java @@ -0,0 +1,294 @@ +package com.fr.plugin.third.party.jsdjdda; + +import com.fanruan.api.log.LogKit; +import com.fanruan.api.util.StringKit; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.plugin.third.party.jsdjdda.config.CustomDataConfig; +import com.fr.stable.fun.impl.AbstractSMSServiceProvider; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class CustomSMSService extends AbstractSMSServiceProvider { + private static Map BUILD_IN_TEMPLATE_MAP = new HashMap<>(); + private static Map BUILD_IN_TEMPLATE_ID_MAP = new HashMap<>(); + + static { + BUILD_IN_TEMPLATE_MAP.put("10", "尊敬的管理员,#taskname#于#time#运行失败,请知晓。"); + BUILD_IN_TEMPLATE_MAP.put("11", "尊敬的#name#,您有一个工单号为:#order_number#的待处理工单,请您及时处理!"); + BUILD_IN_TEMPLATE_MAP.put("13", "您好,#webname#系统内存持续#m#分钟内存高于#n#,可能存在宕机风险,请及时关注。"); + BUILD_IN_TEMPLATE_MAP.put("14", "尊敬的管理员,#taskname#于#time#运行失败,请知晓。"); + BUILD_IN_TEMPLATE_MAP.put("15", "您好,#taskname#于#time#运行成功。"); + BUILD_IN_TEMPLATE_MAP.put("16", "您的手机验证码为#Verifiecode#,请于10分钟内正确输入。"); + BUILD_IN_TEMPLATE_MAP.put("17", "您好,#webname#系统内存持续#m#分钟内存高于#n#,可能存在宕机风险,请及时关注。"); + BUILD_IN_TEMPLATE_MAP.put("18", "恭喜!您的短信服务已经配置成功。"); + BUILD_IN_TEMPLATE_MAP.put("20", "您的手机验证码为#verifiecode#,请于10分钟内正确输入。"); + BUILD_IN_TEMPLATE_MAP.put("49", "您好,#webname#系统日志文件已大于#logsize#M,请及时登录平台进行日志清理。"); + BUILD_IN_TEMPLATE_MAP.put("50", "您好,#webname#系统#clustername#内存持续#m#分钟内存高于#n#,可能存在宕机风险,请及时关注。"); + BUILD_IN_TEMPLATE_MAP.put("51", "你好,#task#出错,请及时处理。该任务开始执行时间:#time#"); + BUILD_IN_TEMPLATE_MAP.put("53", "上报任务 #task#,已经到您这里#time#,请尽快处理!"); + BUILD_IN_TEMPLATE_MAP.put("54", "#name#您好,上报任务#task#已经发起,请尽快处理!"); + BUILD_IN_TEMPLATE_MAP.put("63", "节点#nodename2#,与节点#nodename1#系统时间相差超过#time_different#秒,为避免影响用户使用,请及时调整使各节点时间保持一致。"); + BUILD_IN_TEMPLATE_MAP.put("64", "节点#nodename#已脱离集群环境,可能原因为:节点FullGC、节点宕机、节点间通信不畅、节点负载过高、其他异常。为避免影响用户使用,请及时检查该节点状态,若该节点长时间无法自行恢复,则建议重启该节点。"); + BUILD_IN_TEMPLATE_MAP.put("89", "节点#nodename#,与节点#node1name#的jar包不一致,将影响集群工程的稳定性,请前往集群节点管理页面查看详细异常信息,并及时处理。"); + BUILD_IN_TEMPLATE_MAP.put("90", "节点#nodename#情况异常,用户不能正常访问,请及时检查该节点状态。"); + BUILD_IN_TEMPLATE_MAP.put("125", "您有个#proname#任务即将过期,请您尽快办理。"); + BUILD_IN_TEMPLATE_MAP.put("127", "您有个#proname#任务需要处理,请您尽快办理。发起人:#startpeople#,发起时间:#starttime#。"); + BUILD_IN_TEMPLATE_MAP.put("134", "Redis集群#ip_port#节点已无法正常使用,可能原因为:节点宕机、内存已满、其他异常。为避免影响用户使用,请前往状态服务器配置页面查看详情,并及时处理。"); + BUILD_IN_TEMPLATE_MAP.put("135", "文件服务器出现无法读写的情况,可能原因为:文件服务器宕机、磁盘已满、其他异常。为避免影响用户使用,请及时检查文件服务器状态。"); + BUILD_IN_TEMPLATE_MAP.put("136", "您好,#webname#系统#clustername#当前负载状态过高,可能存在宕机风险,请及时关注。建议使用管理系统-智能运维-云端运维功能分析当前系统存在的性能问题。"); + BUILD_IN_TEMPLATE_MAP.put("239", "您好,预警任务#warningname#达到阈值被触发,请及时关注!模板路径:#templatePath#"); + BUILD_IN_TEMPLATE_MAP.put("264", "更新任务「#job_name#」结束。任务开始于#year#年#month#月#day#日#hr_min#,累计耗时#c_hr#时#c_min#分#c_sec#秒,完成任务:基础表更新 #success_basetable#/#total_basetable# ,自助数据集更新 #success_dataset#/#total_dataset# , 关联更新 #success_relation#/#total_relation#。"); + BUILD_IN_TEMPLATE_MAP.put("265", "报表系统已宕机,请访问运维工具关注问题处理状态或及时进行系统重启。"); + BUILD_IN_TEMPLATE_MAP.put("266", "报表系统已宕机,自动重启系统失败,请及时进行手动重启。"); + BUILD_IN_TEMPLATE_MAP.put("269", "检查到系统环境配置存有不合理项,请及时查看并改正不合理项。"); + BUILD_IN_TEMPLATE_MAP.put("276", "你好,[#taskname#]备份失败,请及时处理,备份时间:#time#"); + BUILD_IN_TEMPLATE_MAP.put("367", "集群节点#node_name#与基准节点存在不一致文件,且无法自动同步。请检查该节点状态"); + BUILD_IN_TEMPLATE_MAP.put("368", "集群节点#node_name#与基准节点存在不一致文件,已自动同步与基准节点一致,不一致文件备份在该节点工程WEB-INF/#directory#/下"); + BUILD_IN_TEMPLATE_MAP.put("509", "尊敬的管理员,用户管理-同步用户于#time#运行失败,可手动触发同步,以查看详细报错。"); + BUILD_IN_TEMPLATE_MAP.put("550", "Dear administrator, \"User>Sync user\" failed to run at #time#, you can trigger the sync manually to view the detailed error report."); + BUILD_IN_TEMPLATE_MAP.put("551", "尊敬的管理員,使用者管理-同步使用者於#time#執行失敗,可手動觸發同步,以檢視詳細報錯。"); + BUILD_IN_TEMPLATE_MAP.put("573", "您好,#etltask# 运行失败,开始执行时间为 #begintime#,结束时间为 #endtime#,请前往 [数据准备]-[ETL作业]-[任务运维] 查看详情。"); + BUILD_IN_TEMPLATE_MAP.put("587", "您好,检测到系统有宕机记录,请访问管理系统——智能运维——宕机处理页面中的宕机自助向导,查看宕机原因,并依据推荐解决方案进行处理"); + BUILD_IN_TEMPLATE_MAP.put("600", "尊敬的#name#,#taskname#于#time#已更新,请及时关注。"); + BUILD_IN_TEMPLATE_MAP.put("602", "#date#日有#templatecount#张模板在使用中出现共#errorcount#次报错,请至智能运维-平台日志中查看并处理模板报错。"); + BUILD_IN_TEMPLATE_MAP.put("605", "您好,#webname#中,生成数据-定时计算任务“#taskname#”执行异常,生成数据失败。请及时登录系统处理"); + BUILD_IN_TEMPLATE_MAP.put("606", "您好,#webname#中,生成数据-定时计算任务“#taskname#”执行成功,已完成#dataTypeText#(#dateRangeText#)数据计算"); + BUILD_IN_TEMPLATE_MAP.put("998", "节点#nodename1#与节点#nodename2#之间通信异常,无法加入节点管理,请检查集群节点间通信端口是否已开放[TCP:7800,7810, 7820,7830, 7840, 7850,7860,7870][UDP:45588~65536 随机端口]。"); + BUILD_IN_TEMPLATE_MAP.put("999", "节点#node_name#的#type#模块存在异常,暂无法正常提供服务,请及时对异常状况进行排查"); + + BUILD_IN_TEMPLATE_ID_MAP.put("10", "10"); + BUILD_IN_TEMPLATE_ID_MAP.put("11", "11"); + BUILD_IN_TEMPLATE_ID_MAP.put("13", "13"); + BUILD_IN_TEMPLATE_ID_MAP.put("14", "14"); + BUILD_IN_TEMPLATE_ID_MAP.put("15", "15"); + BUILD_IN_TEMPLATE_ID_MAP.put("16", "16"); + BUILD_IN_TEMPLATE_ID_MAP.put("17", "17"); + BUILD_IN_TEMPLATE_ID_MAP.put("18", "18"); + BUILD_IN_TEMPLATE_ID_MAP.put("20", "20"); + BUILD_IN_TEMPLATE_ID_MAP.put("49", "49"); + BUILD_IN_TEMPLATE_ID_MAP.put("50", "50"); + BUILD_IN_TEMPLATE_ID_MAP.put("51", "51"); + BUILD_IN_TEMPLATE_ID_MAP.put("53", "53"); + BUILD_IN_TEMPLATE_ID_MAP.put("54", "54"); + BUILD_IN_TEMPLATE_ID_MAP.put("63", "63"); + BUILD_IN_TEMPLATE_ID_MAP.put("64", "64"); + BUILD_IN_TEMPLATE_ID_MAP.put("89", "89"); + BUILD_IN_TEMPLATE_ID_MAP.put("90", "90"); + BUILD_IN_TEMPLATE_ID_MAP.put("125", "125"); + BUILD_IN_TEMPLATE_ID_MAP.put("127", "127"); + BUILD_IN_TEMPLATE_ID_MAP.put("134", "134"); + BUILD_IN_TEMPLATE_ID_MAP.put("135", "135"); + BUILD_IN_TEMPLATE_ID_MAP.put("136", "136"); + BUILD_IN_TEMPLATE_ID_MAP.put("239", "239"); + BUILD_IN_TEMPLATE_ID_MAP.put("264", "264"); + BUILD_IN_TEMPLATE_ID_MAP.put("265", "265"); + BUILD_IN_TEMPLATE_ID_MAP.put("266", "266"); + BUILD_IN_TEMPLATE_ID_MAP.put("269", "269"); + BUILD_IN_TEMPLATE_ID_MAP.put("276", "276"); + BUILD_IN_TEMPLATE_ID_MAP.put("367", "367"); + BUILD_IN_TEMPLATE_ID_MAP.put("368", "368"); + BUILD_IN_TEMPLATE_ID_MAP.put("509", "509"); + BUILD_IN_TEMPLATE_ID_MAP.put("550", "550"); + BUILD_IN_TEMPLATE_ID_MAP.put("551", "551"); + BUILD_IN_TEMPLATE_ID_MAP.put("573", "573"); + BUILD_IN_TEMPLATE_ID_MAP.put("587", "587"); + BUILD_IN_TEMPLATE_ID_MAP.put("600", "600"); + BUILD_IN_TEMPLATE_ID_MAP.put("602", "602"); + BUILD_IN_TEMPLATE_ID_MAP.put("605", "605"); + BUILD_IN_TEMPLATE_ID_MAP.put("606", "606"); + BUILD_IN_TEMPLATE_ID_MAP.put("998", "998"); + BUILD_IN_TEMPLATE_ID_MAP.put("999", "999"); + + } + + /** + * 根据内置的短信模板编号,转换成实际的第三方短信平台的短信模板 + * + * @return 编号和实际模板的键值对集合 + */ + @Override + public Map mapping() { + return BUILD_IN_TEMPLATE_ID_MAP; + } + + /** + * 发送测试短信 + * + * @param mobile 接收短信的手机号 + * @return 结果 + */ + @Override + public Response sendTest(String mobile) { + String buildInTemplateId = "18"; + try { + List mobiles = SmsUtils.createMobiles(mobile, null); + String templateId = getCustomTemplateId(buildInTemplateId); + SmsUtils.sendSms(mobiles, templateId, null); + } catch (Exception e) { + LogKit.error("短信集成,发送测试短信出错,"+ e.getMessage()); + } + String msg = createSmsContent(buildInTemplateId, null); + Response response = Response.create(Response.RES_STATUS_SUCCESS, msg, null); + return response; + } + + /** + * FR包含的短信发送功能 + * + * @param template 发送短信的模板(里面有参数,需要根据后面的para里的参数值进行替换) + * @param mobile 接收短信的手机号 + * @param para 生成最终短信需要的参数 + * @param receiver 接收者(用户) + * @return 结果 + * @throws Exception 异常 + */ + @Override + public Response send(String template, String mobile, JSONObject para, String receiver) throws Exception { + List mobiles = SmsUtils.createMobiles(mobile, receiver); + String templateId = getCustomTemplateId(template); + List params = getJsonValues(para); + SmsUtils.sendSms(mobiles, templateId, params); + List userNames = SmsUtils.createUserNames(receiver); + SmsUtils.sendMsgByAccount(userNames, templateId, params); + String msg = createSmsContent(template, para); + Response response = Response.create(Response.RES_STATUS_SUCCESS, msg, null); + return response; + } + + /** + * FR包含的批量发送短信的功能 + * + * @param template 发送短信的模板(里面有参数,需要根据后面的para里的参数值进行替换) + * @param mobiles 接收短信的手机号列表 + * @param params 对应的生成最终短信需要的参数JSON数组 + * @param receivers 接收者(用户)列表,三个列表/数组,根据序号一一对应 + * @return 结果 + * @throws Exception 异常 + */ + @Override + public Response batchSendSMS(String template, List mobiles, JSONArray params, List receivers) throws Exception { + //SMSManager.getInstance(); + //SMSService.getInstance().getSMSInfo(); + String msg = "短信集成,不支持batchSendSMS"; + LogKit.info(msg); + + Response response = Response.create(Response.RES_STATUS_FAILED, msg, null); + return response; + } + + + private String createSmsContent(String templateId, JSONObject para) { + if (StringKit.isEmpty(templateId)) { + return ""; + } + + if (!BUILD_IN_TEMPLATE_MAP.containsKey(templateId)) { + return ""; + } + + String content = BUILD_IN_TEMPLATE_MAP.get(templateId); + if (StringKit.isEmpty(content)) { + content = ""; + } + if (para == null) { + return content; + } + + List fieldNames = new ArrayList<>(); + fieldNames.addAll(para.fieldNames()); + int size = fieldNames.size(); + if (size <= 0) { + return content; + } + String name, value; + for (int i = 0, max = size - 1; i <= max; i++) { + name = fieldNames.get(i); + value = para.getString(name); + if (StringKit.isEmpty(value)) { + value = ""; + } + content = content.replace(name, value); + } + return content; + } + + private List getJsonValues(JSONObject json) { + List values = new ArrayList<>(); + if (json == null) { + return values; + } + + List fieldNames = new ArrayList<>(); + fieldNames.addAll(json.fieldNames()); + int size = fieldNames.size(); + if (size <= 0) { + return values; + } + String name, value; + for (int i = 0, max = size - 1; i <= max; i++) { + name = fieldNames.get(i); + value = json.getString(name); + if (StringKit.isEmpty(value)) { + value = ""; + } + values.add(value); + } + return values; + } + + + /** + * 获取定制的短信模板编号 + * + * @param id + * @return + */ + private String getCustomTemplateId(String id) { + if (StringKit.isEmpty(id)) { + return ""; + } + + String content = StringKit.trim(CustomDataConfig.getInstance().getTemplateMap()); + if (StringKit.isEmpty(content)) { + return ""; + } + String[] templateMaps = content.split(";"); + if ((templateMaps == null) || (templateMaps.length <= 0)) { + return ""; + } + String tempValue, tempValue1, tempValue2; + + String[] templateIds; + for (int i = 0, max = templateMaps.length - 1; i <= max; i++) { + tempValue = StringKit.trim(templateMaps[i]); + if (StringKit.isEmpty(tempValue)) { + continue; + } + + templateIds = tempValue.split(":"); + if ((templateIds == null) || (templateIds.length <= 1)) { + continue; + } + tempValue1 = StringKit.trim(templateIds[0]); + tempValue2 = StringKit.trim(templateIds[1]); + if (StringKit.isEmpty(tempValue1) || StringKit.isEmpty(tempValue2)) { + continue; + } + if (StringKit.equals(tempValue1, id)) { + return tempValue2; + } + } + return ""; + } + + + + + + + +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/SmsUtils.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/SmsUtils.java new file mode 100644 index 0000000..7cdfc2b --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/SmsUtils.java @@ -0,0 +1,272 @@ +package com.fr.plugin.third.party.jsdjdda; + +import com.fanruan.api.log.LogKit; +import com.fanruan.api.util.StringKit; +import com.fr.decision.authority.AuthorityContext; +import com.fr.decision.authority.data.User; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.third.party.jsdjdda.config.CustomDataConfig; +import com.fr.stable.StringUtils; +import com.fr.stable.query.QueryFactory; +import com.fr.stable.query.restriction.RestrictionFactory; +import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; +import com.fr.third.org.apache.http.client.methods.HttpPost; +import com.fr.third.org.apache.http.entity.StringEntity; +import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class SmsUtils { + + /** + * 根据手机号发送短信消息 + * + * @param mobiles 手机号 + * @param templateId 模板编号 + * @param params 参数 + * @throws IOException + */ + public static synchronized void sendSms(List mobiles, String templateId, List params) throws Exception { + if ((mobiles == null) || (mobiles.size() <= 0) || (StringKit.isEmpty(templateId))) { + return; + } + if (params == null) { + params = new ArrayList<>(); + } + + if (true) { + LogKit.info("短信集成,根据手机号发送短信消息,mobiles:" + mobiles); + LogKit.info("短信集成,根据手机号发送短信消息,templateId:" + templateId); + LogKit.info("短信集成,根据手机号发送短信消息,params:" + params); + //return; + } + + //添加认证 + if (!PluginContexts.currentContext().isAvailable()) { + LogKit.error("短信集成,许可证过期失效"); + return; + } + + String smsUrl = CustomDataConfig.getInstance().getSmsUrl(); + String appId = CustomDataConfig.getInstance().getAppId(); + if (StringKit.isEmpty(smsUrl) || StringKit.isEmpty(appId)) { + return; + } + + CloseableHttpClient httpClient = Utils.createHttpClient(smsUrl); + HttpPost httpPost = new HttpPost(smsUrl); + httpPost.addHeader("User-Agent", Utils.DEFAULT_USER_AGENT); + httpPost.addHeader("Content-Type", "application/json; charset=UTF-8"); + httpPost.addHeader("apikey", CustomDataConfig.getInstance().getApiKey()); + httpPost.setConfig(Utils.REQUEST_CONFIG); + + + /* + { + "appid": "498de05d-0700-420d-9867-612823212573", + "mobile": "13100000000", + "templateid": 334336, + "params": [ + "流程", + "提醒0522" + ] +} + * */ + + + JSONArray paramsJson = new JSONArray(); + for (int i = 0, max = params.size() - 1; i <= max; i++) { + paramsJson.add(params.get(i)); + } + + JSONObject bodyJson = new JSONObject(); + bodyJson.put("appid", appId); + bodyJson.put("templateid", Integer.valueOf(StringKit.trim(templateId))); + bodyJson.put("params", paramsJson); + + StringEntity bodyEntity; + String mobile; + CloseableHttpResponse response; + String bodyContent; + for (int i = 0, max = mobiles.size() - 1; i <= max; i++) { + mobile = mobiles.get(i); + bodyJson.put("mobile", mobile); + bodyContent = bodyJson.toString(); + LogKit.info("短信集成,根据手机号发送短信消息请求体:" + bodyContent); + bodyEntity = new StringEntity(bodyContent, "UTF-8"); + httpPost.setEntity(bodyEntity); + response = httpClient.execute(httpPost); + LogKit.info("短信集成,根据手机号发送短信消息响应status:" + response.getStatusLine().getStatusCode() + "\n" + Utils.getHttpResponseBody(response)); + response.close(); + } + httpClient.close(); + } + + /** + * 根据账号发送消息 + * + * @param accounts + * @param templateId + * @param params + * @throws Exception + */ + public static synchronized void sendMsgByAccount(List accounts, String templateId, List params) throws Exception { + if ((accounts == null) || (accounts.size() <= 0) || (StringKit.isEmpty(templateId))) { + return; + } + if (params == null) { + params = new ArrayList<>(); + } + + if (true) { + LogKit.info("短信集成,根据账号发送消息,accounts:" + accounts); + LogKit.info("短信集成,根据账号发送消息,templateId:" + templateId); + LogKit.info("短信集成,根据账号发送消息,params:" + params); + //return; + } + + //添加认证 + if (!PluginContexts.currentContext().isAvailable()) { + LogKit.error("短信集成,许可证过期失效"); + return; + } + + String smsUrl = CustomDataConfig.getInstance().getAccountSmsUrl(); + String appId = CustomDataConfig.getInstance().getAppId(); + if (StringKit.isEmpty(smsUrl) || StringKit.isEmpty(appId)) { + return; + } + + CloseableHttpClient httpClient = Utils.createHttpClient(smsUrl); + HttpPost httpPost = new HttpPost(smsUrl); + httpPost.addHeader("User-Agent", Utils.DEFAULT_USER_AGENT); + httpPost.addHeader("Content-Type", "application/json; charset=UTF-8"); + httpPost.addHeader("apikey", CustomDataConfig.getInstance().getApiKey()); + httpPost.setConfig(Utils.REQUEST_CONFIG); + + + /* + { + "appid": "498de05d-0700-420d-9867-612823212573", + "mobile": "13100000000", + "templateid": 334336, + "params": [ + "流程", + "提醒0522" + ] +} + * */ + + + JSONArray paramsJson = new JSONArray(); + for (int i = 0, max = params.size() - 1; i <= max; i++) { + paramsJson.add(params.get(i)); + } + + JSONObject bodyJson = new JSONObject(); + bodyJson.put("appid", appId); + bodyJson.put("templateid", Integer.valueOf(StringKit.trim(templateId))); + bodyJson.put("params", paramsJson); + bodyJson.put("url", ""); + + StringEntity bodyEntity; + String account; + CloseableHttpResponse response; + String bodyContent; + for (int i = 0, max = accounts.size() - 1; i <= max; i++) { + account = accounts.get(i); + bodyJson.put("account", account); + bodyContent = bodyJson.toString(); + LogKit.info("短信集成,根据账号发送消息请求体:" + bodyContent); + bodyEntity = new StringEntity(bodyContent, "UTF-8"); + httpPost.setEntity(bodyEntity); + response = httpClient.execute(httpPost); + LogKit.info("短信集成,根据账号发送消息响应status:" + response.getStatusLine().getStatusCode() + "\n" + Utils.getHttpResponseBody(response)); + response.close(); + } + httpClient.close(); + } + + public static List createMobiles(String mobile, String userName) throws Exception { + List mobiles = new ArrayList<>(); + mobiles.add(mobile); + List userNames = new ArrayList<>(); + userNames.add(userName); + return createMobiles(mobiles, userNames); + } + + public static List createMobiles(List mobiles, List userNames) throws Exception { + Set allMobileSet = new HashSet<>(); + Set mobileSet = createSet(mobiles); + Set userMobileSet = createSet(createUserMobiles(userNames)); + allMobileSet.addAll(mobileSet); + allMobileSet.addAll(userMobileSet); + List allMobiles = new ArrayList<>(); + allMobiles.addAll(allMobileSet); + return allMobiles; + } + + public static List createUserNames(String userName) throws Exception { + List userNames = new ArrayList<>(); + if (StringKit.isEmpty(userName)) { + return userNames; + } + userNames.add(userName); + return createUserNames(userNames); + } + + public static List createUserNames(List userNames) throws Exception { + Set userSet = createSet(userNames); + List allUserNames = new ArrayList<>(); + allUserNames.addAll(userSet); + return allUserNames; + } + + + public static Set createSet(List values) { + Set valueSet = new HashSet(); + if ((values == null) || (values.size() <= 0)) { + return valueSet; + } + + String value; + List tempValues = new ArrayList<>(); + tempValues.addAll(values); + for (int i = 0, max = tempValues.size() - 1; i <= max; i++) { + value = StringKit.trim(tempValues.get(i)); + if (StringKit.isEmpty(value)) { + continue; + } + valueSet.add(value); + } + return valueSet; + } + + public static List createUserMobiles(List userNames) throws Exception { + if ((userNames == null) || (userNames.size() <= 0)) { + return new ArrayList<>(); + } + Set userSet = new HashSet(); + String userName; + for (int i = 0, max = userNames.size() - 1; i <= max; i++) { + userName = StringKit.trim(userNames.get(i)); + if (StringKit.isEmpty(userName)) { + continue; + } + userSet.add(userName); + } + if (userSet.size() <= 0) { + return new ArrayList<>(); + } + List userList = AuthorityContext.getInstance().getUserController().find(QueryFactory.create().addRestriction(RestrictionFactory.in("userName", userSet))); + List sysMobiles = userList.stream().filter(e -> StringUtils.isNotBlank(e.getMobile())).map(e -> e.getMobile()).collect(Collectors.toList()); + return sysMobiles; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/Utils.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/Utils.java new file mode 100644 index 0000000..6ca7714 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/Utils.java @@ -0,0 +1,172 @@ +package com.fr.plugin.third.party.jsdjdda; + +import com.fanruan.api.log.LogKit; +import com.fanruan.api.util.StringKit; +import com.fr.general.IOUtils; +import com.fr.third.org.apache.http.HttpEntity; +import com.fr.third.org.apache.http.HttpStatus; +import com.fr.third.org.apache.http.client.config.RequestConfig; +import com.fr.third.org.apache.http.client.methods.CloseableHttpResponse; +import com.fr.third.org.apache.http.client.methods.HttpGet; +import com.fr.third.org.apache.http.client.methods.HttpPost; +import com.fr.third.org.apache.http.conn.ssl.NoopHostnameVerifier; +import com.fr.third.org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import com.fr.third.org.apache.http.entity.StringEntity; +import com.fr.third.org.apache.http.impl.client.CloseableHttpClient; +import com.fr.third.org.apache.http.impl.client.HttpClients; +import com.fr.third.org.apache.http.ssl.SSLContextBuilder; +import com.fr.third.org.apache.http.ssl.TrustStrategy; +import com.fr.third.org.apache.http.util.EntityUtils; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +public class Utils { + public static String DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"; + public static RequestConfig REQUEST_CONFIG = RequestConfig.custom() + .setConnectionRequestTimeout(30000) + .setSocketTimeout(30000) // 服务端相应超时 + .setConnectTimeout(30000) // 建立socket链接超时时间 + .build(); + + public static CloseableHttpClient createSSLClientDefault() { + try { + SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() { + + @Override + public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException { + return true; + } + }).build(); + HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE; + SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, hostnameVerifier); + return HttpClients.custom().setSSLSocketFactory(sslsf).build(); + } catch (Exception e) { + LogKit.error(e.getMessage(), e); + } + return HttpClients.createDefault(); + } + + public static synchronized CloseableHttpClient createHttpClient(String url) { + CloseableHttpClient httpClient = null; + if (StringKit.isEmpty(url)) { + httpClient = HttpClients.createDefault(); + return httpClient; + } + + if (url.startsWith("https://")) { + httpClient = createSSLClientDefault(); + return httpClient; + } + httpClient = HttpClients.createDefault(); + return httpClient; + } + + public static synchronized String createHttpGetContent(CloseableHttpClient httpClient, String url) throws IOException { + if ((httpClient == null) || (StringKit.isEmpty(url))) { + return ""; + } + + HttpGet httpGet = new HttpGet(url); + httpGet.addHeader("User-Agent", Utils.DEFAULT_USER_AGENT); + httpGet.setConfig(Utils.REQUEST_CONFIG); + CloseableHttpResponse response = httpClient.execute(httpGet); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + response.close(); + LogKit.info("http请求出错,http status:" + statusCode); + return ""; + } + + HttpEntity httpEntity = response.getEntity(); + if (httpEntity == null) { + response.close(); + LogKit.info("http请求出错,http响应内容为空"); + return ""; + } + String responseContent = EntityUtils.toString(httpEntity, "UTF-8"); + response.close(); + if (StringKit.isEmpty(responseContent)) { + LogKit.info("http请求出错,http响应内容为空1"); + return ""; + } + return responseContent; + } + + public static synchronized String createHttpPostContent(CloseableHttpClient httpClient, String url, String bodyContent) throws IOException { + if ((httpClient == null) || (StringKit.isEmpty(url)) || (StringKit.isEmpty(bodyContent))) { + return ""; + } + + HttpPost httpPost = new HttpPost(url); + httpPost.addHeader("User-Agent", Utils.DEFAULT_USER_AGENT); + httpPost.setConfig(Utils.REQUEST_CONFIG); + StringEntity bodyEntity = new StringEntity(bodyContent, "UTF-8"); + httpPost.setEntity(bodyEntity); + CloseableHttpResponse response = httpClient.execute(httpPost); + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode != HttpStatus.SC_OK) { + response.close(); + LogKit.info("http请求出错,http status:" + statusCode); + return ""; + } + + HttpEntity httpEntity = response.getEntity(); + if (httpEntity == null) { + response.close(); + LogKit.info("http请求出错,http响应内容为空"); + return ""; + } + String responseContent = EntityUtils.toString(httpEntity, "UTF-8"); + response.close(); + if (StringKit.isEmpty(responseContent)) { + LogKit.info("http请求出错,http响应内容为空1"); + return ""; + } + return responseContent; + } + + /** + * 获取请求主体内容 + * @param req + * @return + * @throws IOException + */ + public static String getHttpRequestBody(HttpServletRequest req) throws IOException { + if (req == null) { + return ""; + } + ServletInputStream inputStream = req.getInputStream(); + if (inputStream == null) { + return ""; + } + String content = IOUtils.inputStream2String(inputStream); + if (StringKit.isEmpty(content)) { + return ""; + } + return content; + } + + public static String getHttpResponseBody(CloseableHttpResponse response) throws IOException { + if (response == null) { + return ""; + } + HttpEntity httpEntity = response.getEntity(); + if (httpEntity == null) { + return ""; + } + String responseContent = EntityUtils.toString(httpEntity, "UTF-8"); + String content = responseContent; + if (StringKit.isEmpty(content)) { + return ""; + } + return content; + } + + +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/config/CustomDataConfig.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/config/CustomDataConfig.java new file mode 100644 index 0000000..93c4977 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/config/CustomDataConfig.java @@ -0,0 +1,103 @@ +package com.fr.plugin.third.party.jsdjdda.config; + +import com.fr.config.*; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; + +/** + * 配置数据保存 + */ +@Visualization(category = "短信集成配置") +public class CustomDataConfig extends DefaultConfiguration { + public String getNameSpace() { + return this.getClass().getName(); + } + + private static volatile CustomDataConfig config = null; + + public static CustomDataConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(CustomDataConfig.class); + } + return config; + } + + @Identifier(value = "apiKey", name = "接口密钥(apikey)", description = "", status = Status.SHOW) + private Conf apiKey = Holders.simple(""); + + @Identifier(value = "appId", name = "发送来源应用ID(appid)", description = "", status = Status.SHOW) + private Conf appId = Holders.simple(""); + + @Identifier(value = "smsUrl", name = "根据手机号发送短信消息接口地址", description = "", status = Status.SHOW) + private Conf smsUrl = Holders.simple(""); + + @Identifier(value = "accountSmsUrl", name = "根据账号发送消息接口地址", description = "", status = Status.SHOW) + private Conf accountSmsUrl = Holders.simple(""); + + + @Identifier(value = "templateMap", name = "报表平台内置短信与集成短信模板对应关系", description = "内置短信编号:短信模板编号;内置短信编号:短信模板编号", status = Status.SHOW) + private Conf templateMap = Holders.simple(""); + + public String getApiKey() { + return apiKey.get(); + } + + public void setApiKey(String apiKey) { + this.apiKey.set(apiKey); + } + + public String getAccountSmsUrl() { + return accountSmsUrl.get(); + } + + public void setAccountSmsUrl(String accountSmsUrl) { + this.accountSmsUrl.set(accountSmsUrl); + } + + @Identifier(value = "buildInMobiles", name = "报表平台内置短信发送手机号", description = "多个用逗号隔开(,)", status = Status.HIDE) + private Conf buildInMobiles = Holders.simple(""); + + public String getBuildInMobiles() { + return buildInMobiles.get(); + } + + public void setBuildInMobiles(String buildInMobiles) { + this.buildInMobiles.set(buildInMobiles); + } + + public String getAppId() { + return appId.get(); + } + + public void setAppId(String appId) { + this.appId.set(appId); + } + + public String getSmsUrl() { + return smsUrl.get(); + } + + public void setSmsUrl(String smsUrl) { + this.smsUrl.set(smsUrl); + } + + public String getTemplateMap() { + return templateMap.get(); + } + + public void setTemplateMap(String templateMap) { + this.templateMap.set(templateMap); + } + + @Override + public Object clone() throws CloneNotSupportedException { + CustomDataConfig cloned = (CustomDataConfig) super.clone(); + cloned.apiKey = (Conf) apiKey.clone(); + cloned.appId = (Conf) appId.clone(); + cloned.smsUrl = (Conf) smsUrl.clone(); + cloned.accountSmsUrl = (Conf) accountSmsUrl.clone(); + cloned.templateMap = (Conf) templateMap.clone(); + cloned.buildInMobiles = (Conf) buildInMobiles.clone(); + return cloned; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/config/DataConfigInitializeMonitor.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/config/DataConfigInitializeMonitor.java new file mode 100644 index 0000000..ee57eac --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/config/DataConfigInitializeMonitor.java @@ -0,0 +1,29 @@ +package com.fr.plugin.third.party.jsdjdda.config; + +import com.fr.config.MarketConfig; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.stable.fun.Authorize; + +/** + * 配置信息初始化 + */ +@EnableMetrics +@Authorize(callSignKey = "com.fr.plugin.third.party.jsdjdda") +public class DataConfigInitializeMonitor extends AbstractPluginLifecycleMonitor { + @Override + @Focus(id = "com.fr.plugin.third.party.jsdjdda", text = "plugin-jsdjdda", source = Original.PLUGIN) + public void afterRun(PluginContext pluginContext) { + CustomDataConfig.getInstance(); + MarketConfig.getInstance().setSMSOpen(true); + //MarketConfig.getInstance().isSMSOpen() || !MarketConfig.getInstance().isSMSAppEnable() + } + + @Override + public void beforeStop(PluginContext pluginContext) { + + } +} \ No newline at end of file diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/http/CustomHttpHandlerProvider.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/CustomHttpHandlerProvider.java new file mode 100644 index 0000000..dff1e90 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/CustomHttpHandlerProvider.java @@ -0,0 +1,13 @@ +package com.fr.plugin.third.party.jsdjdda.http; + +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; +import com.fr.decision.fun.impl.BaseHttpHandler; + +public class CustomHttpHandlerProvider extends AbstractHttpHandlerProvider { + @Override + public BaseHttpHandler[] registerHandlers() { + return new BaseHttpHandler[]{ + new SendSmsHttpHandler() + }; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/http/CustomURLAliasProvider.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/CustomURLAliasProvider.java new file mode 100644 index 0000000..61a84c8 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/CustomURLAliasProvider.java @@ -0,0 +1,14 @@ +package com.fr.plugin.third.party.jsdjdda.http; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; + +public class CustomURLAliasProvider extends AbstractURLAliasProvider { + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/jsdjdda/send/sms", "/jsdjdda/send/sms", true), + }; + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/http/SendSmsHttpHandler.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/SendSmsHttpHandler.java new file mode 100644 index 0000000..ed5b438 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/SendSmsHttpHandler.java @@ -0,0 +1,173 @@ +package com.fr.plugin.third.party.jsdjdda.http; + +import com.fanruan.api.util.StringKit; +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.json.JSONArray; +import com.fr.json.JSONObject; +import com.fr.plugin.third.party.jsdjdda.SmsUtils; +import com.fr.plugin.third.party.jsdjdda.Utils; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 发送短信 + */ +public class SendSmsHttpHandler extends BaseHttpHandler { + private static String MSG_TYPE_MOBILE = "MOBILE"; + private static String MSG_TYPE_ACCOUNT = "ACCOUNT"; + + @Override + public RequestMethod getMethod() { + return RequestMethod.POST; + } + + @Override + public String getPath() { + return "/jsdjdda/send/sms"; + } + + @Override + public boolean isPublic() { + return true; + } + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + res.setContentType("application/json; charset=utf-8"); + String content = Utils.getHttpRequestBody(req); + if (StringKit.isEmpty(content)) { + WebUtils.printAsJSON(res, createFailureJson("请求内容为空")); + return; + } + + JSONObject contentJson = new JSONObject(content); + String templateId = StringKit.trim(contentJson.getString("templateid", "")); + if (StringKit.isEmpty(templateId)) { + WebUtils.printAsJSON(res, createFailureJson("消息模板ID为空")); + return; + } + + List params = createParams(contentJson); + + String msgType = StringKit.trim(contentJson.getString("msgType", "")); + msgType = createMsgType(msgType); + + if (MSG_TYPE_ACCOUNT.equalsIgnoreCase(msgType)) { + String account = StringKit.trim(contentJson.getString("account", "")); + if (StringKit.isEmpty(account)) { + WebUtils.printAsJSON(res, createFailureJson("接收人账号为空")); + return; + } + + List accounts = creatMobiles(account); + if ((accounts == null) || (accounts.size() <= 0)) { + WebUtils.printAsJSON(res, createFailureJson("接收人账号为空1")); + return; + } + + try { + SmsUtils.sendMsgByAccount(accounts, templateId, params); + } catch (Exception e) { + WebUtils.printAsJSON(res, createFailureJson(e.getMessage())); + return; + } + WebUtils.printAsJSON(res, createSuccessJson()); + return; + } + + String mobile = StringKit.trim(contentJson.getString("mobile", "")); + if (StringKit.isEmpty(mobile)) { + WebUtils.printAsJSON(res, createFailureJson("接收人手机号为空")); + return; + } + + List mobiles = creatMobiles(mobile); + if ((mobiles == null) || (mobiles.size() <= 0)) { + WebUtils.printAsJSON(res, createFailureJson("接收人手机号为空1")); + return; + } + + + try { + SmsUtils.sendSms(mobiles, templateId, params); + } catch (Exception e) { + WebUtils.printAsJSON(res, createFailureJson(e.getMessage())); + return; + } + WebUtils.printAsJSON(res, createSuccessJson()); + } + + private List creatMobiles(String mobileContent) { + List mobiles = new ArrayList<>(); + if (StringKit.isEmpty(mobileContent)) { + return mobiles; + } + String[] tempValues = mobileContent.split(","); + if ((tempValues == null) || (tempValues.length <= 0)) { + return mobiles; + } + List values = Arrays.asList(tempValues); + mobiles.addAll(SmsUtils.createSet(values)); + return mobiles; + } + + private List createParams(JSONObject contentJson) { + List params = new ArrayList<>(); + if (contentJson == null) { + return params; + } + if (!contentJson.has("params")) { + return params; + } + + Object valueObj = contentJson.getValue("params"); + if (!(valueObj instanceof JSONArray)) { + params.add(String.valueOf(valueObj)); + return params; + } + + JSONArray jsonArray = (JSONArray) valueObj; + + for (int i = 0, max = jsonArray.size() - 1; i <= max; i++) { + params.add(jsonArray.getString(i)); + } + return params; + } + + private String createMsgType(String type) { + String tempType = StringKit.trim(type); + if (StringKit.isEmpty(tempType)) { + return MSG_TYPE_MOBILE; + } + + if (MSG_TYPE_ACCOUNT.equalsIgnoreCase(tempType)) { + return MSG_TYPE_ACCOUNT; + } + + return MSG_TYPE_MOBILE; + } + + + private JSONObject createSuccessJson() { + return createResultJson("success", "成功"); + } + + private JSONObject createFailureJson(String msg) { + return createResultJson("failure", msg); + } + + private JSONObject createResultJson(String status, String msg) { + JSONObject json = new JSONObject(); + json.put("status", status); + json.put("msg", msg); + return json; + } + + +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/http/SessionGlobalRequestFilterProvider.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/SessionGlobalRequestFilterProvider.java new file mode 100644 index 0000000..14f4e23 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/SessionGlobalRequestFilterProvider.java @@ -0,0 +1,93 @@ +package com.fr.plugin.third.party.jsdjdda.http; + +import com.fanruan.api.log.LogKit; +import com.fanruan.api.util.StringKit; +import com.fr.base.sms.SMSManager; +import com.fr.config.MarketConfig; +import com.fr.decision.fun.impl.AbstractGlobalRequestFilterProvider; +import com.fr.json.JSONObject; +import com.fr.web.utils.WebUtils; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + + +public class SessionGlobalRequestFilterProvider extends AbstractGlobalRequestFilterProvider { + @Override + public String filterName() { + return "com.fr.plugin.third.party.jsdjdda"; + } + + @Override + public String[] urlPatterns() { + return new String[]{"/decision", "/decision/*"}; + } + + @Override + public void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) { + try { + String method = req.getMethod(); + String reqUrl = req.getRequestURL().toString(); + if (!"GET".equalsIgnoreCase(method)) { + filterChain.doFilter(req, res); + return; + } + + if (reqUrl.endsWith("decision/v10/config/sms") || reqUrl.endsWith("decision/v10/config/sms")) { + String reqFullUrl = getRequestFullUrl(req); + LogKit.info("短信集成,请求:" + method + " " + reqFullUrl); + modifySmsConfig(req, res, filterChain); + return; + } + + filterChain.doFilter(req, res); + } catch (Exception e) { + LogKit.error("短信集成出错," + e.getMessage(), e); + } + } + + private void modifySmsConfig(HttpServletRequest req, HttpServletResponse res, FilterChain filterChain) throws Exception { + MarketConfig.getInstance().setSMSOpen(true); + + UrlResponseWrapper wrapperResponse = new UrlResponseWrapper(res);//转换成代理类 + // 这里只拦截返回,直接让请求过去,如果在请求前有处理,可以在这里处理 + filterChain.doFilter(req, wrapperResponse); + JSONObject dataJson = new JSONObject(); + dataJson.put("isSMSOpen", SMSManager.getInstance().isSMSFuncSupport()); + dataJson.put("isSMSFuncSupport", SMSManager.getInstance().isSMSFuncSupport()); + dataJson.put("balance", 999.0); + dataJson.put("accountType", 0); + dataJson.put("sign", signContent); + dataJson.put("isOnline", true); + dataJson.put("isSMSApplied", true); + dataJson.put("testRemain", 999); + dataJson.put("publicModel", publicModelContent); + dataJson.put("privateModel", "[]"); + dataJson.put("username", "短信集成"); + JSONObject configJson = new JSONObject(); + configJson.put("data", dataJson); + res.setContentLength(-1); + WebUtils.printAsJSON(res, configJson); + } + + private static String signContent = "[{\"sign\":\"【信息平台】\",\"id\":2,\"is_default\":true},{\"sign\":\"【帆软软件】\",\"id\":3,\"is_default\":true}]"; + private static String publicModelContent = "[{\"language\":\"zh_CN\",\"id\":\"10\",\"content\":\"【信息平台】尊敬的管理员,#taskname#于#time#运行失败,请知晓。\"},{\"language\":\"zh_CN\",\"id\":\"11\",\"content\":\"【帆软软件】尊敬的#name#,您有一个工单号为:#order_number#的待处理工单,请您及时处理!\"},{\"language\":\"zh_CN\",\"id\":\"13\",\"content\":\"【帆软软件】您好,#webname#系统内存持续#m#分钟内存高于#n#,可能存在宕机风险,请及时关注。\"},{\"language\":\"zh_CN\",\"id\":\"14\",\"content\":\"【帆软软件】尊敬的管理员,#taskname#于#time#运行失败,请知晓。\"},{\"language\":\"zh_CN\",\"id\":\"15\",\"content\":\"【帆软软件】您好,#taskname#于#time#运行成功。\"},{\"language\":\"zh_CN\",\"id\":\"16\",\"content\":\"【帆软软件】您的手机验证码为#Verifiecode#,请于10分钟内正确输入。\"},{\"language\":\"zh_CN\",\"id\":\"17\",\"content\":\"【信息平台】您好,#webname#系统内存持续#m#分钟内存高于#n#,可能存在宕机风险,请及时关注。\"},{\"language\":\"zh_CN\",\"id\":\"18\",\"content\":\"【信息平台】恭喜!您的短信服务已经配置成功。\"},{\"language\":\"zh_CN\",\"id\":\"20\",\"content\":\"【信息平台】您的手机验证码为#verifiecode#,请于10分钟内正确输入。\"},{\"language\":\"zh_CN\",\"id\":\"49\",\"content\":\"【信息平台】您好,#webname#系统日志文件已大于#logsize#M,请及时登录平台进行日志清理。\"},{\"language\":\"zh_CN\",\"id\":\"50\",\"content\":\"【信息平台】您好,#webname#系统#clustername#内存持续#m#分钟内存高于#n#,可能存在宕机风险,请及时关注。\"},{\"language\":\"zh_CN\",\"id\":\"51\",\"content\":\"【信息平台】你好,#task#出错,请及时处理。该任务开始执行时间:#time#\"},{\"language\":\"zh_CN\",\"id\":\"53\",\"content\":\"【信息平台】上报任务 #task#,已经到您这里#time#,请尽快处理!\"},{\"language\":\"zh_CN\",\"id\":\"54\",\"content\":\"【信息平台】#name#您好,上报任务#task#已经发起,请尽快处理!\"},{\"language\":\"zh_CN\",\"id\":\"63\",\"content\":\"【信息平台】节点#nodename2#,与节点#nodename1#系统时间相差超过#time_different#秒,为避免影响用户使用,请及时调整使各节点时间保持一致。\"},{\"language\":\"zh_CN\",\"id\":\"64\",\"content\":\"【信息平台】节点#nodename#已脱离集群环境,可能原因为:节点FullGC、节点宕机、节点间通信不畅、节点负载过高、其他异常。为避免影响用户使用,请及时检查该节点状态,若该节点长时间无法自行恢复,则建议重启该节点。\"},{\"language\":\"zh_CN\",\"id\":\"89\",\"content\":\"【信息平台】节点#nodename#,与节点#node1name#的jar包不一致,将影响集群工程的稳定性,请前往集群节点管理页面查看详细异常信息,并及时处理。\"},{\"language\":\"zh_CN\",\"id\":\"90\",\"content\":\"【信息平台】节点#nodename#情况异常,用户不能正常访问,请及时检查该节点状态。\"},{\"language\":\"zh_CN\",\"id\":\"125\",\"content\":\"【信息平台】您有个#proname#任务即将过期,请您尽快办理。\"},{\"language\":\"zh_CN\",\"id\":\"127\",\"content\":\"【信息平台】您有个#proname#任务需要处理,请您尽快办理。发起人:#startpeople#,发起时间:#starttime#。\"},{\"language\":\"zh_CN\",\"id\":\"134\",\"content\":\"【信息平台】Redis集群#ip_port#节点已无法正常使用,可能原因为:节点宕机、内存已满、其他异常。为避免影响用户使用,请前往状态服务器配置页面查看详情,并及时处理。\"},{\"language\":\"zh_CN\",\"id\":\"135\",\"content\":\"【信息平台】文件服务器出现无法读写的情况,可能原因为:文件服务器宕机、磁盘已满、其他异常。为避免影响用户使用,请及时检查文件服务器状态。\"},{\"language\":\"zh_CN\",\"id\":\"136\",\"content\":\"【信息平台】您好,#webname#系统#clustername#当前负载状态过高,可能存在宕机风险,请及时关注。建议使用管理系统-智能运维-云端运维功能分析当前系统存在的性能问题。\"},{\"language\":\"zh_CN\",\"id\":\"239\",\"content\":\"【帆软软件】您好,预警任务#warningname#达到阈值被触发,请及时关注!模板路径:#templatePath#\"},{\"language\":\"zh_CN\",\"id\":\"264\",\"content\":\"【信息平台】更新任务「#job_name#」结束。任务开始于#year#年#month#月#day#日#hr_min#,累计耗时#c_hr#时#c_min#分#c_sec#秒,完成任务:基础表更新 #success_basetable#/#total_basetable# ,自助数据集更新 #success_dataset#/#total_dataset# , 关联更新 #success_relation#/#total_relation#。\"},{\"language\":\"zh_CN\",\"id\":\"265\",\"content\":\"【信息平台】报表系统已宕机,请访问运维工具关注问题处理状态或及时进行系统重启。\"},{\"language\":\"zh_CN\",\"id\":\"266\",\"content\":\"【信息平台】报表系统已宕机,自动重启系统失败,请及时进行手动重启。\"},{\"language\":\"zh_CN\",\"id\":\"269\",\"content\":\"【信息平台】检查到系统环境配置存有不合理项,请及时查看并改正不合理项。\"},{\"language\":\"zh_CN\",\"id\":\"276\",\"content\":\"【信息平台】你好,[#taskname#]备份失败,请及时处理,备份时间:#time#\"},{\"language\":\"zh_CN\",\"id\":\"367\",\"content\":\"【信息平台】集群节点#node_name#与基准节点存在不一致文件,且无法自动同步。请检查该节点状态\"},{\"language\":\"zh_CN\",\"id\":\"368\",\"content\":\"【信息平台】集群节点#node_name#与基准节点存在不一致文件,已自动同步与基准节点一致,不一致文件备份在该节点工程WEB-INF/#directory#/下\"},{\"language\":\"zh_CN\",\"id\":\"509\",\"content\":\"【信息平台】尊敬的管理员,用户管理-同步用户于#time#运行失败,可手动触发同步,以查看详细报错。\"},{\"language\":\"zh_CN\",\"id\":\"550\",\"content\":\"【信息平台】Dear administrator, \\\"User>Sync user\\\" failed to run at #time#, you can trigger the sync manually to view the detailed error report.\"},{\"language\":\"zh_CN\",\"id\":\"551\",\"content\":\"【信息平台】尊敬的管理員,使用者管理-同步使用者於#time#執行失敗,可手動觸發同步,以檢視詳細報錯。\"},{\"language\":\"zh_CN\",\"id\":\"573\",\"content\":\"【信息平台】您好,#etltask# 运行失败,开始执行时间为 #begintime#,结束时间为 #endtime#,请前往 [数据准备]-[ETL作业]-[任务运维] 查看详情。\"},{\"language\":\"zh_CN\",\"id\":\"587\",\"content\":\"【信息平台】您好,检测到系统有宕机记录,请访问管理系统——智能运维——宕机处理页面中的宕机自助向导,查看宕机原因,并依据推荐解决方案进行处理\"},{\"language\":\"zh_CN\",\"id\":\"600\",\"content\":\"【信息平台】尊敬的#name#,#taskname#于#time#已更新,请及时关注。\"},{\"language\":\"zh_CN\",\"id\":\"602\",\"content\":\"【信息平台】#date#日有#templatecount#张模板在使用中出现共#errorcount#次报错,请至智能运维-平台日志中查看并处理模板报错。\"},{\"language\":\"zh_CN\",\"id\":\"605\",\"content\":\"【信息平台】您好,#webname#中,生成数据-定时计算任务“#taskname#”执行异常,生成数据失败。请及时登录系统处理\"},{\"language\":\"zh_CN\",\"id\":\"606\",\"content\":\"【信息平台】您好,#webname#中,生成数据-定时计算任务“#taskname#”执行成功,已完成#dataTypeText#(#dateRangeText#)数据计算\"},{\"language\":\"zh_CN\",\"id\":\"998\",\"content\":\"【信息平台】节点#nodename1#与节点#nodename2#之间通信异常,无法加入节点管理,请检查集群节点间通信端口是否已开放[TCP:7800,7810, 7820,7830, 7840, 7850,7860,7870][UDP:45588~65536 随机端口]。\"},{\"language\":\"zh_CN\",\"id\":\"999\",\"content\":\"【信息平台】节点#node_name#的#type#模块存在异常,暂无法正常提供服务,请及时对异常状况进行排查\"}]"; + + + private String getRequestFullUrl(HttpServletRequest req) { + if (req == null) { + return ""; + } + String query = req.getQueryString(); + if (StringKit.isEmpty(query) || "null".equalsIgnoreCase(query)) { + query = ""; + } else { + query = "?" + query; + } + String url = req.getRequestURL().toString() + query; + return url; + } + + +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/http/UrlResponseWrapper.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/UrlResponseWrapper.java new file mode 100644 index 0000000..eb42665 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/http/UrlResponseWrapper.java @@ -0,0 +1,91 @@ +package com.fr.plugin.third.party.jsdjdda.http; + +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; +import java.io.*; + +public class UrlResponseWrapper extends HttpServletResponseWrapper { + private ByteArrayOutputStream buffer = null; + private ServletOutputStream out = null; + private PrintWriter writer = null; + + public UrlResponseWrapper(HttpServletResponse resp) throws IOException { + super(resp); + buffer = new ByteArrayOutputStream();// 真正存储数据的流 + out = new WapperedOutputStream(buffer); + writer = new PrintWriter(new OutputStreamWriter(buffer)); + } + + @Override + public ServletOutputStream getOutputStream() throws IOException { + return out; + } + + @Override + public PrintWriter getWriter() throws UnsupportedEncodingException { + return writer; + } + + @Override + public void flushBuffer() throws IOException { + if (out != null) { + out.flush(); + } + if (writer != null) { + writer.flush(); + } + } + + @Override + public void reset() { + buffer.reset(); + } + + public byte[] getResponseData() throws IOException { + flushBuffer(); + return buffer.toByteArray(); + } + + public String getContent() throws IOException{ + flushBuffer(); + return buffer.toString(); + } + + private class WapperedOutputStream extends ServletOutputStream { + private ByteArrayOutputStream bos = null; + + public WapperedOutputStream(ByteArrayOutputStream stream) throws IOException { + bos = stream; + } + + @Override + public void write(int b) throws IOException { + bos.write(b); + } + + @Override + public void write(byte[] b) throws IOException { + bos.write(b, 0, b.length); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + bos.write(b, off, len); + } + + + @Override + public boolean isReady() { + return false; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + + } + + + } +} diff --git a/src/main/java/com/fr/plugin/third/party/jsdjdda/test/Test1.java b/src/main/java/com/fr/plugin/third/party/jsdjdda/test/Test1.java new file mode 100644 index 0000000..cb972e7 --- /dev/null +++ b/src/main/java/com/fr/plugin/third/party/jsdjdda/test/Test1.java @@ -0,0 +1,13 @@ +package com.fr.plugin.third.party.jsdjdda.test; + +import java.util.HashMap; +import java.util.Map; + +public class Test1 { + public static void main(String[] args) { + Map map = new HashMap<>(); + + System.out.println(map.get("111")); + + } +}