mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2026-03-10 00:13:40 +08:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
239ef054ec | ||
|
|
15aff7f93c | ||
|
|
1819b0e492 | ||
|
|
97dff44b3e | ||
|
|
b8dd3662cd | ||
|
|
2c218d85c2 | ||
|
|
10f841c591 | ||
|
|
037c326ebf | ||
|
|
b43a62c3a6 | ||
|
|
b921490253 | ||
|
|
8ec76bda59 | ||
|
|
4b8aa69cca | ||
|
|
36dad7b8d0 | ||
|
|
b00bf13bd7 | ||
|
|
ffe63e71eb | ||
|
|
3fbb260bf7 | ||
|
|
bf4c825279 | ||
|
|
84a3683c35 | ||
|
|
4d6321e69b | ||
|
|
7c3113eec8 | ||
|
|
3003f68cf4 |
20
README.md
20
README.md
@@ -3,12 +3,6 @@ weixin-java-tools
|
||||
|
||||
微信公众号、企业号Java SDK。
|
||||
|
||||
从``1.0.3``开始,本项目拆分成3个部分:
|
||||
|
||||
1. weixin-java-common,公共lib
|
||||
2. weixin-java-cp,企业号SDK
|
||||
3. weixin-java-mp,公众号(订阅号、服务号)SDK
|
||||
|
||||
详细文档请看 [wiki](https://github.com/chanjarster/weixin-java-tools/wiki)。
|
||||
|
||||
## Quick Start
|
||||
@@ -19,7 +13,7 @@ weixin-java-tools
|
||||
<dependency>
|
||||
<groupId>me.chanjar</groupId>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
<version>1.0.7</version>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -29,7 +23,7 @@ weixin-java-tools
|
||||
<dependency>
|
||||
<groupId>me.chanjar</groupId>
|
||||
<artifactId>weixin-java-cp</artifactId>
|
||||
<version>1.0.7</version>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
@@ -45,12 +39,4 @@ weixin-java-tools
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
```
|
||||
|
||||
## 升级指南
|
||||
|
||||
原``1.0.0~1.0.2``版本用户无法平滑升级到``1.0.3``。需要做的是:
|
||||
|
||||
1. maven引用``weixin-java-mp``
|
||||
2. 将原来``WxXXX``的类,改成``WxMpXXX``
|
||||
3. ``WxConsts``, ``WxError``, ``WxMediaUploadResult``, ``WxAccessToken``, ``WxMenu``, ``WxErrorException``不要改
|
||||
```
|
||||
4
pom.xml
4
pom.xml
@@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>me.chanjar</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>WeiXin Java Tools - Parent</name>
|
||||
<description>微信公众号、企业号上级POM</description>
|
||||
@@ -217,7 +217,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<version>2.5.1</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>me.chanjar</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-common</artifactId>
|
||||
|
||||
@@ -89,6 +89,7 @@ public class WxConsts {
|
||||
public static final String EVT_PIC_WEIXIN = "pic_weixin";
|
||||
public static final String EVT_LOCATION_SELECT = "location_select";
|
||||
public static final String EVT_TEMPLATESENDJOBFINISH = "TEMPLATESENDJOBFINISH";
|
||||
public static final String EVT_ENTER_AGENT = "enter_agent";
|
||||
|
||||
///////////////////////
|
||||
// 上传多媒体文件的类型
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package me.chanjar.weixin.common.util;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class LogExceptionHandler implements WxErrorExceptionHandler {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(WxErrorExceptionHandler.class);
|
||||
|
||||
@Override
|
||||
public void handle(WxErrorException e) {
|
||||
|
||||
log.error("Error happens", e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package me.chanjar.weixin.common.util;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
|
||||
/**
|
||||
* WxErrorException处理器
|
||||
*/
|
||||
public interface WxErrorExceptionHandler {
|
||||
|
||||
public void handle(WxErrorException e);
|
||||
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>me.chanjar</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>weixin-java-cp</artifactId>
|
||||
|
||||
@@ -9,21 +9,21 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
*/
|
||||
public class WxCpInMemoryConfigStorage implements WxCpConfigStorage {
|
||||
|
||||
protected String corpId;
|
||||
protected String corpSecret;
|
||||
protected volatile String corpId;
|
||||
protected volatile String corpSecret;
|
||||
|
||||
protected String token;
|
||||
protected String accessToken;
|
||||
protected String aesKey;
|
||||
protected String agentId;
|
||||
protected long expiresTime;
|
||||
protected volatile String token;
|
||||
protected volatile String accessToken;
|
||||
protected volatile String aesKey;
|
||||
protected volatile String agentId;
|
||||
protected volatile long expiresTime;
|
||||
|
||||
protected String oauth2redirectUri;
|
||||
protected volatile String oauth2redirectUri;
|
||||
|
||||
protected String http_proxy_host;
|
||||
protected int http_proxy_port;
|
||||
protected String http_proxy_username;
|
||||
protected String http_proxy_password;
|
||||
protected volatile String http_proxy_host;
|
||||
protected volatile int http_proxy_port;
|
||||
protected volatile String http_proxy_username;
|
||||
protected volatile String http_proxy_password;
|
||||
|
||||
public String getAccessToken() {
|
||||
return this.accessToken;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.chanjar.weixin.cp.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSession;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
|
||||
@@ -24,6 +25,6 @@ public interface WxCpMessageHandler {
|
||||
public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage,
|
||||
Map<String, Object> context,
|
||||
WxCpService wxCpService,
|
||||
WxSessionManager sessionManager);
|
||||
WxSessionManager sessionManager) throws WxErrorException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.chanjar.weixin.cp.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
|
||||
|
||||
@@ -24,6 +25,6 @@ public interface WxCpMessageInterceptor {
|
||||
public boolean intercept(WxCpXmlMessage wxMessage,
|
||||
Map<String, Object> context,
|
||||
WxCpService wxCpService,
|
||||
WxSessionManager sessionManager);
|
||||
WxSessionManager sessionManager) throws WxErrorException;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.chanjar.weixin.cp.api;
|
||||
|
||||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
|
||||
|
||||
/**
|
||||
* 消息匹配器,用在消息路由的时候
|
||||
*/
|
||||
public interface WxCpMessageMatcher {
|
||||
|
||||
/**
|
||||
* 消息是否匹配某种模式
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
public boolean match(WxCpXmlMessage message);
|
||||
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
package me.chanjar.weixin.cp.api;
|
||||
|
||||
import me.chanjar.weixin.common.session.*;
|
||||
import me.chanjar.weixin.common.session.InternalSession;
|
||||
import me.chanjar.weixin.common.session.InternalSessionManager;
|
||||
import me.chanjar.weixin.common.session.StandardSessionManager;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.common.util.LogExceptionHandler;
|
||||
import me.chanjar.weixin.common.util.WxErrorExceptionHandler;
|
||||
import me.chanjar.weixin.common.util.WxMessageDuplicateChecker;
|
||||
import me.chanjar.weixin.common.util.WxMessageInMemoryDuplicateChecker;
|
||||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
|
||||
@@ -9,14 +14,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -24,8 +26,8 @@ import java.util.regex.Pattern;
|
||||
*
|
||||
* 说明:
|
||||
* 1. 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理
|
||||
* 2. 默认情况下消息只会被处理一次,除非使用 {@link Rule#next()}
|
||||
* 3. 规则的结束必须用{@link Rule#end()}或者{@link Rule#next()},否则不会生效
|
||||
* 2. 默认情况下消息只会被处理一次,除非使用 {@link WxCpMessageRouterRule#next()}
|
||||
* 3. 规则的结束必须用{@link WxCpMessageRouterRule#end()}或者{@link WxCpMessageRouterRule#next()},否则不会生效
|
||||
*
|
||||
* 使用方法:
|
||||
* WxCpMessageRouter router = new WxCpMessageRouter();
|
||||
@@ -52,7 +54,7 @@ public class WxCpMessageRouter {
|
||||
|
||||
private static final int DEFAULT_THREAD_POOL_SIZE = 100;
|
||||
|
||||
private final List<Rule> rules = new ArrayList<Rule>();
|
||||
private final List<WxCpMessageRouterRule> rules = new ArrayList<WxCpMessageRouterRule>();
|
||||
|
||||
private final WxCpService wxCpService;
|
||||
|
||||
@@ -62,11 +64,14 @@ public class WxCpMessageRouter {
|
||||
|
||||
private WxSessionManager sessionManager;
|
||||
|
||||
private WxErrorExceptionHandler exceptionHandler;
|
||||
|
||||
public WxCpMessageRouter(WxCpService wxCpService) {
|
||||
this.wxCpService = wxCpService;
|
||||
this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
|
||||
this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker();
|
||||
this.sessionManager = new StandardSessionManager();
|
||||
this.exceptionHandler = new LogExceptionHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +99,7 @@ public class WxCpMessageRouter {
|
||||
/**
|
||||
* <pre>
|
||||
* 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager}
|
||||
* 如果不调用该方法,默认使用 {@linke SessionManagerImpl}
|
||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.session.StandardSessionManager}
|
||||
* </pre>
|
||||
* @param sessionManager
|
||||
*/
|
||||
@@ -102,12 +107,27 @@ public class WxCpMessageRouter {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 设置自定义的{@link me.chanjar.weixin.common.util.WxErrorExceptionHandler}
|
||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.util.LogExceptionHandler}
|
||||
* </pre>
|
||||
* @param exceptionHandler
|
||||
*/
|
||||
public void setExceptionHandler(WxErrorExceptionHandler exceptionHandler) {
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
List<WxCpMessageRouterRule> getRules() {
|
||||
return this.rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始一个新的Route规则
|
||||
* @return
|
||||
*/
|
||||
public Rule rule() {
|
||||
return new Rule(this, wxCpService, sessionManager);
|
||||
public WxCpMessageRouterRule rule() {
|
||||
return new WxCpMessageRouterRule(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,13 +139,13 @@ public class WxCpMessageRouter {
|
||||
// 如果是重复消息,那么就不做处理
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<Rule> matchRules = new ArrayList<Rule>();
|
||||
|
||||
final List<WxCpMessageRouterRule> matchRules = new ArrayList<WxCpMessageRouterRule>();
|
||||
// 收集匹配的规则
|
||||
for (final Rule rule : rules) {
|
||||
for (final WxCpMessageRouterRule rule : rules) {
|
||||
if (rule.test(wxMessage)) {
|
||||
matchRules.add(rule);
|
||||
if(!rule.reEnter) {
|
||||
if(!rule.isReEnter()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -137,18 +157,18 @@ public class WxCpMessageRouter {
|
||||
|
||||
WxCpXmlOutMessage res = null;
|
||||
final List<Future> futures = new ArrayList<Future>();
|
||||
for (final Rule rule : matchRules) {
|
||||
for (final WxCpMessageRouterRule rule : matchRules) {
|
||||
// 返回最后一个非异步的rule的执行结果
|
||||
if(rule.async) {
|
||||
if(rule.isAsync()) {
|
||||
futures.add(
|
||||
executorService.submit(new Runnable() {
|
||||
public void run() {
|
||||
rule.service(wxMessage);
|
||||
rule.service(wxMessage, wxCpService, sessionManager, exceptionHandler);
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
res = rule.service(wxMessage);
|
||||
res = rule.service(wxMessage, wxCpService, sessionManager, exceptionHandler);
|
||||
// 在同步操作结束,session访问结束
|
||||
log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName());
|
||||
sessionEndAccess(wxMessage);
|
||||
@@ -181,7 +201,11 @@ public class WxCpMessageRouter {
|
||||
|
||||
String messageId = "";
|
||||
if (wxMessage.getMsgId() == null) {
|
||||
messageId = wxMessage.getFromUserName() + "-" + String.valueOf(wxMessage.getCreateTime());
|
||||
messageId = String.valueOf(wxMessage.getCreateTime())
|
||||
+ "-" +String.valueOf(wxMessage.getAgentId() == null ? "" : wxMessage.getAgentId())
|
||||
+ "-" + wxMessage.getFromUserName()
|
||||
+ "-" + String.valueOf(wxMessage.getEventKey() == null ? "" : wxMessage.getEvent());
|
||||
;
|
||||
} else {
|
||||
messageId = String.valueOf(wxMessage.getMsgId());
|
||||
}
|
||||
@@ -206,231 +230,5 @@ public class WxCpMessageRouter {
|
||||
|
||||
}
|
||||
|
||||
public static class Rule {
|
||||
|
||||
private final WxCpMessageRouter routerBuilder;
|
||||
|
||||
private final WxCpService wxCpService;
|
||||
|
||||
private final WxSessionManager sessionManager;
|
||||
|
||||
private boolean async = true;
|
||||
|
||||
private String fromUser;
|
||||
|
||||
private String msgType;
|
||||
|
||||
private String event;
|
||||
|
||||
private String eventKey;
|
||||
|
||||
private String content;
|
||||
|
||||
private String rContent;
|
||||
|
||||
private boolean reEnter = false;
|
||||
|
||||
private Integer agentId;
|
||||
|
||||
private List<WxCpMessageHandler> handlers = new ArrayList<WxCpMessageHandler>();
|
||||
|
||||
private List<WxCpMessageInterceptor> interceptors = new ArrayList<WxCpMessageInterceptor>();
|
||||
|
||||
protected Rule(WxCpMessageRouter routerBuilder, WxCpService wxCpService, WxSessionManager sessionManager) {
|
||||
this.routerBuilder = routerBuilder;
|
||||
this.wxCpService = wxCpService;
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否异步执行,默认是true
|
||||
* @param async
|
||||
* @return
|
||||
*/
|
||||
public Rule async(boolean async) {
|
||||
this.async = async;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果agentId匹配
|
||||
* @param agentId
|
||||
* @return
|
||||
*/
|
||||
public Rule agentId(Integer agentId) {
|
||||
this.agentId = agentId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果msgType等于某值
|
||||
* @param msgType
|
||||
* @return
|
||||
*/
|
||||
public Rule msgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果event等于某值
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
public Rule event(String event) {
|
||||
this.event = event;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果eventKey等于某值
|
||||
* @param eventKey
|
||||
* @return
|
||||
*/
|
||||
public Rule eventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content等于某值
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public Rule content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content匹配该正则表达式
|
||||
* @param regex
|
||||
* @return
|
||||
*/
|
||||
public Rule rContent(String regex) {
|
||||
this.rContent = regex;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果fromUser等于某值
|
||||
* @param fromUser
|
||||
* @return
|
||||
*/
|
||||
public Rule fromUser(String fromUser) {
|
||||
this.fromUser = fromUser;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
* @param interceptor
|
||||
* @return
|
||||
*/
|
||||
public Rule interceptor(WxCpMessageInterceptor interceptor) {
|
||||
return interceptor(interceptor, (WxCpMessageInterceptor[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
* @param interceptor
|
||||
* @param otherInterceptors
|
||||
* @return
|
||||
*/
|
||||
public Rule interceptor(WxCpMessageInterceptor interceptor, WxCpMessageInterceptor... otherInterceptors) {
|
||||
this.interceptors.add(interceptor);
|
||||
if (otherInterceptors != null && otherInterceptors.length > 0) {
|
||||
for (WxCpMessageInterceptor i : otherInterceptors) {
|
||||
this.interceptors.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
* @param handler
|
||||
* @return
|
||||
*/
|
||||
public Rule handler(WxCpMessageHandler handler) {
|
||||
return handler(handler, (WxCpMessageHandler[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
* @param handler
|
||||
* @param otherHandlers
|
||||
* @return
|
||||
*/
|
||||
public Rule handler(WxCpMessageHandler handler, WxCpMessageHandler... otherHandlers) {
|
||||
this.handlers.add(handler);
|
||||
if (otherHandlers != null && otherHandlers.length > 0) {
|
||||
for (WxCpMessageHandler i : otherHandlers) {
|
||||
this.handlers.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouter end() {
|
||||
this.routerBuilder.rules.add(this);
|
||||
return this.routerBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,但是消息还会进入其他规则
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouter next() {
|
||||
this.reEnter = true;
|
||||
return end();
|
||||
}
|
||||
|
||||
protected boolean test(WxCpXmlMessage wxMessage) {
|
||||
return
|
||||
(this.fromUser == null || this.fromUser.equals(wxMessage.getFromUserName()))
|
||||
&&
|
||||
(this.agentId == null || this.agentId.equals(wxMessage.getAgentId()))
|
||||
&&
|
||||
(this.msgType == null || this.msgType.equals(wxMessage.getMsgType()))
|
||||
&&
|
||||
(this.event == null || this.event.equals(wxMessage.getEvent()))
|
||||
&&
|
||||
(this.eventKey == null || this.eventKey.equals(wxMessage.getEventKey()))
|
||||
&&
|
||||
(this.content == null || this.content.equals(wxMessage.getContent() == null ? null : wxMessage.getContent().trim()))
|
||||
&&
|
||||
(this.rContent == null || Pattern.matches(this.rContent, wxMessage.getContent() == null ? "" : wxMessage.getContent().trim()))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信推送过来的消息
|
||||
* @param wxMessage
|
||||
* @return true 代表继续执行别的router,false 代表停止执行别的router
|
||||
*/
|
||||
protected WxCpXmlOutMessage service(WxCpXmlMessage wxMessage) {
|
||||
Map<String, Object> context = new HashMap<String, Object>();
|
||||
// 如果拦截器不通过
|
||||
for (WxCpMessageInterceptor interceptor : this.interceptors) {
|
||||
if (!interceptor.intercept(wxMessage, context, wxCpService, sessionManager)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 交给handler处理
|
||||
WxCpXmlOutMessage res = null;
|
||||
for (WxCpMessageHandler handler : this.handlers) {
|
||||
// 返回最后handler的结果
|
||||
res = handler.handle(wxMessage, context, wxCpService, sessionManager);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
package me.chanjar.weixin.cp.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.common.util.WxErrorExceptionHandler;
|
||||
import me.chanjar.weixin.cp.bean.WxCpXmlMessage;
|
||||
import me.chanjar.weixin.cp.bean.WxCpXmlOutMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class WxCpMessageRouterRule {
|
||||
|
||||
private final WxCpMessageRouter routerBuilder;
|
||||
|
||||
private boolean async = true;
|
||||
|
||||
private String fromUser;
|
||||
|
||||
private String msgType;
|
||||
|
||||
private String event;
|
||||
|
||||
private String eventKey;
|
||||
|
||||
private String content;
|
||||
|
||||
private String rContent;
|
||||
|
||||
private WxCpMessageMatcher matcher;
|
||||
|
||||
private boolean reEnter = false;
|
||||
|
||||
private Integer agentId;
|
||||
|
||||
private List<WxCpMessageHandler> handlers = new ArrayList<WxCpMessageHandler>();
|
||||
|
||||
private List<WxCpMessageInterceptor> interceptors = new ArrayList<WxCpMessageInterceptor>();
|
||||
|
||||
protected WxCpMessageRouterRule(WxCpMessageRouter routerBuilder) {
|
||||
this.routerBuilder = routerBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否异步执行,默认是true
|
||||
*
|
||||
* @param async
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule async(boolean async) {
|
||||
this.async = async;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果agentId匹配
|
||||
*
|
||||
* @param agentId
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule agentId(Integer agentId) {
|
||||
this.agentId = agentId;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果msgType等于某值
|
||||
*
|
||||
* @param msgType
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule msgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果event等于某值
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule event(String event) {
|
||||
this.event = event;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果eventKey等于某值
|
||||
*
|
||||
* @param eventKey
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule eventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content等于某值
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content匹配该正则表达式
|
||||
*
|
||||
* @param regex
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule rContent(String regex) {
|
||||
this.rContent = regex;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果fromUser等于某值
|
||||
*
|
||||
* @param fromUser
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule fromUser(String fromUser) {
|
||||
this.fromUser = fromUser;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候
|
||||
*
|
||||
* @param matcher
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule matcher(WxCpMessageMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
*
|
||||
* @param interceptor
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule interceptor(WxCpMessageInterceptor interceptor) {
|
||||
return interceptor(interceptor, (WxCpMessageInterceptor[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
*
|
||||
* @param interceptor
|
||||
* @param otherInterceptors
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule interceptor(WxCpMessageInterceptor interceptor, WxCpMessageInterceptor... otherInterceptors) {
|
||||
this.interceptors.add(interceptor);
|
||||
if (otherInterceptors != null && otherInterceptors.length > 0) {
|
||||
for (WxCpMessageInterceptor i : otherInterceptors) {
|
||||
this.interceptors.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
*
|
||||
* @param handler
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule handler(WxCpMessageHandler handler) {
|
||||
return handler(handler, (WxCpMessageHandler[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
*
|
||||
* @param handler
|
||||
* @param otherHandlers
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouterRule handler(WxCpMessageHandler handler, WxCpMessageHandler... otherHandlers) {
|
||||
this.handlers.add(handler);
|
||||
if (otherHandlers != null && otherHandlers.length > 0) {
|
||||
for (WxCpMessageHandler i : otherHandlers) {
|
||||
this.handlers.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouter end() {
|
||||
this.routerBuilder.getRules().add(this);
|
||||
return this.routerBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,但是消息还会进入其他规则
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WxCpMessageRouter next() {
|
||||
this.reEnter = true;
|
||||
return end();
|
||||
}
|
||||
|
||||
protected boolean test(WxCpXmlMessage wxMessage) {
|
||||
return
|
||||
(this.fromUser == null || this.fromUser.equals(wxMessage.getFromUserName()))
|
||||
&&
|
||||
(this.agentId == null || this.agentId.equals(wxMessage.getAgentId()))
|
||||
&&
|
||||
(this.msgType == null || this.msgType.equals(wxMessage.getMsgType()))
|
||||
&&
|
||||
(this.event == null || this.event.equals(wxMessage.getEvent()))
|
||||
&&
|
||||
(this.eventKey == null || this.eventKey.equals(wxMessage.getEventKey()))
|
||||
&&
|
||||
(this.content == null || this.content
|
||||
.equals(wxMessage.getContent() == null ? null : wxMessage.getContent().trim()))
|
||||
&&
|
||||
(this.rContent == null || Pattern
|
||||
.matches(this.rContent, wxMessage.getContent() == null ? "" : wxMessage.getContent().trim()))
|
||||
&&
|
||||
(this.matcher == null || this.matcher.match(wxMessage))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信推送过来的消息
|
||||
*
|
||||
* @param wxMessage
|
||||
* @return true 代表继续执行别的router,false 代表停止执行别的router
|
||||
*/
|
||||
protected WxCpXmlOutMessage service(WxCpXmlMessage wxMessage,
|
||||
WxCpService wxCpService,
|
||||
WxSessionManager sessionManager,
|
||||
WxErrorExceptionHandler exceptionHandler) {
|
||||
|
||||
try {
|
||||
|
||||
Map<String, Object> context = new HashMap<String, Object>();
|
||||
// 如果拦截器不通过
|
||||
for (WxCpMessageInterceptor interceptor : this.interceptors) {
|
||||
if (!interceptor.intercept(wxMessage, context, wxCpService, sessionManager)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 交给handler处理
|
||||
WxCpXmlOutMessage res = null;
|
||||
for (WxCpMessageHandler handler : this.handlers) {
|
||||
// 返回最后handler的结果
|
||||
res = handler.handle(wxMessage, context, wxCpService, sessionManager);
|
||||
}
|
||||
return res;
|
||||
|
||||
} catch (WxErrorException e) {
|
||||
exceptionHandler.handle(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public void setFromUser(String fromUser) {
|
||||
this.fromUser = fromUser;
|
||||
}
|
||||
|
||||
public void setMsgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public void setEvent(String event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public void setEventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public void setrContent(String rContent) {
|
||||
this.rContent = rContent;
|
||||
}
|
||||
|
||||
public void setMatcher(WxCpMessageMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
public void setAgentId(Integer agentId) {
|
||||
this.agentId = agentId;
|
||||
}
|
||||
|
||||
public void setHandlers(List<WxCpMessageHandler> handlers) {
|
||||
this.handlers = handlers;
|
||||
}
|
||||
|
||||
public void setInterceptors(List<WxCpMessageInterceptor> interceptors) {
|
||||
this.interceptors = interceptors;
|
||||
}
|
||||
|
||||
public boolean isAsync() {
|
||||
return async;
|
||||
}
|
||||
|
||||
public void setAsync(boolean async) {
|
||||
this.async = async;
|
||||
}
|
||||
|
||||
public boolean isReEnter() {
|
||||
return reEnter;
|
||||
}
|
||||
|
||||
public void setReEnter(boolean reEnter) {
|
||||
this.reEnter = reEnter;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,7 +33,7 @@ public interface WxCpService {
|
||||
* @param data 微信传输过来的数据,有可能是echoStr,有可能是xml消息
|
||||
* @return
|
||||
*/
|
||||
public boolean checkSignature(String msgSignature, String timestamp, String nonce, String data);
|
||||
boolean checkSignature(String msgSignature, String timestamp, String nonce, String data);
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -43,7 +43,7 @@ public interface WxCpService {
|
||||
*
|
||||
* @param userId
|
||||
*/
|
||||
public void userAuthenticated(String userId) throws WxErrorException;
|
||||
void userAuthenticated(String userId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取access_token, 不强制刷新access_token
|
||||
@@ -51,7 +51,7 @@ public interface WxCpService {
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public String getAccessToken() throws WxErrorException;
|
||||
String getAccessToken() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -65,7 +65,7 @@ public interface WxCpService {
|
||||
* @return
|
||||
* @throws me.chanjar.weixin.common.exception.WxErrorException
|
||||
*/
|
||||
public String getAccessToken(boolean forceRefresh) throws WxErrorException;
|
||||
String getAccessToken(boolean forceRefresh) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -83,7 +83,7 @@ public interface WxCpService {
|
||||
* @param inputStream 输入流
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream)
|
||||
WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream)
|
||||
throws WxErrorException, IOException;
|
||||
|
||||
/**
|
||||
@@ -92,7 +92,7 @@ public interface WxCpService {
|
||||
* @throws WxErrorException
|
||||
* @see #mediaUpload(String, String, InputStream)
|
||||
*/
|
||||
public WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException;
|
||||
WxMediaUploadResult mediaUpload(String mediaType, File file) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -105,7 +105,7 @@ public interface WxCpService {
|
||||
* @throws WxErrorException
|
||||
* @params media_id
|
||||
*/
|
||||
public File mediaDownload(String media_id) throws WxErrorException;
|
||||
File mediaDownload(String media_id) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -116,7 +116,7 @@ public interface WxCpService {
|
||||
* @param message
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void messageSend(WxCpMessage message) throws WxErrorException;
|
||||
void messageSend(WxCpMessage message) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -127,7 +127,7 @@ public interface WxCpService {
|
||||
* @param menu
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void menuCreate(WxMenu menu) throws WxErrorException;
|
||||
void menuCreate(WxMenu menu) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -137,7 +137,7 @@ public interface WxCpService {
|
||||
*
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void menuDelete() throws WxErrorException;
|
||||
void menuDelete() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -148,7 +148,7 @@ public interface WxCpService {
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public WxMenu menuGet() throws WxErrorException;
|
||||
WxMenu menuGet() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -161,7 +161,7 @@ public interface WxCpService {
|
||||
* @return 部门id
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public Integer departCreate(WxCpDepart depart) throws WxErrorException;
|
||||
Integer departCreate(WxCpDepart depart) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -172,7 +172,7 @@ public interface WxCpService {
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public List<WxCpDepart> departGet() throws WxErrorException;
|
||||
List<WxCpDepart> departGet() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -184,7 +184,7 @@ public interface WxCpService {
|
||||
* @param group 要更新的group,group的id,name必须设置
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void departUpdate(WxCpDepart group) throws WxErrorException;
|
||||
void departUpdate(WxCpDepart group) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -194,10 +194,28 @@ public interface WxCpService {
|
||||
* @param departId
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void departDelete(Integer departId) throws WxErrorException;
|
||||
void departDelete(Integer departId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 获取部门成员(详情)
|
||||
*
|
||||
* http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98.28.E8.AF.A6.E6.83.85.29
|
||||
* </pre>
|
||||
* @param departId 必填。部门id
|
||||
* @param fetchChild 非必填。1/0:是否递归获取子部门下面的成员
|
||||
* @param status 非必填。0获取全部员工,1获取已关注成员列表,2获取禁用成员列表,4获取未关注成员列表。status可叠加
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
List<WxCpUser> userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 获取部门成员
|
||||
*
|
||||
* http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E8.8E.B7.E5.8F.96.E9.83.A8.E9.97.A8.E6.88.90.E5.91.98
|
||||
* </pre>
|
||||
*
|
||||
* @param departId 必填。部门id
|
||||
* @param fetchChild 非必填。1/0:是否递归获取子部门下面的成员
|
||||
@@ -205,7 +223,7 @@ public interface WxCpService {
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public List<WxCpUser> departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException;
|
||||
List<WxCpUser> departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 新建用户
|
||||
@@ -213,7 +231,7 @@ public interface WxCpService {
|
||||
* @param user
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void userCreate(WxCpUser user) throws WxErrorException;
|
||||
void userCreate(WxCpUser user) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 更新用户
|
||||
@@ -221,7 +239,7 @@ public interface WxCpService {
|
||||
* @param user
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void userUpdate(WxCpUser user) throws WxErrorException;
|
||||
void userUpdate(WxCpUser user) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 删除用户
|
||||
@@ -229,7 +247,18 @@ public interface WxCpService {
|
||||
* @param userid
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public void userDelete(String userid) throws WxErrorException;
|
||||
void userDelete(String userid) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 批量删除成员
|
||||
*
|
||||
* http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E6.89.B9.E9.87.8F.E5.88.A0.E9.99.A4.E6.88.90.E5.91.98
|
||||
* </pre>
|
||||
* @param userids 员工UserID列表。对应管理端的帐号
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
void userDelete(String[] userids) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取用户
|
||||
@@ -238,7 +267,7 @@ public interface WxCpService {
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public WxCpUser userGet(String userid) throws WxErrorException;
|
||||
WxCpUser userGet(String userid) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 创建标签
|
||||
@@ -246,7 +275,7 @@ public interface WxCpService {
|
||||
* @param tagName
|
||||
* @return
|
||||
*/
|
||||
public String tagCreate(String tagName) throws WxErrorException;
|
||||
String tagCreate(String tagName) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 更新标签
|
||||
@@ -254,21 +283,21 @@ public interface WxCpService {
|
||||
* @param tagId
|
||||
* @param tagName
|
||||
*/
|
||||
public void tagUpdate(String tagId, String tagName) throws WxErrorException;
|
||||
void tagUpdate(String tagId, String tagName) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 删除标签
|
||||
*
|
||||
* @param tagId
|
||||
*/
|
||||
public void tagDelete(String tagId) throws WxErrorException;
|
||||
void tagDelete(String tagId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获得标签列表
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public List<WxCpTag> tagGet() throws WxErrorException;
|
||||
List<WxCpTag> tagGet() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 获取标签成员
|
||||
@@ -276,7 +305,7 @@ public interface WxCpService {
|
||||
* @param tagId
|
||||
* @return
|
||||
*/
|
||||
public List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException;
|
||||
List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 增加标签成员
|
||||
@@ -284,7 +313,7 @@ public interface WxCpService {
|
||||
* @param tagId
|
||||
* @param userIds
|
||||
*/
|
||||
public void tagAddUsers(String tagId, List<String> userIds) throws WxErrorException;
|
||||
void tagAddUsers(String tagId, List<String> userIds) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -294,7 +323,7 @@ public interface WxCpService {
|
||||
* @param state
|
||||
* @return code
|
||||
*/
|
||||
public String oauth2buildAuthorizationUrl(String state);
|
||||
String oauth2buildAuthorizationUrl(String state);
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -305,7 +334,7 @@ public interface WxCpService {
|
||||
* @param code
|
||||
* @return [userid, deviceid]
|
||||
*/
|
||||
public String[] oauth2getUserInfo(String code) throws WxErrorException;
|
||||
String[] oauth2getUserInfo(String code) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 移除标签成员
|
||||
@@ -313,7 +342,29 @@ public interface WxCpService {
|
||||
* @param tagId
|
||||
* @param userIds
|
||||
*/
|
||||
public void tagRemoveUsers(String tagId, List<String> userIds) throws WxErrorException;
|
||||
void tagRemoveUsers(String tagId, List<String> userIds) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 邀请成员关注
|
||||
* http://qydev.weixin.qq.com/wiki/index.php?title=管理成员#.E9.82.80.E8.AF.B7.E6.88.90.E5.91.98.E5.85.B3.E6.B3.A8
|
||||
* </pre>
|
||||
* @param userId 用户的userid
|
||||
* @param inviteTips 推送到微信上的提示语(只有认证号可以使用)。当使用微信推送时,该字段默认为“请关注XXX企业号”,邮件邀请时,该字段无效。
|
||||
* @return 1:微信邀请 2.邮件邀请
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
int invite(String userId, String inviteTips) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 获取微信服务器的ip段
|
||||
* http://qydev.weixin.qq.com/wiki/index.php?title=回调模式#.E8.8E.B7.E5.8F.96.E5.BE.AE.E4.BF.A1.E6.9C.8D.E5.8A.A1.E5.99.A8.E7.9A.84ip.E6.AE.B5
|
||||
* </pre>
|
||||
* @return { "ip_list": ["101.226.103.*", "101.226.62.*"] }
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
String[] getCallbackIp() throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 当本Service没有实现某个API的时候,可以用这个,针对所有微信API中的GET请求
|
||||
@@ -347,14 +398,14 @@ public interface WxCpService {
|
||||
* @return
|
||||
* @throws WxErrorException
|
||||
*/
|
||||
public <T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException;
|
||||
<T, E> T execute(RequestExecutor<T, E> executor, String uri, E data) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* 注入 {@link WxCpConfigStorage} 的实现
|
||||
*
|
||||
* @param wxConfigProvider
|
||||
*/
|
||||
public void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider);
|
||||
void setWxCpConfigStorage(WxCpConfigStorage wxConfigProvider);
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
|
||||
@@ -78,7 +78,7 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
|
||||
public void userAuthenticated(String userId) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/authsucc?userid=" + userId;
|
||||
execute(new SimpleGetRequestExecutor(), url, null);
|
||||
get(url, null);
|
||||
}
|
||||
|
||||
public String getAccessToken() throws WxErrorException {
|
||||
@@ -123,23 +123,23 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
|
||||
public void messageSend(WxCpMessage message) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/message/send";
|
||||
execute(new SimplePostRequestExecutor(), url, message.toJson());
|
||||
post(url, message.toJson());
|
||||
}
|
||||
|
||||
public void menuCreate(WxMenu menu) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/create?agentid=" + wxCpConfigStorage.getAgentId();
|
||||
execute(new SimplePostRequestExecutor(), url, menu.toJson());
|
||||
post(url, menu.toJson());
|
||||
}
|
||||
|
||||
public void menuDelete() throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/delete?agentid=" + wxCpConfigStorage.getAgentId();
|
||||
execute(new SimpleGetRequestExecutor(), url, null);
|
||||
get(url, null);
|
||||
}
|
||||
|
||||
public WxMenu menuGet() throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/menu/get?agentid=" + wxCpConfigStorage.getAgentId();
|
||||
try {
|
||||
String resultContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||
String resultContent = get(url, null);
|
||||
return WxMenu.fromJson(resultContent);
|
||||
} catch (WxErrorException e) {
|
||||
// 46003 不存在的菜单数据
|
||||
@@ -178,17 +178,17 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
|
||||
public void departUpdate(WxCpDepart group) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/update";
|
||||
execute(new SimplePostRequestExecutor(), url, group.toJson());
|
||||
post(url, group.toJson());
|
||||
}
|
||||
|
||||
public void departDelete(Integer departId) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/delete?id=" + departId;
|
||||
execute(new SimpleGetRequestExecutor(), url, null);
|
||||
get(url, null);
|
||||
}
|
||||
|
||||
public List<WxCpDepart> departGet() throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/department/list";
|
||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||
String responseContent = get(url, null);
|
||||
/*
|
||||
* 操蛋的微信API,创建时返回的是 { group : { id : ..., name : ...} }
|
||||
* 查询时返回的是 { groups : [ { id : ..., name : ..., count : ... }, ... ] }
|
||||
@@ -204,28 +204,62 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
@Override
|
||||
public void userCreate(WxCpUser user) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/create";
|
||||
execute(new SimplePostRequestExecutor(), url, user.toJson());
|
||||
post(url, user.toJson());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userUpdate(WxCpUser user) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/update";
|
||||
execute(new SimplePostRequestExecutor(), url, user.toJson());
|
||||
post(url, user.toJson());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userDelete(String userid) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/delete?userid=" + userid;
|
||||
execute(new SimpleGetRequestExecutor(), url, null);
|
||||
get(url, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void userDelete(String[] userids) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/batchdelete";
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
JsonArray jsonArray = new JsonArray();
|
||||
for (int i = 0; i < userids.length; i++) {
|
||||
jsonArray.add(new JsonPrimitive(userids[i]));
|
||||
}
|
||||
jsonObject.add("useridlist", jsonArray);
|
||||
post(url, jsonObject.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxCpUser userGet(String userid) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/get?userid=" + userid;
|
||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||
String responseContent = get(url, null);
|
||||
return WxCpUser.fromJson(responseContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxCpUser> userList(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/list?department_id=" + departId;
|
||||
String params = "";
|
||||
if (fetchChild != null) {
|
||||
params += "&fetch_child=" + (fetchChild ? "1" : "0");
|
||||
}
|
||||
if (status != null) {
|
||||
params += "&status=" + status;
|
||||
} else {
|
||||
params += "&status=0";
|
||||
}
|
||||
|
||||
String responseContent = get(url, params);
|
||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
|
||||
return WxCpGsonBuilder.INSTANCE.create()
|
||||
.fromJson(
|
||||
tmpJsonElement.getAsJsonObject().get("userlist"),
|
||||
new TypeToken<List<WxCpUser>>() { }.getType()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxCpUser> departGetUsers(Integer departId, Boolean fetchChild, Integer status) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?department_id=" + departId;
|
||||
@@ -239,7 +273,7 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
params += "&status=0";
|
||||
}
|
||||
|
||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, params);
|
||||
String responseContent = get(url, params);
|
||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
|
||||
return WxCpGsonBuilder.INSTANCE.create()
|
||||
.fromJson(
|
||||
@@ -253,7 +287,7 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/create";
|
||||
JsonObject o = new JsonObject();
|
||||
o.addProperty("tagname", tagName);
|
||||
String responseContent = execute(new SimplePostRequestExecutor(), url, o.toString());
|
||||
String responseContent = post(url, o.toString());
|
||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
|
||||
return tmpJsonElement.getAsJsonObject().get("tagid").getAsString();
|
||||
}
|
||||
@@ -264,19 +298,19 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
JsonObject o = new JsonObject();
|
||||
o.addProperty("tagid", tagId);
|
||||
o.addProperty("tagname", tagName);
|
||||
execute(new SimplePostRequestExecutor(), url, o.toString());
|
||||
post(url, o.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tagDelete(String tagId) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/delete?tagid=" + tagId;
|
||||
execute(new SimpleGetRequestExecutor(), url, null);
|
||||
get(url, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<WxCpTag> tagGet() throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/list";
|
||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||
String responseContent = get(url, null);
|
||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
|
||||
return WxCpGsonBuilder.INSTANCE.create()
|
||||
.fromJson(
|
||||
@@ -288,7 +322,7 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
@Override
|
||||
public List<WxCpUser> tagGetUsers(String tagId) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/tag/get?tagid=" + tagId;
|
||||
String responseContent = execute(new SimpleGetRequestExecutor(), url, null);
|
||||
String responseContent = get(url, null);
|
||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
|
||||
return WxCpGsonBuilder.INSTANCE.create()
|
||||
.fromJson(
|
||||
@@ -307,7 +341,7 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
jsonArray.add(new JsonPrimitive(userId));
|
||||
}
|
||||
jsonObject.add("userlist", jsonArray);
|
||||
execute(new SimplePostRequestExecutor(), url, jsonObject.toString());
|
||||
post(url, jsonObject.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -320,7 +354,7 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
jsonArray.add(new JsonPrimitive(userId));
|
||||
}
|
||||
jsonObject.add("userlist", jsonArray);
|
||||
execute(new SimplePostRequestExecutor(), url, jsonObject.toString());
|
||||
post(url, jsonObject.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -357,6 +391,31 @@ public class WxCpServiceImpl implements WxCpService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int invite(String userId, String inviteTips) throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/invite/send";
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("userid", userId);
|
||||
if (StringUtils.isNotEmpty(inviteTips)) {
|
||||
jsonObject.addProperty("invite_tips", inviteTips);
|
||||
}
|
||||
String responseContent = post(url, jsonObject.toString());
|
||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
|
||||
return tmpJsonElement.getAsJsonObject().get("type").getAsInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getCallbackIp() throws WxErrorException {
|
||||
String url = "https://qyapi.weixin.qq.com/cgi-bin/getcallbackip";
|
||||
String responseContent = get(url, null);
|
||||
JsonElement tmpJsonElement = Streams.parse(new JsonReader(new StringReader(responseContent)));
|
||||
JsonArray jsonArray = tmpJsonElement.getAsJsonObject().get("ip_list").getAsJsonArray();
|
||||
String[] ips = new String[jsonArray.size()];
|
||||
for(int i = 0; i < jsonArray.size(); i++) {
|
||||
ips[i] = jsonArray.get(i).getAsString();
|
||||
}
|
||||
return ips;
|
||||
}
|
||||
|
||||
public String get(String url, String queryParam) throws WxErrorException {
|
||||
return execute(new SimpleGetRequestExecutor(), url, queryParam);
|
||||
|
||||
@@ -489,6 +489,45 @@ public class WxCpXmlMessage {
|
||||
this.sendLocationInfo = sendLocationInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WxCpXmlMessage{" +
|
||||
"agentId=" + agentId +
|
||||
", toUserName='" + toUserName + '\'' +
|
||||
", fromUserName='" + fromUserName + '\'' +
|
||||
", createTime=" + createTime +
|
||||
", msgType='" + msgType + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", msgId=" + msgId +
|
||||
", picUrl='" + picUrl + '\'' +
|
||||
", mediaId='" + mediaId + '\'' +
|
||||
", format='" + format + '\'' +
|
||||
", thumbMediaId='" + thumbMediaId + '\'' +
|
||||
", locationX=" + locationX +
|
||||
", locationY=" + locationY +
|
||||
", scale=" + scale +
|
||||
", label='" + label + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", url='" + url + '\'' +
|
||||
", event='" + event + '\'' +
|
||||
", eventKey='" + eventKey + '\'' +
|
||||
", ticket='" + ticket + '\'' +
|
||||
", latitude=" + latitude +
|
||||
", longitude=" + longitude +
|
||||
", precision=" + precision +
|
||||
", recognition='" + recognition + '\'' +
|
||||
", status='" + status + '\'' +
|
||||
", totalCount=" + totalCount +
|
||||
", filterCount=" + filterCount +
|
||||
", sentCount=" + sentCount +
|
||||
", errorCount=" + errorCount +
|
||||
", scanCodeInfo=" + scanCodeInfo +
|
||||
", sendPicsInfo=" + sendPicsInfo +
|
||||
", sendLocationInfo=" + sendLocationInfo +
|
||||
'}';
|
||||
}
|
||||
|
||||
@XStreamAlias("ScanCodeInfo")
|
||||
public static class ScanCodeInfo {
|
||||
|
||||
|
||||
@@ -42,6 +42,12 @@ public class WxCpMessageRouterTest {
|
||||
.rule().async(async).eventKey("KEY_1").handler(new WxEchoCpMessageHandler(sb, "KEY_1")).end()
|
||||
.rule().async(async).content("CONTENT_1").handler(new WxEchoCpMessageHandler(sb, "CONTENT_1")).end()
|
||||
.rule().async(async).rContent(".*bc.*").handler(new WxEchoCpMessageHandler(sb, "abcd")).end()
|
||||
.rule().async(async).matcher(new WxCpMessageMatcher() {
|
||||
@Override
|
||||
public boolean match(WxCpXmlMessage message) {
|
||||
return "strangeformat".equals(message.getFormat());
|
||||
}
|
||||
}).handler(new WxEchoCpMessageHandler(sb, "matcher")).end()
|
||||
.rule().async(async).handler(new WxEchoCpMessageHandler(sb, "ALL")).end();
|
||||
;
|
||||
}
|
||||
@@ -92,6 +98,7 @@ public class WxCpMessageRouterTest {
|
||||
|
||||
Thread.sleep(1000l * 2);
|
||||
}
|
||||
|
||||
@DataProvider(name="messages-1")
|
||||
public Object[][] messages2() {
|
||||
WxCpXmlMessage message1 = new WxCpXmlMessage();
|
||||
@@ -109,9 +116,12 @@ public class WxCpMessageRouterTest {
|
||||
WxCpXmlMessage message5 = new WxCpXmlMessage();
|
||||
message5.setContent("BLA");
|
||||
|
||||
WxCpXmlMessage message6 = new WxCpXmlMessage();
|
||||
WxCpXmlMessage message6 = new WxCpXmlMessage();
|
||||
message6.setContent("abcd");
|
||||
|
||||
|
||||
WxCpXmlMessage message7 = new WxCpXmlMessage();
|
||||
message7.setFormat("strangeformat");
|
||||
|
||||
WxCpXmlMessage c2 = new WxCpXmlMessage();
|
||||
c2.setMsgType(WxConsts.XML_MSG_TEXT);
|
||||
c2.setEvent(WxConsts.EVT_CLICK);
|
||||
@@ -126,7 +136,8 @@ public class WxCpMessageRouterTest {
|
||||
c4.setEvent(WxConsts.EVT_CLICK);
|
||||
c4.setEventKey("KEY_1");
|
||||
c4.setContent("CONTENT_1");
|
||||
|
||||
|
||||
|
||||
return new Object[][] {
|
||||
new Object[] { message1, WxConsts.XML_MSG_TEXT + "," },
|
||||
new Object[] { message2, WxConsts.EVT_CLICK + "," },
|
||||
@@ -134,6 +145,7 @@ public class WxCpMessageRouterTest {
|
||||
new Object[] { message4, "CONTENT_1," },
|
||||
new Object[] { message5, "ALL," },
|
||||
new Object[] { message6, "abcd," },
|
||||
new Object[] { message7, "matcher," },
|
||||
new Object[] { c2, "COMBINE_2," },
|
||||
new Object[] { c3, "COMBINE_3," },
|
||||
new Object[] { c4, "COMBINE_4," }
|
||||
@@ -290,7 +302,6 @@ public class WxCpMessageRouterTest {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>me.chanjar</groupId>
|
||||
<artifactId>weixin-java-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
<artifactId>weixin-java-mp</artifactId>
|
||||
<name>WeiXin Java Tools - MP</name>
|
||||
|
||||
@@ -9,24 +9,22 @@ import me.chanjar.weixin.common.bean.WxAccessToken;
|
||||
*/
|
||||
public class WxMpInMemoryConfigStorage implements WxMpConfigStorage {
|
||||
|
||||
private static final long l = 7000 * 1000l;
|
||||
protected volatile String appId;
|
||||
protected volatile String secret;
|
||||
protected volatile String token;
|
||||
protected volatile String accessToken;
|
||||
protected volatile String aesKey;
|
||||
protected volatile long expiresTime;
|
||||
|
||||
protected String appId;
|
||||
protected String secret;
|
||||
protected String token;
|
||||
protected String accessToken;
|
||||
protected String aesKey;
|
||||
protected long expiresTime;
|
||||
protected volatile String oauth2redirectUri;
|
||||
|
||||
protected String oauth2redirectUri;
|
||||
protected volatile String http_proxy_host;
|
||||
protected volatile int http_proxy_port;
|
||||
protected volatile String http_proxy_username;
|
||||
protected volatile String http_proxy_password;
|
||||
|
||||
protected String http_proxy_host;
|
||||
protected int http_proxy_port;
|
||||
protected String http_proxy_username;
|
||||
protected String http_proxy_password;
|
||||
|
||||
protected String jsapiTicket;
|
||||
protected long jsapiTicketExpiresTime;
|
||||
protected volatile String jsapiTicket;
|
||||
protected volatile long jsapiTicketExpiresTime;
|
||||
|
||||
public String getAccessToken() {
|
||||
return this.accessToken;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.chanjar.weixin.mp.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
@@ -23,6 +24,6 @@ public interface WxMpMessageHandler {
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context,
|
||||
WxMpService wxMpService,
|
||||
WxSessionManager sessionManager);
|
||||
WxSessionManager sessionManager) throws WxErrorException;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.chanjar.weixin.mp.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
|
||||
@@ -24,6 +25,6 @@ public interface WxMpMessageInterceptor {
|
||||
public boolean intercept(WxMpXmlMessage wxMessage,
|
||||
Map<String, Object> context,
|
||||
WxMpService wxMpService,
|
||||
WxSessionManager sessionManager);
|
||||
WxSessionManager sessionManager) throws WxErrorException;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package me.chanjar.weixin.mp.api;
|
||||
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
|
||||
/**
|
||||
* 消息匹配器,用在消息路由的时候
|
||||
*/
|
||||
public interface WxMpMessageMatcher {
|
||||
|
||||
/**
|
||||
* 消息是否匹配某种模式
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
public boolean match(WxMpXmlMessage message);
|
||||
|
||||
}
|
||||
@@ -1,7 +1,11 @@
|
||||
package me.chanjar.weixin.mp.api;
|
||||
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import me.chanjar.weixin.common.session.*;
|
||||
import me.chanjar.weixin.common.session.InternalSession;
|
||||
import me.chanjar.weixin.common.session.InternalSessionManager;
|
||||
import me.chanjar.weixin.common.session.StandardSessionManager;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.common.util.LogExceptionHandler;
|
||||
import me.chanjar.weixin.common.util.WxErrorExceptionHandler;
|
||||
import me.chanjar.weixin.common.util.WxMessageDuplicateChecker;
|
||||
import me.chanjar.weixin.common.util.WxMessageInMemoryDuplicateChecker;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
@@ -10,14 +14,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
@@ -25,8 +26,8 @@ import java.util.regex.Pattern;
|
||||
*
|
||||
* 说明:
|
||||
* 1. 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理
|
||||
* 2. 默认情况下消息只会被处理一次,除非使用 {@link Rule#next()}
|
||||
* 3. 规则的结束必须用{@link Rule#end()}或者{@link Rule#next()},否则不会生效
|
||||
* 2. 默认情况下消息只会被处理一次,除非使用 {@link WxMpMessageRouterRule#next()}
|
||||
* 3. 规则的结束必须用{@link WxMpMessageRouterRule#end()}或者{@link WxMpMessageRouterRule#next()},否则不会生效
|
||||
*
|
||||
* 使用方法:
|
||||
* WxMpMessageRouter router = new WxMpMessageRouter();
|
||||
@@ -44,6 +45,8 @@ import java.util.regex.Pattern;
|
||||
* router.route(message);
|
||||
*
|
||||
* </pre>
|
||||
* @author Daniel Qian
|
||||
*
|
||||
*/
|
||||
public class WxMpMessageRouter {
|
||||
|
||||
@@ -51,7 +54,7 @@ public class WxMpMessageRouter {
|
||||
|
||||
private static final int DEFAULT_THREAD_POOL_SIZE = 100;
|
||||
|
||||
private final List<Rule> rules = new ArrayList<Rule>();
|
||||
private final List<WxMpMessageRouterRule> rules = new ArrayList<WxMpMessageRouterRule>();
|
||||
|
||||
private final WxMpService wxMpService;
|
||||
|
||||
@@ -61,11 +64,14 @@ public class WxMpMessageRouter {
|
||||
|
||||
private WxSessionManager sessionManager;
|
||||
|
||||
private WxErrorExceptionHandler exceptionHandler;
|
||||
|
||||
public WxMpMessageRouter(WxMpService wxMpService) {
|
||||
this.wxMpService = wxMpService;
|
||||
this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
|
||||
this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker();
|
||||
this.sessionManager = new StandardSessionManager();
|
||||
this.exceptionHandler = new LogExceptionHandler();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +99,7 @@ public class WxMpMessageRouter {
|
||||
/**
|
||||
* <pre>
|
||||
* 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager}
|
||||
* 如果不调用该方法,默认使用 {@linke SessionManagerImpl}
|
||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.session.StandardSessionManager}
|
||||
* </pre>
|
||||
* @param sessionManager
|
||||
*/
|
||||
@@ -101,12 +107,27 @@ public class WxMpMessageRouter {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 设置自定义的{@link me.chanjar.weixin.common.util.WxErrorExceptionHandler}
|
||||
* 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.util.LogExceptionHandler}
|
||||
* </pre>
|
||||
* @param exceptionHandler
|
||||
*/
|
||||
public void setExceptionHandler(WxErrorExceptionHandler exceptionHandler) {
|
||||
this.exceptionHandler = exceptionHandler;
|
||||
}
|
||||
|
||||
List<WxMpMessageRouterRule> getRules() {
|
||||
return this.rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始一个新的Route规则
|
||||
* @return
|
||||
*/
|
||||
public Rule rule() {
|
||||
return new Rule(this, wxMpService, sessionManager);
|
||||
public WxMpMessageRouterRule rule() {
|
||||
return new WxMpMessageRouterRule(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,12 +140,12 @@ public class WxMpMessageRouter {
|
||||
return null;
|
||||
}
|
||||
|
||||
final List<Rule> matchRules = new ArrayList<Rule>();
|
||||
final List<WxMpMessageRouterRule> matchRules = new ArrayList<WxMpMessageRouterRule>();
|
||||
// 收集匹配的规则
|
||||
for (final Rule rule : rules) {
|
||||
for (final WxMpMessageRouterRule rule : rules) {
|
||||
if (rule.test(wxMessage)) {
|
||||
matchRules.add(rule);
|
||||
if(!rule.reEnter) {
|
||||
if(!rule.isReEnter()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -136,18 +157,18 @@ public class WxMpMessageRouter {
|
||||
|
||||
WxMpXmlOutMessage res = null;
|
||||
final List<Future> futures = new ArrayList<Future>();
|
||||
for (final Rule rule : matchRules) {
|
||||
for (final WxMpMessageRouterRule rule : matchRules) {
|
||||
// 返回最后一个非异步的rule的执行结果
|
||||
if(rule.async) {
|
||||
if(rule.isAsync()) {
|
||||
futures.add(
|
||||
executorService.submit(new Runnable() {
|
||||
public void run() {
|
||||
rule.service(wxMessage);
|
||||
rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler);
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
res = rule.service(wxMessage);
|
||||
res = rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler);
|
||||
// 在同步操作结束,session访问结束
|
||||
log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName());
|
||||
sessionEndAccess(wxMessage);
|
||||
@@ -180,7 +201,10 @@ public class WxMpMessageRouter {
|
||||
|
||||
String messageId = "";
|
||||
if (wxMessage.getMsgId() == null) {
|
||||
messageId = wxMessage.getFromUserName() + "-" + String.valueOf(wxMessage.getCreateTime());
|
||||
messageId = String.valueOf(wxMessage.getCreateTime())
|
||||
+ "-" + wxMessage.getFromUserName()
|
||||
+ "-" + String.valueOf(wxMessage.getEventKey() == null ? "" : wxMessage.getEvent());
|
||||
;
|
||||
} else {
|
||||
messageId = String.valueOf(wxMessage.getMsgId());
|
||||
}
|
||||
@@ -204,218 +228,4 @@ public class WxMpMessageRouter {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Rule {
|
||||
|
||||
private final WxMpMessageRouter routerBuilder;
|
||||
|
||||
private final WxMpService wxMpService;
|
||||
|
||||
private final WxSessionManager sessionManager;
|
||||
|
||||
private boolean async = true;
|
||||
|
||||
private String fromUser;
|
||||
|
||||
private String msgType;
|
||||
|
||||
private String event;
|
||||
|
||||
private String eventKey;
|
||||
|
||||
private String content;
|
||||
|
||||
private String rContent;
|
||||
|
||||
private boolean reEnter = false;
|
||||
|
||||
private List<WxMpMessageHandler> handlers = new ArrayList<WxMpMessageHandler>();
|
||||
|
||||
private List<WxMpMessageInterceptor> interceptors = new ArrayList<WxMpMessageInterceptor>();
|
||||
|
||||
protected Rule(WxMpMessageRouter routerBuilder, WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
this.routerBuilder = routerBuilder;
|
||||
this.wxMpService = wxMpService;
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否异步执行,默认是true
|
||||
* @param async
|
||||
* @return
|
||||
*/
|
||||
public Rule async(boolean async) {
|
||||
this.async = async;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果msgType等于某值
|
||||
* @param msgType
|
||||
* @return
|
||||
*/
|
||||
public Rule msgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果event等于某值
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
public Rule event(String event) {
|
||||
this.event = event;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果eventKey等于某值
|
||||
* @param eventKey
|
||||
* @return
|
||||
*/
|
||||
public Rule eventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content等于某值
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public Rule content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content匹配该正则表达式
|
||||
* @param regex
|
||||
* @return
|
||||
*/
|
||||
public Rule rContent(String regex) {
|
||||
this.rContent = regex;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果fromUser等于某值
|
||||
* @param fromUser
|
||||
* @return
|
||||
*/
|
||||
public Rule fromUser(String fromUser) {
|
||||
this.fromUser = fromUser;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
* @param interceptor
|
||||
* @return
|
||||
*/
|
||||
public Rule interceptor(WxMpMessageInterceptor interceptor) {
|
||||
return interceptor(interceptor, (WxMpMessageInterceptor[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
* @param interceptor
|
||||
* @param otherInterceptors
|
||||
* @return
|
||||
*/
|
||||
public Rule interceptor(WxMpMessageInterceptor interceptor, WxMpMessageInterceptor... otherInterceptors) {
|
||||
this.interceptors.add(interceptor);
|
||||
if (otherInterceptors != null && otherInterceptors.length > 0) {
|
||||
for (WxMpMessageInterceptor i : otherInterceptors) {
|
||||
this.interceptors.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
* @param handler
|
||||
* @return
|
||||
*/
|
||||
public Rule handler(WxMpMessageHandler handler) {
|
||||
return handler(handler, (WxMpMessageHandler[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
* @param handler
|
||||
* @param otherHandlers
|
||||
* @return
|
||||
*/
|
||||
public Rule handler(WxMpMessageHandler handler, WxMpMessageHandler... otherHandlers) {
|
||||
this.handlers.add(handler);
|
||||
if (otherHandlers != null && otherHandlers.length > 0) {
|
||||
for (WxMpMessageHandler i : otherHandlers) {
|
||||
this.handlers.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouter end() {
|
||||
this.routerBuilder.rules.add(this);
|
||||
return this.routerBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,但是消息还会进入其他规则
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouter next() {
|
||||
this.reEnter = true;
|
||||
return end();
|
||||
}
|
||||
|
||||
protected boolean test(WxMpXmlMessage wxMessage) {
|
||||
return
|
||||
(this.fromUser == null || this.fromUser.equals(wxMessage.getFromUserName()))
|
||||
&&
|
||||
(this.msgType == null || this.msgType.equals(wxMessage.getMsgType()))
|
||||
&&
|
||||
(this.event == null || this.event.equals(wxMessage.getEvent()))
|
||||
&&
|
||||
(this.eventKey == null || this.eventKey.equals(wxMessage.getEventKey()))
|
||||
&&
|
||||
(this.content == null || this.content.equals(wxMessage.getContent() == null ? null : wxMessage.getContent().trim()))
|
||||
&&
|
||||
(this.rContent == null || Pattern.matches(this.rContent, wxMessage.getContent() == null ? "" : wxMessage.getContent().trim()))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信推送过来的消息
|
||||
* @param wxMessage
|
||||
* @return true 代表继续执行别的router,false 代表停止执行别的router
|
||||
*/
|
||||
protected WxMpXmlOutMessage service(WxMpXmlMessage wxMessage) {
|
||||
Map<String, Object> context = new HashMap<String, Object>();
|
||||
// 如果拦截器不通过
|
||||
for (WxMpMessageInterceptor interceptor : this.interceptors) {
|
||||
if (!interceptor.intercept(wxMessage, context, wxMpService, sessionManager)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 交给handler处理
|
||||
WxMpXmlOutMessage res = null;
|
||||
for (WxMpMessageHandler handler : this.handlers) {
|
||||
// 返回最后handler的结果
|
||||
res = handler.handle(wxMessage, context, wxMpService, sessionManager);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
package me.chanjar.weixin.mp.api;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.common.util.WxErrorExceptionHandler;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class WxMpMessageRouterRule {
|
||||
|
||||
private final WxMpMessageRouter routerBuilder;
|
||||
|
||||
private boolean async = true;
|
||||
|
||||
private String fromUser;
|
||||
|
||||
private String msgType;
|
||||
|
||||
private String event;
|
||||
|
||||
private String eventKey;
|
||||
|
||||
private String content;
|
||||
|
||||
private String rContent;
|
||||
|
||||
private WxMpMessageMatcher matcher;
|
||||
|
||||
private boolean reEnter = false;
|
||||
|
||||
private List<WxMpMessageHandler> handlers = new ArrayList<WxMpMessageHandler>();
|
||||
|
||||
private List<WxMpMessageInterceptor> interceptors = new ArrayList<WxMpMessageInterceptor>();
|
||||
|
||||
public WxMpMessageRouterRule(WxMpMessageRouter routerBuilder) {
|
||||
this.routerBuilder = routerBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否异步执行,默认是true
|
||||
*
|
||||
* @param async
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule async(boolean async) {
|
||||
this.async = async;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果msgType等于某值
|
||||
*
|
||||
* @param msgType
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule msgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果event等于某值
|
||||
*
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule event(String event) {
|
||||
this.event = event;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果eventKey等于某值
|
||||
*
|
||||
* @param eventKey
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule eventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content等于某值
|
||||
*
|
||||
* @param content
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule content(String content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果content匹配该正则表达式
|
||||
*
|
||||
* @param regex
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule rContent(String regex) {
|
||||
this.rContent = regex;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果fromUser等于某值
|
||||
*
|
||||
* @param fromUser
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule fromUser(String fromUser) {
|
||||
this.fromUser = fromUser;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果消息匹配某个matcher,用在用户需要自定义更复杂的匹配规则的时候
|
||||
*
|
||||
* @param matcher
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule matcher(WxMpMessageMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
*
|
||||
* @param interceptor
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor) {
|
||||
return interceptor(interceptor, (WxMpMessageInterceptor[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息拦截器
|
||||
*
|
||||
* @param interceptor
|
||||
* @param otherInterceptors
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule interceptor(WxMpMessageInterceptor interceptor, WxMpMessageInterceptor... otherInterceptors) {
|
||||
this.interceptors.add(interceptor);
|
||||
if (otherInterceptors != null && otherInterceptors.length > 0) {
|
||||
for (WxMpMessageInterceptor i : otherInterceptors) {
|
||||
this.interceptors.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
*
|
||||
* @param handler
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule handler(WxMpMessageHandler handler) {
|
||||
return handler(handler, (WxMpMessageHandler[]) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置微信消息处理器
|
||||
*
|
||||
* @param handler
|
||||
* @param otherHandlers
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouterRule handler(WxMpMessageHandler handler, WxMpMessageHandler... otherHandlers) {
|
||||
this.handlers.add(handler);
|
||||
if (otherHandlers != null && otherHandlers.length > 0) {
|
||||
for (WxMpMessageHandler i : otherHandlers) {
|
||||
this.handlers.add(i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,代表如果一个消息匹配该规则,那么它将不再会进入其他规则
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouter end() {
|
||||
this.routerBuilder.getRules().add(this);
|
||||
return this.routerBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规则结束,但是消息还会进入其他规则
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public WxMpMessageRouter next() {
|
||||
this.reEnter = true;
|
||||
return end();
|
||||
}
|
||||
|
||||
protected boolean test(WxMpXmlMessage wxMessage) {
|
||||
return
|
||||
(this.fromUser == null || this.fromUser.equals(wxMessage.getFromUserName()))
|
||||
&&
|
||||
(this.msgType == null || this.msgType.equals(wxMessage.getMsgType()))
|
||||
&&
|
||||
(this.event == null || this.event.equals(wxMessage.getEvent()))
|
||||
&&
|
||||
(this.eventKey == null || this.eventKey.equals(wxMessage.getEventKey()))
|
||||
&&
|
||||
(this.content == null || this.content
|
||||
.equals(wxMessage.getContent() == null ? null : wxMessage.getContent().trim()))
|
||||
&&
|
||||
(this.rContent == null || Pattern
|
||||
.matches(this.rContent, wxMessage.getContent() == null ? "" : wxMessage.getContent().trim()))
|
||||
&&
|
||||
(this.matcher == null || this.matcher.match(wxMessage))
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理微信推送过来的消息
|
||||
*
|
||||
* @param wxMessage
|
||||
* @return true 代表继续执行别的router,false 代表停止执行别的router
|
||||
*/
|
||||
protected WxMpXmlOutMessage service(WxMpXmlMessage wxMessage,
|
||||
WxMpService wxMpService,
|
||||
WxSessionManager sessionManager,
|
||||
WxErrorExceptionHandler exceptionHandler) {
|
||||
|
||||
try {
|
||||
|
||||
Map<String, Object> context = new HashMap<String, Object>();
|
||||
// 如果拦截器不通过
|
||||
for (WxMpMessageInterceptor interceptor : this.interceptors) {
|
||||
if (!interceptor.intercept(wxMessage, context, wxMpService, sessionManager)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 交给handler处理
|
||||
WxMpXmlOutMessage res = null;
|
||||
for (WxMpMessageHandler handler : this.handlers) {
|
||||
// 返回最后handler的结果
|
||||
res = handler.handle(wxMessage, context, wxMpService, sessionManager);
|
||||
}
|
||||
return res;
|
||||
} catch (WxErrorException e) {
|
||||
exceptionHandler.handle(e);
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
public WxMpMessageRouter getRouterBuilder() {
|
||||
return routerBuilder;
|
||||
}
|
||||
|
||||
public boolean isAsync() {
|
||||
return async;
|
||||
}
|
||||
|
||||
public void setAsync(boolean async) {
|
||||
this.async = async;
|
||||
}
|
||||
|
||||
public String getFromUser() {
|
||||
return fromUser;
|
||||
}
|
||||
|
||||
public void setFromUser(String fromUser) {
|
||||
this.fromUser = fromUser;
|
||||
}
|
||||
|
||||
public String getMsgType() {
|
||||
return msgType;
|
||||
}
|
||||
|
||||
public void setMsgType(String msgType) {
|
||||
this.msgType = msgType;
|
||||
}
|
||||
|
||||
public String getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public void setEvent(String event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public String getEventKey() {
|
||||
return eventKey;
|
||||
}
|
||||
|
||||
public void setEventKey(String eventKey) {
|
||||
this.eventKey = eventKey;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getrContent() {
|
||||
return rContent;
|
||||
}
|
||||
|
||||
public void setrContent(String rContent) {
|
||||
this.rContent = rContent;
|
||||
}
|
||||
|
||||
public WxMpMessageMatcher getMatcher() {
|
||||
return matcher;
|
||||
}
|
||||
|
||||
public void setMatcher(WxMpMessageMatcher matcher) {
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
public boolean isReEnter() {
|
||||
return reEnter;
|
||||
}
|
||||
|
||||
public void setReEnter(boolean reEnter) {
|
||||
this.reEnter = reEnter;
|
||||
}
|
||||
|
||||
public List<WxMpMessageHandler> getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
||||
public void setHandlers(List<WxMpMessageHandler> handlers) {
|
||||
this.handlers = handlers;
|
||||
}
|
||||
|
||||
public List<WxMpMessageInterceptor> getInterceptors() {
|
||||
return interceptors;
|
||||
}
|
||||
|
||||
public void setInterceptors(List<WxMpMessageInterceptor> interceptors) {
|
||||
this.interceptors = interceptors;
|
||||
}
|
||||
}
|
||||
@@ -83,12 +83,10 @@ public interface WxMpService {
|
||||
*
|
||||
* 详情请见:http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95
|
||||
* </pre>
|
||||
* @param timestamp 时间戳
|
||||
* @param noncestr 用户自己生成的随机字符串
|
||||
* @param url url
|
||||
* @return
|
||||
*/
|
||||
public String createJsapiSignature(long timestamp, String noncestr, String url) throws WxErrorException;
|
||||
public WxMpJsapiSignature createJsapiSignature(String url) throws WxErrorException;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
|
||||
@@ -42,10 +42,15 @@ import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
public class WxMpServiceImpl implements WxMpService {
|
||||
|
||||
protected final String RANDOM_STR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
|
||||
protected final Random RANDOM = new Random();
|
||||
|
||||
protected final Logger log = LoggerFactory.getLogger(WxMpServiceImpl.class);
|
||||
|
||||
/**
|
||||
@@ -59,7 +64,7 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
protected final Object globalJsapiTicketRefreshLock = new Object();
|
||||
|
||||
protected WxMpConfigStorage wxMpConfigStorage;
|
||||
|
||||
|
||||
protected CloseableHttpClient httpClient;
|
||||
|
||||
protected HttpHost httpProxy;
|
||||
@@ -143,20 +148,36 @@ public class WxMpServiceImpl implements WxMpService {
|
||||
return wxMpConfigStorage.getJsapiTicket();
|
||||
}
|
||||
|
||||
public String createJsapiSignature(long timestamp, String noncestr, String url) throws WxErrorException {
|
||||
public WxMpJsapiSignature createJsapiSignature(String url) throws WxErrorException {
|
||||
long timestamp = System.currentTimeMillis() / 1000;
|
||||
String noncestr = getRandomStr();
|
||||
String jsapiTicket = getJsapiTicket(false);
|
||||
try {
|
||||
return SHA1.genWithAmple(
|
||||
String signature = SHA1.genWithAmple(
|
||||
"jsapi_ticket=" + jsapiTicket,
|
||||
"noncestr=" + noncestr,
|
||||
"timestamp=" + timestamp,
|
||||
"url=" + url
|
||||
);
|
||||
WxMpJsapiSignature jsapiSignature = new WxMpJsapiSignature();
|
||||
jsapiSignature.setTimestamp(timestamp);
|
||||
jsapiSignature.setNoncestr(noncestr);
|
||||
jsapiSignature.setUrl(url);
|
||||
jsapiSignature.setSignature(signature);
|
||||
return jsapiSignature;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getRandomStr() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < 16; i++) {
|
||||
sb.append(RANDOM_STR.charAt(RANDOM.nextInt(RANDOM_STR.length())));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void customMessageSend(WxMpCustomMessage message) throws WxErrorException {
|
||||
String url = "https://api.weixin.qq.com/cgi-bin/message/custom/send";
|
||||
execute(new SimplePostRequestExecutor(), url, message.toJson());
|
||||
|
||||
@@ -619,4 +619,41 @@ public class WxMpXmlMessage {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WxMpXmlMessage{" +
|
||||
"toUserName='" + toUserName + '\'' +
|
||||
", fromUserName='" + fromUserName + '\'' +
|
||||
", createTime=" + createTime +
|
||||
", msgType='" + msgType + '\'' +
|
||||
", content='" + content + '\'' +
|
||||
", msgId=" + msgId +
|
||||
", picUrl='" + picUrl + '\'' +
|
||||
", mediaId='" + mediaId + '\'' +
|
||||
", format='" + format + '\'' +
|
||||
", thumbMediaId='" + thumbMediaId + '\'' +
|
||||
", locationX=" + locationX +
|
||||
", locationY=" + locationY +
|
||||
", scale=" + scale +
|
||||
", label='" + label + '\'' +
|
||||
", title='" + title + '\'' +
|
||||
", description='" + description + '\'' +
|
||||
", url='" + url + '\'' +
|
||||
", event='" + event + '\'' +
|
||||
", eventKey='" + eventKey + '\'' +
|
||||
", ticket='" + ticket + '\'' +
|
||||
", latitude=" + latitude +
|
||||
", longitude=" + longitude +
|
||||
", precision=" + precision +
|
||||
", recognition='" + recognition + '\'' +
|
||||
", status='" + status + '\'' +
|
||||
", totalCount=" + totalCount +
|
||||
", filterCount=" + filterCount +
|
||||
", sentCount=" + sentCount +
|
||||
", errorCount=" + errorCount +
|
||||
", scanCodeInfo=" + scanCodeInfo +
|
||||
", sendPicsInfo=" + sendPicsInfo +
|
||||
", sendLocationInfo=" + sendLocationInfo +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package me.chanjar.weixin.mp.bean.result;
|
||||
|
||||
/**
|
||||
* jspai signature
|
||||
*/
|
||||
public class WxMpJsapiSignature {
|
||||
|
||||
private String noncestr;
|
||||
|
||||
private String jsapiTicket;
|
||||
|
||||
private long timestamp;
|
||||
|
||||
private String url;
|
||||
|
||||
private String signature;
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public String getNoncestr() {
|
||||
return noncestr;
|
||||
}
|
||||
|
||||
public void setNoncestr(String noncestr) {
|
||||
this.noncestr = noncestr;
|
||||
}
|
||||
|
||||
public String getJsapiTicket() {
|
||||
return jsapiTicket;
|
||||
}
|
||||
|
||||
public void setJsapiTicket(String jsapiTicket) {
|
||||
this.jsapiTicket = jsapiTicket;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,6 +42,12 @@ public class WxMpMessageRouterTest {
|
||||
.rule().async(async).eventKey("KEY_1").handler(new WxEchoMpMessageHandler(sb, "KEY_1")).end()
|
||||
.rule().async(async).content("CONTENT_1").handler(new WxEchoMpMessageHandler(sb, "CONTENT_1")).end()
|
||||
.rule().async(async).rContent(".*bc.*").handler(new WxEchoMpMessageHandler(sb, "abcd")).end()
|
||||
.rule().async(async).matcher(new WxMpMessageMatcher() {
|
||||
@Override
|
||||
public boolean match(WxMpXmlMessage message) {
|
||||
return "strangeformat".equals(message.getFormat());
|
||||
}
|
||||
}).handler(new WxEchoMpMessageHandler(sb, "matcher")).end()
|
||||
.rule().async(async).handler(new WxEchoMpMessageHandler(sb, "ALL")).end();
|
||||
;
|
||||
}
|
||||
@@ -109,9 +115,12 @@ public class WxMpMessageRouterTest {
|
||||
WxMpXmlMessage message5 = new WxMpXmlMessage();
|
||||
message5.setContent("BLA");
|
||||
|
||||
WxMpXmlMessage message6 = new WxMpXmlMessage();
|
||||
WxMpXmlMessage message6 = new WxMpXmlMessage();
|
||||
message6.setContent("abcd");
|
||||
|
||||
|
||||
WxMpXmlMessage message7 = new WxMpXmlMessage();
|
||||
message7.setFormat("strangeformat");
|
||||
|
||||
WxMpXmlMessage c2 = new WxMpXmlMessage();
|
||||
c2.setMsgType(WxConsts.XML_MSG_TEXT);
|
||||
c2.setEvent(WxConsts.EVT_CLICK);
|
||||
@@ -134,6 +143,7 @@ public class WxMpMessageRouterTest {
|
||||
new Object[] { message4, "CONTENT_1," },
|
||||
new Object[] { message5, "ALL," },
|
||||
new Object[] { message6, "abcd," },
|
||||
new Object[] { message7, "matcher," },
|
||||
new Object[] { c2, "COMBINE_2," },
|
||||
new Object[] { c3, "COMBINE_3," },
|
||||
new Object[] { c4, "COMBINE_4," }
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSession;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageMatcher;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.WxMpCustomMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMatcher {
|
||||
|
||||
private Random random = new Random();
|
||||
|
||||
private Pattern pattern = Pattern.compile("\\d+");
|
||||
|
||||
@Override
|
||||
public boolean match(WxMpXmlMessage message) {
|
||||
return isUserWantGuess(message) || isUserAnswering(message);
|
||||
}
|
||||
|
||||
private boolean isUserWantGuess(WxMpXmlMessage message) {
|
||||
return "猜数字".equals(message.getContent());
|
||||
}
|
||||
|
||||
private boolean isUserAnswering(WxMpXmlMessage message) {
|
||||
return pattern.matcher(message.getContent()).matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) throws WxErrorException {
|
||||
|
||||
if (isUserWantGuess(wxMessage)) {
|
||||
letsGo(wxMessage, wxMpService, sessionManager);
|
||||
}
|
||||
|
||||
if (isUserAnswering(wxMessage)) {
|
||||
giveHint(wxMessage, wxMpService, sessionManager);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
protected void letsGo(WxMpXmlMessage wxMessage, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
|
||||
WxSession session = sessionManager.getSession(wxMessage.getFromUserName());
|
||||
if (session.getAttribute("guessing") == null) {
|
||||
WxMpCustomMessage m = WxMpCustomMessage
|
||||
.TEXT()
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.content("请猜一个100以内的数字")
|
||||
.build();
|
||||
wxMpService.customMessageSend(m);
|
||||
} else {
|
||||
WxMpCustomMessage m = WxMpCustomMessage
|
||||
.TEXT()
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.content("放弃了吗?那请重新猜一个100以内的数字")
|
||||
.build();
|
||||
wxMpService.customMessageSend(m);
|
||||
}
|
||||
|
||||
session.setAttribute("guessing", Boolean.TRUE);
|
||||
session.setAttribute("number", random.nextInt(100));
|
||||
}
|
||||
|
||||
|
||||
protected void giveHint(WxMpXmlMessage wxMessage, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException {
|
||||
|
||||
WxSession session = sessionManager.getSession(wxMessage.getFromUserName());
|
||||
|
||||
if (session.getAttribute("guessing") == null) {
|
||||
return;
|
||||
}
|
||||
boolean guessing = (Boolean) session.getAttribute("guessing");
|
||||
if (!guessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
int answer = (Integer) session.getAttribute("number");
|
||||
int guessNumber = Integer.valueOf(wxMessage.getContent());
|
||||
if (guessNumber < answer) {
|
||||
WxMpCustomMessage m = WxMpCustomMessage
|
||||
.TEXT()
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.content("小了")
|
||||
.build();
|
||||
wxMpService.customMessageSend(m);
|
||||
|
||||
} else if (guessNumber > answer) {
|
||||
WxMpCustomMessage m = WxMpCustomMessage
|
||||
.TEXT()
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.content("大了")
|
||||
.build();
|
||||
wxMpService.customMessageSend(m);
|
||||
} else {
|
||||
WxMpCustomMessage m = WxMpCustomMessage
|
||||
.TEXT()
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.content("Bingo!")
|
||||
.build();
|
||||
session.removeAttribute("guessing");
|
||||
wxMpService.customMessageSend(m);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public class DemoImageHandler implements WxMpMessageHandler {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
try {
|
||||
WxMediaUploadResult wxMediaUploadResult = wxMpService
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
|
||||
WxMpXmlOutImageMessage m
|
||||
= WxMpXmlOutMessage
|
||||
.IMAGE()
|
||||
.mediaId(wxMediaUploadResult.getMediaId())
|
||||
.fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.build();
|
||||
return m;
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by qianjia on 15/1/22.
|
||||
*/
|
||||
public class DemoLogHandler implements WxMpMessageHandler {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService,
|
||||
WxSessionManager sessionManager) {
|
||||
System.out.println(wxMessage.toString());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by qianjia on 15/1/22.
|
||||
*/
|
||||
public class DemoOAuth2Handler implements WxMpMessageHandler {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
String href = "<a href=\"" + wxMpService.oauth2buildAuthorizationUrl(WxConsts.OAUTH2_SCOPE_USER_INFO, null)
|
||||
+ "\">测试oauth2</a>";
|
||||
return WxMpXmlOutMessage
|
||||
.TEXT()
|
||||
.content(href)
|
||||
.fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName()).build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
|
||||
import me.chanjar.weixin.mp.api.WxMpService;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by qianjia on 15/1/22.
|
||||
*/
|
||||
public class DemoTextHandler implements WxMpMessageHandler {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
WxMpXmlOutTextMessage m
|
||||
= WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName()).build();
|
||||
return m;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +1,12 @@
|
||||
package me.chanjar.weixin.mp.demo;
|
||||
|
||||
import me.chanjar.weixin.common.api.WxConsts;
|
||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.exception.WxErrorException;
|
||||
import me.chanjar.weixin.common.session.WxSessionManager;
|
||||
import me.chanjar.weixin.mp.api.*;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
|
||||
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.servlet.ServletHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
public class WxMpDemoServer {
|
||||
|
||||
@@ -42,79 +33,26 @@ public class WxMpDemoServer {
|
||||
}
|
||||
|
||||
private static void initWeixin() {
|
||||
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
|
||||
WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage.fromXml(is1);
|
||||
InputStream is1 = ClassLoader.getSystemResourceAsStream("test-config.xml");
|
||||
WxMpDemoInMemoryConfigStorage config = WxMpDemoInMemoryConfigStorage.fromXml(is1);
|
||||
|
||||
wxMpConfigStorage = config;
|
||||
wxMpService = new WxMpServiceImpl();
|
||||
wxMpService.setWxMpConfigStorage(config);
|
||||
wxMpConfigStorage = config;
|
||||
wxMpService = new WxMpServiceImpl();
|
||||
wxMpService.setWxMpConfigStorage(config);
|
||||
|
||||
WxMpMessageHandler textHandler = new WxMpMessageHandler() {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
WxMpXmlOutTextMessage m
|
||||
= WxMpXmlOutMessage.TEXT().content("测试加密消息").fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName()).build();
|
||||
return m;
|
||||
}
|
||||
};
|
||||
WxMpMessageHandler logHandler = new DemoLogHandler();
|
||||
WxMpMessageHandler textHandler = new DemoTextHandler();
|
||||
WxMpMessageHandler imageHandler = new DemoImageHandler();
|
||||
WxMpMessageHandler oauth2handler = new DemoOAuth2Handler();
|
||||
DemoGuessNumberHandler guessNumberHandler = new DemoGuessNumberHandler();
|
||||
|
||||
WxMpMessageHandler imageHandler = new WxMpMessageHandler() {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
try {
|
||||
WxMediaUploadResult wxMediaUploadResult = wxMpService
|
||||
.mediaUpload(WxConsts.MEDIA_IMAGE, WxConsts.FILE_JPG, ClassLoader.getSystemResourceAsStream("mm.jpeg"));
|
||||
WxMpXmlOutImageMessage m
|
||||
= WxMpXmlOutMessage
|
||||
.IMAGE()
|
||||
.mediaId(wxMediaUploadResult.getMediaId())
|
||||
.fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName())
|
||||
.build();
|
||||
return m;
|
||||
} catch (WxErrorException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
WxMpMessageHandler oauth2handler = new WxMpMessageHandler() {
|
||||
@Override
|
||||
public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context,
|
||||
WxMpService wxMpService, WxSessionManager sessionManager) {
|
||||
String href = "<a href=\"" + wxMpService.oauth2buildAuthorizationUrl(WxConsts.OAUTH2_SCOPE_USER_INFO, null)
|
||||
+ "\">测试oauth2</a>";
|
||||
return WxMpXmlOutMessage
|
||||
.TEXT()
|
||||
.content(href)
|
||||
.fromUser(wxMessage.getToUserName())
|
||||
.toUser(wxMessage.getFromUserName()).build();
|
||||
}
|
||||
};
|
||||
|
||||
wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
|
||||
wxMpMessageRouter = new WxMpMessageRouter(wxMpService);
|
||||
wxMpMessageRouter
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("哈哈") // 拦截内容为“哈哈”的消息
|
||||
.handler(textHandler)
|
||||
.end()
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("图片")
|
||||
.handler(imageHandler)
|
||||
.end()
|
||||
.rule()
|
||||
.async(false)
|
||||
.content("oauth")
|
||||
.handler(oauth2handler)
|
||||
.end()
|
||||
.rule().handler(logHandler).next()
|
||||
.rule().msgType(WxConsts.XML_MSG_TEXT).matcher(guessNumberHandler).handler(guessNumberHandler).end()
|
||||
.rule().async(false).content("哈哈").handler(textHandler).end()
|
||||
.rule().async(false).content("图片").handler(imageHandler).end()
|
||||
.rule().async(false).content("oauth").handler(oauth2handler).end()
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,9 @@ public class WxMpEndpointServlet extends HttpServlet {
|
||||
// 明文传输的消息
|
||||
WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request.getInputStream());
|
||||
WxMpXmlOutMessage outMessage = wxMpMessageRouter.route(inMessage);
|
||||
response.getWriter().write(outMessage.toXml());
|
||||
if (outMessage != null) {
|
||||
response.getWriter().write(outMessage.toXml());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user