commit e525fa5e371884deb2a34ddaeed4dccf6b92399e Author: pioneer Date: Wed Nov 9 16:20:06 2022 +0800 open diff --git a/README.md b/README.md new file mode 100644 index 0000000..9552b2d --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# open-JSD-9948 + +JSD-9948 定时调度实现企业微信发送模板图片给指定的某个人\ +免责说明:该源码为第三方爱好者提供,不保证源码和方案的可靠性,也不提供任何形式的源码教学指导和协助!\ +仅作为开发者学习参考使用!禁止用于任何商业用途!\ +为保护开发者隐私,开发者信息已隐去!若原开发者希望公开自己的信息,可联系【pioneer】处理。 \ No newline at end of file diff --git a/doc/JSD-9948配置使用文档.docx b/doc/JSD-9948配置使用文档.docx new file mode 100644 index 0000000..fb6cc96 Binary files /dev/null and b/doc/JSD-9948配置使用文档.docx differ diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..08eb4dc --- /dev/null +++ b/plugin.xml @@ -0,0 +1,33 @@ + + com.fr.plugin.xx.wechat.img.output + + yes + 1.9 + 10.0 + 2018-07-31 + fr.open + + + [2022-07-19]【1.1】方案修改。
+ [2022-07-20]【1.2】token获取修改。
+ [2022-07-20]【1.3】上传文件修改。
+ [2022-07-20]【1.4】代码修改。
+ [2022-07-21]【1.5】消息接口调整。
+ [2022-07-22]【1.6】参数调整。
+ [2022-07-22]【1.7】参数调整。
+ [2022-07-23]【1.8】调度调整。
+ [2022-07-25]【1.9】动态参数调整。
+ ]]>
+ + + + + + + + + + + +
\ No newline at end of file diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/ExportRequestHandlerBridge.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/ExportRequestHandlerBridge.java new file mode 100644 index 0000000..82c9a48 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/ExportRequestHandlerBridge.java @@ -0,0 +1,35 @@ +package com.fr.plugin.xx.wechat.img.output; + +import com.fr.decision.fun.HttpHandler; +import com.fr.decision.fun.impl.AbstractHttpHandlerProvider; +import com.fr.intelli.record.Focus; +import com.fr.intelli.record.Original; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xx.wechat.img.output.handle.ExportHandler; +import com.fr.plugin.xx.wechat.img.output.handle.RestTest; +import com.fr.record.analyzer.EnableMetrics; +import com.fr.stable.fun.Authorize; + +/** + * @Author xx + * @Date 2021/11/16 + * @Description + **/ +@Authorize(callSignKey = PluginConstants.PLUGIN_ID) +@EnableMetrics +public class ExportRequestHandlerBridge extends AbstractHttpHandlerProvider { + + @Override + @Focus(id = PluginConstants.PLUGIN_ID, text = PluginConstants.PLUGIN_NAME, source = Original.PLUGIN) + public HttpHandler[] registerHandlers() { + if (PluginContexts.currentContext().isAvailable()) { + return new HttpHandler[]{ + new ExportHandler(), + new RestTest(), + }; + } + return new HttpHandler[]{ + + }; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/ExportRequestURLAliasBridge.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/ExportRequestURLAliasBridge.java new file mode 100644 index 0000000..23e4255 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/ExportRequestURLAliasBridge.java @@ -0,0 +1,20 @@ +package com.fr.plugin.xx.wechat.img.output; + +import com.fr.decision.fun.impl.AbstractURLAliasProvider; +import com.fr.decision.webservice.url.alias.URLAlias; +import com.fr.decision.webservice.url.alias.URLAliasFactory; + +/** + * @Author xx + * @Date 2021/11/16 + * @Description + **/ +public class ExportRequestURLAliasBridge extends AbstractURLAliasProvider { + @Override + public URLAlias[] registerAlias() { + return new URLAlias[]{ + URLAliasFactory.createPluginAlias("/export", "/export", true), + URLAliasFactory.createPluginAlias("/test", "/test", true), + }; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/ImgConfigDBAccessProvider.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/ImgConfigDBAccessProvider.java new file mode 100644 index 0000000..5405dfd --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/ImgConfigDBAccessProvider.java @@ -0,0 +1,45 @@ +package com.fr.plugin.xx.wechat.img.output; + +import com.fr.db.fun.impl.AbstractDBAccessProvider; +import com.fr.plugin.xx.wechat.img.output.dao.ImgConfigDao; +import com.fr.plugin.xx.wechat.img.output.entity.ImgConfigEntity; +import com.fr.stable.db.accessor.DBAccessor; +import com.fr.stable.db.dao.BaseDAO; +import com.fr.stable.db.dao.DAOProvider; + +/** + * @Author xx + * @Date 2020/11/29 + **/ +public class ImgConfigDBAccessProvider extends AbstractDBAccessProvider { + + private static DBAccessor dbAccessor = null; + + public static DBAccessor getDbAccessor() { + return dbAccessor; + } + + @Override + public DAOProvider[] registerDAO() { + return new DAOProvider[]{ + new DAOProvider(){ + + @Override + public Class getEntityClass() { + return ImgConfigEntity.class; + } + + @Override + public Class getDAOClass() { + return ImgConfigDao.class; + } + } + + }; + } + + @Override + public void onDBAvailable(DBAccessor dbAccessor) { + ImgConfigDBAccessProvider.dbAccessor = dbAccessor; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/ImgOutputDBAccess.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/ImgOutputDBAccess.java new file mode 100644 index 0000000..3f0c090 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/ImgOutputDBAccess.java @@ -0,0 +1,43 @@ +package com.fr.plugin.xx.wechat.img.output; + +import com.fr.decision.plugin.db.AbstractDecisionDBAccessProvider; +import com.fr.plugin.xx.wechat.img.output.dao.ImgOutputDao; +import com.fr.plugin.xx.wechat.img.output.entity.WebHookEntity; +import com.fr.stable.db.accessor.DBAccessor; +import com.fr.stable.db.dao.BaseDAO; +import com.fr.stable.db.dao.DAOProvider; + +/** + * @Author xx + * @Date 2020/9/15 + * @Description + **/ +public class ImgOutputDBAccess extends AbstractDecisionDBAccessProvider { + + private static DBAccessor dbAccessor; + public DBAccessor getDbAccessor() { + return dbAccessor; + } + + @Override + public DAOProvider[] registerDAO() { + return new DAOProvider[]{ + new DAOProvider() { + @Override + public Class getEntityClass() { + return WebHookEntity.class; + } + + @Override + public Class getDAOClass() { + return ImgOutputDao.class; + } + } + }; + } + + @Override + public void onDBAvailable(DBAccessor dbAccessor) { + ImgOutputDBAccess.dbAccessor = dbAccessor; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/LogUtils.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/LogUtils.java new file mode 100644 index 0000000..daf63f3 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/LogUtils.java @@ -0,0 +1,121 @@ +package com.fr.plugin.xx.wechat.img.output; + +import com.fr.log.FineLoggerFactory; +import com.fr.log.FineLoggerProvider; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xx.wechat.img.output.conf.ImgPushConfig; +import com.fr.stable.StringUtils; + +/** + * @author xx + * @since 2021/12/04 + */ +public final class LogUtils { + private static final String DEBUG_PREFIX = "[插件调试] "; + private static String LOG_PREFIX = PluginConstants.PLUGIN_NAME; + private static final String PLUGIN_VERSION; + + private static final FineLoggerProvider LOGGER = FineLoggerFactory.getLogger(); + + static { + String version = PluginContexts.currentContext().getMarker().getVersion(); + if (StringUtils.isNotBlank(version)) { + PLUGIN_VERSION = "[v" + version + "] "; + } else { + PLUGIN_VERSION = "[unknown version] "; + } + + LOG_PREFIX = LOG_PREFIX + PLUGIN_VERSION; + } + + public static void setPrefix(String prefix) { + if (prefix != null) { + LOG_PREFIX = prefix; + } + } + + public static boolean isDebugEnabled() { + return LOGGER.isDebugEnabled(); + } + + public static void debug(String s) { + LOGGER.debug(LOG_PREFIX + s); + } + + public static void debug(String s, Object... objects) { + LOGGER.debug(LOG_PREFIX + s, objects); + } + + public static void debug(String s, Throwable throwable) { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + + public static void debug4plugin(String s) { + if (ImgPushConfig.getInstance().getDebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s); + } else { + LOGGER.debug(LOG_PREFIX + s); + } + } + + public static void debug4plugin(String s, Object... objects) { + if (ImgPushConfig.getInstance().getDebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, objects); + } else { + LOGGER.debug(LOG_PREFIX + s, objects); + } + } + + public static void debug4plugin(String s, Throwable throwable) { + if (ImgPushConfig.getInstance().getDebugSwitch()) { + LOGGER.error(DEBUG_PREFIX + LOG_PREFIX + s, throwable); + } else { + LOGGER.debug(LOG_PREFIX + s, throwable); + } + } + + + public static boolean isInfoEnabled() { + return LOGGER.isInfoEnabled(); + } + + public static void info(String s) { + LOGGER.info(LOG_PREFIX + s); + } + + public static void info(String s, Object... objects) { + LOGGER.info(LOG_PREFIX + s, objects); + } + + public static void warn(String s) { + LOGGER.warn(LOG_PREFIX + s); + } + + public static void warn(String s, Object... objects) { + LOGGER.warn(LOG_PREFIX + s, objects); + } + + public static void warn(String s, Throwable throwable) { + LOGGER.warn(LOG_PREFIX + s, throwable); + } + + public static void warn(Throwable throwable, String s, Object... objects) { + LOGGER.warn(throwable, LOG_PREFIX + s, objects); + } + + public static void error(String s) { + LOGGER.error(LOG_PREFIX + s); + } + + public static void error(String s, Object... objects) { + LOGGER.error(LOG_PREFIX + s, objects); + } + + public static void error(String s, Throwable throwable) { + LOGGER.error(LOG_PREFIX + s, throwable); + } + + public static void error(Throwable throwable, String s, Object... objects) { + LOGGER.error(throwable, LOG_PREFIX + s, objects); + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/OutputPluginLifecycleMonitor.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/OutputPluginLifecycleMonitor.java new file mode 100644 index 0000000..f9ff500 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/OutputPluginLifecycleMonitor.java @@ -0,0 +1,30 @@ +package com.fr.plugin.xx.wechat.img.output; + +import com.fr.plugin.context.PluginContext; +import com.fr.plugin.xx.wechat.img.output.conf.ImgPushConfig; +import com.fr.plugin.xx.wechat.img.output.entity.OutputWebHook; +import com.fr.plugin.xx.wechat.img.output.entity.WebHookEntity; +import com.fr.plugin.xx.wechat.img.output.handle.WebHookHandle; +import com.fr.plugin.observer.inner.AbstractPluginLifecycleMonitor; +import com.fr.schedule.feature.ScheduleOutputActionEntityRegister; +import com.fr.schedule.feature.output.OutputActionHandler; + +/** + * @Author xx + * @Date 2020/9/15 + * @Description + **/ +public class OutputPluginLifecycleMonitor extends AbstractPluginLifecycleMonitor { + @Override + public void afterRun(PluginContext pluginContext) { + ImgPushConfig.getInstance(); + OutputActionHandler.registerHandler(new WebHookHandle(), OutputWebHook.class.getName()); + ScheduleOutputActionEntityRegister.getInstance().addClass(WebHookEntity.class); + } + + @Override + public void beforeStop(PluginContext pluginContext) { + OutputActionHandler.removeOutputHandler(OutputWebHook.class.getName()); + ScheduleOutputActionEntityRegister.getInstance().removeClass(WebHookEntity.class); + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/PluginConstants.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/PluginConstants.java new file mode 100644 index 0000000..d4221fd --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/PluginConstants.java @@ -0,0 +1,13 @@ +package com.fr.plugin.xx.wechat.img.output; + +/** + * @author xx + * @since 2021/12/04 + */ +public class PluginConstants { + + public static final String PLUGIN_ID = "com.fr.plugin.xx.wechat.img.output"; + + public static final String PLUGIN_NAME = "微信消息推送"; + +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/conf/ImgPushConfig.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/conf/ImgPushConfig.java new file mode 100644 index 0000000..c727c14 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/conf/ImgPushConfig.java @@ -0,0 +1,80 @@ +package com.fr.plugin.xx.wechat.img.output.conf; + +import com.fr.config.*; +import com.fr.config.holder.Conf; +import com.fr.config.holder.factory.Holders; +import com.fr.stable.StringUtils; + + +/** + * @author xx + * @since 2021/12/04 + */ +@Visualization(category = "企微推送调度配置") +public class ImgPushConfig extends DefaultConfiguration { + + private static volatile ImgPushConfig config = null; + + public static ImgPushConfig getInstance() { + if (config == null) { + config = ConfigContext.getConfigInstance(ImgPushConfig.class); + } + return config; + } + + @Identifier(value = "debugSwitch", name = "插件调试开关", description = "日志调试模式", status = Status.SHOW) + private Conf debugSwitch = Holders.simple(true); + + public Boolean getDebugSwitch() { + return this.debugSwitch.get(); + } + + public void setDebugSwitch(Boolean debugSwitch) { + this.debugSwitch.set(debugSwitch); + } + + @Identifier(value = "host", name = "企微接口地址", description = "http://{{ip}}:{{port}}", status = Status.SHOW) + private Conf host = Holders.simple(StringUtils.EMPTY); + public String getHost() { + return host.get(); + } + + public void setHost(String host) { + this.host.set(host); + } + + @Identifier(value = "apiUserCode", name = "系统编码", description = "企业微信系统编码", status = Status.SHOW) + private Conf apiUserCode = Holders.simple(StringUtils.EMPTY); + + public String getApiUserCode() { + return apiUserCode.get(); + } + + public void setApiUserCode(String apiUserCode) { + this.apiUserCode.set(apiUserCode); + } + + @Identifier(value = "apiUserSecret", name = "系统秘钥", description = "企业微信系统秘钥", status = Status.SHOW) + private Conf apiUserSecret = Holders.simple(StringUtils.EMPTY); + + public String getApiUserSecret() { + return apiUserSecret.get(); + } + + public void setApiUserSecret(String apiUserSecret) { + this.apiUserSecret.set(apiUserSecret); + } + + @Override + public Object clone() throws CloneNotSupportedException { + ImgPushConfig cloned = (ImgPushConfig) super.clone(); + cloned.debugSwitch = (Conf) debugSwitch.clone(); + cloned.host = (Conf) host.clone(); + return cloned; + } + + + public boolean isConfiged() { + return StringUtils.isNotBlank(getHost()); + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/dao/ImgConfigDao.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/dao/ImgConfigDao.java new file mode 100644 index 0000000..513a320 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/dao/ImgConfigDao.java @@ -0,0 +1,21 @@ +package com.fr.plugin.xx.wechat.img.output.dao; + +import com.fr.plugin.xx.wechat.img.output.entity.ImgConfigEntity; +import com.fr.stable.db.dao.BaseDAO; +import com.fr.stable.db.session.DAOSession; + +/** + * @Author xx + * @Date 2022/7/16 + * @Description + **/ +public class ImgConfigDao extends BaseDAO { + public ImgConfigDao(DAOSession daoSession) { + super(daoSession); + } + + @Override + protected Class getEntityClass() { + return ImgConfigEntity.class; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/dao/ImgOutputDao.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/dao/ImgOutputDao.java new file mode 100644 index 0000000..ba4e480 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/dao/ImgOutputDao.java @@ -0,0 +1,21 @@ +package com.fr.plugin.xx.wechat.img.output.dao; + +import com.fr.plugin.xx.wechat.img.output.entity.WebHookEntity; +import com.fr.stable.db.dao.BaseDAO; +import com.fr.stable.db.session.DAOSession; + +/** + * @Author xx + * @Date 2020/9/15 + * @Description + **/ +public class ImgOutputDao extends BaseDAO { + public ImgOutputDao(DAOSession daoSession) { + super(daoSession); + } + + @Override + protected Class getEntityClass() { + return WebHookEntity.class; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/ImgConfigEntity.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/ImgConfigEntity.java new file mode 100644 index 0000000..7878053 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/ImgConfigEntity.java @@ -0,0 +1,106 @@ +package com.fr.plugin.xx.wechat.img.output.entity; + +import com.fr.stable.db.entity.BaseEntity; +import com.fr.third.javax.persistence.Column; +import com.fr.third.javax.persistence.Entity; +import com.fr.third.javax.persistence.Table; + +import java.util.HashMap; +import java.util.Map; + +/** + * @Author xx + * @Date 2022/7/14 + * @Description + **/ +@Entity +@Table(name = "plugin_img_config") +public class ImgConfigEntity extends BaseEntity { + + @Column(name = "deptName") + private String deptName; + + @Column(name = "deptId") + private String deptId; + + @Column(name = "date") + private String date; + + @Column(name = "upname") + private String upname; + + @Column(name = "level") + private String level; + + @Column(name = "name") + private String name; + + @Column(name = "actNumber") + private String actNumber; + + + public String getDeptName() { + return deptName; + } + + public void setDeptName(String deptName) { + this.deptName = deptName; + } + + public String getDeptId() { + return deptId; + } + + public void setDeptId(String deptId) { + this.deptId = deptId; + } + + public String getDate() { + return date; + } + + public void setDate(String date) { + this.date = date; + } + + public String getUpname() { + return upname; + } + + public void setUpname(String upname) { + this.upname = upname; + } + + public String getLevel() { + return level; + } + + public void setLevel(String level) { + this.level = level; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getActNumber() { + return actNumber; + } + + public void setActNumber(String actNumber) { + this.actNumber = actNumber; + } + + public Map toMap() { + Map params = new HashMap<>(); + params.put("date",date); + params.put("upname",upname); + params.put("level",level); + params.put("name",name); + return params; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/OutputWebHook.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/OutputWebHook.java new file mode 100644 index 0000000..29a0934 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/OutputWebHook.java @@ -0,0 +1,61 @@ +package com.fr.plugin.xx.wechat.img.output.entity; + +import com.fr.schedule.base.bean.output.BaseOutputAction; +import com.fr.schedule.base.entity.AbstractScheduleEntity; +import com.fr.schedule.base.type.RunType; +import com.fr.third.fasterxml.jackson.annotation.JsonSubTypes; + +/** + * @Author xx + * @Date 2020/9/15 + * @Description + **/ +@JsonSubTypes.Type(value = OutputWebHook.class, name = "OutputWebHook") +public class OutputWebHook extends BaseOutputAction { + + private static final long serialVersionUID = 8245931480823179622L; + private String hookUrl = null; + + public OutputWebHook() { + super(); + } + + @Override + public boolean willExecuteByUser() { + return true; + } + + @Override + public RunType runType() { + return RunType.SEND_FILE; + } + + @Override + public Class outputActionEntityClass() { + return WebHookEntity.class; + } + + @Override + public AbstractScheduleEntity createOutputActionEntity() { + return (new WebHookEntity()).id(this.getId()).hookUrl(this.hookUrl); + } + + @Override + public OutputWebHook id(String id) { + setId(id); + return this; + } + + public String getHookUrl() { + return hookUrl; + } + + public void setHookUrl(String hookUrl) { + this.hookUrl = hookUrl; + } + + public OutputWebHook hookUrl(String hookUrl) { + setHookUrl(hookUrl); + return this; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/WebHookEntity.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/WebHookEntity.java new file mode 100644 index 0000000..9c9bb8d --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/entity/WebHookEntity.java @@ -0,0 +1,48 @@ +package com.fr.plugin.xx.wechat.img.output.entity; + +import com.fr.schedule.base.bean.BaseBean; +import com.fr.schedule.base.entity.AbstractScheduleEntity; +import com.fr.stable.db.entity.TableAssociation; +import com.fr.third.javax.persistence.Column; +import com.fr.third.javax.persistence.Entity; +import com.fr.third.javax.persistence.Table; + +/** + * @Author xx + * @Date 2020/9/15 + * @Description + **/ +@Entity +@Table(name = "fine_output_webHook") //表名 +@TableAssociation(associated = true) +public class WebHookEntity extends AbstractScheduleEntity { + + @Column(name = "hookUrl") + private String hookUrl; + + public WebHookEntity() { + } + + @Override + public BaseBean createBean() { + return new OutputWebHook().id(this.getId()).hookUrl(this.hookUrl); + } + + public String getHookUrl() { + return hookUrl; + } + + public void setHookUrl(String hookUrl) { + this.hookUrl = hookUrl; + } + + public WebHookEntity hookUrl(String hookUrl) { + setHookUrl(hookUrl); + return this; + } + + public WebHookEntity id(String id) { + setId(id); + return this; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/ExportHandler.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/ExportHandler.java new file mode 100644 index 0000000..75d935b --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/ExportHandler.java @@ -0,0 +1,178 @@ +package com.fr.plugin.xx.wechat.img.output.handle; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.decision.webservice.Response; +import com.fr.io.TemplateWorkBookIO; +import com.fr.io.exporter.ImageExporter; +import com.fr.json.JSONObject; +import com.fr.main.TemplateWorkBook; +import com.fr.main.workbook.ResultWorkBook; +import com.fr.plugin.xx.wechat.img.output.LogUtils; +import com.fr.plugin.xx.wechat.img.output.conf.ImgPushConfig; +import com.fr.plugin.xx.wechat.img.output.entity.ImgConfigEntity; +import com.fr.plugin.xx.wechat.img.output.service.ImgConfigService; +import com.fr.plugin.xx.wechat.img.output.util.HttpsUtil; +import com.fr.stable.StringUtils; +import com.fr.stable.ViewActor; +import com.fr.third.org.apache.commons.lang3.math.NumberUtils; +import com.fr.third.springframework.core.io.ByteArrayResource; +import com.fr.third.springframework.http.HttpEntity; +import com.fr.third.springframework.http.HttpHeaders; +import com.fr.third.springframework.http.MediaType; +import com.fr.third.springframework.http.ResponseEntity; +import com.fr.third.springframework.util.LinkedMultiValueMap; +import com.fr.third.springframework.util.MultiValueMap; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; +import com.fr.third.springframework.web.client.RestTemplate; +import com.fr.web.utils.WebUtils; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Author xx + * @Date 2021/11/16 + * @Description + **/ +public class ExportHandler extends BaseHttpHandler { + + private final static String UPLOAD = "%s/wx-work/open-api/media/upload"; + + private final static String MESSAGE = "%s/wx-work/open-api/insideMessage/send"; + + private final static String TOKEN = "%s/wx-work/open-api/login?apiUserCode=%s&apiUserSecret=%s"; + + private final static Integer SIZE = 10; + + @Override + public RequestMethod getMethod() { + return RequestMethod.GET; + } + + @Override + public String getPath() { + return "/export"; + } + + @Override + public boolean isPublic() { + return true; + } + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + Integer poolSize = SIZE; + String cptName = WebUtils.getHTTPRequestParameter(req, "cptName"); + LogUtils.debug4plugin("cptName is {}", cptName); + if (StringUtils.isBlank(cptName)) { + setError(res, "cptName is not null"); + return; + } + String upname = WebUtils.getHTTPRequestParameter(req, "upname"); + LogUtils.debug4plugin("upname is {}", upname); + if (StringUtils.isBlank(upname)) { + setError(res, "upname is not null"); + return; + } + String pool = WebUtils.getHTTPRequestParameter(req, "poolSize"); + if (NumberUtils.isCreatable(pool)) { + poolSize = Integer.parseInt(pool); + } + + List list = ImgConfigService.getListByUpName(upname); + ExecutorService es = Executors.newFixedThreadPool(poolSize); + String token = getToken(); + if(StringUtils.isBlank(token)){ + setError(res, "token is null"); + return; + } + Map header = new HashMap<>(); + header.put("X-Auth-Token",token); + for (ImgConfigEntity e : list) { + es.submit(() -> { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + Map params = e.toMap(); + TemplateWorkBook wb = TemplateWorkBookIO.readTemplateWorkBook(cptName); + ImageExporter exporter = new ImageExporter("png", 96); + ResultWorkBook resultWorkBook = wb.execute(params, new ViewActor()); + exporter.export(os, resultWorkBook); + LogUtils.debug4plugin("execute temp {} by param {}",cptName,params); + String mediaId = upload(os,token); + if (StringUtils.isBlank(mediaId)) { + LogUtils.warn("{} upload file error", e.getId()); + return; + } + sendMess(e.getActNumber(), mediaId,header); + } catch (Exception ex) { + LogUtils.error(ex.getMessage(), e); + }finally { + try { + os.close(); + } catch (IOException exception) { + LogUtils.error(exception.getMessage(),exception); + } + } + }); + } + WebUtils.printAsJSON(res, JSONObject.mapFrom(Response.ok(list.size()))); + } + + private String getToken() { + ImgPushConfig config = ImgPushConfig.getInstance(); + String url = String.format(TOKEN, config.getHost(), config.getApiUserCode(), config.getApiUserSecret()); + LogUtils.debug4plugin("token url is {}",url); + String res = HttpsUtil.sendPost(url, new HashMap(), JSONObject.create()); + LogUtils.debug4plugin("get token res is {}",res); + JSONObject object = new JSONObject(res); + return object.getJSONObject("data").getJSONObject("details").getString("token"); + } + + private void sendMess(String phone, String mediaId, Map header) { + JSONObject image = JSONObject.create().put("mediaId", mediaId); + JSONObject body = JSONObject.create().put("toPhone", phone).put("image", image).put("msgType","image"); + LogUtils.debug4plugin("send to {} body is {}", phone, body.toString()); + String res = HttpsUtil.sendPost(String.format(MESSAGE, ImgPushConfig.getInstance().getHost()), header, body); + LogUtils.debug4plugin("send to {} res is {}", phone, res); + } + + private String upload(ByteArrayOutputStream os, String token) throws UnsupportedEncodingException { + ByteArrayResource fileAsResource = new ByteArrayResource(os.toByteArray()) { + @Override + public String getFilename() { + return UUID.randomUUID().toString()+".png"; + } + + @Override + public long contentLength() { + return os.size(); + } + }; + MultiValueMap multipartRequest = new LinkedMultiValueMap<>(); + multipartRequest.add("file", fileAsResource); + multipartRequest.add("mediaType", "image"); + HttpHeaders headers = new HttpHeaders(); + headers.add("X-Auth-Token",token); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + HttpEntity> requestEntity = new HttpEntity(multipartRequest, headers); + ResponseEntity res = + new RestTemplate().postForEntity(String.format(UPLOAD, ImgPushConfig.getInstance().getHost()), requestEntity, String.class); + //String upload = HttpsUtil.doEntityPost(String.format(UPLOAD, ImgPushConfig.getInstance().getHost()), header, builder.build()); + LogUtils.debug4plugin("send png res is {}", res.getBody()); + JSONObject object = new JSONObject(res.getBody()); + return object.getJSONObject("data").getString("mediaId"); + } + + private void setError(HttpServletResponse res, String mess) throws Exception { + WebUtils.printAsJSON(res, JSONObject.mapFrom(Response.error(mess, mess))); + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/RestTest.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/RestTest.java new file mode 100644 index 0000000..9b23301 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/RestTest.java @@ -0,0 +1,59 @@ +package com.fr.plugin.xx.wechat.img.output.handle; + +import com.fr.decision.fun.impl.BaseHttpHandler; +import com.fr.io.TemplateWorkBookIO; +import com.fr.io.exporter.ImageExporter; +import com.fr.main.TemplateWorkBook; +import com.fr.main.workbook.ResultWorkBook; +import com.fr.plugin.xx.wechat.img.output.LogUtils; +import com.fr.stable.ViewActor; +import com.fr.third.springframework.web.bind.annotation.RequestMethod; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.FileOutputStream; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * @Author xx + * @Date 2022/7/21 + * @Description + **/ +public class RestTest extends BaseHttpHandler { + + + @Override + public RequestMethod getMethod() { + return RequestMethod.GET; + } + + @Override + public String getPath() { + return "/test"; + } + + @Override + public boolean isPublic() { + return true; + } + + @Override + public void handle(HttpServletRequest req, HttpServletResponse res) throws Exception { + String file = "/Users/hujian/Desktop/test/"; + FileOutputStream os = new FileOutputStream(new File(file+ UUID.randomUUID().toString()+".png")); + String cptName = "单C穿透日报-分支去边.cpt"; + Map params = new HashMap<>(); + params.put("date","date"); + params.put("upname","upname"); + params.put("level","level"); + params.put("name","name"); + TemplateWorkBook wb = TemplateWorkBookIO.readTemplateWorkBook(cptName); + ImageExporter exporter = new ImageExporter("png", 96); + ResultWorkBook resultWorkBook = wb.execute(params, new ViewActor()); + exporter.export(os, resultWorkBook); + LogUtils.debug4plugin("execute temp {} by param {}",cptName,params); + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/WebHookHandle.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/WebHookHandle.java new file mode 100644 index 0000000..71f49a1 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/handle/WebHookHandle.java @@ -0,0 +1,172 @@ +package com.fr.plugin.xx.wechat.img.output.handle; + +import com.fr.base.Formula; +import com.fr.io.TemplateWorkBookIO; +import com.fr.io.exporter.ImageExporter; +import com.fr.json.JSONObject; +import com.fr.main.TemplateWorkBook; +import com.fr.main.workbook.ResultWorkBook; +import com.fr.plugin.xx.wechat.img.output.LogUtils; +import com.fr.plugin.xx.wechat.img.output.conf.ImgPushConfig; +import com.fr.plugin.xx.wechat.img.output.entity.ImgConfigEntity; +import com.fr.plugin.xx.wechat.img.output.entity.OutputWebHook; +import com.fr.plugin.xx.wechat.img.output.service.ImgConfigService; +import com.fr.plugin.xx.wechat.img.output.util.HttpsUtil; +import com.fr.schedule.base.constant.ScheduleConstants; +import com.fr.schedule.feature.output.OutputActionHandler; +import com.fr.stable.StringUtils; +import com.fr.stable.ViewActor; +import com.fr.third.org.apache.commons.lang3.math.NumberUtils; +import com.fr.third.springframework.core.io.ByteArrayResource; +import com.fr.third.springframework.http.HttpEntity; +import com.fr.third.springframework.http.HttpHeaders; +import com.fr.third.springframework.http.MediaType; +import com.fr.third.springframework.http.ResponseEntity; +import com.fr.third.springframework.util.LinkedMultiValueMap; +import com.fr.third.springframework.util.MultiValueMap; +import com.fr.third.springframework.web.client.RestTemplate; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * @Author xx + * @Date 2020/9/15 + * @Description + **/ +public class WebHookHandle extends OutputActionHandler { + + private final static String UPLOAD = "%s/wx-work/open-api/media/upload"; + + private final static String MESSAGE = "%s/wx-work/open-api/insideMessage/send"; + + private final static String TOKEN = "%s/wx-work/open-api/login?apiUserCode=%s&apiUserSecret=%s"; + + @Override + public void doAction(OutputWebHook outputWebHook, Map map) throws Exception { + Integer pool = 10; + String upname = getParam(map, "upname"); + if(StringUtils.isBlank(upname)){ + throw new Exception("upname参数不能为空"); + } + String cptName = getParam(map, "cpt"); + if(StringUtils.isBlank(cptName)){ + throw new Exception("cpt参数不能为空"); + } + String poolSize = getParam(map, "poolSize"); + if (NumberUtils.isCreatable(poolSize)) { + pool = Integer.valueOf(poolSize); + } + String date = getParam(map, "date"); + List list = ImgConfigService.getListByUpName(upname); + ExecutorService es = Executors.newFixedThreadPool(pool); + String token = getToken(); + if (StringUtils.isBlank(token)) { + throw new Exception("token is null"); + } + Map header = new HashMap<>(); + header.put("X-Auth-Token", token); + for (ImgConfigEntity e : list) { + es.submit(() -> { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + try { + Map params = e.toMap(); + if(StringUtils.isNotBlank(date)){ + params.put("date",date); + } + TemplateWorkBook wb = TemplateWorkBookIO.readTemplateWorkBook(cptName); + ImageExporter exporter = new ImageExporter("png", 96); + ResultWorkBook resultWorkBook = wb.execute(params, new ViewActor()); + exporter.export(os, resultWorkBook); + LogUtils.debug4plugin("execute temp {} by param {}", cptName, params); + String mediaId = upload(os, token); + if (StringUtils.isBlank(mediaId)) { + LogUtils.warn("{} upload file error", e.getId()); + return; + } + sendMess(e.getActNumber(), mediaId, header); + } catch (Exception ex) { + LogUtils.error(ex.getMessage(), e); + } finally { + try { + os.close(); + } catch (IOException exception) { + LogUtils.error(exception.getMessage(), exception); + } + } + }); + } + } + + private String getParam(Map map, String p) { + List list = (List) map.get(ScheduleConstants.RECORD_LIST); + Object title = StringUtils.EMPTY; + if (list == null || list.isEmpty()) { + return StringUtils.EMPTY; + } + Object param = list.get(0).get(p); + if (param == null) { + return StringUtils.EMPTY; + } + if (param instanceof Formula) { + Formula formula = (Formula) param; + title = formula.getResult(); + } else { + title = param.toString(); + } + return title.toString(); + } + + private String getToken() { + ImgPushConfig config = ImgPushConfig.getInstance(); + String url = String.format(TOKEN, config.getHost(), config.getApiUserCode(), config.getApiUserSecret()); + LogUtils.debug4plugin("token url is {}", url); + String res = HttpsUtil.sendPost(url, new HashMap(), JSONObject.create()); + LogUtils.debug4plugin("get token res is {}", res); + JSONObject object = new JSONObject(res); + return object.getJSONObject("data").getJSONObject("details").getString("token"); + } + + private void sendMess(String phone, String mediaId, Map header) { + JSONObject image = JSONObject.create().put("mediaId", mediaId); + JSONObject body = JSONObject.create().put("toPhone", phone).put("image", image).put("msgType", "image"); + LogUtils.debug4plugin("send to {} body is {}", phone, body.toString()); + String res = HttpsUtil.sendPost(String.format(MESSAGE, ImgPushConfig.getInstance().getHost()), header, body); + LogUtils.debug4plugin("send to {} res is {}", phone, res); + } + + private String upload(ByteArrayOutputStream os, String token) throws UnsupportedEncodingException { + ByteArrayResource fileAsResource = new ByteArrayResource(os.toByteArray()) { + @Override + public String getFilename() { + return UUID.randomUUID().toString() + ".png"; + } + + @Override + public long contentLength() { + return os.size(); + } + }; + MultiValueMap multipartRequest = new LinkedMultiValueMap<>(); + multipartRequest.add("file", fileAsResource); + multipartRequest.add("mediaType", "image"); + HttpHeaders headers = new HttpHeaders(); + headers.add("X-Auth-Token", token); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + HttpEntity> requestEntity = new HttpEntity(multipartRequest, headers); + ResponseEntity res = + new RestTemplate().postForEntity(String.format(UPLOAD, ImgPushConfig.getInstance().getHost()), requestEntity, String.class); + //String upload = HttpsUtil.doEntityPost(String.format(UPLOAD, ImgPushConfig.getInstance().getHost()), header, builder.build()); + LogUtils.debug4plugin("send png res is {}", res.getBody()); + JSONObject object = new JSONObject(res.getBody()); + return object.getJSONObject("data").getString("mediaId"); + } + +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/js/FileDef.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/js/FileDef.java new file mode 100644 index 0000000..1e82657 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/js/FileDef.java @@ -0,0 +1,54 @@ +package com.fr.plugin.xx.wechat.img.output.js; + +import com.fr.plugin.transform.ExecuteFunctionRecord; +import com.fr.web.struct.Component; +import com.fr.web.struct.Filter; +import com.fr.web.struct.browser.RequestClient; +import com.fr.web.struct.category.ScriptPath; +import com.fr.web.struct.category.StylePath; + +/** + * @author xx + * @date 2019/6/12 + */ +public class FileDef extends Component { + public static final FileDef KEY = new FileDef(); + private FileDef(){} + /** + * 返回需要引入的JS脚本路径 + * @param client 请求客户端描述 + * @return JS脚本路径 + */ + @Override + public ScriptPath script(RequestClient client ) { + //如果不需要就直接返回 ScriptPath.EMPTY + return ScriptPath.build("com/fr/plugin/xx/wechat/img/output/theme.js"); + } + + /** + * 返回需要引入的CSS样式路径 + * @param client 请求客户端描述 + * @return CSS样式路径 + */ + @Override + public StylePath style(RequestClient client ) { + //如果不需要就直接返回 StylePath.EMPTY; + return StylePath.EMPTY; + } + + /** + * 通过给定的资源过滤器控制是否加载这个资源 + * @return 资源过滤器 + */ + @ExecuteFunctionRecord + @Override + public Filter filter() { + return new Filter(){ + @Override + public boolean accept() { + //任何情况下我们都在平台组件加载时加载我们的组件 + return true; + } + }; + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/js/JSCSSBridge.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/js/JSCSSBridge.java new file mode 100644 index 0000000..07cdc92 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/js/JSCSSBridge.java @@ -0,0 +1,33 @@ +package com.fr.plugin.xx.wechat.img.output.js; + +import com.fr.decision.fun.impl.AbstractWebResourceProvider; +import com.fr.decision.web.MainComponent; +import com.fr.plugin.context.PluginContexts; +import com.fr.plugin.xx.wechat.img.output.PluginConstants; +import com.fr.plugin.transform.FunctionRecorder; +import com.fr.stable.fun.Authorize; +import com.fr.web.struct.Atom; + +/** + * @author xx + * @date 2019/6/12 + */ +@FunctionRecorder +@Authorize(callSignKey = PluginConstants.PLUGIN_ID) +public class JSCSSBridge extends AbstractWebResourceProvider { + @Override + public Atom attach() { + //在平台主组件加载时添加我们自己的组件 + return MainComponent.KEY; + } + + @Override + public Atom client() { + //我们自己要引入的组件 + if(PluginContexts.currentContext().isAvailable()){ + return FileDef.KEY; + }else { + return MainComponent.KEY; + } + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/service/ImgConfigService.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/service/ImgConfigService.java new file mode 100644 index 0000000..ecdb29a --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/service/ImgConfigService.java @@ -0,0 +1,40 @@ +package com.fr.plugin.xx.wechat.img.output.service; + +import com.fr.plugin.xx.wechat.img.output.ImgConfigDBAccessProvider; +import com.fr.plugin.xx.wechat.img.output.LogUtils; +import com.fr.plugin.xx.wechat.img.output.dao.ImgConfigDao; +import com.fr.plugin.xx.wechat.img.output.entity.ImgConfigEntity; +import com.fr.stable.db.action.DBAction; +import com.fr.stable.db.dao.DAOContext; +import com.fr.stable.query.QueryFactory; +import com.fr.stable.query.restriction.RestrictionFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * @Author xx + * @Date 2022/7/16 + * @Description + **/ +public class ImgConfigService { + + /** + * 获取分组要执行的配置 + * @param name + * @return + */ + public static List getListByUpName(String name) { + try { + return ImgConfigDBAccessProvider.getDbAccessor().runQueryAction(new DBAction>() { + @Override + public List run(DAOContext daoContext) throws Exception { + return daoContext.getDAO(ImgConfigDao.class).find(QueryFactory.create().addRestriction(RestrictionFactory.eq("upname", name))); + } + }); + } catch (Exception e) { + LogUtils.error(e.getMessage(), e); + } + return new ArrayList<>(); + } +} diff --git a/src/main/java/com/fr/plugin/xx/wechat/img/output/util/HttpsUtil.java b/src/main/java/com/fr/plugin/xx/wechat/img/output/util/HttpsUtil.java new file mode 100644 index 0000000..f3314b2 --- /dev/null +++ b/src/main/java/com/fr/plugin/xx/wechat/img/output/util/HttpsUtil.java @@ -0,0 +1,346 @@ +package com.fr.plugin.xx.wechat.img.output.util; + +import com.fr.json.JSONObject; +import com.fr.log.FineLoggerFactory; +import com.fr.third.org.apache.http.HttpEntity; +import com.fr.third.org.apache.http.HttpResponse; +import com.fr.third.org.apache.http.HttpStatus; +import com.fr.third.org.apache.http.client.HttpClient; +import com.fr.third.org.apache.http.client.methods.HttpPost; +import com.fr.third.org.apache.http.config.Registry; +import com.fr.third.org.apache.http.config.RegistryBuilder; +import com.fr.third.org.apache.http.conn.socket.ConnectionSocketFactory; +import com.fr.third.org.apache.http.conn.socket.PlainConnectionSocketFactory; +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.HttpClients; +import com.fr.third.org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import com.fr.third.org.apache.http.util.EntityUtils; + +import javax.net.ssl.*; +import java.io.*; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.security.cert.CertificateException; +import java.util.Iterator; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Author xx + * @Date 2020/9/15 + * @Description + **/ +public class HttpsUtil { + + private static HostnameVerifier hv = new HostnameVerifier() { + @Override + public boolean verify(String urlHostName, SSLSession session) { + System.out.println("Warning: URL Host: " + urlHostName + " vs. " + + session.getPeerHost()); + return true; + } + }; + + /** + * 发送get请求 + * + * @param url + * @param param + * @param header + * @return + * @throws IOException + */ + public static String sendGet(String url, Map param, Map header) { + String result = ""; + BufferedReader in = null; + String urlNameString = url; + try { + if (param != null) { + urlNameString += "?"; + urlNameString += param.entrySet() + .stream() + .map(entry -> entry.getKey() + "=" + entry.getValue()) + .collect(Collectors.joining("&")); + } + + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + HttpURLConnection connection; + if (url.startsWith("https")) { + trustAllHttpsCertificates(); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + connection = (HttpURLConnection) realUrl.openConnection(); + } else { + connection = (HttpURLConnection) realUrl.openConnection(); + } + //设置超时时间 + connection.setDoInput(true); + connection.setRequestMethod("GET"); + connection.setConnectTimeout(5000); + connection.setReadTimeout(15000); + // 设置通用的请求属性 + if (header != null) { + Iterator> it = header.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry entry = it.next(); + System.out.println(entry.getKey() + ":::" + entry.getValue()); + connection.setRequestProperty(entry.getKey(), entry.getValue()); + } + } + connection.setRequestProperty("accept", "*/*"); + connection.setRequestProperty("connection", "Keep-Alive"); + connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + // 建立实际的连接 + connection.connect(); + // 定义 BufferedReader输入流来读取URL的响应,设置utf8防止中文乱码 + in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "utf-8")); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + if (in != null) { + in.close(); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e, "get url error ,url is:{},error is {}", urlNameString, e.getMessage()); + } + return result; + } + + public static String sendPost(String url, Map header, JSONObject body) { + PrintWriter out = null; + BufferedReader in = null; + String result = null; + String res = null; + try { + String urlNameString = url; + + URL realUrl = new URL(urlNameString); + // 打开和URL之间的连接 + HttpURLConnection conn; + if (url.startsWith("https")) { + trustAllHttpsCertificates(); + HttpsURLConnection.setDefaultHostnameVerifier(hv); + conn = (HttpURLConnection) realUrl.openConnection(); + } else { + conn = (HttpURLConnection) realUrl.openConnection(); + } + // 设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); +// conn.setRequestProperty("user-agent", +// "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); + if (header != null) { + header.forEach((k, v) -> { + conn.setRequestProperty(k, String.valueOf(v)); + }); + } + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + //获取请求头 + + // 获取URLConnection对象对应的输出流 + out = new PrintWriter(conn.getOutputStream()); + // 发送请求参数 + if (body != null) { + FineLoggerFactory.getLogger().error("content data: {}", body.toString()); + FineLoggerFactory.getLogger().error("content cover data: {}", new String(body.toString().getBytes("UTF-8"), "UTF-8")); + out.print(new String(body.toString().getBytes("UTF-8"), "UTF-8")); + } + // flush输出流的缓冲 + out.flush(); + // 定义BufferedReader输入流来读取URL的响应 + in = new BufferedReader( + new InputStreamReader(conn.getInputStream())); + String line; + while ((line = in.readLine()) != null) { + result += line; + } + res = result; + if (res.startsWith("null")) { + res = res.replace("null", ""); + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + //使用finally块来关闭输出流、输入流 + finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + } + return res; + } + + + public static String doPost(String url, Map header, JSONObject json) { + HttpClient client = HttpClients.createDefault(); + if (url.startsWith("https")) { + SSLContext sslcontext = createIgnoreVerifySSL(); + Registry socketFactoryRegistry = RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.INSTANCE) + .register("https", new SSLConnectionSocketFactory(sslcontext)) + .build(); + PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + HttpClients.custom().setConnectionManager(connManager); + client = HttpClients.custom().setConnectionManager(connManager).build(); + } + HttpPost post = new HttpPost(url); + post.setHeader("accept", "*/*"); + post.setHeader("connection", "Keep-Alive"); + post.setHeader("Content-Type", "application/json"); + if (header != null) { + header.forEach((k, v) -> { + post.setHeader(k, String.valueOf(v)); + }); + } + try { + StringEntity s = new StringEntity(json.toString(),"UTF-8"); + s.setContentEncoding("UTF-8"); + s.setContentType("application/json; charset=UTF-8");//发送json数据需要设置contentType + post.setEntity(s); + HttpResponse res = client.execute(post); + if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + String result = EntityUtils.toString(res.getEntity());// 返回json格式: + return result; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + return null; + } + + + public static String doEntityPost(String url, Map header, HttpEntity entity) { + HttpClient client = HttpClients.createDefault(); + if (url.startsWith("https")) { + SSLContext sslcontext = createIgnoreVerifySSL(); + Registry socketFactoryRegistry = RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.INSTANCE) + .register("https", new SSLConnectionSocketFactory(sslcontext)) + .build(); + PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + HttpClients.custom().setConnectionManager(connManager); + client = HttpClients.custom().setConnectionManager(connManager).build(); + } + HttpPost post = new HttpPost(url); + post.setHeader("accept", "*/*"); + post.setHeader("connection", "Keep-Alive"); + if (header != null) { + header.forEach((k, v) -> { + post.setHeader(k, String.valueOf(v)); + }); + } + try { + post.setEntity(entity); + HttpResponse res = client.execute(post); + if (res.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { + String result = EntityUtils.toString(res.getEntity());// 返回json格式: + return result; + } + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(),e); + } + return null; + } + + private static void trustAllHttpsCertificates() throws Exception { + TrustManager[] trustAllCerts = new TrustManager[1]; + TrustManager tm = new miTM(); + trustAllCerts[0] = tm; + SSLContext sc = SSLContext.getInstance("SSL", "SunJSSE"); + sc.init(null, trustAllCerts, null); + HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); + } + + + /** + * encode url by UTF-8 + * + * @param url url before encoding + * @return url after encoding + */ + public static String encodeUrl(String url) { + String eurl = url; + try { + eurl = URLEncoder.encode(url, "UTF-8"); + } catch (UnsupportedEncodingException e) { + } + return eurl; + } + + private static class miTM implements TrustManager, + X509TrustManager { + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public boolean isServerTrusted( + java.security.cert.X509Certificate[] certs) { + return true; + } + + public boolean isClientTrusted( + java.security.cert.X509Certificate[] certs) { + return true; + } + + @Override + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) + throws CertificateException { + return; + } + + @Override + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) + throws CertificateException { + return; + } + } + + public static SSLContext createIgnoreVerifySSL() { + try { + SSLContext sc = SSLContext.getInstance("SSLv3"); + + // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法 + X509TrustManager trustManager = new X509TrustManager() { + @Override + public void checkClientTrusted( + java.security.cert.X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + } + + @Override + public void checkServerTrusted( + java.security.cert.X509Certificate[] paramArrayOfX509Certificate, + String paramString) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + }; + + sc.init(null, new TrustManager[]{trustManager}, null); + return sc; + } catch (Exception e) { + FineLoggerFactory.getLogger().error(e.getMessage(), e); + } + return null; + } +} diff --git a/src/main/resources/com/fr/plugin/xx/wechat/img/output/theme.js b/src/main/resources/com/fr/plugin/xx/wechat/img/output/theme.js new file mode 100644 index 0000000..f182dfc --- /dev/null +++ b/src/main/resources/com/fr/plugin/xx/wechat/img/output/theme.js @@ -0,0 +1,65 @@ +!(function () { + var Plugin = BI.inherit(BI.Widget, { + props: { + baseCls: "", + value: { + hookUrl: "1", + } + }, + render: function () { + var t = this, + e = this.options.value[0]==undefined?{hookUrl: "1"}: this.options.value[0]; + return { + type: "bi.flex_vertical", + tgap: 15, + items: [/*{ + type: "dec.label.editor.item", + errorTop: 16, + textCls: "dec-font-weight-bold", + text: "webHookUrl", + textWidth: 115, + editorWidth: 300, + value: e.hookUrl, + ref: function(e) { + t.hookUrl = e + } + }*/] + }; + }, + /** + * + * + * @returns {boolean} + */ + validation: function () { + var e = !0, + t = this.isVisible(); + return true; + /*return BI.isEmpty(this.hookUrl.getValue()) && (t && this.hookUrl.showError(BI.i18nText("Dec-Error_Null")), e = !1), + e*/ + }, + /** + * + * outputActionList + * @returns {{}} + */ + getValue: function() { + var _self= this; + return {OutputWebHook: BI.extend(_self.value,{ + "@class": "com.fr.plugin.xx.wechat.img.output.entity.OutputWebHook", + actionName: "com.fr.plugin.xx.wechat.img.output.entity.OutputWebHook", + hookUrl: "1", + })} + }, + }); + BI.shortcut("dec.schedule.task.file.handling.plugin", Plugin); + + BI.config("dec.provider.schedule", function (provider) { + provider.registerHandingWay({ + text: "企微调度推送", + value: "com.fr.plugin.xx.wechat.img.output.entity.OutputWebHook", // actionName + cardType: "dec.schedule.task.file.handling.plugin", + actions: [] // action + }, [DecCst.Schedule.TaskType.DEFAULT, DecCst.Schedule.TaskType.REPORT, DecCst.Schedule.TaskType.BI]); + }); +}());