removed WeixinException class

This commit is contained in:
jinyu 2017-06-23 18:26:25 +08:00
parent 4c0f96fcfe
commit 3c92d75276
27 changed files with 1210 additions and 1457 deletions

View File

@ -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();
}

View File

@ -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;
}

View File

@ -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("是你,是你,还是你。");
}

View File

@ -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文本
*/

View File

@ -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("欢迎关注~");
}
}

View File

@ -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("收到了文本消息");
}
}

View File

@ -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) {
/**
* 返回一段文字给用户
*/

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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大小

View File

@ -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;
}

View File

@ -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时权重降序排列,数字越大优先级越高

View File

@ -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

View File

@ -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时权重降序排列,数字越大优先级越高

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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) {
@ -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"));
}
}

View File

@ -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;
}

View File

@ -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) {

View File

@ -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();
}
/**