@@ -8,13 +8,22 @@ import me.chanjar.weixin.common.session.WxSessionManager; | |||||
import java.util.Map; | import java.util.Map; | ||||
/** | /** | ||||
* 处理小程序推送消息的处理器接口 | |||||
* 处理小程序推送消息的处理器接口. | |||||
* | * | ||||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||||
*/ | */ | ||||
public interface WxMaMessageHandler { | public interface WxMaMessageHandler { | ||||
void handle(WxMaMessage message, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException; | |||||
/** | |||||
* 处理消息. | |||||
* | |||||
* @param message 输入消息 | |||||
* @param context 上下文 | |||||
* @param service 服务类 | |||||
* @param sessionManager session管理器 | |||||
* @return 输出消息 | |||||
* @throws WxErrorException 异常 | |||||
*/ | |||||
WxMaXmlOutMessage handle(WxMaMessage message, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException; | |||||
} | } |
@@ -8,17 +8,21 @@ import me.chanjar.weixin.common.session.WxSessionManager; | |||||
import java.util.Map; | import java.util.Map; | ||||
/** | /** | ||||
* 微信消息拦截器,可以用来做验证 | |||||
* 微信消息拦截器,可以用来做验证. | |||||
* | * | ||||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||||
*/ | */ | ||||
public interface WxMaMessageInterceptor { | public interface WxMaMessageInterceptor { | ||||
/** | /** | ||||
* 拦截微信消息 | |||||
* 拦截微信消息. | |||||
* | * | ||||
* @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个 | |||||
* @param wxMessage . | |||||
* @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个 | |||||
* @param wxMaService . | |||||
* @param sessionManager . | |||||
* @return true代表OK,false代表不OK | * @return true代表OK,false代表不OK | ||||
* @throws WxErrorException . | |||||
*/ | */ | ||||
boolean intercept(WxMaMessage wxMessage, | boolean intercept(WxMaMessage wxMessage, | ||||
Map<String, Object> context, | Map<String, Object> context, | ||||
@@ -3,14 +3,17 @@ package cn.binarywang.wx.miniapp.message; | |||||
import cn.binarywang.wx.miniapp.bean.WxMaMessage; | import cn.binarywang.wx.miniapp.bean.WxMaMessage; | ||||
/** | /** | ||||
* 消息匹配器,用在消息路由的时候 | |||||
* 消息匹配器,用在消息路由的时候. | |||||
* | * | ||||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||||
*/ | */ | ||||
public interface WxMaMessageMatcher { | public interface WxMaMessageMatcher { | ||||
/** | /** | ||||
* 消息是否匹配某种模式 | |||||
* 消息是否匹配某种模式. | |||||
* | |||||
* @param message 消息 | |||||
* @return 是否匹配 | |||||
*/ | */ | ||||
boolean match(WxMaMessage message); | boolean match(WxMaMessage message); | ||||
@@ -32,8 +32,6 @@ public class WxMaMessageRouter { | |||||
private ExecutorService executorService; | private ExecutorService executorService; | ||||
private WxMessageDuplicateChecker messageDuplicateChecker; | |||||
private WxSessionManager sessionManager; | private WxSessionManager sessionManager; | ||||
private WxErrorExceptionHandler exceptionHandler; | private WxErrorExceptionHandler exceptionHandler; | ||||
@@ -43,7 +41,6 @@ public class WxMaMessageRouter { | |||||
ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("WxMaMessageRouter-pool-%d").build(); | ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("WxMaMessageRouter-pool-%d").build(); | ||||
this.executorService = new ThreadPoolExecutor(DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_SIZE, | this.executorService = new ThreadPoolExecutor(DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_SIZE, | ||||
0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), namedThreadFactory); | 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), namedThreadFactory); | ||||
this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); | |||||
this.sessionManager = new StandardSessionManager(); | this.sessionManager = new StandardSessionManager(); | ||||
this.exceptionHandler = new LogExceptionHandler(); | this.exceptionHandler = new LogExceptionHandler(); | ||||
} | } | ||||
@@ -58,16 +55,6 @@ public class WxMaMessageRouter { | |||||
this.executorService = executorService; | this.executorService = executorService; | ||||
} | } | ||||
/** | |||||
* <pre> | |||||
* 设置自定义的 {@link me.chanjar.weixin.common.api.WxMessageDuplicateChecker} | |||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker} | |||||
* </pre> | |||||
*/ | |||||
public void setMessageDuplicateChecker(WxMessageDuplicateChecker messageDuplicateChecker) { | |||||
this.messageDuplicateChecker = messageDuplicateChecker; | |||||
} | |||||
/** | /** | ||||
* <pre> | * <pre> | ||||
* 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager} | * 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager} | ||||
@@ -93,16 +80,16 @@ public class WxMaMessageRouter { | |||||
} | } | ||||
/** | /** | ||||
* 开始一个新的Route规则 | |||||
* 开始一个新的Route规则. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule rule() { | public WxMaMessageRouterRule rule() { | ||||
return new WxMaMessageRouterRule(this); | return new WxMaMessageRouterRule(this); | ||||
} | } | ||||
/** | /** | ||||
* 处理微信消息 | |||||
* 处理微信消息. | |||||
*/ | */ | ||||
public void route(final WxMaMessage wxMessage, final Map<String, Object> context) { | |||||
private WxMaXmlOutMessage route(final WxMaMessage wxMessage, final Map<String, Object> context) { | |||||
final List<WxMaMessageRouterRule> matchRules = new ArrayList<>(); | final List<WxMaMessageRouterRule> matchRules = new ArrayList<>(); | ||||
// 收集匹配的规则 | // 收集匹配的规则 | ||||
for (final WxMaMessageRouterRule rule : this.rules) { | for (final WxMaMessageRouterRule rule : this.rules) { | ||||
@@ -115,10 +102,11 @@ public class WxMaMessageRouter { | |||||
} | } | ||||
if (matchRules.size() == 0) { | if (matchRules.size() == 0) { | ||||
return; | |||||
return null; | |||||
} | } | ||||
final List<Future<?>> futures = new ArrayList<>(); | final List<Future<?>> futures = new ArrayList<>(); | ||||
WxMaXmlOutMessage result = null; | |||||
for (final WxMaMessageRouterRule rule : matchRules) { | for (final WxMaMessageRouterRule rule : matchRules) { | ||||
// 返回最后一个非异步的rule的执行结果 | // 返回最后一个非异步的rule的执行结果 | ||||
if (rule.isAsync()) { | if (rule.isAsync()) { | ||||
@@ -131,7 +119,7 @@ public class WxMaMessageRouter { | |||||
}) | }) | ||||
); | ); | ||||
} else { | } else { | ||||
rule.service(wxMessage, context, this.wxMaService, this.sessionManager, this.exceptionHandler); | |||||
result = rule.service(wxMessage, context, this.wxMaService, this.sessionManager, this.exceptionHandler); | |||||
// 在同步操作结束,session访问结束 | // 在同步操作结束,session访问结束 | ||||
this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUser()); | this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUser()); | ||||
sessionEndAccess(wxMessage); | sessionEndAccess(wxMessage); | ||||
@@ -155,18 +143,17 @@ public class WxMaMessageRouter { | |||||
} | } | ||||
}); | }); | ||||
} | } | ||||
return result; | |||||
} | } | ||||
public void route(final WxMaMessage wxMessage) { | |||||
this.route(wxMessage, new HashMap<String, Object>(2)); | |||||
public WxMaXmlOutMessage route(final WxMaMessage wxMessage) { | |||||
return this.route(wxMessage, new HashMap<String, Object>(2)); | |||||
} | } | ||||
/** | /** | ||||
* 对session的访问结束 | |||||
* 对session的访问结束. | |||||
*/ | */ | ||||
protected void sessionEndAccess(WxMaMessage wxMessage) { | |||||
private void sessionEndAccess(WxMaMessage wxMessage) { | |||||
InternalSession session = ((InternalSessionManager) this.sessionManager).findSession(wxMessage.getFromUser()); | InternalSession session = ((InternalSessionManager) this.sessionManager).findSession(wxMessage.getFromUser()); | ||||
if (session != null) { | if (session != null) { | ||||
session.endAccess(); | session.endAccess(); | ||||
@@ -16,7 +16,6 @@ import java.util.regex.Pattern; | |||||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||||
*/ | */ | ||||
public class WxMaMessageRouterRule { | public class WxMaMessageRouterRule { | ||||
private final WxMaMessageRouter routerBuilder; | private final WxMaMessageRouter routerBuilder; | ||||
private boolean async = true; | private boolean async = true; | ||||
@@ -46,7 +45,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 设置是否异步执行,默认是true | |||||
* 设置是否异步执行,默认是true. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule async(boolean async) { | public WxMaMessageRouterRule async(boolean async) { | ||||
this.async = async; | this.async = async; | ||||
@@ -54,7 +53,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 如果msgType等于某值 | |||||
* 如果msgType等于某值. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule msgType(String msgType) { | public WxMaMessageRouterRule msgType(String msgType) { | ||||
this.msgType = msgType; | this.msgType = msgType; | ||||
@@ -62,7 +61,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 如果event等于某值 | |||||
* 如果event等于某值. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule event(String event) { | public WxMaMessageRouterRule event(String event) { | ||||
this.event = event; | this.event = event; | ||||
@@ -70,7 +69,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 如果eventKey等于某值 | |||||
* 如果eventKey等于某值. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule eventKey(String eventKey) { | public WxMaMessageRouterRule eventKey(String eventKey) { | ||||
this.eventKey = eventKey; | this.eventKey = eventKey; | ||||
@@ -78,7 +77,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 如果content等于某值 | |||||
* 如果content等于某值. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule content(String content) { | public WxMaMessageRouterRule content(String content) { | ||||
this.content = content; | this.content = content; | ||||
@@ -86,7 +85,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 如果content匹配该正则表达式 | |||||
* 如果content匹配该正则表达式. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule rContent(String regex) { | public WxMaMessageRouterRule rContent(String regex) { | ||||
this.rContent = regex; | this.rContent = regex; | ||||
@@ -94,7 +93,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 如果fromUser等于某值 | |||||
* 如果fromUser等于某值. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule fromUser(String fromUser) { | public WxMaMessageRouterRule fromUser(String fromUser) { | ||||
this.fromUser = fromUser; | this.fromUser = fromUser; | ||||
@@ -102,7 +101,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候 | |||||
* 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule matcher(WxMaMessageMatcher matcher) { | public WxMaMessageRouterRule matcher(WxMaMessageMatcher matcher) { | ||||
this.matcher = matcher; | this.matcher = matcher; | ||||
@@ -110,14 +109,14 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 设置微信消息拦截器 | |||||
* 设置微信消息拦截器. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule interceptor(WxMaMessageInterceptor interceptor) { | public WxMaMessageRouterRule interceptor(WxMaMessageInterceptor interceptor) { | ||||
return interceptor(interceptor, (WxMaMessageInterceptor[]) null); | return interceptor(interceptor, (WxMaMessageInterceptor[]) null); | ||||
} | } | ||||
/** | /** | ||||
* 设置微信消息拦截器 | |||||
* 设置微信消息拦截器. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule interceptor(WxMaMessageInterceptor interceptor, WxMaMessageInterceptor... otherInterceptors) { | public WxMaMessageRouterRule interceptor(WxMaMessageInterceptor interceptor, WxMaMessageInterceptor... otherInterceptors) { | ||||
this.interceptors.add(interceptor); | this.interceptors.add(interceptor); | ||||
@@ -130,14 +129,14 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 设置微信消息处理器 | |||||
* 设置微信消息处理器. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule handler(WxMaMessageHandler handler) { | public WxMaMessageRouterRule handler(WxMaMessageHandler handler) { | ||||
return handler(handler, (WxMaMessageHandler[]) null); | return handler(handler, (WxMaMessageHandler[]) null); | ||||
} | } | ||||
/** | /** | ||||
* 设置微信消息处理器 | |||||
* 设置微信消息处理器. | |||||
*/ | */ | ||||
public WxMaMessageRouterRule handler(WxMaMessageHandler handler, WxMaMessageHandler... otherHandlers) { | public WxMaMessageRouterRule handler(WxMaMessageHandler handler, WxMaMessageHandler... otherHandlers) { | ||||
this.handlers.add(handler); | this.handlers.add(handler); | ||||
@@ -150,7 +149,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则 | |||||
* 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则. | |||||
*/ | */ | ||||
public WxMaMessageRouter end() { | public WxMaMessageRouter end() { | ||||
this.routerBuilder.getRules().add(this); | this.routerBuilder.getRules().add(this); | ||||
@@ -158,7 +157,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 规则结束,但是消息还会进入其他规则 | |||||
* 规则结束,但是消息还会进入其他规则. | |||||
*/ | */ | ||||
public WxMaMessageRouter next() { | public WxMaMessageRouter next() { | ||||
this.reEnter = true; | this.reEnter = true; | ||||
@@ -166,7 +165,7 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 将微信自定义的事件修正为不区分大小写, | |||||
* 将微信自定义的事件修正为不区分大小写. | |||||
* 比如框架定义的事件常量为click,但微信传递过来的却是CLICK | * 比如框架定义的事件常量为click,但微信传递过来的却是CLICK | ||||
*/ | */ | ||||
protected boolean test(WxMaMessage wxMessage) { | protected boolean test(WxMaMessage wxMessage) { | ||||
@@ -188,9 +187,9 @@ public class WxMaMessageRouterRule { | |||||
} | } | ||||
/** | /** | ||||
* 处理微信推送过来的消息 | |||||
* 处理微信推送过来的消息. | |||||
*/ | */ | ||||
protected void service(WxMaMessage wxMessage, | |||||
protected WxMaXmlOutMessage service(WxMaMessage wxMessage, | |||||
Map<String, Object> context, | Map<String, Object> context, | ||||
WxMaService wxMaService, | WxMaService wxMaService, | ||||
WxSessionManager sessionManager, | WxSessionManager sessionManager, | ||||
@@ -199,11 +198,12 @@ public class WxMaMessageRouterRule { | |||||
context = new HashMap<>(16); | context = new HashMap<>(16); | ||||
} | } | ||||
WxMaXmlOutMessage outMessage = null; | |||||
try { | try { | ||||
// 如果拦截器不通过 | // 如果拦截器不通过 | ||||
for (WxMaMessageInterceptor interceptor : this.interceptors) { | for (WxMaMessageInterceptor interceptor : this.interceptors) { | ||||
if (!interceptor.intercept(wxMessage, context, wxMaService, sessionManager)) { | if (!interceptor.intercept(wxMessage, context, wxMaService, sessionManager)) { | ||||
return; | |||||
return null; | |||||
} | } | ||||
} | } | ||||
@@ -213,11 +213,13 @@ public class WxMaMessageRouterRule { | |||||
if (handler == null) { | if (handler == null) { | ||||
continue; | continue; | ||||
} | } | ||||
handler.handle(wxMessage, context, wxMaService, sessionManager); | |||||
outMessage = handler.handle(wxMessage, context, wxMaService, sessionManager); | |||||
} | } | ||||
} catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
exceptionHandler.handle(e); | exceptionHandler.handle(e); | ||||
} | } | ||||
return outMessage; | |||||
} | } | ||||
public WxMaMessageRouter getRouterBuilder() { | public WxMaMessageRouter getRouterBuilder() { | ||||
@@ -0,0 +1,60 @@ | |||||
package cn.binarywang.wx.miniapp.message; | |||||
import cn.binarywang.wx.miniapp.config.WxMaConfig; | |||||
import cn.binarywang.wx.miniapp.util.crypt.WxMaCryptUtils; | |||||
import cn.binarywang.wx.miniapp.util.xml.XStreamTransformer; | |||||
import com.thoughtworks.xstream.annotations.XStreamAlias; | |||||
import com.thoughtworks.xstream.annotations.XStreamConverter; | |||||
import lombok.AllArgsConstructor; | |||||
import lombok.Builder; | |||||
import lombok.Data; | |||||
import lombok.NoArgsConstructor; | |||||
import lombok.experimental.Accessors; | |||||
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter; | |||||
import java.io.Serializable; | |||||
/** | |||||
* 微信小程序输出给微信服务器的消息. | |||||
* | |||||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | |||||
* @date 2019-06-22 | |||||
*/ | |||||
@Data | |||||
@XStreamAlias("xml") | |||||
@Accessors(chain = true) | |||||
@Builder | |||||
@AllArgsConstructor | |||||
@NoArgsConstructor | |||||
public class WxMaXmlOutMessage implements Serializable { | |||||
private static final long serialVersionUID = 4241135225946919153L; | |||||
@XStreamAlias("ToUserName") | |||||
@XStreamConverter(value = XStreamCDataConverter.class) | |||||
protected String toUserName; | |||||
@XStreamAlias("FromUserName") | |||||
@XStreamConverter(value = XStreamCDataConverter.class) | |||||
protected String fromUserName; | |||||
@XStreamAlias("CreateTime") | |||||
protected Long createTime; | |||||
@XStreamAlias("MsgType") | |||||
@XStreamConverter(value = XStreamCDataConverter.class) | |||||
protected String msgType; | |||||
@SuppressWarnings("unchecked") | |||||
public String toXml() { | |||||
return XStreamTransformer.toXml((Class<WxMaXmlOutMessage>) this.getClass(), this); | |||||
} | |||||
/** | |||||
* 转换成加密的xml格式. | |||||
*/ | |||||
public String toEncryptedXml(WxMaConfig config) { | |||||
String plainXml = toXml(); | |||||
WxMaCryptUtils pc = new WxMaCryptUtils(config); | |||||
return pc.encrypt(plainXml); | |||||
} | |||||
} |
@@ -1,15 +1,5 @@ | |||||
package cn.binarywang.wx.miniapp.demo; | package cn.binarywang.wx.miniapp.demo; | ||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.util.Map; | |||||
import java.util.concurrent.locks.ReentrantLock; | |||||
import org.eclipse.jetty.server.Server; | |||||
import org.eclipse.jetty.servlet.ServletHandler; | |||||
import org.eclipse.jetty.servlet.ServletHolder; | |||||
import cn.binarywang.wx.miniapp.api.WxMaService; | import cn.binarywang.wx.miniapp.api.WxMaService; | ||||
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; | import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl; | ||||
import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; | import cn.binarywang.wx.miniapp.bean.WxMaKefuMessage; | ||||
@@ -20,11 +10,23 @@ import cn.binarywang.wx.miniapp.config.WxMaConfig; | |||||
import cn.binarywang.wx.miniapp.constant.WxMaConstants; | import cn.binarywang.wx.miniapp.constant.WxMaConstants; | ||||
import cn.binarywang.wx.miniapp.message.WxMaMessageHandler; | import cn.binarywang.wx.miniapp.message.WxMaMessageHandler; | ||||
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; | import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; | ||||
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage; | |||||
import cn.binarywang.wx.miniapp.test.TestConfig; | import cn.binarywang.wx.miniapp.test.TestConfig; | ||||
import com.google.common.collect.Lists; | import com.google.common.collect.Lists; | ||||
import me.chanjar.weixin.common.api.WxConsts; | |||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; | ||||
import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
import org.eclipse.jetty.server.Server; | |||||
import org.eclipse.jetty.servlet.ServletHandler; | |||||
import org.eclipse.jetty.servlet.ServletHolder; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.util.Calendar; | |||||
import java.util.Map; | |||||
import java.util.concurrent.locks.ReentrantLock; | |||||
/** | /** | ||||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||||
@@ -33,29 +35,31 @@ public class WxMaDemoServer { | |||||
private static final WxMaMessageHandler logHandler = new WxMaMessageHandler() { | private static final WxMaMessageHandler logHandler = new WxMaMessageHandler() { | ||||
@Override | @Override | ||||
public void handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException { | |||||
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException { | |||||
System.out.println("收到消息:" + wxMessage.toString()); | System.out.println("收到消息:" + wxMessage.toString()); | ||||
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson()) | service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("收到信息为:" + wxMessage.toJson()) | ||||
.toUser(wxMessage.getFromUser()).build()); | .toUser(wxMessage.getFromUser()).build()); | ||||
return null; | |||||
} | } | ||||
}; | }; | ||||
private static final WxMaMessageHandler textHandler = new WxMaMessageHandler() { | private static final WxMaMessageHandler textHandler = new WxMaMessageHandler() { | ||||
@Override | @Override | ||||
public void handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) | |||||
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) | |||||
throws WxErrorException { | throws WxErrorException { | ||||
service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息") | service.getMsgService().sendKefuMsg(WxMaKefuMessage.newTextBuilder().content("回复文本消息") | ||||
.toUser(wxMessage.getFromUser()).build()); | .toUser(wxMessage.getFromUser()).build()); | ||||
return null; | |||||
} | } | ||||
}; | }; | ||||
private static final WxMaMessageHandler picHandler = new WxMaMessageHandler() { | private static final WxMaMessageHandler picHandler = new WxMaMessageHandler() { | ||||
@Override | @Override | ||||
public void handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException { | |||||
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException { | |||||
try { | try { | ||||
WxMediaUploadResult uploadResult = service.getMediaService() | WxMediaUploadResult uploadResult = service.getMediaService() | ||||
.uploadMedia(WxMaConstants.MediaType.IMAGE, "png", | .uploadMedia(WxMaConstants.MediaType.IMAGE, "png", | ||||
@@ -69,13 +73,14 @@ public class WxMaDemoServer { | |||||
} catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} | } | ||||
return null; | |||||
} | } | ||||
}; | }; | ||||
private static final WxMaMessageHandler qrcodeHandler = new WxMaMessageHandler() { | private static final WxMaMessageHandler qrcodeHandler = new WxMaMessageHandler() { | ||||
@Override | @Override | ||||
public void handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException { | |||||
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) throws WxErrorException { | |||||
try { | try { | ||||
final File file = service.getQrcodeService().createQrcode("123", 430); | final File file = service.getQrcodeService().createQrcode("123", 430); | ||||
WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia(WxMaConstants.MediaType.IMAGE, file); | WxMediaUploadResult uploadResult = service.getMediaService().uploadMedia(WxMaConstants.MediaType.IMAGE, file); | ||||
@@ -88,13 +93,14 @@ public class WxMaDemoServer { | |||||
} catch (WxErrorException e) { | } catch (WxErrorException e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} | } | ||||
return null; | |||||
} | } | ||||
}; | }; | ||||
private static final WxMaMessageHandler templateMsgHandler = new WxMaMessageHandler() { | private static final WxMaMessageHandler templateMsgHandler = new WxMaMessageHandler() { | ||||
@Override | @Override | ||||
public void handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) | |||||
public WxMaXmlOutMessage handle(WxMaMessage wxMessage, Map<String, Object> context, | |||||
WxMaService service, WxSessionManager sessionManager) | |||||
throws WxErrorException { | throws WxErrorException { | ||||
service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder() | service.getMsgService().sendTemplateMsg(WxMaTemplateMessage.builder() | ||||
.templateId(templateId).data(Lists.newArrayList( | .templateId(templateId).data(Lists.newArrayList( | ||||
@@ -102,10 +108,22 @@ public class WxMaDemoServer { | |||||
.toUser(wxMessage.getFromUser()) | .toUser(wxMessage.getFromUser()) | ||||
.formId("自己替换可用的formid") | .formId("自己替换可用的formid") | ||||
.build()); | .build()); | ||||
return null; | |||||
} | } | ||||
}; | }; | ||||
private static final WxMaMessageHandler customerServiceMessageHandler = new WxMaMessageHandler() { | |||||
@Override | |||||
public WxMaXmlOutMessage handle(WxMaMessage message, Map<String, Object> context, WxMaService service, WxSessionManager sessionManager) { | |||||
return new WxMaXmlOutMessage() | |||||
.setMsgType(WxConsts.XmlMsgType.TRANSFER_CUSTOMER_SERVICE) | |||||
.setFromUserName(message.getToUser()) | |||||
.setCreateTime(Calendar.getInstance().getTimeInMillis() / 1000) | |||||
.setToUserName(message.getFromUser()); | |||||
} | |||||
}; | |||||
private static WxMaConfig config; | private static WxMaConfig config; | ||||
private static WxMaService service; | private static WxMaService service; | ||||
private static WxMaMessageRouter router; | private static WxMaMessageRouter router; | ||||
@@ -142,7 +160,8 @@ public class WxMaDemoServer { | |||||
.rule().async(false).content("模板").handler(templateMsgHandler).end() | .rule().async(false).content("模板").handler(templateMsgHandler).end() | ||||
.rule().async(false).content("文本").handler(textHandler).end() | .rule().async(false).content("文本").handler(textHandler).end() | ||||
.rule().async(false).content("图片").handler(picHandler).end() | .rule().async(false).content("图片").handler(picHandler).end() | ||||
.rule().async(false).content("二维码").handler(qrcodeHandler).end(); | |||||
.rule().async(false).content("二维码").handler(qrcodeHandler).end() | |||||
.rule().async(false).content("转发客服").handler(customerServiceMessageHandler).end(); | |||||
} catch (IOException e) { | } catch (IOException e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
} | } | ||||
@@ -5,6 +5,8 @@ import cn.binarywang.wx.miniapp.bean.WxMaMessage; | |||||
import cn.binarywang.wx.miniapp.config.WxMaConfig; | import cn.binarywang.wx.miniapp.config.WxMaConfig; | ||||
import cn.binarywang.wx.miniapp.constant.WxMaConstants; | import cn.binarywang.wx.miniapp.constant.WxMaConstants; | ||||
import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; | import cn.binarywang.wx.miniapp.message.WxMaMessageRouter; | ||||
import cn.binarywang.wx.miniapp.message.WxMaXmlOutMessage; | |||||
import lombok.AllArgsConstructor; | |||||
import org.apache.commons.io.IOUtils; | import org.apache.commons.io.IOUtils; | ||||
import org.apache.commons.lang3.StringUtils; | import org.apache.commons.lang3.StringUtils; | ||||
@@ -18,19 +20,13 @@ import java.util.Objects; | |||||
/** | /** | ||||
* @author <a href="https://github.com/binarywang">Binary Wang</a> | * @author <a href="https://github.com/binarywang">Binary Wang</a> | ||||
*/ | */ | ||||
@AllArgsConstructor | |||||
public class WxMaPortalServlet extends HttpServlet { | public class WxMaPortalServlet extends HttpServlet { | ||||
private static final long serialVersionUID = 1L; | private static final long serialVersionUID = 1L; | ||||
private WxMaConfig wxMaConfig; | |||||
private WxMaService wxMaService; | |||||
private WxMaMessageRouter wxMaMessageRouter; | |||||
WxMaPortalServlet(WxMaConfig wxMaConfig, WxMaService wxMaService, | |||||
WxMaMessageRouter wxMaMessageRouter) { | |||||
this.wxMaConfig = wxMaConfig; | |||||
this.wxMaService = wxMaService; | |||||
this.wxMaMessageRouter = wxMaMessageRouter; | |||||
} | |||||
private WxMaConfig config; | |||||
private WxMaService service; | |||||
private WxMaMessageRouter messageRouter; | |||||
@Override | @Override | ||||
protected void service(HttpServletRequest request, HttpServletResponse response) | protected void service(HttpServletRequest request, HttpServletResponse response) | ||||
@@ -42,7 +38,7 @@ public class WxMaPortalServlet extends HttpServlet { | |||||
String nonce = request.getParameter("nonce"); | String nonce = request.getParameter("nonce"); | ||||
String timestamp = request.getParameter("timestamp"); | String timestamp = request.getParameter("timestamp"); | ||||
if (!this.wxMaService.checkSignature(timestamp, nonce, signature)) { | |||||
if (!this.service.checkSignature(timestamp, nonce, signature)) { | |||||
// 消息签名不正确,说明不是公众平台发过来的消息 | // 消息签名不正确,说明不是公众平台发过来的消息 | ||||
response.getWriter().println("非法请求"); | response.getWriter().println("非法请求"); | ||||
return; | return; | ||||
@@ -56,7 +52,7 @@ public class WxMaPortalServlet extends HttpServlet { | |||||
} | } | ||||
String encryptType = request.getParameter("encrypt_type"); | String encryptType = request.getParameter("encrypt_type"); | ||||
final boolean isJson = Objects.equals(this.wxMaConfig.getMsgDataFormat(), WxMaConstants.MsgDataFormat.JSON); | |||||
final boolean isJson = Objects.equals(this.config.getMsgDataFormat(), WxMaConstants.MsgDataFormat.JSON); | |||||
if (StringUtils.isBlank(encryptType)) { | if (StringUtils.isBlank(encryptType)) { | ||||
// 明文传输的消息 | // 明文传输的消息 | ||||
WxMaMessage inMessage; | WxMaMessage inMessage; | ||||
@@ -66,7 +62,12 @@ public class WxMaPortalServlet extends HttpServlet { | |||||
inMessage = WxMaMessage.fromXml(request.getInputStream()); | inMessage = WxMaMessage.fromXml(request.getInputStream()); | ||||
} | } | ||||
this.wxMaMessageRouter.route(inMessage); | |||||
final WxMaXmlOutMessage outMessage = this.messageRouter.route(inMessage); | |||||
if (outMessage != null) { | |||||
response.getWriter().write(outMessage.toXml()); | |||||
return; | |||||
} | |||||
response.getWriter().write("success"); | response.getWriter().write("success"); | ||||
return; | return; | ||||
} | } | ||||
@@ -76,12 +77,16 @@ public class WxMaPortalServlet extends HttpServlet { | |||||
String msgSignature = request.getParameter("msg_signature"); | String msgSignature = request.getParameter("msg_signature"); | ||||
WxMaMessage inMessage; | WxMaMessage inMessage; | ||||
if (isJson) { | if (isJson) { | ||||
inMessage = WxMaMessage.fromEncryptedJson(request.getInputStream(), this.wxMaConfig); | |||||
inMessage = WxMaMessage.fromEncryptedJson(request.getInputStream(), this.config); | |||||
} else {//xml | } else {//xml | ||||
inMessage = WxMaMessage.fromEncryptedXml(request.getInputStream(), this.wxMaConfig, timestamp, nonce, msgSignature); | |||||
inMessage = WxMaMessage.fromEncryptedXml(request.getInputStream(), this.config, timestamp, nonce, msgSignature); | |||||
} | } | ||||
this.wxMaMessageRouter.route(inMessage); | |||||
final WxMaXmlOutMessage outMessage = this.messageRouter.route(inMessage); | |||||
if (outMessage != null) { | |||||
response.getWriter().write(outMessage.toEncryptedXml(this.config)); | |||||
return; | |||||
} | |||||
response.getWriter().write("success"); | response.getWriter().write("success"); | ||||
return; | return; | ||||
} | } | ||||