From b5d93747bea398d6bbaa195d9ccbfdfe12c80e8f Mon Sep 17 00:00:00 2001 From: fancy Date: Tue, 1 Mar 2022 20:22:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BE=AE=E4=BF=A1=E5=85=AC=E4=BC=97=E5=8F=B7?= =?UTF-8?q?=E6=8E=A5=E6=94=B6=E6=96=87=E6=9C=AC=E6=B6=88=E6=81=AF=E5=90=8E?= =?UTF-8?q?=E8=84=9A=E6=9C=AC=E5=A4=84=E7=90=86=20=E5=BE=AE=E4=BF=A1?= =?UTF-8?q?=E5=85=AC=E4=BC=97=E5=8F=B7=E8=8F=9C=E5=8D=95=E5=9B=9E=E5=A4=8D?= =?UTF-8?q?=E5=AA=92=E4=BD=93=E6=B6=88=E6=81=AF=20=E8=8F=9C=E5=8D=95?= =?UTF-8?q?=E6=89=A7=E8=A1=8C=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../x/base/core/project/config/MPweixin.java | 11 ++ .../jaxrs/mpweixin/ActionReceiveMsg.java | 162 +++++++++++++++++- .../center/jaxrs/mpweixin/BaseAction.java | 9 +- .../center/jaxrs/mpweixin/MPWeixinAction.java | 2 +- 4 files changed, 178 insertions(+), 6 deletions(-) diff --git a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/MPweixin.java b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/MPweixin.java index 5875e45ea3..c02a5cb6d4 100644 --- a/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/MPweixin.java +++ b/o2server/x_base_core_project/src/main/java/com/x/base/core/project/config/MPweixin.java @@ -30,6 +30,8 @@ public class MPweixin extends ConfigObject { private String encodingAesKey=""; @FieldDescribe("微信公众号测试菜单的门户地址") private String portalId = ""; + @FieldDescribe("接收到文本消息默认执行的服务脚本id") + private String scriptId = ""; @FieldDescribe("是否启用公众号模版消息") private Boolean messageEnable; @@ -59,6 +61,7 @@ public class MPweixin extends ConfigObject { this.token = ""; this.encodingAesKey = ""; this.portalId = ""; + this.scriptId = ""; this.messageEnable = false; this.tempMessageId = ""; this.fieldList = new ArrayList<>(); @@ -188,6 +191,14 @@ public class MPweixin extends ConfigObject { this.fieldList = fieldList; } + public String getScriptId() { + return scriptId; + } + + public void setScriptId(String scriptId) { + this.scriptId = scriptId; + } + /** * 微信使用code获取accessToken openid 等数据 */ diff --git a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/ActionReceiveMsg.java b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/ActionReceiveMsg.java index 5fcee33b15..6c7c0c1f89 100644 --- a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/ActionReceiveMsg.java +++ b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/ActionReceiveMsg.java @@ -6,6 +6,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import com.x.base.core.project.Application; +import com.x.base.core.project.config.CenterServer; +import com.x.base.core.project.config.Config; +import com.x.base.core.project.connection.ActionResponse; +import com.x.base.core.project.connection.CipherConnectionAction; +import com.x.base.core.project.gson.GsonPropertyObject; +import com.x.base.core.project.x_jpush_assemble_control; import org.apache.commons.lang3.StringUtils; import org.dom4j.Document; import org.dom4j.Element; @@ -38,7 +45,7 @@ public class ActionReceiveMsg extends BaseAction { Map map = xmlToMap(inputStream); String msgType = map.get("MsgType"); - if (WX_MSG_RECEIVE_TYPE_EVENT.equals(msgType)) { // + if (WX_MSG_RECEIVE_TYPE_EVENT.equals(msgType)) { // 事件出发 String event = map.get("Event"); String eventKey = map.get("EventKey"); logger.info("接收到事件消息: event: {} , eventKey: {}", event, eventKey); @@ -49,9 +56,42 @@ public class ActionReceiveMsg extends BaseAction { String content = menu.getContent(); String toUser = map.get("FromUserName"); String fromUser = map.get("ToUserName"); - String xml = txtMessageBack(toUser, fromUser, content); - logger.info("回复点击菜单消息: {}", xml); - wo.setText(xml); + // 特殊消息处理 默认是回复文字消息 如果是媒体消息 需要配置特殊的头 media:image: 后面跟微信素材的mediaId + if (content.startsWith(WX_MSG_BACK_MEDIA_KEY_IMAGE)) { + String mediaId = content.substring(WX_MSG_BACK_MEDIA_KEY_IMAGE.length()); + String xml = imageMessageBack(toUser, fromUser, mediaId); + logger.info("回复点击菜单消息: {}", xml); + wo.setText(xml); + } else if (content.startsWith(WX_MSG_BACK_MEDIA_KEY_VOICE)) { + String mediaId = content.substring(WX_MSG_BACK_MEDIA_KEY_VOICE.length()); + String xml = voiceMessageBack(toUser, fromUser, mediaId); + logger.info("回复点击菜单消息: {}", xml); + wo.setText(xml); + } else if (content.startsWith(WX_MSG_BACK_MEDIA_KEY_VIDEO)) { + // 视频消息需要多两个字段 title和description 用|分割 如: mediaId|title|description + String videoContent = content.substring(WX_MSG_BACK_MEDIA_KEY_VIDEO.length()); + String xml = null; + try { + String[] arr = videoContent.split("\\|"); + xml = videoMessageBack(toUser, fromUser, arr[0], arr[1], arr[2]); + } catch (Exception e) { + logger.error(e); + xml = txtMessageBack(toUser, fromUser, content); + } + logger.info("回复点击菜单消息: {}", xml); + wo.setText(xml); + } else if (content.startsWith(WX_MSG_BACK_MEDIA_KEY_SCRIPT)) { + String scriptId = content.substring(WX_MSG_BACK_MEDIA_KEY_SCRIPT.length()); + if (StringUtils.isNotBlank(scriptId)) { + ExecuteServiceScriptThread runner1 = new ExecuteServiceScriptThread(toUser, "", scriptId); + Thread thread1 = new Thread(runner1); + thread1.start(); + } + } else { + String xml = txtMessageBack(toUser, fromUser, content); + logger.info("回复点击菜单消息: {}", xml); + wo.setText(xml); + } actionResult.setData(wo); return actionResult; } else { @@ -72,6 +112,17 @@ public class ActionReceiveMsg extends BaseAction { logger.info("没有查询到对应的 eventKey:{}", eventKey); } } + } else if (WX_MSG_RECEIVE_TYPE_TEXT.equalsIgnoreCase(msgType)) { // 接收到文本消息 + String text = map.get("Content"); + String toUser = map.get("FromUserName"); + logger.info("接收到文本消息: text: {} ", text); + //TODO 目前支持异步执行服务脚本,这里必须马上返回 否则会超时,脚本里面可以调用微信客服消息进行回复. 脚本id暂时先保存到配置文件 + String id = Config.mPweixin().getScriptId(); + if (StringUtils.isNotBlank(id)) { + ExecuteServiceScriptThread runner1 = new ExecuteServiceScriptThread(toUser, text, id); + Thread thread1 = new Thread(runner1); + thread1.start(); + } } else { logger.info("未处理消息类型, MsgType: {}", msgType); } @@ -84,6 +135,7 @@ public class ActionReceiveMsg extends BaseAction { } + // 回复文本消息 private String txtMessageBack(String toUser, String from, String content) { long time = new Date().getTime(); String xml = "" + @@ -96,8 +148,52 @@ public class ActionReceiveMsg extends BaseAction { return xml; } + // 回复图片消息 + private String imageMessageBack(String toUser, String from, String mediaId) { + long time = new Date().getTime(); + String xml = "" + + "" + + "" + + "" + time + "" + + "" + + "" + + ""; + return xml; + } + // 回复音频消息 + private String voiceMessageBack(String toUser, String from, String mediaId) { + long time = new Date().getTime(); + String xml = "" + + "" + + "" + + "" + time + "" + + "" + + "" + + ""; + return xml; + } + //回复视频消息 + private String videoMessageBack(String toUser, String from, String mediaId, String title, String description) { + long time = new Date().getTime(); + String xml = "" + + "" + + "" + + "" + time + "" + + "" + + "" + + ""; + return xml; + } + + private void asyncPostServiceScript(String text) { + + } /** @@ -128,4 +224,62 @@ public class ActionReceiveMsg extends BaseAction { public static class Wo extends WoText { } + + + public static class ExecuteServiceScriptThread implements Runnable { + String toUser; + String text; + String scriptId; + ExecuteServiceScriptThread(String toUser, String text, String scriptId) { + this.toUser = toUser; + this.text = text; + this.scriptId = scriptId; + } + @Override + public void run() { + evalRemote(); + } + + private void evalRemote() { + try { + if (StringUtils.isNotBlank(scriptId)) { + ScriptExecuteBody body = new ScriptExecuteBody(); + body.setKeyword(text); + body.setOpenId(toUser); + ActionResponse result = CipherConnectionAction.post(false, + Config.url_x_program_center_jaxrs("invoke",scriptId, "execute"), body); + logger.info("执行脚本结果: " + result.toJson()); + } else { + logger.warn("没有配置服务脚本id"); + } + } catch (Exception e) { + logger.error(e); + } + } + } + + /** + * 脚本执行传入对象 + */ + public static class ScriptExecuteBody extends GsonPropertyObject { + // 微信公众号 用户的 openId + private String openId; + private String keyword; + + public String getOpenId() { + return openId; + } + + public void setOpenId(String openId) { + this.openId = openId; + } + + public String getKeyword() { + return keyword; + } + + public void setKeyword(String keyword) { + this.keyword = keyword; + } + } } diff --git a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/BaseAction.java b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/BaseAction.java index 3379a369e1..b3b0f5bcfe 100644 --- a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/BaseAction.java +++ b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/BaseAction.java @@ -13,7 +13,8 @@ import java.util.List; abstract class BaseAction extends StandardJaxrsAction { - public static final String WX_MSG_RECEIVE_TYPE_EVENT = "event"; //消息类型 事件 + public static final String WX_MSG_RECEIVE_TYPE_EVENT = "event"; //公众号接收到的消息类型 事件 主要是菜单点击和订阅取消订阅 + public static final String WX_MSG_RECEIVE_TYPE_TEXT = "text"; //公众号接收到的消息类型 文本 @@ -24,6 +25,12 @@ abstract class BaseAction extends StandardJaxrsAction { public static final String WX_MSG_RECEIVE_EVENT_VIEW = "VIEW"; //点击菜单跳转链接时的事件推送 + public static final String WX_MSG_BACK_MEDIA_KEY_IMAGE = "media:image:"; + public static final String WX_MSG_BACK_MEDIA_KEY_VIDEO = "media:video:"; + public static final String WX_MSG_BACK_MEDIA_KEY_VOICE = "media:voice:"; + public static final String WX_MSG_BACK_MEDIA_KEY_SCRIPT = "o2oa:script:"; + + diff --git a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/MPWeixinAction.java b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/MPWeixinAction.java index 33ec0d6aa2..93a19fded5 100644 --- a/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/MPWeixinAction.java +++ b/o2server/x_program_center/src/main/java/com/x/program/center/jaxrs/mpweixin/MPWeixinAction.java @@ -77,7 +77,7 @@ public class MPWeixinAction extends StandardJaxrsAction { @Path("media/add/forever") @Consumes(MediaType.MULTIPART_FORM_DATA) @Produces(HttpMediaType.APPLICATION_JSON_UTF_8) - public void androidPackStart(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request, + public void addMedia(@Suspended final AsyncResponse asyncResponse, @Context HttpServletRequest request, @JaxrsParameterDescribe("类型: image、voice、video 、thumb") @FormDataParam("type") String type, @JaxrsParameterDescribe("视频标题 video的类型必须传") @FormDataParam("videoTitle") String videoTitle, @JaxrsParameterDescribe("视频介绍 video的类型必须传") @FormDataParam("videoIntroduction") String videoIntroduction, -- GitLab