1 package com.foxinmy.weixin4j.socket;
2
3 import java.util.List;
4 import java.util.Map;
5 import java.util.Map.Entry;
6 import java.util.concurrent.ConcurrentHashMap;
7
8 import com.foxinmy.weixin4j.request.WeixinRequest;
9 import com.foxinmy.weixin4j.type.EncryptType;
10 import com.foxinmy.weixin4j.util.AesToken;
11 import com.foxinmy.weixin4j.util.MessageUtil;
12 import com.foxinmy.weixin4j.util.ServerToolkits;
13 import com.foxinmy.weixin4j.xml.EncryptMessageHandler;
14
15 import io.netty.channel.ChannelHandler;
16 import io.netty.channel.ChannelHandlerContext;
17 import io.netty.handler.codec.MessageToMessageDecoder;
18 import io.netty.handler.codec.http.FullHttpRequest;
19 import io.netty.handler.codec.http.HttpMethod;
20 import io.netty.handler.codec.http.QueryStringDecoder;
21 import io.netty.util.internal.logging.InternalLogger;
22 import io.netty.util.internal.logging.InternalLoggerFactory;
23
24
25
26
27
28
29
30
31
32
33
34
35 @ChannelHandler.Sharable
36 public class WeixinMessageDecoder extends MessageToMessageDecoder<FullHttpRequest> {
37 private final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());
38
39 private Map<String, AesToken> aesTokenMap = new ConcurrentHashMap<String, AesToken>();
40
41 public WeixinMessageDecoder(final Map<String, AesToken> aesTokenMap) {
42 for (Entry<String, AesToken> entry : aesTokenMap.entrySet()) {
43 this.aesTokenMap.put(entry.getKey() == null ? "" : entry.getKey(), entry.getValue());
44 }
45 }
46
47 public void addAesToken(final AesToken asetoken) {
48 aesTokenMap.put(asetoken.getWeixinId(), asetoken);
49 }
50
51 @Override
52 protected void decode(ChannelHandlerContext ctx, FullHttpRequest req, List<Object> out) {
53 String messageContent = req.content().toString(ServerToolkits.UTF_8);
54 QueryStringDecoder queryDecoder = new QueryStringDecoder(req.uri(), true);
55 HttpMethod method = req.method();
56 logger.info("decode request:{} use {} method invoking", req.uri(), method);
57 Map<String, List<String>> parameters = queryDecoder.parameters();
58 EncryptType encryptType = parameters.containsKey("encrypt_type")
59 ? EncryptType.valueOf(parameters.get("encrypt_type").get(0).toUpperCase()) : EncryptType.RAW;
60 String echoStr = parameters.containsKey("echostr") ? parameters.get("echostr").get(0) : "";
61 String timeStamp = parameters.containsKey("timestamp") ? parameters.get("timestamp").get(0) : "";
62 String nonce = parameters.containsKey("nonce") ? parameters.get("nonce").get(0) : "";
63 String signature = parameters.containsKey("signature") ? parameters.get("signature").get(0) : "";
64 String msgSignature = parameters.containsKey("msg_signature") ? parameters.get("msg_signature").get(0) : "";
65 String weixinId = parameters.containsKey("weixin_id") ? parameters.get("weixin_id").get(0) : "";
66 AesToken aesToken = aesTokenMap.get(weixinId);
67 String encryptContent = null;
68 if (!ServerToolkits.isBlank(messageContent) && encryptType == EncryptType.AES) {
69 if (ServerToolkits.isBlank(aesToken.getAesKey())) {
70 throw new RuntimeException("EncodingAESKey not be empty in safety(AES) mode");
71 }
72 EncryptMessageHandler encryptHandler = EncryptMessageHandler.parser(messageContent);
73 encryptContent = encryptHandler.getEncryptContent();
74
75
76
77 if (aesToken.getWeixinId().startsWith("tj")) {
78 aesToken = new AesToken(encryptHandler.getToUserName(), aesToken.getToken(), aesToken.getAesKey());
79 }
80 messageContent = MessageUtil.aesDecrypt(aesToken.getWeixinId(), aesToken.getAesKey(), encryptContent);
81 }
82 logger.info("read original message {}", messageContent);
83 WeixinRequest request = new WeixinRequest(req.headers(), method, req.uri(), encryptType, echoStr, timeStamp,
84 nonce, signature, msgSignature, messageContent, encryptContent, aesToken);
85 request.setDecoderResult(req.decoderResult());
86 request.setProtocolVersion(req.protocolVersion());
87 out.add(request);
88 }
89 }