View Javadoc
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   * @className WeixinMessageDecoder
28   * @author jinyu(foxinmy@gmail.com)
29   * @date 2014年11月13日
30   * @since JDK 1.6
31   * @see <a href=
32   *      "http://mp.weixin.qq.com/wiki/0/61c3a8b9d50ac74f18bdf2e54ddfc4e0.html">加密接入指引</a>
33   * @see com.foxinmy.weixin4j.request.WeixinRequest
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  }