weixin4j-server:添加拦截器测试

This commit is contained in:
jinyu 2015-05-11 08:53:15 +08:00
parent 52c46ae5f0
commit 29cbb6221c
14 changed files with 228 additions and 102 deletions

View File

@ -6,7 +6,7 @@ weixin4j
项目说明 项目说明
------- -------
`weixin4j`是一个用java编写针对微信开发的工具包,包含[weixin4j-mp](./weixin4j-mp)(微信公众平台API)[weixin4j-qy](./weixin4j-qy)(微信企业号API)以及[weixin4j-server](./weixin4j-server)(微信被动消息服务器)三个工程 `weixin4j`是一个用java编写针对微信开发的工具包,包含[weixin4j-mp](./weixin4j-mp)(微信公众平台API)[weixin4j-qy](./weixin4j-qy)(微信企业号API)以及[weixin4j-server](./weixin4j-server)(微信被动消息服务器)三个工程.
功能列表 功能列表
------- -------

View File

@ -1,8 +1,8 @@
weixin4j-server weixin4j-server
=============== ===============
微信消息netty服务器 微信消息服务器
------------------ -------------
功能列表 功能列表
------- -------
@ -11,7 +11,7 @@ weixin4j-server
* `消息分发` * `消息分发`
* `消息拦截`(待测试) * `消息拦截`
如何使用 如何使用
------- -------
@ -57,6 +57,37 @@ weixin4j-server
DebugMessageHandler.global).startup(); DebugMessageHandler.global).startup();
} }
} }
编写一个拦截器
public static void main(String[] args) {
// 拦截所有请求
WeixinMessageInterceptor interceptor = new MessageInterceptorAdapter() {
@Override
public boolean preHandle(ChannelHandlerContext context,
WeixinRequest request, WeixinMessage message,
WeixinMessageHandler handler) throws WeixinException {
context.write(new TextResponse("所有消息被拦截了!"));
return false;
}
@Override
public void postHandle(ChannelHandlerContext context,
WeixinRequest request, WeixinResponse response,
WeixinMessage message, WeixinMessageHandler handler)
throws WeixinException {
System.err.println("preHandle返回为true,执行handler后");
}
@Override
public void afterCompletion(ChannelHandlerContext context,
WeixinRequest request, WeixinMessage message,
WeixinMessageHandler handler, WeixinException exception)
throws WeixinException {
System.err.println("请求处理完毕");
}
};
new WeixinServerBootstrap("token").addInterceptor(interceptor)
.addHandler(BlankMessageHandler.global).startup();
}
更多内容将会写在wiki里 更多内容将会写在wiki里
@ -125,6 +156,5 @@ assembly打包(辅助)
[spring-webmvc:HandlerInterceptor](https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerInterceptor.java) [spring-webmvc:HandlerInterceptor](https://github.com/spring-projects/spring-framework/blob/master/spring-webmvc/src/main/java/org/springframework/web/servlet/HandlerInterceptor.java)
[更新LOG](./CHANGE.md) [更新LOG](./CHANGE.md)
---------------------- ----------------------

View File

@ -31,7 +31,7 @@ public class AesToken implements Serializable {
public AesToken(String token) { public AesToken(String token) {
this.token = token; this.token = token;
} }
public AesToken(String appid, String token, String aesKey) { public AesToken(String appid, String token, String aesKey) {
this.appid = appid; this.appid = appid;
this.token = token; this.token = token;

View File

@ -34,10 +34,13 @@ public class MessageHandlerExecutor {
*/ */
private final WeixinMessageInterceptor[] messageInterceptors; private final WeixinMessageInterceptor[] messageInterceptors;
private final ChannelHandlerContext context;
private int interceptorIndex = -1; private int interceptorIndex = -1;
public MessageHandlerExecutor(WeixinMessageHandler messageHandler, public MessageHandlerExecutor(ChannelHandlerContext context,
WeixinMessageHandler messageHandler,
WeixinMessageInterceptor[] messageInterceptors) { WeixinMessageInterceptor[] messageInterceptors) {
this.context = context;
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
this.messageInterceptors = messageInterceptors; this.messageInterceptors = messageInterceptors;
} }
@ -46,15 +49,14 @@ public class MessageHandlerExecutor {
return messageHandler; return messageHandler;
} }
public boolean applyPreHandle(ChannelHandlerContext ctx, public boolean applyPreHandle(WeixinRequest request, WeixinMessage message)
WeixinRequest request, WeixinMessage message)
throws WeixinException { throws WeixinException {
if (messageInterceptors != null) { if (messageInterceptors != null) {
for (int i = 0; i < messageInterceptors.length; i++) { for (int i = 0; i < messageInterceptors.length; i++) {
WeixinMessageInterceptor interceptor = messageInterceptors[i]; WeixinMessageInterceptor interceptor = messageInterceptors[i];
if (!interceptor.preHandle(ctx, request, message, if (!interceptor.preHandle(context, request, message,
messageHandler)) { messageHandler)) {
triggerAfterCompletion(ctx, request, message, null); triggerAfterCompletion(request, message, null);
return false; return false;
} }
this.interceptorIndex = i; this.interceptorIndex = i;
@ -63,29 +65,27 @@ public class MessageHandlerExecutor {
return true; return true;
} }
public void applyPostHandle(ChannelHandlerContext ctx, public void applyPostHandle(WeixinRequest request, WeixinResponse response,
WeixinRequest request, WeixinResponse response,
WeixinMessage message) throws WeixinException { WeixinMessage message) throws WeixinException {
if (messageInterceptors == null) { if (messageInterceptors == null) {
return; return;
} }
for (int i = messageInterceptors.length - 1; i >= 0; i--) { for (int i = messageInterceptors.length - 1; i >= 0; i--) {
WeixinMessageInterceptor interceptor = messageInterceptors[i]; WeixinMessageInterceptor interceptor = messageInterceptors[i];
interceptor.postHandle(ctx, request, response, message, interceptor.postHandle(context, request, response, message,
messageHandler); messageHandler);
} }
} }
public void triggerAfterCompletion(ChannelHandlerContext ctx, public void triggerAfterCompletion(WeixinRequest request,
WeixinRequest request, WeixinMessage message, WeixinException ex) WeixinMessage message, WeixinException ex) throws WeixinException {
throws WeixinException {
if (messageInterceptors == null) { if (messageInterceptors == null) {
return; return;
} }
for (int i = this.interceptorIndex; i >= 0; i--) { for (int i = this.interceptorIndex; i >= 0; i--) {
WeixinMessageInterceptor interceptor = messageInterceptors[i]; WeixinMessageInterceptor interceptor = messageInterceptors[i];
try { try {
interceptor.afterCompletion(ctx, request, message, interceptor.afterCompletion(context, request, message,
messageHandler, ex); messageHandler, ex);
} catch (WeixinException e) { } catch (WeixinException e) {
logger.error( logger.error(

View File

@ -1,9 +1,8 @@
package com.foxinmy.weixin4j.dispatcher; 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.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
@ -17,13 +16,10 @@ import com.foxinmy.weixin4j.bean.BeanFactory;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.handler.WeixinMessageHandler; import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor; import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
import com.foxinmy.weixin4j.request.ResponseMessage;
import com.foxinmy.weixin4j.request.WeixinMessage; import com.foxinmy.weixin4j.request.WeixinMessage;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.response.WeixinResponse; import com.foxinmy.weixin4j.response.WeixinResponse;
import com.foxinmy.weixin4j.type.EncryptType;
import com.foxinmy.weixin4j.util.ClassUtil; import com.foxinmy.weixin4j.util.ClassUtil;
import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.HttpUtil; import com.foxinmy.weixin4j.util.HttpUtil;
import com.foxinmy.weixin4j.util.ReflectionUtil; import com.foxinmy.weixin4j.util.ReflectionUtil;
@ -71,46 +67,40 @@ public class WeixinMessageDispatcher {
public void doDispatch(final ChannelHandlerContext context, public void doDispatch(final ChannelHandlerContext context,
final WeixinRequest request, final WeixinMessage message) final WeixinRequest request, final WeixinMessage message)
throws WeixinException { throws WeixinException {
MessageHandlerExecutor handlerExecutor = getHandlerExecutor(request, MessageHandlerExecutor handlerExecutor = getHandlerExecutor(context,
message); request, message);
if (handlerExecutor == null if (handlerExecutor == null
|| handlerExecutor.getMessageHandler() == null) { || handlerExecutor.getMessageHandler() == null) {
noHandlerFound(context, request, message); noHandlerFound(context, request, message);
return; return;
} }
if (!handlerExecutor.applyPreHandle(context, request, message)) { if (!handlerExecutor.applyPreHandle(request, message)) {
return; return;
} }
WeixinException dispatchException = null; WeixinException dispatchException = null;
try { try {
WeixinResponse _response = handlerExecutor.getMessageHandler() WeixinResponse response = handlerExecutor.getMessageHandler()
.doHandle(request, message); .doHandle(request, message);
log.info( log.info(
"\n=================message response=================\n{}", "\n=================message response=================\n{}",
_response); response);
handlerExecutor.applyPostHandle(context, request, _response, handlerExecutor.applyPostHandle(request, response, message);
message); context.write(response);
ResponseMessage response = new ResponseMessage(message, _response);
if (request.getEncryptType() == EncryptType.RAW) {
context.write(HttpUtil.createWeixinMessageResponse(
response.toXml(), Consts.CONTENTTYPE$APPLICATION_XML));
} else {
context.write(response);
}
} catch (WeixinException e) { } catch (WeixinException e) {
dispatchException = e; dispatchException = e;
} }
handlerExecutor.triggerAfterCompletion(context, request, message, handlerExecutor.triggerAfterCompletion(request, message,
dispatchException); dispatchException);
} }
protected void noHandlerFound(ChannelHandlerContext ctx, protected void noHandlerFound(ChannelHandlerContext ctx,
WeixinRequest request, WeixinMessage message) { WeixinRequest request, WeixinMessage message) {
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, ctx.writeAndFlush(HttpUtil.createHttpResponse(null, NOT_FOUND, null))
HttpResponseStatus.NOT_FOUND)); .addListener(ChannelFutureListener.CLOSE);
} }
protected MessageHandlerExecutor getHandlerExecutor(WeixinRequest request, protected MessageHandlerExecutor getHandlerExecutor(
ChannelHandlerContext context, WeixinRequest request,
WeixinMessage message) throws WeixinException { WeixinMessage message) throws WeixinException {
WeixinMessageHandler messageHandler = null; WeixinMessageHandler messageHandler = null;
WeixinMessageHandler[] messageHandlers = getMessageHandlers(); WeixinMessageHandler[] messageHandlers = getMessageHandlers();
@ -123,7 +113,8 @@ public class WeixinMessageDispatcher {
break; break;
} }
} }
return new MessageHandlerExecutor(messageHandler, messageInterceptors); return new MessageHandlerExecutor(context, messageHandler,
getMessageInterceptors());
} }
public WeixinMessageHandler[] getMessageHandlers() throws WeixinException { public WeixinMessageHandler[] getMessageHandlers() throws WeixinException {
@ -173,7 +164,7 @@ public class WeixinMessageDispatcher {
public WeixinMessageInterceptor[] getMessageInterceptors() public WeixinMessageInterceptor[] getMessageInterceptors()
throws WeixinException { throws WeixinException {
if (this.messageInterceptors == null) { if (this.messageInterceptors == null) {
if (this.messageInterceptorList != null) { if (this.messageInterceptorPackages != null) {
List<Class<?>> messageInterceptorClass = new LinkedList<Class<?>>(); List<Class<?>> messageInterceptorClass = new LinkedList<Class<?>>();
for (String packageName : messageInterceptorPackages) { for (String packageName : messageInterceptorPackages) {
messageInterceptorClass.addAll(ClassUtil messageInterceptorClass.addAll(ClassUtil

View File

@ -12,20 +12,21 @@ public abstract class MessageInterceptorAdapter implements
WeixinMessageInterceptor { WeixinMessageInterceptor {
@Override @Override
public boolean preHandle(ChannelHandlerContext ctx, WeixinRequest request, public boolean preHandle(ChannelHandlerContext context,
WeixinMessage message, WeixinMessageHandler handler) WeixinRequest request, WeixinMessage message,
throws WeixinException { WeixinMessageHandler handler) throws WeixinException {
return true; return true;
} }
@Override @Override
public void postHandle(ChannelHandlerContext ctx, WeixinRequest request, public void postHandle(ChannelHandlerContext context,
WeixinResponse response, WeixinMessage message, WeixinRequest request, WeixinResponse response,
WeixinMessageHandler handler) throws WeixinException { WeixinMessage message, WeixinMessageHandler handler)
throws WeixinException {
} }
@Override @Override
public void afterCompletion(ChannelHandlerContext ctx, public void afterCompletion(ChannelHandlerContext context,
WeixinRequest request, WeixinMessage message, WeixinRequest request, WeixinMessage message,
WeixinMessageHandler handler, WeixinException exception) WeixinMessageHandler handler, WeixinException exception)
throws WeixinException { throws WeixinException {

View File

@ -30,7 +30,7 @@ public interface WeixinMessageInterceptor {
* 微信消息 * 微信消息
* @param handler * @param handler
* 消息处理器 * 消息处理器
* @return * @return 返回true执行下一个拦截器
* @throws WeixinException * @throws WeixinException
*/ */
boolean preHandle(ChannelHandlerContext ctx, WeixinRequest request, boolean preHandle(ChannelHandlerContext ctx, WeixinRequest request,

View File

@ -17,6 +17,7 @@ import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.type.EncryptType; import com.foxinmy.weixin4j.type.EncryptType;
import com.foxinmy.weixin4j.util.Consts; import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.MessageUtil; import com.foxinmy.weixin4j.util.MessageUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.EncryptMessageHandler; import com.foxinmy.weixin4j.xml.EncryptMessageHandler;
/** /**
@ -70,10 +71,10 @@ public class WeixinMessageDecoder extends
String msgSignature = parameters.containsKey("msg_signature") ? parameters String msgSignature = parameters.containsKey("msg_signature") ? parameters
.get("msg_signature").get(0) : ""; .get("msg_signature").get(0) : "";
message.setMsgSignature(msgSignature); message.setMsgSignature(msgSignature);
if (!content.isEmpty()) { if (!content.isEmpty()) {
if (message.getEncryptType() == EncryptType.AES) { if (message.getEncryptType() == EncryptType.AES) {
if (aesToken.getAesKey() == null || aesToken.getAppid() == null) { if (StringUtil.isBlank(aesToken.getAesKey())
|| StringUtil.isBlank(aesToken.getAppid())) {
throw new WeixinException( throw new WeixinException(
"AESEncodingKey or AppId not be null in AES mode"); "AESEncodingKey or AppId not be null in AES mode");
} }

View File

@ -1,5 +1,6 @@
package com.foxinmy.weixin4j.socket; package com.foxinmy.weixin4j.socket;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.handler.codec.MessageToMessageEncoder;
@ -10,11 +11,14 @@ import org.slf4j.LoggerFactory;
import com.foxinmy.weixin4j.bean.AesToken; import com.foxinmy.weixin4j.bean.AesToken;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.request.ResponseMessage; import com.foxinmy.weixin4j.response.BlankResponse;
import com.foxinmy.weixin4j.response.WeixinResponse;
import com.foxinmy.weixin4j.type.EncryptType;
import com.foxinmy.weixin4j.util.Consts; import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.HttpUtil; import com.foxinmy.weixin4j.util.HttpUtil;
import com.foxinmy.weixin4j.util.MessageUtil; import com.foxinmy.weixin4j.util.MessageUtil;
import com.foxinmy.weixin4j.util.RandomUtil; import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil;
/** /**
* 微信消息编码类 * 微信消息编码类
@ -27,8 +31,10 @@ import com.foxinmy.weixin4j.util.RandomUtil;
* href="http://mp.weixin.qq.com/wiki/0/61c3a8b9d50ac74f18bdf2e54ddfc4e0.html">加密接入指引</a> * href="http://mp.weixin.qq.com/wiki/0/61c3a8b9d50ac74f18bdf2e54ddfc4e0.html">加密接入指引</a>
*/ */
public class WeixinMessageEncoder extends public class WeixinMessageEncoder extends
MessageToMessageEncoder<ResponseMessage> { MessageToMessageEncoder<WeixinResponse> {
private final Logger log = LoggerFactory.getLogger(getClass()); private final Logger log = LoggerFactory.getLogger(getClass());
private final AesToken aesToken; private final AesToken aesToken;
public WeixinMessageEncoder(AesToken aesToken) { public WeixinMessageEncoder(AesToken aesToken) {
@ -36,34 +42,58 @@ public class WeixinMessageEncoder extends
} }
@Override @Override
protected void encode(ChannelHandlerContext ctx, ResponseMessage response, protected void encode(ChannelHandlerContext ctx, WeixinResponse response,
List<Object> out) throws WeixinException { List<Object> out) throws WeixinException {
if (aesToken.getAesKey() == null || aesToken.getAppid() == null) { EncryptType encryptType = ctx.channel().attr(Consts.ENCRYPTTYPE_KEY)
throw new WeixinException( .get();
"AESEncodingKey or AppId not be null in AES mode"); String userOpenId = ctx.channel().attr(Consts.USEROPENID_KEY).get();
String accountOpenId = ctx.channel().attr(Consts.ACCOUNTOPENID_KEY)
.get();
if (StringUtil.isBlank(accountOpenId)) {
accountOpenId = aesToken.getAppid();
} }
String nonce = RandomUtil.generateString(32);
String timestamp = String.valueOf(System.currentTimeMillis() / 1000l);
String encrtypt = MessageUtil.aesEncrypt(aesToken.getAppid(),
aesToken.getAesKey(), response.toXml());
String msgSignature = MessageUtil.signature(aesToken.getToken(), nonce,
timestamp, encrtypt);
StringBuilder content = new StringBuilder(); StringBuilder content = new StringBuilder();
content.append("<xml>"); if (response instanceof BlankResponse) {
content.append(String.format("<Nonce><![CDATA[%s]]></Nonce>", nonce)); content.append(response.toContent());
content.append(String.format("<TimeStamp><![CDATA[%s]]></TimeStamp>", } else {
timestamp)); content.append("<xml>");
content.append(String.format( content.append(String.format(
"<MsgSignature><![CDATA[%s]]></MsgSignature>", msgSignature)); "<ToUserName><![CDATA[%s]]></ToUserName>", userOpenId));
content.append(String.format("<Encrypt><![CDATA[%s]]></Encrypt>", content.append(String.format(
encrtypt)); "<FromUserName><![CDATA[%s]]></FromUserName>",
content.append("</xml>"); accountOpenId));
content.append(String.format(
out.add(HttpUtil.createWeixinMessageResponse(content.toString(), "<CreateTime><![CDATA[%d]]></CreateTime>",
System.currentTimeMillis() / 1000l));
content.append(String.format("<MsgType><![CDATA[%s]]></MsgType>",
response.getMsgType()));
content.append(response.toContent());
content.append("</xml>");
if (encryptType == EncryptType.AES) {
String nonce = RandomUtil.generateString(32);
String timestamp = String
.valueOf(System.currentTimeMillis() / 1000l);
String encrtypt = MessageUtil.aesEncrypt(accountOpenId,
aesToken.getAesKey(), content.toString());
String msgSignature = MessageUtil.signature(
aesToken.getToken(), nonce, timestamp, encrtypt);
content.delete(0, content.length() - 1);
content.append("<xml>");
content.append(String.format("<Nonce><![CDATA[%s]]></Nonce>",
nonce));
content.append(String.format(
"<TimeStamp><![CDATA[%s]]></TimeStamp>", timestamp));
content.append(String.format(
"<MsgSignature><![CDATA[%s]]></MsgSignature>",
msgSignature));
content.append(String.format(
"<Encrypt><![CDATA[%s]]></Encrypt>", encrtypt));
content.append("</xml>");
}
}
ctx.writeAndFlush(HttpUtil.createHttpResponse(content.toString(), OK,
Consts.CONTENTTYPE$APPLICATION_XML)); Consts.CONTENTTYPE$APPLICATION_XML));
log.info("\n=================response message=================");
log.info("\n=================aes encrtypt out=================");
log.info("{}", content); log.info("{}", content);
} }
} }

View File

@ -1,11 +1,12 @@
package com.foxinmy.weixin4j.socket; package com.foxinmy.weixin4j.socket;
import static io.netty.handler.codec.http.HttpResponseStatus.FORBIDDEN;
import static io.netty.handler.codec.http.HttpResponseStatus.METHOD_NOT_ALLOWED;
import static io.netty.handler.codec.http.HttpResponseStatus.OK;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -26,6 +27,7 @@ import com.foxinmy.weixin4j.util.ClassUtil;
import com.foxinmy.weixin4j.util.Consts; import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.HttpUtil; import com.foxinmy.weixin4j.util.HttpUtil;
import com.foxinmy.weixin4j.util.MessageUtil; import com.foxinmy.weixin4j.util.MessageUtil;
import com.foxinmy.weixin4j.util.StringUtil;
/** /**
* 微信被动消息处理类 * 微信被动消息处理类
@ -74,19 +76,23 @@ public class WeixinMessageHandler extends
if (MessageUtil.signature(aesToken.getToken(), if (MessageUtil.signature(aesToken.getToken(),
request.getTimeStamp(), request.getNonce()).equals( request.getTimeStamp(), request.getNonce()).equals(
request.getSignature())) { request.getSignature())) {
ctx.write(HttpUtil.createWeixinMessageResponse( ctx.writeAndFlush(
request.getEchoStr(), Consts.CONTENTTYPE$TEXT_PLAIN)); HttpUtil.createHttpResponse(request.getEchoStr(), OK,
Consts.CONTENTTYPE$TEXT_PLAIN)).addListener(
ChannelFutureListener.CLOSE);
return; return;
} }
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, ctx.writeAndFlush(
HttpResponseStatus.FORBIDDEN)); HttpUtil.createHttpResponse(null, FORBIDDEN, null))
.addListener(ChannelFutureListener.CLOSE);
return; return;
} else if (request.getMethod().equals(HttpMethod.POST.name())) { } else if (request.getMethod().equals(HttpMethod.POST.name())) {
if (!MessageUtil.signature(aesToken.getToken(), if (!MessageUtil.signature(aesToken.getToken(),
request.getTimeStamp(), request.getNonce()).equals( request.getTimeStamp(), request.getNonce()).equals(
request.getSignature())) { request.getSignature())) {
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, ctx.writeAndFlush(
HttpResponseStatus.FORBIDDEN)); HttpUtil.createHttpResponse(null, FORBIDDEN, null))
.addListener(ChannelFutureListener.CLOSE);
return; return;
} }
if (request.getEncryptType() == EncryptType.AES) { if (request.getEncryptType() == EncryptType.AES) {
@ -94,14 +100,16 @@ public class WeixinMessageHandler extends
request.getTimeStamp(), request.getNonce(), request.getTimeStamp(), request.getNonce(),
request.getEncryptContent()).equals( request.getEncryptContent()).equals(
request.getMsgSignature())) { request.getMsgSignature())) {
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, ctx.writeAndFlush(
HttpResponseStatus.FORBIDDEN)); HttpUtil.createHttpResponse(null, FORBIDDEN, null))
.addListener(ChannelFutureListener.CLOSE);
return; return;
} }
} }
} else { } else {
ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, ctx.writeAndFlush(
HttpResponseStatus.METHOD_NOT_ALLOWED)); HttpUtil.createHttpResponse(null, METHOD_NOT_ALLOWED, null))
.addListener(ChannelFutureListener.CLOSE);
return; return;
} }
WeixinMessage weixinMessage = null; WeixinMessage weixinMessage = null;
@ -113,6 +121,14 @@ public class WeixinMessageHandler extends
} catch (JAXBException e) { } catch (JAXBException e) {
throw new WeixinException(e); throw new WeixinException(e);
} }
ctx.channel().attr(Consts.ENCRYPTTYPE_KEY)
.set(request.getEncryptType());
ctx.channel().attr(Consts.USEROPENID_KEY)
.set(weixinMessage.getFromUserName());
if (StringUtil.isBlank(aesToken.getAppid())) {
ctx.channel().attr(Consts.ACCOUNTOPENID_KEY)
.set(weixinMessage.getToUserName());
}
final WeixinRequest cloneRequest = (WeixinRequest) ClassUtil final WeixinRequest cloneRequest = (WeixinRequest) ClassUtil
.deepClone(request); .deepClone(request);
final WeixinMessage cloneMessage = (WeixinMessage) ClassUtil final WeixinMessage cloneMessage = (WeixinMessage) ClassUtil

View File

@ -66,8 +66,8 @@ public final class WeixinServerBootstrap {
/** /**
* 明文模式 * 明文模式
* *
* @param token * * @param appid 公众号的唯一ID
* 开发者填写的token *
*/ */
public WeixinServerBootstrap(String token) { public WeixinServerBootstrap(String token) {
this(new AesToken(token)); this(new AesToken(token));

View File

@ -1,7 +1,11 @@
package com.foxinmy.weixin4j.util; package com.foxinmy.weixin4j.util;
import io.netty.util.AttributeKey;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import com.foxinmy.weixin4j.type.EncryptType;
/** /**
* 常量类 * 常量类
* *
@ -30,4 +34,11 @@ public final class Consts {
public static final String PROTOCOL_JAR = "jar"; public static final String PROTOCOL_JAR = "jar";
public static final String CONTENTTYPE$APPLICATION_XML = "application/xml"; public static final String CONTENTTYPE$APPLICATION_XML = "application/xml";
public static final String CONTENTTYPE$TEXT_PLAIN = "text/plain"; public static final String CONTENTTYPE$TEXT_PLAIN = "text/plain";
public static final AttributeKey<EncryptType> ENCRYPTTYPE_KEY = AttributeKey
.valueOf("ENCRYPTTYPE");
public static final AttributeKey<String> ACCOUNTOPENID_KEY = AttributeKey
.valueOf("ACCOUNTOPENID");
public static final AttributeKey<String> USEROPENID_KEY = AttributeKey
.valueOf("USEROPENID");
} }

View File

@ -12,6 +12,7 @@ import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders.Values; import io.netty.handler.codec.http.HttpHeaders.Values;
import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import java.util.Date; import java.util.Date;
@ -26,10 +27,19 @@ import java.util.Date;
*/ */
public class HttpUtil { public class HttpUtil {
public static HttpResponse createWeixinMessageResponse(String content, public static HttpResponse createHttpResponse(String content,
String contentType) { HttpResponseStatus status, String contentType) {
if (content == null) {
content = "";
}
if (StringUtil.isBlank(contentType)) {
contentType = Consts.CONTENTTYPE$TEXT_PLAIN;
}
if (status == null) {
status = OK;
}
FullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, FullHttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1,
OK, Unpooled.copiedBuffer(content, Consts.UTF_8)); status, Unpooled.copiedBuffer(content, Consts.UTF_8));
httpResponse.headers().set( httpResponse.headers().set(
CONTENT_TYPE, CONTENT_TYPE,
String.format("%s;encoding=%s", contentType, String.format("%s;encoding=%s", contentType,

View File

@ -1,8 +1,13 @@
package com.foxinmy.weixin4j.server.test; package com.foxinmy.weixin4j.server.test;
import io.netty.channel.ChannelHandlerContext;
import com.foxinmy.weixin4j.exception.WeixinException; import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.handler.BlankMessageHandler;
import com.foxinmy.weixin4j.handler.DebugMessageHandler; import com.foxinmy.weixin4j.handler.DebugMessageHandler;
import com.foxinmy.weixin4j.handler.WeixinMessageHandler; import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
import com.foxinmy.weixin4j.interceptor.MessageInterceptorAdapter;
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
import com.foxinmy.weixin4j.request.WeixinMessage; import com.foxinmy.weixin4j.request.WeixinMessage;
import com.foxinmy.weixin4j.request.WeixinRequest; import com.foxinmy.weixin4j.request.WeixinRequest;
import com.foxinmy.weixin4j.response.TextResponse; import com.foxinmy.weixin4j.response.TextResponse;
@ -20,9 +25,9 @@ import com.foxinmy.weixin4j.startup.WeixinServerBootstrap;
*/ */
public class MessageServerStarup { public class MessageServerStarup {
final String appid = "appid"; final String appid = "公众号appid";
final String token = "carsonliu13450438112"; final String token = "开发者token";
final String aesKey = "aeskey"; final String aesKey = "aes加密密钥";
/** /**
* 明文模式 * 明文模式
@ -78,7 +83,38 @@ public class MessageServerStarup {
.startup(); .startup();
} }
public void test5() throws WeixinException {
// 拦截所有请求
WeixinMessageInterceptor interceptor = new MessageInterceptorAdapter() {
@Override
public boolean preHandle(ChannelHandlerContext context,
WeixinRequest request, WeixinMessage message,
WeixinMessageHandler handler) throws WeixinException {
context.write(new TextResponse("所有消息被拦截了!"));
return false;
}
@Override
public void postHandle(ChannelHandlerContext context,
WeixinRequest request, WeixinResponse response,
WeixinMessage message, WeixinMessageHandler handler)
throws WeixinException {
System.err.println("preHandle返回为true,执行handler后");
}
@Override
public void afterCompletion(ChannelHandlerContext context,
WeixinRequest request, WeixinMessage message,
WeixinMessageHandler handler, WeixinException exception)
throws WeixinException {
System.err.println("请求处理完毕");
}
};
new WeixinServerBootstrap(token).addInterceptor(interceptor)
.addHandler(BlankMessageHandler.global).startup();
}
public static void main(String[] args) throws WeixinException { public static void main(String[] args) throws WeixinException {
new MessageServerStarup().test4(); new MessageServerStarup().test5();
} }
} }