weixin4j-qy: 新增userid与openid互换接口

This commit is contained in:
jinyu 2015-06-24 20:57:24 +08:00
parent bb79042d4e
commit f6b1f76210
23 changed files with 255 additions and 195 deletions

View File

@ -347,4 +347,8 @@
+ **weixin4j-mp**: 新增企业付款查询接口 + **weixin4j-mp**: 新增企业付款查询接口
+ **weixin4j-server**: 对多个公众号的接入支持 + **weixin4j-server**: 对多个公众号的接入支持
* 2015-06-24
+ **weixin4j-qy**: 新增userid与openid互换接口

View File

@ -4,7 +4,6 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.util.regex.Pattern;
/** /**
* 对$n结尾的节点注解 * 对$n结尾的节点注解
@ -18,9 +17,5 @@ import java.util.regex.Pattern;
@Target(ElementType.FIELD) @Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
public @interface ListsuffixResult { public @interface ListsuffixResult {
String[] value() default { DEFAULT_REGEX }; String[] value() default { "(_\\d)$" };
public final static String DEFAULT_REGEX = "(_\\d)$";
public final static Pattern DEFAULT_PATTERN = Pattern
.compile(DEFAULT_REGEX);
} }

View File

@ -42,6 +42,26 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/ */
public class ListsuffixResultDeserializer { public class ListsuffixResultDeserializer {
private static Pattern DEFAULT_PATTERN;
static {
String regex = null;
try {
Object value = ListsuffixResult.class.getMethod("value")
.getDefaultValue();
if (value instanceof String) {
regex = (String) value;
} else if (value instanceof String[]) {
regex = ((String[]) value)[0];
}
} catch (NoSuchMethodException e) {
;
}
if (StringUtil.isBlank(regex)) {
regex = "(_\\d)$";
}
DEFAULT_PATTERN = Pattern.compile(regex);
}
/** /**
* 对包含$n节点的xml序列化 * 对包含$n节点的xml序列化
* *
@ -109,9 +129,8 @@ public class ListsuffixResultDeserializer {
} else if (event == XMLStreamConstants.CHARACTERS) { } else if (event == XMLStreamConstants.CHARACTERS) {
String key = matcher.group(); String key = matcher.group();
if (!pattern.pattern().equals( if (!pattern.pattern().equals(
ListsuffixResult.DEFAULT_REGEX)) { DEFAULT_PATTERN.pattern())) {
matcher = ListsuffixResult.DEFAULT_PATTERN matcher = DEFAULT_PATTERN.matcher(name);
.matcher(name);
matcher.find(); matcher.find();
key = matcher.group(); key = matcher.group();
} }
@ -146,7 +165,7 @@ public class ListsuffixResultDeserializer {
.getDefaultValue().toString())) { .getDefaultValue().toString())) {
itemName = rootElement.name(); itemName = rootElement.name();
} }
} catch (Exception e) { } catch (NoSuchMethodException e) {
; ;
} }
} }

View File

@ -60,4 +60,8 @@
* 2015-06-22 * 2015-06-22
+ 新增企业号[第三方应用代理](src/main/java/com/foxinmy/weixin4j/qy/WeixinSuiteProxy.java)。 + 新增企业号[第三方应用代理](src/main/java/com/foxinmy/weixin4j/qy/WeixinSuiteProxy.java)。
* 2015-06-24
+ 新增userid与openid互换接口

View File

@ -851,4 +851,39 @@ public class WeixinProxy {
public BatchResult getresult(String jobId) throws WeixinException { public BatchResult getresult(String jobId) throws WeixinException {
return batchApi.getresult(jobId); return batchApi.getresult(jobId);
} }
/**
* userid转换成openid:该接口使用场景为微信支付微信红包和企业转账企业号用户在使用微信支付的功能时
* 需要自行将企业号的userid转成openid 在使用微信红包功能时需要将应用id和userid转成appid和openid才能使用
*
* @param userid
* 企业号内的成员id 必填
* @param agentid
* 需要发送红包的应用ID若只是使用微信支付和企业转账则无需该参数 传入0或负数则忽略
* @return 结果数组 第一个元素为对应的openid 第二个元素则为应用的appid(如果有)
* @throws WeixinException
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=Userid%E4%B8%8Eopenid%E4%BA%92%E6%8D%A2%E6%8E%A5%E5%8F%A3">userid转换成openid</a>
*/
public String[] userid2openid(String userid, int agentid)
throws WeixinException {
return userApi.userid2openid(userid, agentid);
}
/**
* openid转换成userid:该接口主要应用于使用微信支付微信红包和企业转账之后的结果查询
* 开发者需要知道某个结果事件的openid对应企业号内成员的信息时可以通过调用该接口进行转换查询
*
* @param openid
* 在使用微信支付微信红包和企业转账之后返回结果的openid
* @return 该openid在企业号中对应的成员userid
* @throws WeixinException
* @see com.foxinmy.weixin4j.qy.api.UserApi
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=Userid%E4%B8%8Eopenid%E4%BA%92%E6%8D%A2%E6%8E%A5%E5%8F%A3">openid转换成userid</a>
*/
public String openid2userid(String openid) throws WeixinException {
return userApi.openid2userid(openid);
}
} }

View File

@ -15,7 +15,6 @@ import com.foxinmy.weixin4j.qy.model.User;
import com.foxinmy.weixin4j.qy.type.InviteType; import com.foxinmy.weixin4j.qy.type.InviteType;
import com.foxinmy.weixin4j.qy.type.UserStatus; import com.foxinmy.weixin4j.qy.type.UserStatus;
import com.foxinmy.weixin4j.token.TokenHolder; import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.util.StringUtil;
/** /**
* 成员API * 成员API
@ -304,9 +303,7 @@ public class UserApi extends QyApi {
throws WeixinException { throws WeixinException {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("userid", userId); obj.put("userid", userId);
if (StringUtil.isBlank(tips)) { obj.put("invite_tips", tips);
obj.put("invite_tips", tips);
}
String invite_user_uri = getRequestUri("invite_user_uri"); String invite_user_uri = getRequestUri("invite_user_uri");
Token token = tokenHolder.getToken(); Token token = tokenHolder.getToken();
WeixinResponse response = weixinClient.post( WeixinResponse response = weixinClient.post(
@ -321,4 +318,51 @@ public class UserApi extends QyApi {
return null; return null;
} }
} }
/**
* userid转换成openid:该接口使用场景为微信支付微信红包和企业转账企业号用户在使用微信支付的功能时
* 需要自行将企业号的userid转成openid 在使用微信红包功能时需要将应用id和userid转成appid和openid才能使用
*
* @param userid
* 企业号内的成员id 必填
* @param agentid
* 需要发送红包的应用ID若只是使用微信支付和企业转账则无需该参数 传入0或负数则忽略
* @return 结果数组 第一个元素为对应的openid 第二个元素则为应用的appid(如果有)
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=Userid%E4%B8%8Eopenid%E4%BA%92%E6%8D%A2%E6%8E%A5%E5%8F%A3">userid转换成openid</a>
*/
public String[] userid2openid(String userid, int agentid)
throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("userid", userid);
if (agentid > 0) {
obj.put("agentid", agentid);
}
String userid2openid_uri = getRequestUri("userid2openid_uri");
WeixinResponse response = weixinClient.post(
String.format(userid2openid_uri, tokenHolder.getAccessToken()),
obj.toJSONString());
obj = response.getAsJson();
return new String[] { obj.getString("openid"), obj.getString("appid") };
}
/**
* openid转换成userid:该接口主要应用于使用微信支付微信红包和企业转账之后的结果查询
* 开发者需要知道某个结果事件的openid对应企业号内成员的信息时可以通过调用该接口进行转换查询
*
* @param openid
* 在使用微信支付微信红包和企业转账之后返回结果的openid
* @return 该openid在企业号中对应的成员userid
* @throws WeixinException
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=Userid%E4%B8%8Eopenid%E4%BA%92%E6%8D%A2%E6%8E%A5%E5%8F%A3">openid转换成userid</a>
*/
public String openid2userid(String openid) throws WeixinException {
String openid2userid_uri = getRequestUri("openid2userid_uri");
WeixinResponse response = weixinClient.post(
String.format(openid2userid_uri, tokenHolder.getAccessToken()),
String.format("{\"openid\": \"%s\"}", openid));
return response.getAsJson().getString("userid");
}
} }

View File

@ -95,4 +95,8 @@ suite_get_authinfo_uri={api_base_url}/service/get_auth_info?suite_access_token=%
# \u83b7\u53d6\u4f01\u4e1a\u53f7\u5e94\u7528 # \u83b7\u53d6\u4f01\u4e1a\u53f7\u5e94\u7528
suite_get_agent_uri={api_base_url}/service/get_agent?suite_access_token=%s suite_get_agent_uri={api_base_url}/service/get_agent?suite_access_token=%s
# \u8bbe\u7f6e\u4f01\u4e1a\u53f7\u5e94\u7528 # \u8bbe\u7f6e\u4f01\u4e1a\u53f7\u5e94\u7528
suite_set_agent_uri={api_base_url}/service/set_agent?suite_access_token=%s suite_set_agent_uri={api_base_url}/service/set_agent?suite_access_token=%s
# userid\u8f6c\u6362\u6210openid
userid2openid_uri={api_base_url}/user/convert_to_openid?access_token=%s
# openid\u8f6c\u6362\u6210userid
openid2userid_uri={api_base_url}/user/convert_to_userid?access_token=%s

View File

@ -89,4 +89,11 @@ public class UserTest extends TokenTest {
public void invite() throws WeixinException { public void invite() throws WeixinException {
userApi.inviteUser("11", null); userApi.inviteUser("11", null);
} }
@Test
public void convert() throws WeixinException {
String[] result = userApi.userid2openid("jinyu", 1);
System.err.println(result);
System.err.println(userApi.openid2userid(result[0]));
}
} }

View File

@ -4,6 +4,8 @@ import io.netty.channel.ChannelHandlerContext;
import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory; import io.netty.util.internal.logging.InternalLoggerFactory;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.handler.WeixinMessageHandler; import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor; import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
@ -33,16 +35,22 @@ public class MessageHandlerExecutor {
* 消息拦截器 * 消息拦截器
*/ */
private final WeixinMessageInterceptor[] messageInterceptors; private final WeixinMessageInterceptor[] messageInterceptors;
/**
* 节点名称集合
*/
private final Set<String> nodeNames;
private final ChannelHandlerContext context; private final ChannelHandlerContext context;
private int interceptorIndex = -1; private int interceptorIndex = -1;
public MessageHandlerExecutor(ChannelHandlerContext context, public MessageHandlerExecutor(ChannelHandlerContext context,
WeixinMessageHandler messageHandler, WeixinMessageHandler messageHandler,
WeixinMessageInterceptor[] messageInterceptors) { WeixinMessageInterceptor[] messageInterceptors,
Set<String> nodeNames) {
this.context = context; this.context = context;
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
this.messageInterceptors = messageInterceptors; this.messageInterceptors = messageInterceptors;
this.nodeNames = nodeNames;
} }
public WeixinMessageHandler getMessageHandler() { public WeixinMessageHandler getMessageHandler() {
@ -65,7 +73,7 @@ public class MessageHandlerExecutor {
for (int i = 0; i < messageInterceptors.length; i++) { for (int i = 0; i < messageInterceptors.length; i++) {
WeixinMessageInterceptor interceptor = messageInterceptors[i]; WeixinMessageInterceptor interceptor = messageInterceptors[i];
if (!interceptor.preHandle(context, request, message, if (!interceptor.preHandle(context, request, message,
messageHandler)) { nodeNames, messageHandler)) {
triggerAfterCompletion(request, message, null); triggerAfterCompletion(request, message, null);
return false; return false;
} }
@ -94,7 +102,7 @@ public class MessageHandlerExecutor {
for (int i = messageInterceptors.length - 1; i >= 0; i--) { for (int i = messageInterceptors.length - 1; i >= 0; i--) {
WeixinMessageInterceptor interceptor = messageInterceptors[i]; WeixinMessageInterceptor interceptor = messageInterceptors[i];
interceptor.postHandle(context, request, response, message, interceptor.postHandle(context, request, response, message,
messageHandler); nodeNames, messageHandler);
} }
} }
@ -118,7 +126,7 @@ public class MessageHandlerExecutor {
WeixinMessageInterceptor interceptor = messageInterceptors[i]; WeixinMessageInterceptor interceptor = messageInterceptors[i];
try { try {
interceptor.afterCompletion(context, request, message, interceptor.afterCompletion(context, request, message,
messageHandler, exception); nodeNames, messageHandler, exception);
} catch (WeixinException e) { } catch (WeixinException e) {
logger.error( logger.error(
"MessageInterceptor.afterCompletion threw exception", e); "MessageInterceptor.afterCompletion threw exception", e);

View File

@ -15,6 +15,7 @@ import java.util.HashMap;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBElement;
@ -29,6 +30,7 @@ import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor; import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.response.WeixinResponse; import com.foxinmy.weixin4j.response.WeixinResponse;
import com.foxinmy.weixin4j.type.AccountType;
import com.foxinmy.weixin4j.util.ClassUtil; import com.foxinmy.weixin4j.util.ClassUtil;
import com.foxinmy.weixin4j.util.Consts; import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.HttpUtil; import com.foxinmy.weixin4j.util.HttpUtil;
@ -110,17 +112,16 @@ public class WeixinMessageDispatcher {
public void doDispatch(final ChannelHandlerContext context, public void doDispatch(final ChannelHandlerContext context,
final WeixinRequest request, final CruxMessageHandler cruxMessage) final WeixinRequest request, final CruxMessageHandler cruxMessage)
throws WeixinException { throws WeixinException {
MessageKey messageKey = new MessageKey(cruxMessage.getMsgType(), MessageKey messageKey = defineMessageKey(cruxMessage.getMsgType(),
cruxMessage.getEventType(), cruxMessage.getAccountType()); cruxMessage.getEventType(), cruxMessage.getAccountType());
Class<?> targetClass = messageMatcher.match(messageKey); Class<?> targetClass = messageMatcher.match(messageKey);
Object message = request.getOriginalContent(); Object message = request.getOriginalContent();
if (targetClass != null) { if (targetClass != null) {
message = messageRead(request.getOriginalContent(), targetClass); message = messageRead(request.getOriginalContent(), targetClass);
} }
logger.info("define '{}' matched '{}'", messageKey, logger.info("define '{}' matched '{}'", messageKey, targetClass);
targetClass);
MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context, MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context,
request, messageKey, message); request, messageKey, message, cruxMessage.getNodeNames());
if (handlerExecutor == null if (handlerExecutor == null
|| handlerExecutor.getMessageHandler() == null) { || handlerExecutor.getMessageHandler() == null) {
noHandlerFound(context, request, message); noHandlerFound(context, request, message);
@ -132,7 +133,7 @@ public class WeixinMessageDispatcher {
WeixinException dispatchException = null; WeixinException dispatchException = null;
try { try {
WeixinResponse response = handlerExecutor.getMessageHandler() WeixinResponse response = handlerExecutor.getMessageHandler()
.doHandle(request, message); .doHandle(request, message, cruxMessage.getNodeNames());
handlerExecutor.applyPostHandle(request, response, message); handlerExecutor.applyPostHandle(request, response, message);
context.write(response); context.write(response);
} catch (WeixinException e) { } catch (WeixinException e) {
@ -142,6 +143,22 @@ public class WeixinMessageDispatcher {
dispatchException); dispatchException);
} }
/**
* 声明messagekey
*
* @param messageType
* 消息类型
* @param eventType
* 事件类型
* @param accountType
* 账号类型
* @return
*/
protected MessageKey defineMessageKey(String messageType, String eventType,
AccountType accountType) {
return new MessageKey(messageType, eventType, accountType);
}
/** /**
* 未匹配到handler时触发 * 未匹配到handler时触发
* *
@ -170,13 +187,16 @@ public class WeixinMessageDispatcher {
* 消息的key * 消息的key
* @param message * @param message
* 微信消息 * 微信消息
* @param nodeNames
* 节点名称集合
* @return MessageHandlerExecutor * @return MessageHandlerExecutor
* @see com.foxinmy.weixin4j.dispatcher.MessageHandlerExecutor * @see com.foxinmy.weixin4j.dispatcher.MessageHandlerExecutor
* @throws WeixinException * @throws WeixinException
*/ */
protected MessageHandlerExecutor getHandlerExecutor( protected MessageHandlerExecutor getHandlerExecutor(
ChannelHandlerContext context, WeixinRequest request, ChannelHandlerContext context, WeixinRequest request,
MessageKey messageKey, Object message) throws WeixinException { MessageKey messageKey, Object message, Set<String> nodeNames)
throws WeixinException {
WeixinMessageHandler messageHandler = null; WeixinMessageHandler messageHandler = null;
WeixinMessageHandler[] messageHandlers = getMessageHandlers(); WeixinMessageHandler[] messageHandlers = getMessageHandlers();
if (messageHandlers == null) { if (messageHandlers == null) {
@ -186,7 +206,7 @@ public class WeixinMessageDispatcher {
if (handler instanceof MessageHandlerAdapter) { if (handler instanceof MessageHandlerAdapter) {
Class<?> genericType = genericTypeRead(handler); Class<?> genericType = genericTypeRead(handler);
if (genericType == message.getClass() if (genericType == message.getClass()
&& handler.canHandle(request, message)) { && handler.canHandle(request, message, nodeNames)) {
messageHandler = handler; messageHandler = handler;
break; break;
} }
@ -195,14 +215,14 @@ public class WeixinMessageDispatcher {
if (messageHandler == null) { if (messageHandler == null) {
for (WeixinMessageHandler handler : messageHandlers) { for (WeixinMessageHandler handler : messageHandlers) {
if (!(handler instanceof MessageHandlerAdapter) if (!(handler instanceof MessageHandlerAdapter)
&& handler.canHandle(request, message)) { && handler.canHandle(request, message, nodeNames)) {
messageHandler = handler; messageHandler = handler;
break; break;
} }
} }
} }
return new MessageHandlerExecutor(context, messageHandler, return new MessageHandlerExecutor(context, messageHandler,
getMessageInterceptors()); getMessageInterceptors(), nodeNames);
} }
/** /**

View File

@ -1,5 +1,7 @@
package com.foxinmy.weixin4j.handler; package com.foxinmy.weixin4j.handler;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.response.BlankResponse; import com.foxinmy.weixin4j.response.BlankResponse;
@ -23,14 +25,14 @@ public class BlankMessageHandler implements WeixinMessageHandler {
} }
@Override @Override
public boolean canHandle(WeixinRequest request, Object message) public boolean canHandle(WeixinRequest request, Object message,
throws WeixinException { Set<String> nodeNames) throws WeixinException {
return true; return true;
} }
@Override @Override
public WeixinResponse doHandle(WeixinRequest request, Object message) public WeixinResponse doHandle(WeixinRequest request, Object message,
throws WeixinException { Set<String> nodeNames) throws WeixinException {
return BlankResponse.global; return BlankResponse.global;
} }
} }

View File

@ -1,5 +1,7 @@
package com.foxinmy.weixin4j.handler; package com.foxinmy.weixin4j.handler;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.response.TextResponse; import com.foxinmy.weixin4j.response.TextResponse;
@ -23,14 +25,14 @@ public class DebugMessageHandler implements WeixinMessageHandler {
} }
@Override @Override
public boolean canHandle(WeixinRequest request, Object message) public boolean canHandle(WeixinRequest request, Object message,
throws WeixinException { Set<String> nodeNames) throws WeixinException {
return true; return true;
} }
@Override @Override
public WeixinResponse doHandle(WeixinRequest request, Object message) public WeixinResponse doHandle(WeixinRequest request, Object message,
throws WeixinException { Set<String> nodeNames) throws WeixinException {
return new TextResponse(message.toString()); return new TextResponse(message.toString());
} }
} }

View File

@ -1,5 +1,7 @@
package com.foxinmy.weixin4j.handler; package com.foxinmy.weixin4j.handler;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.response.WeixinResponse; import com.foxinmy.weixin4j.response.WeixinResponse;
@ -17,8 +19,8 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
public abstract class MessageHandlerAdapter<M> implements WeixinMessageHandler { public abstract class MessageHandlerAdapter<M> implements WeixinMessageHandler {
@Override @Override
public boolean canHandle(WeixinRequest request, Object message) public boolean canHandle(WeixinRequest request, Object message,
throws WeixinException { Set<String> nodeNames) throws WeixinException {
return canHandle0(request, (M) message); return canHandle0(request, (M) message);
} }
@ -38,8 +40,8 @@ public abstract class MessageHandlerAdapter<M> implements WeixinMessageHandler {
} }
@Override @Override
public WeixinResponse doHandle(WeixinRequest request, Object message) public WeixinResponse doHandle(WeixinRequest request, Object message,
throws WeixinException { Set<String> nodeNames) throws WeixinException {
return doHandle0(request, (M) message); return doHandle0(request, (M) message);
} }

View File

@ -1,5 +1,7 @@
package com.foxinmy.weixin4j.handler; package com.foxinmy.weixin4j.handler;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.response.WeixinResponse; import com.foxinmy.weixin4j.response.WeixinResponse;
@ -22,10 +24,12 @@ public interface WeixinMessageHandler {
* 微信请求 * 微信请求
* @param message * @param message
* 微信消息 * 微信消息
* @param nodeNames
* 节点名称集合
* @return true则执行doHandle * @return true则执行doHandle
*/ */
public boolean canHandle(WeixinRequest request, Object message) public boolean canHandle(WeixinRequest request, Object message,
throws WeixinException; Set<String> nodeNames) throws WeixinException;
/** /**
* 处理请求 * 处理请求
@ -34,8 +38,10 @@ public interface WeixinMessageHandler {
* 微信请求 * 微信请求
* @param message * @param message
* 微信消息 * 微信消息
* @return * @param nodeNames
* 节点名称集合
* @return 回复内容
*/ */
public WeixinResponse doHandle(WeixinRequest request, Object message) public WeixinResponse doHandle(WeixinRequest request, Object message,
throws WeixinException; Set<String> nodeNames) throws WeixinException;
} }

View File

@ -2,6 +2,8 @@ package com.foxinmy.weixin4j.interceptor;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.handler.WeixinMessageHandler; import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
@ -21,20 +23,21 @@ public abstract class MessageInterceptorAdapter implements
@Override @Override
public boolean preHandle(ChannelHandlerContext context, public boolean preHandle(ChannelHandlerContext context,
WeixinRequest request, Object message, WeixinMessageHandler handler) WeixinRequest request, Object message, Set<String> nodeNames,
throws WeixinException { WeixinMessageHandler handler) throws WeixinException {
return true; return true;
} }
@Override @Override
public void postHandle(ChannelHandlerContext context, public void postHandle(ChannelHandlerContext context,
WeixinRequest request, WeixinResponse response, Object message, WeixinRequest request, WeixinResponse response, Object message,
WeixinMessageHandler handler) throws WeixinException { Set<String> nodeNames, WeixinMessageHandler handler)
throws WeixinException {
} }
@Override @Override
public void afterCompletion(ChannelHandlerContext context, public void afterCompletion(ChannelHandlerContext context,
WeixinRequest request, Object message, WeixinRequest request, Object message, Set<String> nodeNames,
WeixinMessageHandler handler, WeixinException exception) WeixinMessageHandler handler, WeixinException exception)
throws WeixinException { throws WeixinException {
} }

View File

@ -2,6 +2,8 @@ package com.foxinmy.weixin4j.interceptor;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.handler.WeixinMessageHandler; import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
@ -27,13 +29,15 @@ public interface WeixinMessageInterceptor {
* 微信请求 * 微信请求
* @param message * @param message
* 微信消息 * 微信消息
* @param nodeNames
* 节点名称集合
* @param handler * @param handler
* 消息处理器 * 消息处理器
* @return 返回true执行下一个拦截器 * @return 返回true执行下一个拦截器
* @throws WeixinException * @throws WeixinException
*/ */
boolean preHandle(ChannelHandlerContext context, WeixinRequest request, boolean preHandle(ChannelHandlerContext context, WeixinRequest request,
Object message, WeixinMessageHandler handler) Object message, Set<String> nodeNames, WeixinMessageHandler handler)
throws WeixinException; throws WeixinException;
/** /**
@ -47,12 +51,14 @@ public interface WeixinMessageInterceptor {
* 微信响应 * 微信响应
* @param message * @param message
* 微信消息 * 微信消息
* @param nodeNames
* 节点名称集合
* @param handler * @param handler
* 消息处理器 * 消息处理器
* @throws WeixinException * @throws WeixinException
*/ */
void postHandle(ChannelHandlerContext context, WeixinRequest request, void postHandle(ChannelHandlerContext context, WeixinRequest request,
WeixinResponse response, Object message, WeixinResponse response, Object message, Set<String> nodeNames,
WeixinMessageHandler handler) throws WeixinException; WeixinMessageHandler handler) throws WeixinException;
/** /**
@ -64,6 +70,8 @@ public interface WeixinMessageInterceptor {
* 微信请求 * 微信请求
* @param message * @param message
* 微信消息 * 微信消息
* @param nodeNames
* 节点名称集合
* @param handler * @param handler
* 消息处理器 * 消息处理器
* @param exception * @param exception
@ -71,6 +79,7 @@ public interface WeixinMessageInterceptor {
* @throws WeixinException * @throws WeixinException
*/ */
void afterCompletion(ChannelHandlerContext context, WeixinRequest request, void afterCompletion(ChannelHandlerContext context, WeixinRequest request,
Object message, WeixinMessageHandler handler, Object message, Set<String> nodeNames,
WeixinException exception) throws WeixinException; WeixinMessageHandler handler, WeixinException exception)
throws WeixinException;
} }

View File

@ -18,6 +18,7 @@ import com.foxinmy.weixin4j.util.AesToken;
import com.foxinmy.weixin4j.util.Consts; import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.HttpUtil; import com.foxinmy.weixin4j.util.HttpUtil;
import com.foxinmy.weixin4j.util.MessageUtil; import com.foxinmy.weixin4j.util.MessageUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.CruxMessageHandler; import com.foxinmy.weixin4j.xml.CruxMessageHandler;
/** /**
@ -36,8 +37,7 @@ public class WeixinRequestHandler extends
private final WeixinMessageDispatcher messageDispatcher; private final WeixinMessageDispatcher messageDispatcher;
public WeixinRequestHandler(WeixinMessageDispatcher messageDispatcher) public WeixinRequestHandler(WeixinMessageDispatcher messageDispatcher) {
throws WeixinException {
this.messageDispatcher = messageDispatcher; this.messageDispatcher = messageDispatcher;
} }
@ -70,9 +70,10 @@ public class WeixinRequestHandler extends
.addListener(ChannelFutureListener.CLOSE); .addListener(ChannelFutureListener.CLOSE);
return; return;
} else if (request.getMethod().equals(HttpMethod.POST.name())) { } else if (request.getMethod().equals(HttpMethod.POST.name())) {
if (!MessageUtil.signature(aesToken.getToken(), if (!StringUtil.isBlank(request.getSignature())
request.getTimeStamp(), request.getNonce()).equals( && !MessageUtil.signature(aesToken.getToken(),
request.getSignature())) { request.getTimeStamp(), request.getNonce()).equals(
request.getSignature())) {
ctx.writeAndFlush( ctx.writeAndFlush(
HttpUtil.createHttpResponse(null, FORBIDDEN, null)) HttpUtil.createHttpResponse(null, FORBIDDEN, null))
.addListener(ChannelFutureListener.CLOSE); .addListener(ChannelFutureListener.CLOSE);
@ -103,4 +104,6 @@ public class WeixinRequestHandler extends
ctx.channel().attr(Consts.MESSAGE_TRANSFER_KEY).set(messageTransfer); ctx.channel().attr(Consts.MESSAGE_TRANSFER_KEY).set(messageTransfer);
messageDispatcher.doDispatch(ctx, request, cruxMessage); messageDispatcher.doDispatch(ctx, request, cruxMessage);
} }
} }

View File

@ -36,7 +36,7 @@ public class WeixinServerInitializer extends ChannelInitializer<SocketChannel> {
} }
@Override @Override
protected void initChannel(SocketChannel channel) throws WeixinException { protected void initChannel(SocketChannel channel) {
ChannelPipeline pipeline = channel.pipeline(); ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65536)); pipeline.addLast(new HttpObjectAggregator(65536));

View File

@ -1,26 +0,0 @@
package com.foxinmy.weixin4j.suite;
/**
* 应用套件回调事件
*
* @className SuiteEventType
* @author jy
* @date 2015年6月21日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AC%AC%E4%B8%89%E6%96%B9%E5%9B%9E%E8%B0%83%E5%8D%8F%E8%AE%AE">第三方回调协议</a>
*/
public enum SuiteEventType {
/**
* 推送ticket
*/
suite_ticket,
/**
* 变更授权
*/
change_auth,
/**
* 取消授权
*/
cancel_auth;
}

View File

@ -1,23 +0,0 @@
package com.foxinmy.weixin4j.suite;
import com.foxinmy.weixin4j.response.SingleResponse;
/**
* 处理第三方应用套件请求
*
* @className SuiteMessageHandler
* @author jy
* @date 2015年6月23日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AC%AC%E4%B8%89%E6%96%B9%E5%9B%9E%E8%B0%83%E5%8D%8F%E8%AE%AE">套件回调协议</a>
*/
public interface SuiteMessageHandler {
/**
* 处理套件消息
*
* @param suiteMessage
* @return
*/
public SingleResponse handle(WeixinSuiteMessage suiteMessage);
}

View File

@ -1,76 +0,0 @@
package com.foxinmy.weixin4j.suite;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* 套件消息
*
* @className WeixinSuiteMessage
* @author jy
* @date 2015年6月23日
* @since JDK 1.7
* @see
*/
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
public class WeixinSuiteMessage implements Serializable {
private static final long serialVersionUID = 6457919241019021514L;
/**
* 应用套件的SuiteId
*/
@XmlElement(name = "SuiteId")
private String suiteId;
/**
* 事件类型
*/
@XmlElement(name = "InfoType")
private SuiteEventType eventType;
/**
* 时间戳
*/
@XmlElement(name = "TimeStamp")
private long timeStamp;
/**
* Ticket内容
*/
@XmlElement(name = "SuiteTicket")
private String SuiteTicket;
/**
* 授权方企业号的corpid
*/
@XmlElement(name = "AuthCorpId")
private String authCorpId;
public String getSuiteId() {
return suiteId;
}
public SuiteEventType getEventType() {
return eventType;
}
public long getTimeStamp() {
return timeStamp;
}
public String getSuiteTicket() {
return SuiteTicket;
}
public String getAuthCorpId() {
return authCorpId;
}
@Override
public String toString() {
return "WeixinSuiteMessage [suiteId=" + suiteId + ", eventType="
+ eventType + ", timeStamp=" + timeStamp + ", SuiteTicket="
+ SuiteTicket + ", authCorpId=" + authCorpId + "]";
}
}

View File

@ -2,6 +2,8 @@ package com.foxinmy.weixin4j.xml;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import org.xml.sax.InputSource; import org.xml.sax.InputSource;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -28,7 +30,8 @@ public class CruxMessageHandler extends DefaultHandler {
private String toUserName; private String toUserName;
private String msgType; private String msgType;
private String eventType; private String eventType;
private String agentId; private boolean agentId;
private Set<String> nodeNames;
private String content; private String content;
@ -38,12 +41,14 @@ public class CruxMessageHandler extends DefaultHandler {
toUserName = null; toUserName = null;
msgType = null; msgType = null;
eventType = null; eventType = null;
agentId = null; agentId = false;
nodeNames = new HashSet<String>();
} }
@Override @Override
public void endElement(String uri, String localName, String qName) public void endElement(String uri, String localName, String qName)
throws SAXException { throws SAXException {
nodeNames.add(localName.toLowerCase());
if (localName.equalsIgnoreCase("fromUserName")) { if (localName.equalsIgnoreCase("fromUserName")) {
fromUserName = content; fromUserName = content;
} else if (localName.equalsIgnoreCase("toUserName")) { } else if (localName.equalsIgnoreCase("toUserName")) {
@ -53,7 +58,7 @@ public class CruxMessageHandler extends DefaultHandler {
} else if (localName.equalsIgnoreCase("event")) { } else if (localName.equalsIgnoreCase("event")) {
eventType = content.toLowerCase(); eventType = content.toLowerCase();
} else if (localName.equalsIgnoreCase("agentId")) { } else if (localName.equalsIgnoreCase("agentId")) {
agentId = content; agentId = true;
} }
} }
@ -64,7 +69,13 @@ public class CruxMessageHandler extends DefaultHandler {
} }
public AccountType getAccountType() { public AccountType getAccountType() {
return StringUtil.isBlank(agentId) ? AccountType.MP : AccountType.QY; if (agentId) {
return AccountType.QY;
}
if (StringUtil.isBlank(msgType) && StringUtil.isBlank(eventType)) {
return null;
}
return AccountType.MP;
} }
public String getMsgType() { public String getMsgType() {
@ -83,6 +94,10 @@ public class CruxMessageHandler extends DefaultHandler {
return toUserName; return toUserName;
} }
public Set<String> getNodeNames() {
return nodeNames;
}
private static CruxMessageHandler global = new CruxMessageHandler(); private static CruxMessageHandler global = new CruxMessageHandler();
public static CruxMessageHandler parser(String xmlContent) public static CruxMessageHandler parser(String xmlContent)

View File

@ -2,6 +2,8 @@ package com.foxinmy.weixin4j.server.test;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import java.util.Set;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.handler.BlankMessageHandler; import com.foxinmy.weixin4j.handler.BlankMessageHandler;
import com.foxinmy.weixin4j.handler.DebugMessageHandler; import com.foxinmy.weixin4j.handler.DebugMessageHandler;
@ -88,7 +90,8 @@ public class MessageServerStartup {
@Override @Override
public boolean preHandle(ChannelHandlerContext context, public boolean preHandle(ChannelHandlerContext context,
WeixinRequest request, Object message, WeixinRequest request, Object message,
WeixinMessageHandler handler) throws WeixinException { Set<String> nodeNames, WeixinMessageHandler handler)
throws WeixinException {
context.writeAndFlush(new TextResponse("所有消息被拦截了!")); context.writeAndFlush(new TextResponse("所有消息被拦截了!"));
return false; return false;
} }
@ -96,16 +99,16 @@ public class MessageServerStartup {
@Override @Override
public void postHandle(ChannelHandlerContext context, public void postHandle(ChannelHandlerContext context,
WeixinRequest request, WeixinResponse response, WeixinRequest request, WeixinResponse response,
Object message, WeixinMessageHandler handler) Object message, Set<String> nodeNames,
throws WeixinException { WeixinMessageHandler handler) throws WeixinException {
System.err.println("preHandle返回为true,执行handler后"); System.err.println("preHandle返回为true,执行handler后");
} }
@Override @Override
public void afterCompletion(ChannelHandlerContext context, public void afterCompletion(ChannelHandlerContext context,
WeixinRequest request, Object message, WeixinRequest request, Object message,
WeixinMessageHandler handler, WeixinException exception) Set<String> nodeNames, WeixinMessageHandler handler,
throws WeixinException { WeixinException exception) throws WeixinException {
System.err.println("请求处理完毕"); System.err.println("请求处理完毕");
} }
}; };