removed WeixinException class
This commit is contained in:
parent
4c0f96fcfe
commit
3c92d75276
@ -66,16 +66,12 @@ public class Weixin4jServerStartupWithThread implements ApplicationContextAware
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
bootstrap = new WeixinServerBootstrap(aesToken) // 指定开发者token信息。
|
||||
.handlerPackagesToScan(handlerPackage) // 扫描处理消息的包。
|
||||
.resolveBeanFactory(new SpringBeanFactory(applicationContext)) // 声明处理消息类由Spring容器去实例化。
|
||||
.addHandler(DebugMessageHandler.global) // 当没有匹配到消息处理时输出调试信息,开发环境打开。
|
||||
.openAlwaysResponse(); // 当没有匹配到消息处理时输出空白回复(公众号不会出现「该公众号无法提供服务的提示」),正式环境打开。
|
||||
bootstrap.startup(port); // 绑定服务的端口号,即对外暴露(微信服务器URL地址)的服务端口。
|
||||
} catch (WeixinException e) {
|
||||
InternalLoggerFactory.getInstance(getClass()).error("weixin4j server startup:FAIL", e);
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.example.server.handler;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.qy.chat.WeixinChatMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
@ -13,15 +12,12 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
public class ChatMessageHandler implements WeixinMessageHandler {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException {
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return nodeNames.contains("PackageId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request,
|
||||
WeixinMessage message, Set<String> nodeNames)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
WeixinChatMessage chatMessage = null; // 转换为实体
|
||||
return BlankResponse.global;
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
/**
|
||||
* 自定义处理消息
|
||||
*
|
||||
* @className CustomMessageHandler
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2017年1月19日
|
||||
@ -20,16 +21,13 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
public class CustomMessageHandler implements WeixinMessageHandler {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException {
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
// 消息来源某个用户
|
||||
return message.getFromUserName().equals("xxx");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request,
|
||||
WeixinMessage message, Set<String> nodeNames)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return new TextResponse("是你,是你,还是你。");
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.example.server.handler;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.message.TextMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.TextResponse;
|
||||
@ -20,8 +19,7 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
public class HelloMessageHandler extends TextMessageHandler {
|
||||
|
||||
@Override
|
||||
public boolean canHandle0(WeixinRequest request, TextMessage message)
|
||||
throws WeixinException {
|
||||
public boolean canHandle0(WeixinRequest request, TextMessage message) {
|
||||
/**
|
||||
* 用户输入hello时
|
||||
*/
|
||||
@ -29,8 +27,7 @@ public class HelloMessageHandler extends TextMessageHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle0(WeixinRequest request, TextMessage message)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle0(WeixinRequest request, TextMessage message) {
|
||||
/**
|
||||
* 返回用户「world」文本
|
||||
*/
|
||||
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.example.server.handler;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.MessageHandlerAdapter;
|
||||
import com.foxinmy.weixin4j.mp.event.ScribeEventMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
@ -18,12 +17,10 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
* @since JDK 1.6
|
||||
*/
|
||||
@Component
|
||||
public class SubscribeMessageHandler extends
|
||||
MessageHandlerAdapter<ScribeEventMessage> {
|
||||
public class SubscribeMessageHandler extends MessageHandlerAdapter<ScribeEventMessage> {
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle0(WeixinRequest request, ScribeEventMessage message)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle0(WeixinRequest request, ScribeEventMessage message) {
|
||||
return new TextResponse("欢迎关注~");
|
||||
}
|
||||
}
|
||||
|
||||
@ -20,8 +20,7 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
@Component
|
||||
public class TextMessageHandler extends MessageHandlerAdapter<TextMessage> {
|
||||
@Override
|
||||
public WeixinResponse doHandle0(WeixinRequest request, TextMessage message)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle0(WeixinRequest request, TextMessage message) {
|
||||
return new TextResponse("收到了文本消息");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.example.server.handler;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.MessageHandlerAdapter;
|
||||
import com.foxinmy.weixin4j.message.VoiceMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
@ -21,8 +20,7 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
public class VoiceMessageHandler extends MessageHandlerAdapter<VoiceMessage> {
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle0(WeixinRequest request, VoiceMessage message)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle0(WeixinRequest request, VoiceMessage message) {
|
||||
/**
|
||||
* 返回一段文字给用户
|
||||
*/
|
||||
|
||||
@ -2,8 +2,6 @@ package com.foxinmy.weixin4j.dispatcher;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
/**
|
||||
* Bean构造
|
||||
*
|
||||
@ -14,11 +12,11 @@ import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
* @see
|
||||
*/
|
||||
public interface BeanFactory {
|
||||
Object getBean(String name) throws WeixinException;
|
||||
Object getBean(String name);
|
||||
|
||||
<T> T getBean(Class<T> clazz) throws WeixinException;
|
||||
<T> T getBean(Class<T> clazz);
|
||||
|
||||
<T> T getBean(String name, Class<T> clazz) throws WeixinException;
|
||||
<T> T getBean(String name, Class<T> clazz);
|
||||
|
||||
<T> Map<String, T> getBeans(Class<T> clazz) throws WeixinException;
|
||||
<T> Map<String, T> getBeans(Class<T> clazz);
|
||||
}
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
package com.foxinmy.weixin4j.dispatcher;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
/**
|
||||
* 微信消息的处理执行
|
||||
*
|
||||
@ -63,8 +62,7 @@ public class MessageHandlerExecutor {
|
||||
* @return true则继续执行往下执行
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public boolean applyPreHandle(WeixinRequest request, WeixinMessage message)
|
||||
throws WeixinException {
|
||||
public boolean applyPreHandle(WeixinRequest request, WeixinMessage message){
|
||||
if (messageInterceptors != null) {
|
||||
for (int i = 0; i < messageInterceptors.length; i++) {
|
||||
WeixinMessageInterceptor interceptor = messageInterceptors[i];
|
||||
@ -91,7 +89,7 @@ public class MessageHandlerExecutor {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void applyPostHandle(WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message) throws WeixinException {
|
||||
WeixinMessage message){
|
||||
if (messageInterceptors == null) {
|
||||
return;
|
||||
}
|
||||
@ -117,7 +115,7 @@ public class MessageHandlerExecutor {
|
||||
*/
|
||||
public void triggerAfterCompletion(WeixinRequest request,
|
||||
WeixinResponse response, WeixinMessage message, Exception exception)
|
||||
throws WeixinException {
|
||||
{
|
||||
if (messageInterceptors == null) {
|
||||
return;
|
||||
}
|
||||
@ -126,7 +124,7 @@ public class MessageHandlerExecutor {
|
||||
try {
|
||||
interceptor.afterCompletion(context, request, response,
|
||||
message, messageHandler, exception);
|
||||
} catch (WeixinException e) {
|
||||
} catch (Exception e) {
|
||||
logger.error(
|
||||
"MessageInterceptor.afterCompletion threw exception", e);
|
||||
}
|
||||
|
||||
@ -1,12 +1,6 @@
|
||||
package com.foxinmy.weixin4j.dispatcher;
|
||||
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
@ -26,7 +20,6 @@ import javax.xml.bind.Unmarshaller;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
@ -39,6 +32,13 @@ import com.foxinmy.weixin4j.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
import com.foxinmy.weixin4j.xml.MessageTransferHandler;
|
||||
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.http.DefaultFullHttpResponse;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
/**
|
||||
* 微信消息分发器
|
||||
*
|
||||
@ -54,8 +54,7 @@ import com.foxinmy.weixin4j.xml.MessageTransferHandler;
|
||||
*/
|
||||
public class WeixinMessageDispatcher {
|
||||
|
||||
private final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(getClass());
|
||||
private final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
|
||||
|
||||
/**
|
||||
* 消息处理器
|
||||
@ -112,25 +111,18 @@ public class WeixinMessageDispatcher {
|
||||
* @param request
|
||||
* 微信请求
|
||||
* @param messageTransfer
|
||||
* 微信消息
|
||||
* @throws WeixinException
|
||||
* 微信消息 @
|
||||
*/
|
||||
public void doDispatch(final ChannelHandlerContext context,
|
||||
final WeixinRequest request) throws WeixinException {
|
||||
WeixinMessageTransfer messageTransfer = MessageTransferHandler
|
||||
.parser(request);
|
||||
context.channel().attr(ServerToolkits.MESSAGE_TRANSFER_KEY)
|
||||
.set(messageTransfer);
|
||||
public void doDispatch(final ChannelHandlerContext context, final WeixinRequest request) {
|
||||
WeixinMessageTransfer messageTransfer = MessageTransferHandler.parser(request);
|
||||
context.channel().attr(ServerToolkits.MESSAGE_TRANSFER_KEY).set(messageTransfer);
|
||||
WeixinMessageKey messageKey = defineMessageKey(messageTransfer, request);
|
||||
Class<? extends WeixinMessage> targetClass = messageMatcher
|
||||
.match(messageKey);
|
||||
WeixinMessage message = messageRead(request.getOriginalContent(),
|
||||
targetClass);
|
||||
Class<? extends WeixinMessage> targetClass = messageMatcher.match(messageKey);
|
||||
WeixinMessage message = messageRead(request.getOriginalContent(), targetClass);
|
||||
logger.info("define '{}' matched '{}'", messageKey, targetClass);
|
||||
MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context,
|
||||
request, messageKey, message, messageTransfer.getNodeNames());
|
||||
if (handlerExecutor == null
|
||||
|| handlerExecutor.getMessageHandler() == null) {
|
||||
MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context, request, messageKey, message,
|
||||
messageTransfer.getNodeNames());
|
||||
if (handlerExecutor == null || handlerExecutor.getMessageHandler() == null) {
|
||||
noHandlerFound(context, request, message);
|
||||
return;
|
||||
}
|
||||
@ -140,15 +132,13 @@ public class WeixinMessageDispatcher {
|
||||
Exception exception = null;
|
||||
WeixinResponse response = null;
|
||||
try {
|
||||
response = handlerExecutor.getMessageHandler().doHandle(request,
|
||||
message, messageTransfer.getNodeNames());
|
||||
response = handlerExecutor.getMessageHandler().doHandle(request, message, messageTransfer.getNodeNames());
|
||||
handlerExecutor.applyPostHandle(request, response, message);
|
||||
context.writeAndFlush(response);
|
||||
} catch (Exception e) {
|
||||
exception = e;
|
||||
}
|
||||
handlerExecutor.triggerAfterCompletion(request, response, message,
|
||||
exception);
|
||||
handlerExecutor.triggerAfterCompletion(request, response, message, exception);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -160,10 +150,8 @@ public class WeixinMessageDispatcher {
|
||||
* 请求信息
|
||||
* @return
|
||||
*/
|
||||
protected WeixinMessageKey defineMessageKey(
|
||||
WeixinMessageTransfer messageTransfer, WeixinRequest request) {
|
||||
return new WeixinMessageKey(messageTransfer.getMsgType(),
|
||||
messageTransfer.getEventType(),
|
||||
protected WeixinMessageKey defineMessageKey(WeixinMessageTransfer messageTransfer, WeixinRequest request) {
|
||||
return new WeixinMessageKey(messageTransfer.getMsgType(), messageTransfer.getEventType(),
|
||||
messageTransfer.getAccountType());
|
||||
}
|
||||
|
||||
@ -177,17 +165,14 @@ public class WeixinMessageDispatcher {
|
||||
* @param message
|
||||
* 微信消息
|
||||
*/
|
||||
protected void noHandlerFound(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinMessage message) {
|
||||
protected void noHandlerFound(ChannelHandlerContext context, WeixinRequest request, WeixinMessage message) {
|
||||
logger.warn("no handler found for {}", request);
|
||||
if (alwaysResponse) {
|
||||
context.write(BlankResponse.global);
|
||||
} else {
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(
|
||||
request.getProtocolVersion(), NOT_FOUND);
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(request.getProtocolVersion(), NOT_FOUND);
|
||||
HttpUtil.resolveHeaders(response);
|
||||
context.writeAndFlush(response).addListener(
|
||||
ChannelFutureListener.CLOSE);
|
||||
context.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,13 +190,10 @@ public class WeixinMessageDispatcher {
|
||||
* @param nodeNames
|
||||
* 节点名称集合
|
||||
* @return MessageHandlerExecutor
|
||||
* @see MessageHandlerExecutor
|
||||
* @throws WeixinException
|
||||
* @see MessageHandlerExecutor @
|
||||
*/
|
||||
protected MessageHandlerExecutor getHandlerExecutor(
|
||||
ChannelHandlerContext context, WeixinRequest request,
|
||||
WeixinMessageKey messageKey, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException {
|
||||
protected MessageHandlerExecutor getHandlerExecutor(ChannelHandlerContext context, WeixinRequest request,
|
||||
WeixinMessageKey messageKey, WeixinMessage message, Set<String> nodeNames) {
|
||||
WeixinMessageHandler[] messageHandlers = getMessageHandlers();
|
||||
if (messageHandlers == null) {
|
||||
return null;
|
||||
@ -226,52 +208,41 @@ public class WeixinMessageDispatcher {
|
||||
if (matchedMessageHandlers.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Collections.sort(matchedMessageHandlers,
|
||||
new Comparator<WeixinMessageHandler>() {
|
||||
Collections.sort(matchedMessageHandlers, new Comparator<WeixinMessageHandler>() {
|
||||
@Override
|
||||
public int compare(WeixinMessageHandler m1,
|
||||
WeixinMessageHandler m2) {
|
||||
public int compare(WeixinMessageHandler m1, WeixinMessageHandler m2) {
|
||||
return m2.weight() - m1.weight();
|
||||
}
|
||||
});
|
||||
logger.info("matched message handlers '{}'", matchedMessageHandlers);
|
||||
return new MessageHandlerExecutor(context,
|
||||
matchedMessageHandlers.get(0), getMessageInterceptors());
|
||||
return new MessageHandlerExecutor(context, matchedMessageHandlers.get(0), getMessageInterceptors());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有的handler
|
||||
*
|
||||
* @return handler集合
|
||||
* @see com.foxinmy.weixin4j.handler.WeixinMessageHandler
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.handler.WeixinMessageHandler @
|
||||
*/
|
||||
public WeixinMessageHandler[] getMessageHandlers() throws WeixinException {
|
||||
public WeixinMessageHandler[] getMessageHandlers() {
|
||||
if (this.messageHandlers == null) {
|
||||
if (messageHandlerPackages != null) {
|
||||
List<Class<?>> messageHandlerClass = new ArrayList<Class<?>>();
|
||||
for (String packageName : messageHandlerPackages) {
|
||||
messageHandlerClass.addAll(ClassUtil
|
||||
.getClasses(packageName));
|
||||
messageHandlerClass.addAll(ClassUtil.getClasses(packageName));
|
||||
}
|
||||
if (beanFactory != null) {
|
||||
for (Class<?> clazz : messageHandlerClass) {
|
||||
if (clazz.isInterface()
|
||||
|| Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageHandler.class
|
||||
.isAssignableFrom(clazz)) {
|
||||
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageHandler.class.isAssignableFrom(clazz)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
messageHandlerList
|
||||
.add((WeixinMessageHandler) beanFactory
|
||||
.getBean(clazz));
|
||||
messageHandlerList.add((WeixinMessageHandler) beanFactory.getBean(clazz));
|
||||
} catch (RuntimeException ex) { // multiple
|
||||
for (Object o : beanFactory.getBeans(clazz)
|
||||
.values()) {
|
||||
for (Object o : beanFactory.getBeans(clazz).values()) {
|
||||
if (o.getClass() == clazz) {
|
||||
messageHandlerList
|
||||
.add((WeixinMessageHandler) o);
|
||||
messageHandlerList.add((WeixinMessageHandler) o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -279,30 +250,23 @@ public class WeixinMessageDispatcher {
|
||||
}
|
||||
} else {
|
||||
for (Class<?> clazz : messageHandlerClass) {
|
||||
if (clazz.isInterface()
|
||||
|| Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageHandler.class
|
||||
.isAssignableFrom(clazz)) {
|
||||
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageHandler.class.isAssignableFrom(clazz)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Constructor<?> ctor = clazz
|
||||
.getDeclaredConstructor();
|
||||
Constructor<?> ctor = clazz.getDeclaredConstructor();
|
||||
ServerToolkits.makeConstructorAccessible(ctor);
|
||||
messageHandlerList.add((WeixinMessageHandler) ctor
|
||||
.newInstance((Object[]) null));
|
||||
messageHandlerList.add((WeixinMessageHandler) ctor.newInstance((Object[]) null));
|
||||
} catch (Exception ex) {
|
||||
throw new WeixinException(clazz.getName()
|
||||
+ " instantiate fail", ex);
|
||||
throw new RuntimeException(clazz.getName() + " instantiate fail", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (messageHandlerList != null
|
||||
&& !this.messageHandlerList.isEmpty()) {
|
||||
if (messageHandlerList != null && !this.messageHandlerList.isEmpty()) {
|
||||
this.messageHandlers = this.messageHandlerList
|
||||
.toArray(new WeixinMessageHandler[this.messageHandlerList
|
||||
.size()]);
|
||||
.toArray(new WeixinMessageHandler[this.messageHandlerList.size()]);
|
||||
}
|
||||
}
|
||||
return this.messageHandlers;
|
||||
@ -312,36 +276,27 @@ public class WeixinMessageDispatcher {
|
||||
* 获取所有的interceptor
|
||||
*
|
||||
* @return interceptor集合
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor
|
||||
* @ @see com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor
|
||||
*/
|
||||
public WeixinMessageInterceptor[] getMessageInterceptors()
|
||||
throws WeixinException {
|
||||
public WeixinMessageInterceptor[] getMessageInterceptors() {
|
||||
if (this.messageInterceptors == null) {
|
||||
if (this.messageInterceptorPackages != null) {
|
||||
List<Class<?>> messageInterceptorClass = new ArrayList<Class<?>>();
|
||||
for (String packageName : messageInterceptorPackages) {
|
||||
messageInterceptorClass.addAll(ClassUtil
|
||||
.getClasses(packageName));
|
||||
messageInterceptorClass.addAll(ClassUtil.getClasses(packageName));
|
||||
}
|
||||
if (beanFactory != null) {
|
||||
for (Class<?> clazz : messageInterceptorClass) {
|
||||
if (clazz.isInterface()
|
||||
|| Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageInterceptor.class
|
||||
.isAssignableFrom(clazz)) {
|
||||
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageInterceptor.class.isAssignableFrom(clazz)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
messageInterceptorList
|
||||
.add((WeixinMessageInterceptor) beanFactory
|
||||
.getBean(clazz));
|
||||
messageInterceptorList.add((WeixinMessageInterceptor) beanFactory.getBean(clazz));
|
||||
} catch (RuntimeException ex) { // multiple
|
||||
for (Object o : beanFactory.getBeans(clazz)
|
||||
.values()) {
|
||||
for (Object o : beanFactory.getBeans(clazz).values()) {
|
||||
if (o.getClass() == clazz) {
|
||||
messageInterceptorList
|
||||
.add((WeixinMessageInterceptor) o);
|
||||
messageInterceptorList.add((WeixinMessageInterceptor) o);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -349,43 +304,32 @@ public class WeixinMessageDispatcher {
|
||||
}
|
||||
} else {
|
||||
for (Class<?> clazz : messageInterceptorClass) {
|
||||
if (clazz.isInterface()
|
||||
|| Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageInterceptor.class
|
||||
.isAssignableFrom(clazz)) {
|
||||
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())
|
||||
|| !WeixinMessageInterceptor.class.isAssignableFrom(clazz)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
Constructor<?> ctor = clazz
|
||||
.getDeclaredConstructor();
|
||||
Constructor<?> ctor = clazz.getDeclaredConstructor();
|
||||
ServerToolkits.makeConstructorAccessible(ctor);
|
||||
messageInterceptorList
|
||||
.add((WeixinMessageInterceptor) ctor
|
||||
.newInstance((Object[]) null));
|
||||
messageInterceptorList.add((WeixinMessageInterceptor) ctor.newInstance((Object[]) null));
|
||||
} catch (Exception ex) {
|
||||
throw new WeixinException(clazz.getName()
|
||||
+ " instantiate fail", ex);
|
||||
throw new RuntimeException(clazz.getName() + " instantiate fail", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.messageInterceptorList != null
|
||||
&& !this.messageInterceptorList.isEmpty()) {
|
||||
Collections.sort(messageInterceptorList,
|
||||
new Comparator<WeixinMessageInterceptor>() {
|
||||
if (this.messageInterceptorList != null && !this.messageInterceptorList.isEmpty()) {
|
||||
Collections.sort(messageInterceptorList, new Comparator<WeixinMessageInterceptor>() {
|
||||
@Override
|
||||
public int compare(WeixinMessageInterceptor m1,
|
||||
WeixinMessageInterceptor m2) {
|
||||
public int compare(WeixinMessageInterceptor m1, WeixinMessageInterceptor m2) {
|
||||
return m2.weight() - m1.weight();
|
||||
}
|
||||
});
|
||||
this.messageInterceptors = this.messageInterceptorList
|
||||
.toArray(new WeixinMessageInterceptor[this.messageInterceptorList
|
||||
.size()]);
|
||||
.toArray(new WeixinMessageInterceptor[this.messageInterceptorList.size()]);
|
||||
}
|
||||
}
|
||||
logger.info("resolve message interceptors '{}'",
|
||||
this.messageInterceptorList);
|
||||
logger.info("resolve message interceptors '{}'", this.messageInterceptorList);
|
||||
return this.messageInterceptors;
|
||||
}
|
||||
|
||||
@ -396,22 +340,18 @@ public class WeixinMessageDispatcher {
|
||||
* xml消息
|
||||
* @param clazz
|
||||
* 消息类型
|
||||
* @return 消息对象
|
||||
* @throws WeixinException
|
||||
* @return 消息对象 @
|
||||
*/
|
||||
protected <M extends WeixinMessage> M messageRead(String message,
|
||||
Class<M> clazz) throws WeixinException {
|
||||
protected <M extends WeixinMessage> M messageRead(String message, Class<M> clazz) {
|
||||
if (clazz == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
Source source = new StreamSource(new ByteArrayInputStream(
|
||||
ServerToolkits.getBytesUtf8(message)));
|
||||
JAXBElement<M> jaxbElement = getUnmarshaller(clazz).unmarshal(
|
||||
source, clazz);
|
||||
Source source = new StreamSource(new ByteArrayInputStream(ServerToolkits.getBytesUtf8(message)));
|
||||
JAXBElement<M> jaxbElement = getUnmarshaller(clazz).unmarshal(source, clazz);
|
||||
return jaxbElement.getValue();
|
||||
} catch (JAXBException e) {
|
||||
throw new WeixinException(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -420,11 +360,9 @@ public class WeixinMessageDispatcher {
|
||||
*
|
||||
* @param clazz
|
||||
* 消息类型
|
||||
* @return 消息转换器
|
||||
* @throws WeixinException
|
||||
* @return 消息转换器 @
|
||||
*/
|
||||
protected Unmarshaller getUnmarshaller(Class<? extends WeixinMessage> clazz)
|
||||
throws WeixinException {
|
||||
protected Unmarshaller getUnmarshaller(Class<? extends WeixinMessage> clazz) {
|
||||
Unmarshaller unmarshaller = messageUnmarshaller.get(clazz);
|
||||
if (unmarshaller == null) {
|
||||
try {
|
||||
@ -432,19 +370,17 @@ public class WeixinMessageDispatcher {
|
||||
unmarshaller = jaxbContext.createUnmarshaller();
|
||||
messageUnmarshaller.put(clazz, unmarshaller);
|
||||
} catch (JAXBException e) {
|
||||
throw new WeixinException(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return unmarshaller;
|
||||
}
|
||||
|
||||
public void setMessageHandlerList(
|
||||
List<WeixinMessageHandler> messageHandlerList) {
|
||||
public void setMessageHandlerList(List<WeixinMessageHandler> messageHandlerList) {
|
||||
this.messageHandlerList = messageHandlerList;
|
||||
}
|
||||
|
||||
public void setMessageInterceptorList(
|
||||
List<WeixinMessageInterceptor> messageInterceptorList) {
|
||||
public void setMessageInterceptorList(List<WeixinMessageInterceptor> messageInterceptorList) {
|
||||
this.messageInterceptorList = messageInterceptorList;
|
||||
}
|
||||
|
||||
@ -460,8 +396,7 @@ public class WeixinMessageDispatcher {
|
||||
this.messageHandlerPackages = messageHandlerPackages;
|
||||
}
|
||||
|
||||
public void setMessageInterceptorPackages(
|
||||
String... messageInterceptorPackages) {
|
||||
public void setMessageInterceptorPackages(String... messageInterceptorPackages) {
|
||||
this.messageInterceptorPackages = messageInterceptorPackages;
|
||||
}
|
||||
|
||||
@ -473,8 +408,7 @@ public class WeixinMessageDispatcher {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
public void registMessageClass(WeixinMessageKey messageKey,
|
||||
Class<? extends WeixinMessage> messageClass) {
|
||||
public void registMessageClass(WeixinMessageKey messageKey, Class<? extends WeixinMessage> messageClass) {
|
||||
messageMatcher.regist(messageKey, messageClass);
|
||||
}
|
||||
|
||||
|
||||
@ -1,50 +0,0 @@
|
||||
package com.foxinmy.weixin4j.exception;
|
||||
|
||||
/**
|
||||
* 微信异常
|
||||
*
|
||||
* @className WeixinException
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年4月10日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class WeixinException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 7148145661883468514L;
|
||||
|
||||
private String errorCode;
|
||||
private String errorMsg;
|
||||
|
||||
public WeixinException(String errorCode, String errorMsg) {
|
||||
this.errorCode = errorCode;
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public WeixinException(String errorMsg) {
|
||||
this.errorCode = "-1";
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public WeixinException(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
public WeixinException(String errorMsg, Exception e) {
|
||||
super(e);
|
||||
this.errorMsg = errorMsg;
|
||||
}
|
||||
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
public String getErrorMsg() {
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return this.errorCode + "," + this.errorMsg;
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.handler;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.TextResponse;
|
||||
@ -26,16 +25,14 @@ public class DebugMessageHandler implements WeixinMessageHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException {
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException {
|
||||
String content = message == null ? request.getOriginalContent()
|
||||
.replaceAll("\\!\\[CDATA\\[", "").replaceAll("\\]\\]", "")
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
String content = message == null
|
||||
? request.getOriginalContent().replaceAll("\\!\\[CDATA\\[", "").replaceAll("\\]\\]", "")
|
||||
: message.toString();
|
||||
return new TextResponse(content);
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.handler;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
@ -18,14 +17,11 @@ import com.foxinmy.weixin4j.util.ClassUtil;
|
||||
* @see com.foxinmy.weixin4j.request.WeixinMessage
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public abstract class MessageHandlerAdapter<M extends WeixinMessage> implements
|
||||
WeixinMessageHandler {
|
||||
public abstract class MessageHandlerAdapter<M extends WeixinMessage> implements WeixinMessageHandler {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException {
|
||||
return message != null
|
||||
&& message.getClass() == ClassUtil.getGenericType(getClass())
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return message != null && message.getClass() == ClassUtil.getGenericType(getClass())
|
||||
&& canHandle0(request, (M) message);
|
||||
}
|
||||
|
||||
@ -36,18 +32,14 @@ public abstract class MessageHandlerAdapter<M extends WeixinMessage> implements
|
||||
* 微信请求
|
||||
* @param message
|
||||
* 微信消息
|
||||
* @return true则执行doHandler0
|
||||
* @throws WeixinException
|
||||
* @return true则执行doHandler0 @
|
||||
*/
|
||||
public boolean canHandle0(WeixinRequest request, M message)
|
||||
throws WeixinException {
|
||||
public boolean canHandle0(WeixinRequest request, M message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request,
|
||||
WeixinMessage message, Set<String> nodeNames)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return doHandle0(request, (M) message);
|
||||
}
|
||||
|
||||
@ -60,8 +52,7 @@ public abstract class MessageHandlerAdapter<M extends WeixinMessage> implements
|
||||
* 微信消息
|
||||
* @return
|
||||
*/
|
||||
public abstract WeixinResponse doHandle0(WeixinRequest request, M message)
|
||||
throws WeixinException;
|
||||
public abstract WeixinResponse doHandle0(WeixinRequest request, M message);
|
||||
|
||||
/**
|
||||
* 缺省值为1,存在多个匹配到的MessageHandler则比较weight大小
|
||||
|
||||
@ -3,7 +3,6 @@ package com.foxinmy.weixin4j.handler;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
|
||||
@ -32,8 +31,7 @@ public abstract class MultipleMessageHandlerAdapter implements WeixinMessageHand
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames)
|
||||
throws WeixinException {
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return message != null && messageClasses.contains(message.getClass()) && canHandle0(request, message);
|
||||
}
|
||||
|
||||
@ -47,7 +45,7 @@ public abstract class MultipleMessageHandlerAdapter implements WeixinMessageHand
|
||||
* @return true则执行doHandler
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public boolean canHandle0(WeixinRequest request, WeixinMessage message) throws WeixinException {
|
||||
public boolean canHandle0(WeixinRequest request, WeixinMessage message) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.handler;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
@ -30,8 +29,7 @@ public interface WeixinMessageHandler {
|
||||
* 节点名称集合
|
||||
* @return true则执行doHandle
|
||||
*/
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException;
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames);
|
||||
|
||||
/**
|
||||
* 处理请求
|
||||
@ -44,8 +42,7 @@ public interface WeixinMessageHandler {
|
||||
* 节点名称集合
|
||||
* @return 回复内容
|
||||
*/
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message,
|
||||
Set<String> nodeNames) throws WeixinException;
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames);
|
||||
|
||||
/**
|
||||
* 用于匹配到多个MessageHandler时权重降序排列,数字越大优先级越高
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
package com.foxinmy.weixin4j.interceptor;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
/**
|
||||
* 消息拦截适配
|
||||
*
|
||||
@ -17,27 +16,22 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public abstract class MessageInterceptorAdapter implements
|
||||
WeixinMessageInterceptor {
|
||||
public abstract class MessageInterceptorAdapter implements WeixinMessageInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinMessage message, WeixinMessageHandler handler)
|
||||
throws WeixinException {
|
||||
public boolean preHandle(ChannelHandlerContext context, WeixinRequest request, WeixinMessage message,
|
||||
WeixinMessageHandler handler) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinResponse response, WeixinMessage message,
|
||||
WeixinMessageHandler handler) throws WeixinException {
|
||||
public void postHandle(ChannelHandlerContext context, WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinResponse response, WeixinMessage message,
|
||||
WeixinMessageHandler handler, Exception exception)
|
||||
throws WeixinException {
|
||||
public void afterCompletion(ChannelHandlerContext context, WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler, Exception exception) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
package com.foxinmy.weixin4j.interceptor;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
/**
|
||||
* 微信消息拦截器
|
||||
*
|
||||
@ -34,8 +33,7 @@ public interface WeixinMessageInterceptor {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
boolean preHandle(ChannelHandlerContext context, WeixinRequest request,
|
||||
WeixinMessage message, WeixinMessageHandler handler)
|
||||
throws WeixinException;
|
||||
WeixinMessage message, WeixinMessageHandler handler);
|
||||
|
||||
/**
|
||||
* 执行handler后
|
||||
@ -54,7 +52,7 @@ public interface WeixinMessageInterceptor {
|
||||
*/
|
||||
void postHandle(ChannelHandlerContext context, WeixinRequest request,
|
||||
WeixinResponse response, WeixinMessage message,
|
||||
WeixinMessageHandler handler) throws WeixinException;
|
||||
WeixinMessageHandler handler);
|
||||
|
||||
/**
|
||||
* 全部执行后
|
||||
@ -73,8 +71,7 @@ public interface WeixinMessageInterceptor {
|
||||
*/
|
||||
void afterCompletion(ChannelHandlerContext context, WeixinRequest request,
|
||||
WeixinResponse response, WeixinMessage message,
|
||||
WeixinMessageHandler handler, Exception exception)
|
||||
throws WeixinException;
|
||||
WeixinMessageHandler handler, Exception exception);
|
||||
|
||||
/**
|
||||
* 用于匹配到多个MessageHandler时权重降序排列,数字越大优先级越高
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
package com.foxinmy.weixin4j.socket;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.response.SingleResponse;
|
||||
import com.foxinmy.weixin4j.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.response.SingleResponse;
|
||||
import com.foxinmy.weixin4j.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
|
||||
/**
|
||||
* 单一回复编码类
|
||||
*
|
||||
@ -23,18 +22,14 @@ import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
* @see com.foxinmy.weixin4j.response.SingleResponse
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
public class SingleResponseEncoder extends
|
||||
MessageToMessageEncoder<SingleResponse> {
|
||||
public class SingleResponseEncoder extends MessageToMessageEncoder<SingleResponse> {
|
||||
|
||||
private final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(getClass());
|
||||
private final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, SingleResponse response,
|
||||
List<Object> out) throws WeixinException {
|
||||
protected void encode(ChannelHandlerContext ctx, SingleResponse response, List<Object> out) {
|
||||
String content = response.toContent();
|
||||
ctx.writeAndFlush(HttpUtil.createHttpResponse(content,
|
||||
ServerToolkits.CONTENTTYPE$TEXT_PLAIN));
|
||||
ctx.writeAndFlush(HttpUtil.createHttpResponse(content, ServerToolkits.CONTENTTYPE$TEXT_PLAIN));
|
||||
logger.info("encode single response:{}", content);
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.util.AesToken;
|
||||
@ -50,7 +49,7 @@ public class WeixinMessageDecoder extends MessageToMessageDecoder<FullHttpReques
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, FullHttpRequest req, List<Object> out) throws WeixinException {
|
||||
protected void decode(ChannelHandlerContext ctx, FullHttpRequest req, List<Object> out) {
|
||||
String messageContent = req.content().toString(ServerToolkits.UTF_8);
|
||||
QueryStringDecoder queryDecoder = new QueryStringDecoder(req.uri(), true);
|
||||
HttpMethod method = req.method();
|
||||
@ -68,7 +67,7 @@ public class WeixinMessageDecoder extends MessageToMessageDecoder<FullHttpReques
|
||||
String encryptContent = null;
|
||||
if (!ServerToolkits.isBlank(messageContent) && encryptType == EncryptType.AES) {
|
||||
if (ServerToolkits.isBlank(aesToken.getAesKey())) {
|
||||
throw new WeixinException("EncodingAESKey not be empty in safety(AES) mode");
|
||||
throw new RuntimeException("EncodingAESKey not be empty in safety(AES) mode");
|
||||
}
|
||||
EncryptMessageHandler encryptHandler = EncryptMessageHandler.parser(messageContent);
|
||||
encryptContent = encryptHandler.getEncryptContent();
|
||||
|
||||
@ -3,6 +3,16 @@ package com.foxinmy.weixin4j.socket;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;
|
||||
import static io.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
|
||||
|
||||
import com.foxinmy.weixin4j.dispatcher.WeixinMessageDispatcher;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.SingleResponse;
|
||||
import com.foxinmy.weixin4j.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.util.AesToken;
|
||||
import com.foxinmy.weixin4j.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
@ -13,16 +23,6 @@ import io.netty.handler.codec.http.HttpResponseStatus;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import com.foxinmy.weixin4j.dispatcher.WeixinMessageDispatcher;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.request.WeixinRequest;
|
||||
import com.foxinmy.weixin4j.response.SingleResponse;
|
||||
import com.foxinmy.weixin4j.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.util.AesToken;
|
||||
import com.foxinmy.weixin4j.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
|
||||
/**
|
||||
* 微信请求处理类
|
||||
*
|
||||
@ -32,10 +32,8 @@ import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
* @since JDK 1.6
|
||||
* @see com.foxinmy.weixin4j.dispatcher.WeixinMessageDispatcher
|
||||
*/
|
||||
public class WeixinRequestHandler extends
|
||||
SimpleChannelInboundHandler<WeixinRequest> {
|
||||
private final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(getClass());
|
||||
public class WeixinRequestHandler extends SimpleChannelInboundHandler<WeixinRequest> {
|
||||
private final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
|
||||
|
||||
private final WeixinMessageDispatcher messageDispatcher;
|
||||
|
||||
@ -54,15 +52,12 @@ public class WeixinRequestHandler extends
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, WeixinRequest request)
|
||||
throws WeixinException {
|
||||
protected void channelRead0(ChannelHandlerContext ctx, WeixinRequest request) {
|
||||
AesToken aesToken = request.getAesToken();
|
||||
// 消息字段不完整返回400
|
||||
if (aesToken == null
|
||||
|| (ServerToolkits.isBlank(request.getSignature()) && ServerToolkits
|
||||
.isBlank(request.getMsgSignature()))) {
|
||||
ctx.writeAndFlush(resolveResponse(BAD_REQUEST, request))
|
||||
.addListener(ChannelFutureListener.CLOSE);
|
||||
if (aesToken == null || (ServerToolkits.isBlank(request.getSignature())
|
||||
&& ServerToolkits.isBlank(request.getMsgSignature()))) {
|
||||
ctx.writeAndFlush(resolveResponse(BAD_REQUEST, request)).addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
/**
|
||||
@ -73,58 +68,46 @@ public class WeixinRequestHandler extends
|
||||
if (request.getMethod() == HttpMethod.GET) {
|
||||
// URL参数签名验证
|
||||
if (!ServerToolkits.isBlank(request.getSignature())
|
||||
&& MessageUtil.signature(aesToken.getToken(),
|
||||
request.getTimeStamp(), request.getNonce()).equals(
|
||||
request.getSignature())) {
|
||||
&& MessageUtil.signature(aesToken.getToken(), request.getTimeStamp(), request.getNonce())
|
||||
.equals(request.getSignature())) {
|
||||
ctx.writeAndFlush(new SingleResponse(request.getEchoStr()));
|
||||
return;
|
||||
}
|
||||
// XML消息签名验证
|
||||
if (!ServerToolkits.isBlank(request.getMsgSignature())
|
||||
&& MessageUtil.signature(aesToken.getToken(),
|
||||
request.getTimeStamp(), request.getNonce(),
|
||||
request.getEchoStr()).equals(
|
||||
request.getMsgSignature())) {
|
||||
ctx.writeAndFlush(new SingleResponse(MessageUtil.aesDecrypt(
|
||||
null, aesToken.getAesKey(), request.getEchoStr())));
|
||||
if (!ServerToolkits.isBlank(request.getMsgSignature()) && MessageUtil
|
||||
.signature(aesToken.getToken(), request.getTimeStamp(), request.getNonce(), request.getEchoStr())
|
||||
.equals(request.getMsgSignature())) {
|
||||
ctx.writeAndFlush(
|
||||
new SingleResponse(MessageUtil.aesDecrypt(null, aesToken.getAesKey(), request.getEchoStr())));
|
||||
return;
|
||||
}
|
||||
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request)).addListener(
|
||||
ChannelFutureListener.CLOSE);
|
||||
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request)).addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
} else if (request.getMethod() == HttpMethod.POST) {
|
||||
// URL参数签名验证
|
||||
if (!ServerToolkits.isBlank(request.getSignature())
|
||||
&& !MessageUtil.signature(aesToken.getToken(),
|
||||
request.getTimeStamp(), request.getNonce()).equals(
|
||||
request.getSignature())) {
|
||||
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request))
|
||||
.addListener(ChannelFutureListener.CLOSE);
|
||||
&& !MessageUtil.signature(aesToken.getToken(), request.getTimeStamp(), request.getNonce())
|
||||
.equals(request.getSignature())) {
|
||||
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request)).addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
// XML消息签名验证
|
||||
if (request.getEncryptType() == EncryptType.AES
|
||||
&& !MessageUtil.signature(aesToken.getToken(),
|
||||
request.getTimeStamp(), request.getNonce(),
|
||||
request.getEncryptContent()).equals(
|
||||
request.getMsgSignature())) {
|
||||
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request))
|
||||
.addListener(ChannelFutureListener.CLOSE);
|
||||
&& !MessageUtil.signature(aesToken.getToken(), request.getTimeStamp(), request.getNonce(),
|
||||
request.getEncryptContent()).equals(request.getMsgSignature())) {
|
||||
ctx.writeAndFlush(resolveResponse(FORBIDDEN, request)).addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// 访问其它URL
|
||||
ctx.writeAndFlush(resolveResponse(METHOD_NOT_ALLOWED, request))
|
||||
.addListener(ChannelFutureListener.CLOSE);
|
||||
ctx.writeAndFlush(resolveResponse(METHOD_NOT_ALLOWED, request)).addListener(ChannelFutureListener.CLOSE);
|
||||
return;
|
||||
}
|
||||
messageDispatcher.doDispatch(ctx, request);
|
||||
}
|
||||
|
||||
private FullHttpResponse resolveResponse(HttpResponseStatus responseStatus,
|
||||
WeixinRequest request) {
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(
|
||||
request.getProtocolVersion(), responseStatus);
|
||||
private FullHttpResponse resolveResponse(HttpResponseStatus responseStatus, WeixinRequest request) {
|
||||
FullHttpResponse response = new DefaultFullHttpResponse(request.getProtocolVersion(), responseStatus);
|
||||
HttpUtil.resolveHeaders(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
@ -1,14 +1,7 @@
|
||||
package com.foxinmy.weixin4j.socket;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.util.AesToken;
|
||||
@ -16,6 +9,12 @@ import com.foxinmy.weixin4j.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import io.netty.util.internal.logging.InternalLogger;
|
||||
import io.netty.util.internal.logging.InternalLoggerFactory;
|
||||
|
||||
/**
|
||||
* 微信回复编码类
|
||||
*
|
||||
@ -23,16 +22,14 @@ import com.foxinmy.weixin4j.util.ServerToolkits;
|
||||
* @author jinyu(foxinmy@gmail.com)
|
||||
* @date 2014年11月13日
|
||||
* @since JDK 1.6
|
||||
* @see <a
|
||||
* href="http://mp.weixin.qq.com/wiki/0/61c3a8b9d50ac74f18bdf2e54ddfc4e0.html">加密接入指引</a>
|
||||
* @see <a href=
|
||||
* "http://mp.weixin.qq.com/wiki/0/61c3a8b9d50ac74f18bdf2e54ddfc4e0.html">加密接入指引</a>
|
||||
* @see com.foxinmy.weixin4j.response.WeixinResponse
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
public class WeixinResponseEncoder extends
|
||||
MessageToMessageEncoder<WeixinResponse> {
|
||||
public class WeixinResponseEncoder extends MessageToMessageEncoder<WeixinResponse> {
|
||||
|
||||
protected final InternalLogger logger = InternalLoggerFactory
|
||||
.getInstance(getClass());
|
||||
protected final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
|
||||
|
||||
private final String XML_START = "<xml>";
|
||||
// ---------------明文节点
|
||||
@ -48,31 +45,23 @@ public class WeixinResponseEncoder extends
|
||||
private final String XML_END = "</xml>";
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, WeixinResponse response,
|
||||
List<Object> out) throws WeixinException {
|
||||
WeixinMessageTransfer messageTransfer = ctx.channel()
|
||||
.attr(ServerToolkits.MESSAGE_TRANSFER_KEY).get();
|
||||
protected void encode(ChannelHandlerContext ctx, WeixinResponse response, List<Object> out) {
|
||||
WeixinMessageTransfer messageTransfer = ctx.channel().attr(ServerToolkits.MESSAGE_TRANSFER_KEY).get();
|
||||
EncryptType encryptType = messageTransfer.getEncryptType();
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.append(XML_START);
|
||||
content.append(String.format(ELEMENT_TOUSERNAME,
|
||||
messageTransfer.getFromUserName()));
|
||||
content.append(String.format(ELEMENT_FROMUSERNAME,
|
||||
messageTransfer.getToUserName()));
|
||||
content.append(String.format(ELEMENT_CREATETIME,
|
||||
System.currentTimeMillis() / 1000l));
|
||||
content.append(String.format(ELEMENT_TOUSERNAME, messageTransfer.getFromUserName()));
|
||||
content.append(String.format(ELEMENT_FROMUSERNAME, messageTransfer.getToUserName()));
|
||||
content.append(String.format(ELEMENT_CREATETIME, System.currentTimeMillis() / 1000l));
|
||||
content.append(String.format(ELEMENT_MSGTYPE, response.getMsgType()));
|
||||
content.append(response.toContent());
|
||||
content.append(XML_END);
|
||||
if (encryptType == EncryptType.AES) {
|
||||
AesToken aesToken = messageTransfer.getAesToken();
|
||||
String nonce = ServerToolkits.generateRandomString(32);
|
||||
String timestamp = Long
|
||||
.toString(System.currentTimeMillis() / 1000l);
|
||||
String encrtypt = MessageUtil.aesEncrypt(aesToken.getWeixinId(),
|
||||
aesToken.getAesKey(), content.toString());
|
||||
String msgSignature = MessageUtil.signature(aesToken.getToken(),
|
||||
nonce, timestamp, encrtypt);
|
||||
String timestamp = Long.toString(System.currentTimeMillis() / 1000l);
|
||||
String encrtypt = MessageUtil.aesEncrypt(aesToken.getWeixinId(), aesToken.getAesKey(), content.toString());
|
||||
String msgSignature = MessageUtil.signature(aesToken.getToken(), nonce, timestamp, encrtypt);
|
||||
content.delete(0, content.length());
|
||||
content.append(XML_START);
|
||||
content.append(String.format(ELEMENT_NONCE, nonce));
|
||||
@ -81,8 +70,7 @@ public class WeixinResponseEncoder extends
|
||||
content.append(String.format(ELEMENT_ENCRYPT, encrtypt));
|
||||
content.append(XML_END);
|
||||
}
|
||||
ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(),
|
||||
ServerToolkits.CONTENTTYPE$APPLICATION_XML));
|
||||
ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(), ServerToolkits.CONTENTTYPE$APPLICATION_XML));
|
||||
logger.info("{} encode weixin response:{}", encryptType, content);
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,6 @@ import java.util.Map;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import com.foxinmy.weixin4j.dispatcher.BeanFactory;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
/**
|
||||
* 使用spring容器获取bean
|
||||
@ -25,22 +24,22 @@ public class SpringBeanFactory implements BeanFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getBean(String name) throws WeixinException {
|
||||
public Object getBean(String name) {
|
||||
return context.getBean(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getBean(Class<T> classType) throws WeixinException {
|
||||
public <T> T getBean(Class<T> classType) {
|
||||
return context.getBean(classType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getBean(String name, Class<T> classType) throws WeixinException {
|
||||
public <T> T getBean(String name, Class<T> classType) {
|
||||
return context.getBean(name, classType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Map<String, T> getBeans(Class<T> clazz) throws WeixinException {
|
||||
public <T> Map<String, T> getBeans(Class<T> clazz) {
|
||||
return context.getBeansOfType(clazz);
|
||||
}
|
||||
}
|
||||
@ -11,7 +11,6 @@ import com.foxinmy.weixin4j.dispatcher.DefaultMessageMatcher;
|
||||
import com.foxinmy.weixin4j.dispatcher.WeixinMessageDispatcher;
|
||||
import com.foxinmy.weixin4j.dispatcher.WeixinMessageKey;
|
||||
import com.foxinmy.weixin4j.dispatcher.WeixinMessageMatcher;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
|
||||
import com.foxinmy.weixin4j.request.WeixinMessage;
|
||||
@ -173,7 +172,7 @@ public final class WeixinServerBootstrap {
|
||||
* 默认端口(30000)启动服务
|
||||
*
|
||||
*/
|
||||
public void startup() throws WeixinException {
|
||||
public void startup() {
|
||||
startup(DEFAULT_SERVERPORT);
|
||||
}
|
||||
|
||||
@ -181,7 +180,7 @@ public final class WeixinServerBootstrap {
|
||||
* 指定端口启动服务
|
||||
*
|
||||
*/
|
||||
public void startup(int serverPort) throws WeixinException {
|
||||
public void startup(int serverPort) {
|
||||
startup(DEFAULT_BOSSTHREADS, DEFAULT_WORKERTHREADS, serverPort);
|
||||
}
|
||||
|
||||
@ -197,7 +196,7 @@ public final class WeixinServerBootstrap {
|
||||
* @return
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void startup(int bossThreads, int workerThreads, final int serverPort) throws WeixinException {
|
||||
public void startup(int bossThreads, int workerThreads, final int serverPort) {
|
||||
messageDispatcher.setMessageHandlerList(messageHandlerList);
|
||||
messageDispatcher.setMessageInterceptorList(messageInterceptorList);
|
||||
try {
|
||||
@ -218,7 +217,7 @@ public final class WeixinServerBootstrap {
|
||||
}).sync().channel();
|
||||
ch.closeFuture().sync();
|
||||
} catch (InterruptedException e) {
|
||||
throw new WeixinException("netty server startup FAIL", e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
shutdown();
|
||||
}
|
||||
|
||||
@ -18,8 +18,6 @@ import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
/**
|
||||
* 对class的获取
|
||||
*
|
||||
@ -40,8 +38,7 @@ public final class ClassUtil {
|
||||
* 包名
|
||||
* @return
|
||||
*/
|
||||
public static List<Class<?>> getClasses(String packageName)
|
||||
throws WeixinException {
|
||||
public static List<Class<?>> getClasses(String packageName) {
|
||||
String packageFileName = packageName.replace(POINT, File.separator);
|
||||
URL fullPath = getDefaultClassLoader().getResource(packageFileName);
|
||||
String protocol = fullPath.getProtocol();
|
||||
@ -50,16 +47,13 @@ public final class ClassUtil {
|
||||
File dir = new File(fullPath.toURI());
|
||||
return findClassesByFile(dir, packageName);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new WeixinException(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else if (protocol.equals(ServerToolkits.PROTOCOL_JAR)) {
|
||||
try {
|
||||
return findClassesByJar(
|
||||
((JarURLConnection) fullPath.openConnection())
|
||||
.getJarFile(),
|
||||
packageName);
|
||||
return findClassesByJar(((JarURLConnection) fullPath.openConnection()).getJarFile(), packageName);
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -85,12 +79,10 @@ public final class ClassUtil {
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
classes.addAll(findClassesByFile(file, packageName + POINT
|
||||
+ file.getName()));
|
||||
classes.addAll(findClassesByFile(file, packageName + POINT + file.getName()));
|
||||
} else {
|
||||
try {
|
||||
classes.add(Class.forName(packageName + POINT
|
||||
+ file.getName().replace(CLASS, "")));
|
||||
classes.add(Class.forName(packageName + POINT + file.getName().replace(CLASS, "")));
|
||||
} catch (ClassNotFoundException e) {
|
||||
;
|
||||
}
|
||||
@ -109,8 +101,7 @@ public final class ClassUtil {
|
||||
* 包的全限类名
|
||||
* @return
|
||||
*/
|
||||
private static List<Class<?>> findClassesByJar(JarFile jar,
|
||||
String packageName) {
|
||||
private static List<Class<?>> findClassesByJar(JarFile jar, String packageName) {
|
||||
List<Class<?>> classes = new ArrayList<Class<?>>();
|
||||
Enumeration<JarEntry> jarEntries = jar.entries();
|
||||
while (jarEntries.hasMoreElements()) {
|
||||
@ -118,10 +109,8 @@ public final class ClassUtil {
|
||||
if (jarEntry.isDirectory()) {
|
||||
continue;
|
||||
}
|
||||
String className = jarEntry.getName()
|
||||
.replace(File.separator, POINT);
|
||||
if (!className.startsWith(packageName)
|
||||
|| !className.endsWith(CLASS)) {
|
||||
String className = jarEntry.getName().replace(File.separator, POINT);
|
||||
if (!className.startsWith(packageName) || !className.endsWith(CLASS)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
@ -133,7 +122,7 @@ public final class ClassUtil {
|
||||
return classes;
|
||||
}
|
||||
|
||||
public static Object deepClone(Object obj) throws WeixinException {
|
||||
public static Object deepClone(Object obj) {
|
||||
ByteArrayOutputStream bos = null;
|
||||
ObjectOutputStream oos = null;
|
||||
ByteArrayInputStream bis = null;
|
||||
@ -146,9 +135,9 @@ public final class ClassUtil {
|
||||
ois = new ObjectInputStream(bis);
|
||||
return ois.readObject();
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e);
|
||||
throw new RuntimeException(e);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new WeixinException(e);
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
try {
|
||||
if (bos != null) {
|
||||
@ -176,7 +165,7 @@ public final class ClassUtil {
|
||||
* @return
|
||||
*/
|
||||
public static Class<?> getGenericType(Class<?> clazz) {
|
||||
if(clazz == Object.class){
|
||||
if (clazz == Object.class) {
|
||||
return null;
|
||||
}
|
||||
Type type = clazz.getGenericSuperclass();
|
||||
@ -212,7 +201,7 @@ public final class ClassUtil {
|
||||
return cl;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws WeixinException {
|
||||
public static void main(String[] args) {
|
||||
System.err.println(getClasses("com.foxinmy.weixin4j.qy.event"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import com.foxinmy.weixin4j.base64.Base64;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
|
||||
/**
|
||||
* 消息工具类
|
||||
@ -26,8 +25,8 @@ public final class MessageUtil {
|
||||
* 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数
|
||||
* @return 开发者通过检验signature对请求进行相关校验。若确认此次GET请求来自微信服务器
|
||||
* 请原样返回echostr参数内容,则接入生效 成为开发者成功,否则接入失败
|
||||
* @see <a
|
||||
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN">接入指南</a>
|
||||
* @see <a href=
|
||||
* "https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421135319&token=&lang=zh_CN">接入指南</a>
|
||||
*/
|
||||
public static String signature(String... para) {
|
||||
Arrays.sort(para);
|
||||
@ -50,16 +49,14 @@ public final class MessageUtil {
|
||||
* @return aes加密后的消息体
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static String aesEncrypt(String appId, String encodingAesKey,
|
||||
String xmlContent) throws WeixinException {
|
||||
public static String aesEncrypt(String appId, String encodingAesKey, String xmlContent) {
|
||||
/**
|
||||
* 其中,msg_encrypt=Base64_Encode(AES_Encrypt [random(16B)+ msg_len(4B) +
|
||||
* msg + $AppId])
|
||||
*
|
||||
* random(16B)为16字节的随机字符串;msg_len为msg长度,占4个字节(网络字节序),$AppId为公众账号的AppId
|
||||
*/
|
||||
byte[] randomBytes = ServerToolkits.getBytesUtf8(ServerToolkits
|
||||
.generateRandomString(16));
|
||||
byte[] randomBytes = ServerToolkits.getBytesUtf8(ServerToolkits.generateRandomString(16));
|
||||
byte[] xmlBytes = ServerToolkits.getBytesUtf8(xmlContent);
|
||||
int xmlLength = xmlBytes.length;
|
||||
byte[] orderBytes = new byte[4];
|
||||
@ -69,24 +66,20 @@ public final class MessageUtil {
|
||||
orderBytes[0] = (byte) (xmlLength >> 24 & 0xFF);
|
||||
byte[] appidBytes = ServerToolkits.getBytesUtf8(appId);
|
||||
|
||||
int byteLength = randomBytes.length + xmlLength + orderBytes.length
|
||||
+ appidBytes.length;
|
||||
int byteLength = randomBytes.length + xmlLength + orderBytes.length + appidBytes.length;
|
||||
// ... + pad: 使用自定义的填充方式对明文进行补位填充
|
||||
byte[] padBytes = PKCS7Encoder.encode(byteLength);
|
||||
// random + endian + xml + appid + pad 获得最终的字节流
|
||||
byte[] unencrypted = new byte[byteLength + padBytes.length];
|
||||
byteLength = 0;
|
||||
// src:源数组;srcPos:源数组要复制的起始位置;dest:目的数组;destPos:目的数组放置的起始位置;length:复制的长度
|
||||
System.arraycopy(randomBytes, 0, unencrypted, byteLength,
|
||||
randomBytes.length);
|
||||
System.arraycopy(randomBytes, 0, unencrypted, byteLength, randomBytes.length);
|
||||
byteLength += randomBytes.length;
|
||||
System.arraycopy(orderBytes, 0, unencrypted, byteLength,
|
||||
orderBytes.length);
|
||||
System.arraycopy(orderBytes, 0, unencrypted, byteLength, orderBytes.length);
|
||||
byteLength += orderBytes.length;
|
||||
System.arraycopy(xmlBytes, 0, unencrypted, byteLength, xmlBytes.length);
|
||||
byteLength += xmlBytes.length;
|
||||
System.arraycopy(appidBytes, 0, unencrypted, byteLength,
|
||||
appidBytes.length);
|
||||
System.arraycopy(appidBytes, 0, unencrypted, byteLength, appidBytes.length);
|
||||
byteLength += appidBytes.length;
|
||||
System.arraycopy(padBytes, 0, unencrypted, byteLength, padBytes.length);
|
||||
try {
|
||||
@ -100,10 +93,9 @@ public final class MessageUtil {
|
||||
byte[] encrypted = cipher.doFinal(unencrypted);
|
||||
// 使用BASE64对加密后的字符串进行编码
|
||||
// return Base64.encodeBase64String(encrypted);
|
||||
return Base64
|
||||
.encodeBase64String(encrypted);
|
||||
return Base64.encodeBase64String(encrypted);
|
||||
} catch (Exception e) {
|
||||
throw new WeixinException("-40006", "AES加密失败:" + e.getMessage());
|
||||
throw new RuntimeException("-40006,AES加密失败:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,23 +110,21 @@ public final class MessageUtil {
|
||||
* @return 解密后的字符
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static String aesDecrypt(String appId, String encodingAesKey,
|
||||
String encryptContent) throws WeixinException {
|
||||
public static String aesDecrypt(String appId, String encodingAesKey, String encryptContent) {
|
||||
byte[] aesKey = Base64.decodeBase64(encodingAesKey + "=");
|
||||
byte[] original;
|
||||
try {
|
||||
// 设置解密模式为AES的CBC模式
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||
SecretKeySpec key_spec = new SecretKeySpec(aesKey, ServerToolkits.AES);
|
||||
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey,
|
||||
0, 16));
|
||||
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
|
||||
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
|
||||
// 使用BASE64对密文进行解码
|
||||
byte[] encrypted = Base64.decodeBase64(encryptContent);
|
||||
// 解密
|
||||
original = cipher.doFinal(encrypted);
|
||||
} catch (Exception e) {
|
||||
throw new WeixinException("-40007", "AES解密失败:" + e.getMessage());
|
||||
throw new RuntimeException("-40007,AES解密失败:" + e.getMessage());
|
||||
}
|
||||
String xmlContent, fromAppId;
|
||||
try {
|
||||
@ -148,20 +138,16 @@ public final class MessageUtil {
|
||||
byte[] lengthByte = Arrays.copyOfRange(bytes, 16, 20);
|
||||
// 获取xml消息主体的长度(byte[]2int)
|
||||
// http://my.oschina.net/u/169390/blog/97495
|
||||
int xmlLength = lengthByte[3] & 0xff | (lengthByte[2] & 0xff) << 8
|
||||
| (lengthByte[1] & 0xff) << 16
|
||||
int xmlLength = lengthByte[3] & 0xff | (lengthByte[2] & 0xff) << 8 | (lengthByte[1] & 0xff) << 16
|
||||
| (lengthByte[0] & 0xff) << 24;
|
||||
xmlContent = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes, 20,
|
||||
20 + xmlLength));
|
||||
fromAppId = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes,
|
||||
20 + xmlLength, bytes.length));
|
||||
xmlContent = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes, 20, 20 + xmlLength));
|
||||
fromAppId = ServerToolkits.newStringUtf8(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length));
|
||||
} catch (Exception e) {
|
||||
throw new WeixinException("-40008", "xml内容不合法:" + e.getMessage());
|
||||
throw new RuntimeException("-40008,xml内容不合法:" + e.getMessage());
|
||||
}
|
||||
// 校验appId是否一致
|
||||
if (appId != null && !fromAppId.trim().equals(appId)) {
|
||||
throw new WeixinException("-40005", "校验AppID失败,expect " + appId
|
||||
+ ",but actual is " + fromAppId);
|
||||
throw new RuntimeException("-40005,校验AppID失败,expect " + appId + ",but actual is " + fromAppId);
|
||||
}
|
||||
return xmlContent;
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package com.foxinmy.weixin4j.server.ext;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
|
||||
import com.foxinmy.weixin4j.qy.suite.SuiteEventType;
|
||||
import com.foxinmy.weixin4j.qy.suite.SuiteMessage;
|
||||
@ -22,14 +21,12 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
public class SuiteMessageHandler implements WeixinMessageHandler {
|
||||
|
||||
@Override
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames)
|
||||
throws WeixinException {
|
||||
public boolean canHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return nodeNames.contains("suiteid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
SuiteMessage suiteMessage = null; // 转换为 SuiteMessage
|
||||
SuiteEventType eventType = suiteMessage.getFormatEventType();
|
||||
if (eventType == SuiteEventType.suite_ticket) {
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
package com.foxinmy.weixin4j.server.test;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
import com.foxinmy.weixin4j.dispatcher.BeanFactory;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.handler.DebugMessageHandler;
|
||||
import com.foxinmy.weixin4j.handler.MessageHandlerAdapter;
|
||||
import com.foxinmy.weixin4j.handler.MultipleMessageHandlerAdapter;
|
||||
@ -23,6 +20,8 @@ import com.foxinmy.weixin4j.response.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.spring.SpringBeanFactory;
|
||||
import com.foxinmy.weixin4j.startup.WeixinServerBootstrap;
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
|
||||
/**
|
||||
* 服务启动测试类
|
||||
*
|
||||
@ -44,12 +43,10 @@ public class MessageServerStartup {
|
||||
/**
|
||||
* 调试输出用户发来的消息
|
||||
*
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void test1() throws WeixinException {
|
||||
public void test1() {
|
||||
// 明文模式
|
||||
new WeixinServerBootstrap(token).addHandler(DebugMessageHandler.global)
|
||||
.startup();
|
||||
new WeixinServerBootstrap(token).addHandler(DebugMessageHandler.global).startup();
|
||||
// 密文模式
|
||||
// new WeixinServerBootstrap(weixinId, token, aesKey).addHandler(
|
||||
// DebugMessageHandler.global).startup();
|
||||
@ -58,96 +55,83 @@ public class MessageServerStartup {
|
||||
/**
|
||||
* 针对特定消息类型
|
||||
*
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void test2() throws WeixinException {
|
||||
public void test2() {
|
||||
// 针对文本消息回复
|
||||
WeixinMessageHandler textMessageHandler = new MessageHandlerAdapter<TextMessage>() {
|
||||
@Override
|
||||
public WeixinResponse doHandle0(WeixinRequest request,
|
||||
TextMessage message) throws WeixinException {
|
||||
public WeixinResponse doHandle0(WeixinRequest request, TextMessage message) {
|
||||
return new TextResponse("HelloWorld!");
|
||||
}
|
||||
};
|
||||
// 针对语音消息回复
|
||||
WeixinMessageHandler voiceMessageHandler = new MessageHandlerAdapter<VoiceMessage>() {
|
||||
@Override
|
||||
public WeixinResponse doHandle0(WeixinRequest request,
|
||||
VoiceMessage message) throws WeixinException {
|
||||
public WeixinResponse doHandle0(WeixinRequest request, VoiceMessage message) {
|
||||
return new TextResponse("HelloWorld!");
|
||||
}
|
||||
};
|
||||
// 当消息类型为文本(text)或者语音时回复「HelloWorld」, 否则回复调试消息
|
||||
new WeixinServerBootstrap(weixinId, token, aesKey).addHandler(
|
||||
textMessageHandler, voiceMessageHandler,
|
||||
DebugMessageHandler.global).startup();
|
||||
new WeixinServerBootstrap(weixinId, token, aesKey)
|
||||
.addHandler(textMessageHandler, voiceMessageHandler, DebugMessageHandler.global).startup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 多种消息类型处理
|
||||
*
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public void test3() throws WeixinException {
|
||||
public void test3() {
|
||||
@SuppressWarnings("unchecked")
|
||||
MultipleMessageHandlerAdapter messageHandler = new MultipleMessageHandlerAdapter(
|
||||
ScanEventMessage.class, TextMessage.class) {
|
||||
MultipleMessageHandlerAdapter messageHandler = new MultipleMessageHandlerAdapter(ScanEventMessage.class,
|
||||
TextMessage.class) {
|
||||
@Override
|
||||
public WeixinResponse doHandle(WeixinRequest request,
|
||||
WeixinMessage message, Set<String> nodeNames)
|
||||
throws WeixinException {
|
||||
public WeixinResponse doHandle(WeixinRequest request, WeixinMessage message, Set<String> nodeNames) {
|
||||
return new TextResponse("处理了扫描和文字消息");
|
||||
}
|
||||
};
|
||||
new WeixinServerBootstrap(token).addHandler(messageHandler,
|
||||
DebugMessageHandler.global).startup();
|
||||
new WeixinServerBootstrap(token).addHandler(messageHandler, DebugMessageHandler.global).startup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描包添加handler
|
||||
*
|
||||
* @throws WeixinException
|
||||
* @
|
||||
*/
|
||||
public void test4() throws WeixinException {
|
||||
public void test4() {
|
||||
// handler处理所在的包名(子包也会扫描)
|
||||
String packageToScan = "com.foxinmy.weixin4j.handler";
|
||||
// handler默认使用 Class.newInstance
|
||||
// 方式实例化,如果handler中含有service等类需要注入,可以声明一个BeanFactory,如SpringBeanFactory
|
||||
ApplicationContext applicationContext = null; // spring容器
|
||||
BeanFactory beanFactory = new SpringBeanFactory(applicationContext);
|
||||
new WeixinServerBootstrap(token).handlerPackagesToScan(packageToScan)
|
||||
.openAlwaysResponse().resolveBeanFactory(beanFactory).startup();
|
||||
new WeixinServerBootstrap(token).handlerPackagesToScan(packageToScan).openAlwaysResponse()
|
||||
.resolveBeanFactory(beanFactory).startup();
|
||||
}
|
||||
|
||||
/**
|
||||
* 拦截器应用
|
||||
*
|
||||
* @throws WeixinException
|
||||
* @
|
||||
*/
|
||||
public void test5() throws WeixinException {
|
||||
public void test5() {
|
||||
// 拦截所有请求
|
||||
WeixinMessageInterceptor interceptor = new WeixinMessageInterceptor() {
|
||||
@Override
|
||||
public boolean preHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinMessage message,
|
||||
WeixinMessageHandler handler) throws WeixinException {
|
||||
public boolean preHandle(ChannelHandlerContext context, WeixinRequest request, WeixinMessage message,
|
||||
WeixinMessageHandler handler) {
|
||||
context.writeAndFlush(new TextResponse("所有消息被拦截了!"));
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler)
|
||||
throws WeixinException {
|
||||
public void postHandle(ChannelHandlerContext context, WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler) {
|
||||
System.err.println("preHandle返回为true,执行handler后");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(ChannelHandlerContext context,
|
||||
WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler,
|
||||
Exception exception) throws WeixinException {
|
||||
public void afterCompletion(ChannelHandlerContext context, WeixinRequest request, WeixinResponse response,
|
||||
WeixinMessage message, WeixinMessageHandler handler, Exception exception) {
|
||||
System.err.println("请求处理完毕");
|
||||
}
|
||||
|
||||
@ -156,8 +140,7 @@ public class MessageServerStartup {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
new WeixinServerBootstrap(token).addInterceptor(interceptor)
|
||||
.openAlwaysResponse().startup();
|
||||
new WeixinServerBootstrap(token).addInterceptor(interceptor).openAlwaysResponse().startup();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user