forked from chanjarster/weixin-java-tools
-
-
Notifications
You must be signed in to change notification settings - Fork 8.5k
CP_微信消息路由器
Binary Wang edited this page Jan 30, 2024
·
8 revisions
微信推送给公众号的消息类型很多,而公众号也需要针对用户不同的输入做出不同的反应。
如果使用if ... else ...
来实现的话非常难以维护,这时可以使用WxMessageRouter
来对消息进行路由。
WxMessageRouter
支持从5个角度对消息进行匹配,然后交给事先指定的WxMessageHandler
:
- agentId
- msgType
- event
- eventKey
- content
在整个应用程序中,WxMessageRouter
应该是单例的。
WxCpMessageRouter router = new WxCpMessageRouter();
router
.rule()
.agentId(1)
.handler(hander)
.end()
// 4个条件必须全部匹配的路由规则
.rule()
.msgType(WxConsts.XML_MSG_TEXT)
.event(WxConsts.EVT_SUBSCRIBE)
.eventKey("EVENT_KEY")
.content("CONTENT")
.rContent("content正则表达式")
.handler(handler)
.end()
// 只匹配1个条件的路由规则
.rule()
.msgType("MSG_TYPE")
.handler(handler)
.end()
// 消息经过这个规则后可以继续尝试后面的路由规则
.rule()
.msgType("MSG_TYPE")
.handler(handler)
.next()
// 另一个同步处理的路由规则
.rule()
.async(false)
.msgType("MSG_TYPE")
.handler(handler)
.end()
// 添加了拦截器的路由规则
.rule()
.msgType("MSG_TYPE")
.interceptor(interceptor)
.handler(handler)
.end()
// 兜底路由规则,一般放到最后
.rule()
.handler(handler)
.end()
;
// 将WxXmlMessage交给消息路由器
HttpServletRequest request =...;
WxCpXmlMessage message =...;
router.route(message);
- 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理
- 规则的结束必须用
Rule.end()
或者Rule.next()
,否则不会生效 - 具体使用可以看源代码中的
WxCpMessageRouterTest
单元测试,或者查看Javadoc
关于如何构造WxCpXmlMessage
请看同步回复消息。
public interface WxCpMessageHandler {
/**
*
* @param wxMessage
* @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个
* @param wxCpService
* @return xml格式的消息,如果在异步规则里处理的话,可以返回null
*/
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage,
Map<String, Object> context,
WxCpService wxCpService,
WxSessionManager sessionManager);
}
关于WxSessionManager
请看WxSession的使用。
public interface WxCpMessageInterceptor {
/**
* 拦截微信消息
* @param wxMessage
* @param context 上下文,如果handler或interceptor之间有信息要传递,可以用这个
* @param wxCpService
* @return true代表OK,false代表不OK
*/
public boolean intercept(WxCpXmlMessage wxMessage,
Map<String, Object> context,
WxCpService wxCpService,
WxSessionManager sessionManager);
}
关于WxSessionManager
请看WxSession的使用。
String encType = request.getParameter("encrypt_type");
String nonce = request.getParameter("nonce");
String timestamp = request.getParameter("timestamp");
String msgSignature = request.getParameter("msg_signature");
String signature = request.getParameter("signature");
String openid = request.getParameter("openid");
log.info("接收微信请求:[openid=[{}], [openid=[{}],[signature=[{}], encType=[{}], msgSignature=[{}],"
+ " timestamp=[{}], nonce=[{}], requestBody=[{}] ",
appid, openid, signature, encType, msgSignature, timestamp, nonce, requestBody);
// 请求里面没有对应信息。 // if (!this.wxMpService.switchover(appid)) { //appid // throw new IllegalArgumentException(String.format("未找到对应appid=[%s]的配置,请核实!", appid)); // }
if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
throw new IllegalArgumentException("非法请求,可能属于伪造的请求!");
}
return ResponseEntity.ok("");