diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java
index fead486ea..a809fe3b1 100755
--- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java
+++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/crypto/WxCryptUtil.java
@@ -1,300 +1,300 @@
-/**
- * 对公众平台发送给公众账号的消息加解密示例代码.
- *
- * @copyright Copyright (c) 1998-2014 Tencent Inc.
- *
- * 针对org.apache.commons.codec.binary.Base64,
- * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
- * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
- */
-
-// ------------------------------------------------------------------------
-
-/**
- * 针对org.apache.commons.codec.binary.Base64,
- * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
- * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
- */
-package me.chanjar.weixin.common.util.crypto;
-
-import java.io.StringReader;
-import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.Random;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.commons.codec.binary.Base64;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.InputSource;
-
-public class WxCryptUtil {
-
- private static final Base64 base64 = new Base64();
- private static final Charset CHARSET = Charset.forName("utf-8");
-
- private static final ThreadLocal builderLocal = new ThreadLocal() {
- @Override
- protected DocumentBuilder initialValue() {
- try {
- return DocumentBuilderFactory.newInstance().newDocumentBuilder();
- } catch (ParserConfigurationException exc) {
- throw new IllegalArgumentException(exc);
- }
- }
- };
-
- protected byte[] aesKey;
- protected String token;
- protected String appidOrCorpid;
-
- public WxCryptUtil() {
- super();
- }
-
- /**
- * 构造函数
- *
- * @param token 公众平台上,开发者设置的token
- * @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey
- * @param appidOrCorpid 公众平台appid/corpid
- */
- public WxCryptUtil(String token, String encodingAesKey,
- String appidOrCorpid) {
- this.token = token;
- this.appidOrCorpid = appidOrCorpid;
- this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
- }
-
- static String extractEncryptPart(String xml) {
- try {
- DocumentBuilder db = builderLocal.get();
- Document document = db.parse(new InputSource(new StringReader(xml)));
-
- Element root = document.getDocumentElement();
- return root.getElementsByTagName("Encrypt").item(0).getTextContent();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * 将公众平台回复用户的消息加密打包.
- *
- * - 对要发送的消息进行AES-CBC加密
- * - 生成安全签名
- * - 将消息密文和安全签名打包成xml格式
- *
- *
- * @param plainText 公众平台待回复用户的消息,xml格式的字符串
- * @return 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串
- */
- public String encrypt(String plainText) {
- // 加密
- String encryptedXml = encrypt(genRandomStr(), plainText);
-
- // 生成安全签名
- String timeStamp = Long.toString(System.currentTimeMillis() / 1000l);
- String nonce = genRandomStr();
-
- String signature = SHA1.gen(this.token, timeStamp, nonce, encryptedXml);
- String result = generateXml(encryptedXml, signature, timeStamp, nonce);
- return result;
- }
-
- /**
- * 对明文进行加密.
- *
- * @param plainText 需要加密的明文
- * @return 加密后base64编码的字符串
- */
- protected String encrypt(String randomStr, String plainText) {
- ByteGroup byteCollector = new ByteGroup();
- byte[] randomStringBytes = randomStr.getBytes(CHARSET);
- byte[] plainTextBytes = plainText.getBytes(CHARSET);
- byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(
- plainTextBytes.length);
- byte[] appIdBytes = this.appidOrCorpid.getBytes(CHARSET);
-
- // randomStr + networkBytesOrder + text + appid
- byteCollector.addBytes(randomStringBytes);
- byteCollector.addBytes(bytesOfSizeInNetworkOrder);
- byteCollector.addBytes(plainTextBytes);
- byteCollector.addBytes(appIdBytes);
-
- // ... + pad: 使用自定义的填充方式对明文进行补位填充
- byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
- byteCollector.addBytes(padBytes);
-
- // 获得最终的字节流, 未加密
- byte[] unencrypted = byteCollector.toBytes();
-
- try {
- // 设置加密模式为AES的CBC模式
- Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
- SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES");
- IvParameterSpec iv = new IvParameterSpec(this.aesKey, 0, 16);
- cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
-
- // 加密
- byte[] encrypted = cipher.doFinal(unencrypted);
-
- // 使用BASE64对加密后的字符串进行编码
- String base64Encrypted = base64.encodeToString(encrypted);
-
- return base64Encrypted;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- /**
- * 检验消息的真实性,并且获取解密后的明文.
- *
- * - 利用收到的密文生成安全签名,进行签名验证
- * - 若验证通过,则提取xml中的加密消息
- * - 对消息进行解密
- *
- *
- * @param msgSignature 签名串,对应URL参数的msg_signature
- * @param timeStamp 时间戳,对应URL参数的timestamp
- * @param nonce 随机串,对应URL参数的nonce
- * @param encryptedXml 密文,对应POST请求的数据
- * @return 解密后的原文
- */
- public String decrypt(String msgSignature, String timeStamp, String nonce,
- String encryptedXml) {
- // 密钥,公众账号的app corpSecret
- // 提取密文
- String cipherText = extractEncryptPart(encryptedXml);
-
- // 验证安全签名
- String signature = SHA1.gen(this.token, timeStamp, nonce, cipherText);
- if (!signature.equals(msgSignature)) {
- throw new RuntimeException("加密消息签名校验失败");
- }
-
- // 解密
- String result = decrypt(cipherText);
- return result;
- }
-
- /**
- * 对密文进行解密.
- *
- * @param cipherText 需要解密的密文
- * @return 解密得到的明文
- */
- public String decrypt(String cipherText) {
- byte[] original;
- try {
- // 设置解密模式为AES的CBC模式
- Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
- SecretKeySpec key_spec = new SecretKeySpec(this.aesKey, "AES");
- IvParameterSpec iv = new IvParameterSpec(
- Arrays.copyOfRange(this.aesKey, 0, 16));
- cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
-
- // 使用BASE64对密文进行解码
- byte[] encrypted = Base64.decodeBase64(cipherText);
-
- // 解密
- original = cipher.doFinal(encrypted);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- String xmlContent, from_appid;
- try {
- // 去除补位字符
- byte[] bytes = PKCS7Encoder.decode(original);
-
- // 分离16位随机字符串,网络字节序和AppId
- byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
-
- int xmlLength = bytesNetworkOrder2Number(networkOrder);
-
- xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength),
- CHARSET);
- from_appid = new String(
- Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
-
- // appid不相同的情况
- if (!from_appid.equals(this.appidOrCorpid)) {
- throw new RuntimeException("AppID不正确");
- }
-
- return xmlContent;
-
- }
-
- /**
- * 将一个数字转换成生成4个字节的网络字节序bytes数组
- *
- * @param number
- */
- private static byte[] number2BytesInNetworkOrder(int number) {
- byte[] orderBytes = new byte[4];
- orderBytes[3] = (byte) (number & 0xFF);
- orderBytes[2] = (byte) (number >> 8 & 0xFF);
- orderBytes[1] = (byte) (number >> 16 & 0xFF);
- orderBytes[0] = (byte) (number >> 24 & 0xFF);
- return orderBytes;
- }
-
- /**
- * 4个字节的网络字节序bytes数组还原成一个数字
- *
- * @param bytesInNetworkOrder
- */
- private static int bytesNetworkOrder2Number(byte[] bytesInNetworkOrder) {
- int sourceNumber = 0;
- for (int i = 0; i < 4; i++) {
- sourceNumber <<= 8;
- sourceNumber |= bytesInNetworkOrder[i] & 0xff;
- }
- return sourceNumber;
- }
-
- /**
- * 随机生成16位字符串
- */
- private static String genRandomStr() {
- String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
- Random random = new Random();
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < 16; i++) {
- int number = random.nextInt(base.length());
- sb.append(base.charAt(number));
- }
- return sb.toString();
- }
-
- /**
- * 生成xml消息
- *
- * @param encrypt 加密后的消息密文
- * @param signature 安全签名
- * @param timestamp 时间戳
- * @param nonce 随机字符串
- * @return 生成的xml字符串
- */
- private static String generateXml(String encrypt, String signature,
- String timestamp, String nonce) {
- String format = "\n" + "\n"
- + "\n"
- + "%3$s\n" + "\n"
- + "";
- return String.format(format, encrypt, signature, timestamp, nonce);
- }
-
-}
+/**
+ * 对公众平台发送给公众账号的消息加解密示例代码.
+ *
+ * @copyright Copyright (c) 1998-2014 Tencent Inc.
+ *
+ * 针对org.apache.commons.codec.binary.Base64,
+ * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
+ * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * 针对org.apache.commons.codec.binary.Base64,
+ * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
+ * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
+ */
+package me.chanjar.weixin.common.util.crypto;
+
+import java.io.StringReader;
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.Random;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.codec.binary.Base64;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+
+public class WxCryptUtil {
+
+ private static final Base64 base64 = new Base64();
+ private static final Charset CHARSET = Charset.forName("utf-8");
+
+ private static final ThreadLocal builderLocal = new ThreadLocal() {
+ @Override
+ protected DocumentBuilder initialValue() {
+ try {
+ return DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ } catch (ParserConfigurationException exc) {
+ throw new IllegalArgumentException(exc);
+ }
+ }
+ };
+
+ protected byte[] aesKey;
+ protected String token;
+ protected String appidOrCorpid;
+
+ public WxCryptUtil() {
+ super();
+ }
+
+ /**
+ * 构造函数
+ *
+ * @param token 公众平台上,开发者设置的token
+ * @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey
+ * @param appidOrCorpid 公众平台appid/corpid
+ */
+ public WxCryptUtil(String token, String encodingAesKey,
+ String appidOrCorpid) {
+ this.token = token;
+ this.appidOrCorpid = appidOrCorpid;
+ this.aesKey = Base64.decodeBase64(encodingAesKey + "=");
+ }
+
+ static String extractEncryptPart(String xml) {
+ try {
+ DocumentBuilder db = builderLocal.get();
+ Document document = db.parse(new InputSource(new StringReader(xml)));
+
+ Element root = document.getDocumentElement();
+ return root.getElementsByTagName("Encrypt").item(0).getTextContent();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 将公众平台回复用户的消息加密打包.
+ *
+ * - 对要发送的消息进行AES-CBC加密
+ * - 生成安全签名
+ * - 将消息密文和安全签名打包成xml格式
+ *
+ *
+ * @param plainText 公众平台待回复用户的消息,xml格式的字符串
+ * @return 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串
+ */
+ public String encrypt(String plainText) {
+ // 加密
+ String encryptedXml = encrypt(genRandomStr(), plainText);
+
+ // 生成安全签名
+ String timeStamp = Long.toString(System.currentTimeMillis() / 1000l);
+ String nonce = genRandomStr();
+
+ String signature = SHA1.gen(this.token, timeStamp, nonce, encryptedXml);
+ String result = generateXml(encryptedXml, signature, timeStamp, nonce);
+ return result;
+ }
+
+ /**
+ * 对明文进行加密.
+ *
+ * @param plainText 需要加密的明文
+ * @return 加密后base64编码的字符串
+ */
+ protected String encrypt(String randomStr, String plainText) {
+ ByteGroup byteCollector = new ByteGroup();
+ byte[] randomStringBytes = randomStr.getBytes(CHARSET);
+ byte[] plainTextBytes = plainText.getBytes(CHARSET);
+ byte[] bytesOfSizeInNetworkOrder = number2BytesInNetworkOrder(
+ plainTextBytes.length);
+ byte[] appIdBytes = this.appidOrCorpid.getBytes(CHARSET);
+
+ // randomStr + networkBytesOrder + text + appid
+ byteCollector.addBytes(randomStringBytes);
+ byteCollector.addBytes(bytesOfSizeInNetworkOrder);
+ byteCollector.addBytes(plainTextBytes);
+ byteCollector.addBytes(appIdBytes);
+
+ // ... + pad: 使用自定义的填充方式对明文进行补位填充
+ byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
+ byteCollector.addBytes(padBytes);
+
+ // 获得最终的字节流, 未加密
+ byte[] unencrypted = byteCollector.toBytes();
+
+ try {
+ // 设置加密模式为AES的CBC模式
+ Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ SecretKeySpec keySpec = new SecretKeySpec(this.aesKey, "AES");
+ IvParameterSpec iv = new IvParameterSpec(this.aesKey, 0, 16);
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
+
+ // 加密
+ byte[] encrypted = cipher.doFinal(unencrypted);
+
+ // 使用BASE64对加密后的字符串进行编码
+ String base64Encrypted = base64.encodeToString(encrypted);
+
+ return base64Encrypted;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 检验消息的真实性,并且获取解密后的明文.
+ *
+ * - 利用收到的密文生成安全签名,进行签名验证
+ * - 若验证通过,则提取xml中的加密消息
+ * - 对消息进行解密
+ *
+ *
+ * @param msgSignature 签名串,对应URL参数的msg_signature
+ * @param timeStamp 时间戳,对应URL参数的timestamp
+ * @param nonce 随机串,对应URL参数的nonce
+ * @param encryptedXml 密文,对应POST请求的数据
+ * @return 解密后的原文
+ */
+ public String decrypt(String msgSignature, String timeStamp, String nonce,
+ String encryptedXml) {
+ // 密钥,公众账号的app corpSecret
+ // 提取密文
+ String cipherText = extractEncryptPart(encryptedXml);
+
+ // 验证安全签名
+ String signature = SHA1.gen(this.token, timeStamp, nonce, cipherText);
+ if (!signature.equals(msgSignature)) {
+ throw new RuntimeException("加密消息签名校验失败");
+ }
+
+ // 解密
+ String result = decrypt(cipherText);
+ return result;
+ }
+
+ /**
+ * 对密文进行解密.
+ *
+ * @param cipherText 需要解密的密文
+ * @return 解密得到的明文
+ */
+ public String decrypt(String cipherText) {
+ byte[] original;
+ try {
+ // 设置解密模式为AES的CBC模式
+ Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ SecretKeySpec key_spec = new SecretKeySpec(this.aesKey, "AES");
+ IvParameterSpec iv = new IvParameterSpec(
+ Arrays.copyOfRange(this.aesKey, 0, 16));
+ cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
+
+ // 使用BASE64对密文进行解码
+ byte[] encrypted = Base64.decodeBase64(cipherText);
+
+ // 解密
+ original = cipher.doFinal(encrypted);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ String xmlContent, from_appid;
+ try {
+ // 去除补位字符
+ byte[] bytes = PKCS7Encoder.decode(original);
+
+ // 分离16位随机字符串,网络字节序和AppId
+ byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
+
+ int xmlLength = bytesNetworkOrder2Number(networkOrder);
+
+ xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength),
+ CHARSET);
+ from_appid = new String(
+ Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), CHARSET);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ // appid不相同的情况
+ if (!from_appid.equals(this.appidOrCorpid)) {
+ throw new RuntimeException("AppID不正确");
+ }
+
+ return xmlContent;
+
+ }
+
+ /**
+ * 将一个数字转换成生成4个字节的网络字节序bytes数组
+ *
+ * @param number
+ */
+ private static byte[] number2BytesInNetworkOrder(int number) {
+ byte[] orderBytes = new byte[4];
+ orderBytes[3] = (byte) (number & 0xFF);
+ orderBytes[2] = (byte) (number >> 8 & 0xFF);
+ orderBytes[1] = (byte) (number >> 16 & 0xFF);
+ orderBytes[0] = (byte) (number >> 24 & 0xFF);
+ return orderBytes;
+ }
+
+ /**
+ * 4个字节的网络字节序bytes数组还原成一个数字
+ *
+ * @param bytesInNetworkOrder
+ */
+ private static int bytesNetworkOrder2Number(byte[] bytesInNetworkOrder) {
+ int sourceNumber = 0;
+ for (int i = 0; i < 4; i++) {
+ sourceNumber <<= 8;
+ sourceNumber |= bytesInNetworkOrder[i] & 0xff;
+ }
+ return sourceNumber;
+ }
+
+ /**
+ * 随机生成16位字符串
+ */
+ private static String genRandomStr() {
+ String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+ Random random = new Random();
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < 16; i++) {
+ int number = random.nextInt(base.length());
+ sb.append(base.charAt(number));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 生成xml消息
+ *
+ * @param encrypt 加密后的消息密文
+ * @param signature 安全签名
+ * @param timestamp 时间戳
+ * @param nonce 随机字符串
+ * @return 生成的xml字符串
+ */
+ private static String generateXml(String encrypt, String signature,
+ String timestamp, String nonce) {
+ String format = "\n" + "\n"
+ + "\n"
+ + "%3$s\n" + "\n"
+ + "";
+ return String.format(format, encrypt, signature, timestamp, nonce);
+ }
+
+}
diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/WxCryptUtilTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/WxCryptUtilTest.java
index e76921653..91095a20e 100755
--- a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/WxCryptUtilTest.java
+++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/crypto/WxCryptUtilTest.java
@@ -1,103 +1,103 @@
-package me.chanjar.weixin.common.util.crypto;
-
-import org.testng.annotations.Test;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NodeList;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.IOException;
-import java.io.StringReader;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
-
-@Test
-public class WxCryptUtilTest {
- String encodingAesKey = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG";
- String token = "pamtest";
- String timestamp = "1409304348";
- String nonce = "xxxxxx";
- String appId = "wxb11529c136998cb6";
- String randomStr = "aaaabbbbccccdddd";
-
- String xmlFormat = "";
- String replyMsg = "我是中文abcd123";
-
- String afterAesEncrypt = "jn1L23DB+6ELqJ+6bruv21Y6MD7KeIfP82D6gU39rmkgczbWwt5+3bnyg5K55bgVtVzd832WzZGMhkP72vVOfg==";
-
- String replyMsg2 = "1407743423";
- String afterAesEncrypt2 = "jn1L23DB+6ELqJ+6bruv23M2GmYfkv0xBh2h+XTBOKVKcgDFHle6gqcZ1cZrk3e1qjPQ1F4RsLWzQRG9udbKWesxlkupqcEcW7ZQweImX9+wLMa0GaUzpkycA8+IamDBxn5loLgZpnS7fVAbExOkK5DYHBmv5tptA9tklE/fTIILHR8HLXa5nQvFb3tYPKAlHF3rtTeayNf0QuM+UW/wM9enGIDIJHF7CLHiDNAYxr+r+OrJCmPQyTy8cVWlu9iSvOHPT/77bZqJucQHQ04sq7KZI27OcqpQNSto2OdHCoTccjggX5Z9Mma0nMJBU+jLKJ38YB1fBIz+vBzsYjrTmFQ44YfeEuZ+xRTQwr92vhA9OxchWVINGC50qE/6lmkwWTwGX9wtQpsJKhP+oS7rvTY8+VdzETdfakjkwQ5/Xka042OlUb1/slTwo4RscuQ+RdxSGvDahxAJ6+EAjLt9d8igHngxIbf6YyqqROxuxqIeIch3CssH/LqRs+iAcILvApYZckqmA7FNERspKA5f8GoJ9sv8xmGvZ9Yrf57cExWtnX8aCMMaBropU/1k+hKP5LVdzbWCG0hGwx/dQudYR/eXp3P0XxjlFiy+9DMlaFExWUZQDajPkdPrEeOwofJb";
-
- public void testNormal() throws ParserConfigurationException, SAXException, IOException {
- WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
- String encryptedXml = pc.encrypt(this.replyMsg);
-
- System.out.println(encryptedXml);
-
- DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
- Document document = documentBuilder.parse(new InputSource(new StringReader(encryptedXml)));
-
- Element root = document.getDocumentElement();
- String cipherText = root.getElementsByTagName("Encrypt").item(0).getTextContent();
- System.out.println(cipherText);
-
- String msgSignature = root.getElementsByTagName("MsgSignature").item(0).getTextContent();
- System.out.println(msgSignature);
-
- String timestamp = root.getElementsByTagName("TimeStamp").item(0).getTextContent();
- System.out.println(timestamp);
-
- String nonce = root.getElementsByTagName("Nonce").item(0).getTextContent();
- System.out.println(nonce);
-
- String messageText = String.format(this.xmlFormat, cipherText);
- System.out.println(messageText);
-
- // 第三方收到企业号平台发送的消息
- String plainMessage = pc.decrypt(cipherText);
- System.out.println(plainMessage);
-
- assertEquals(plainMessage, this.replyMsg);
- }
-
- public void testAesEncrypt() {
- WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
- assertEquals(pc.encrypt(this.randomStr, this.replyMsg), this.afterAesEncrypt);
- }
-
- public void testAesEncrypt2() {
- WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
- assertEquals(pc.encrypt(this.randomStr, this.replyMsg2), this.afterAesEncrypt2);
- }
-
- public void testValidateSignatureError() throws ParserConfigurationException, SAXException,
- IOException {
- try {
- WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
- String afterEncrpt = pc.encrypt(this.replyMsg);
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- DocumentBuilder db = dbf.newDocumentBuilder();
- StringReader sr = new StringReader(afterEncrpt);
- InputSource is = new InputSource(sr);
- Document document = db.parse(is);
-
- Element root = document.getDocumentElement();
- NodeList nodelist1 = root.getElementsByTagName("Encrypt");
-
- String encrypt = nodelist1.item(0).getTextContent();
- String fromXML = String.format(this.xmlFormat, encrypt);
- pc.decrypt("12345", this.timestamp, this.nonce, fromXML); // 这里签名错误
- } catch (RuntimeException e) {
- assertEquals(e.getMessage(), "加密消息签名校验失败");
- return;
- }
- fail("错误流程不抛出异常???");
- }
-
-}
+package me.chanjar.weixin.common.util.crypto;
+
+import org.testng.annotations.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.StringReader;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+@Test
+public class WxCryptUtilTest {
+ String encodingAesKey = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFG";
+ String token = "pamtest";
+ String timestamp = "1409304348";
+ String nonce = "xxxxxx";
+ String appId = "wxb11529c136998cb6";
+ String randomStr = "aaaabbbbccccdddd";
+
+ String xmlFormat = "";
+ String replyMsg = "我是中文abcd123";
+
+ String afterAesEncrypt = "jn1L23DB+6ELqJ+6bruv21Y6MD7KeIfP82D6gU39rmkgczbWwt5+3bnyg5K55bgVtVzd832WzZGMhkP72vVOfg==";
+
+ String replyMsg2 = "1407743423";
+ String afterAesEncrypt2 = "jn1L23DB+6ELqJ+6bruv23M2GmYfkv0xBh2h+XTBOKVKcgDFHle6gqcZ1cZrk3e1qjPQ1F4RsLWzQRG9udbKWesxlkupqcEcW7ZQweImX9+wLMa0GaUzpkycA8+IamDBxn5loLgZpnS7fVAbExOkK5DYHBmv5tptA9tklE/fTIILHR8HLXa5nQvFb3tYPKAlHF3rtTeayNf0QuM+UW/wM9enGIDIJHF7CLHiDNAYxr+r+OrJCmPQyTy8cVWlu9iSvOHPT/77bZqJucQHQ04sq7KZI27OcqpQNSto2OdHCoTccjggX5Z9Mma0nMJBU+jLKJ38YB1fBIz+vBzsYjrTmFQ44YfeEuZ+xRTQwr92vhA9OxchWVINGC50qE/6lmkwWTwGX9wtQpsJKhP+oS7rvTY8+VdzETdfakjkwQ5/Xka042OlUb1/slTwo4RscuQ+RdxSGvDahxAJ6+EAjLt9d8igHngxIbf6YyqqROxuxqIeIch3CssH/LqRs+iAcILvApYZckqmA7FNERspKA5f8GoJ9sv8xmGvZ9Yrf57cExWtnX8aCMMaBropU/1k+hKP5LVdzbWCG0hGwx/dQudYR/eXp3P0XxjlFiy+9DMlaFExWUZQDajPkdPrEeOwofJb";
+
+ public void testNormal() throws ParserConfigurationException, SAXException, IOException {
+ WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
+ String encryptedXml = pc.encrypt(this.replyMsg);
+
+ System.out.println(encryptedXml);
+
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ Document document = documentBuilder.parse(new InputSource(new StringReader(encryptedXml)));
+
+ Element root = document.getDocumentElement();
+ String cipherText = root.getElementsByTagName("Encrypt").item(0).getTextContent();
+ System.out.println(cipherText);
+
+ String msgSignature = root.getElementsByTagName("MsgSignature").item(0).getTextContent();
+ System.out.println(msgSignature);
+
+ String timestamp = root.getElementsByTagName("TimeStamp").item(0).getTextContent();
+ System.out.println(timestamp);
+
+ String nonce = root.getElementsByTagName("Nonce").item(0).getTextContent();
+ System.out.println(nonce);
+
+ String messageText = String.format(this.xmlFormat, cipherText);
+ System.out.println(messageText);
+
+ // 第三方收到企业号平台发送的消息
+ String plainMessage = pc.decrypt(cipherText);
+ System.out.println(plainMessage);
+
+ assertEquals(plainMessage, this.replyMsg);
+ }
+
+ public void testAesEncrypt() {
+ WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
+ assertEquals(pc.encrypt(this.randomStr, this.replyMsg), this.afterAesEncrypt);
+ }
+
+ public void testAesEncrypt2() {
+ WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
+ assertEquals(pc.encrypt(this.randomStr, this.replyMsg2), this.afterAesEncrypt2);
+ }
+
+ public void testValidateSignatureError() throws ParserConfigurationException, SAXException,
+ IOException {
+ try {
+ WxCryptUtil pc = new WxCryptUtil(this.token, this.encodingAesKey, this.appId);
+ String afterEncrpt = pc.encrypt(this.replyMsg);
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ StringReader sr = new StringReader(afterEncrpt);
+ InputSource is = new InputSource(sr);
+ Document document = db.parse(is);
+
+ Element root = document.getDocumentElement();
+ NodeList nodelist1 = root.getElementsByTagName("Encrypt");
+
+ String encrypt = nodelist1.item(0).getTextContent();
+ String fromXML = String.format(this.xmlFormat, encrypt);
+ pc.decrypt("12345", this.timestamp, this.nonce, fromXML); // 这里签名错误
+ } catch (RuntimeException e) {
+ assertEquals(e.getMessage(), "加密消息签名校验失败");
+ return;
+ }
+ fail("错误流程不抛出异常???");
+ }
+
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageHandler.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageHandler.java
index dae2a238b..5a336bc8d 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageHandler.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageHandler.java
@@ -2,8 +2,8 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import java.util.Map;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageInterceptor.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageInterceptor.java
index 3fcd6d951..15223895b 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageInterceptor.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageInterceptor.java
@@ -2,7 +2,7 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
import java.util.Map;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java
index 68798ae26..812992c9b 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageMatcher.java
@@ -1,6 +1,6 @@
package me.chanjar.weixin.mp.api;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
/**
* 消息匹配器,用在消息路由的时候
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java
index 7db50e794..24dc4451a 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouter.java
@@ -1,230 +1,230 @@
-package me.chanjar.weixin.mp.api;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import me.chanjar.weixin.common.api.WxErrorExceptionHandler;
-import me.chanjar.weixin.common.api.WxMessageDuplicateChecker;
-import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker;
-import me.chanjar.weixin.common.session.InternalSession;
-import me.chanjar.weixin.common.session.InternalSessionManager;
-import me.chanjar.weixin.common.session.StandardSessionManager;
-import me.chanjar.weixin.common.session.WxSessionManager;
-import me.chanjar.weixin.common.util.LogExceptionHandler;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
-
-/**
- *
- * 微信消息路由器,通过代码化的配置,把来自微信的消息交给handler处理
- *
- * 说明:
- * 1. 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理
- * 2. 默认情况下消息只会被处理一次,除非使用 {@link WxMpMessageRouterRule#next()}
- * 3. 规则的结束必须用{@link WxMpMessageRouterRule#end()}或者{@link WxMpMessageRouterRule#next()},否则不会生效
- *
- * 使用方法:
- * WxMpMessageRouter router = new WxMpMessageRouter();
- * router
- * .rule()
- * .msgType("MSG_TYPE").event("EVENT").eventKey("EVENT_KEY").content("CONTENT")
- * .interceptor(interceptor, ...).handler(handler, ...)
- * .end()
- * .rule()
- * // 另外一个匹配规则
- * .end()
- * ;
- *
- * // 将WxXmlMessage交给消息路由器
- * router.route(message);
- *
- *
- * @author Daniel Qian
- *
- */
-public class WxMpMessageRouter {
-
- protected final Logger log = LoggerFactory.getLogger(WxMpMessageRouter.class);
-
- private static final int DEFAULT_THREAD_POOL_SIZE = 100;
-
- private final List rules = new ArrayList<>();
-
- private final WxMpService wxMpService;
-
- private ExecutorService executorService;
-
- private WxMessageDuplicateChecker messageDuplicateChecker;
-
- private WxSessionManager sessionManager;
-
- private WxErrorExceptionHandler exceptionHandler;
-
- public WxMpMessageRouter(WxMpService wxMpService) {
- this.wxMpService = wxMpService;
- this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
- this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker();
- this.sessionManager = new StandardSessionManager();
- this.exceptionHandler = new LogExceptionHandler();
- }
-
- /**
- *
- * 设置自定义的 {@link ExecutorService}
- * 如果不调用该方法,默认使用 Executors.newFixedThreadPool(100)
- *
- * @param executorService
- */
- public void setExecutorService(ExecutorService executorService) {
- this.executorService = executorService;
- }
-
- /**
- *
- * 设置自定义的 {@link me.chanjar.weixin.common.api.WxMessageDuplicateChecker}
- * 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker}
- *
- * @param messageDuplicateChecker
- */
- public void setMessageDuplicateChecker(WxMessageDuplicateChecker messageDuplicateChecker) {
- this.messageDuplicateChecker = messageDuplicateChecker;
- }
-
- /**
- *
- * 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager}
- * 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.session.StandardSessionManager}
- *
- * @param sessionManager
- */
- public void setSessionManager(WxSessionManager sessionManager) {
- this.sessionManager = sessionManager;
- }
-
- /**
- *
- * 设置自定义的{@link me.chanjar.weixin.common.api.WxErrorExceptionHandler}
- * 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.util.LogExceptionHandler}
- *
- * @param exceptionHandler
- */
- public void setExceptionHandler(WxErrorExceptionHandler exceptionHandler) {
- this.exceptionHandler = exceptionHandler;
- }
-
- List getRules() {
- return this.rules;
- }
-
- /**
- * 开始一个新的Route规则
- */
- public WxMpMessageRouterRule rule() {
- return new WxMpMessageRouterRule(this);
- }
-
- /**
- * 处理微信消息
- * @param wxMessage
- */
- public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage) {
- if (isDuplicateMessage(wxMessage)) {
- // 如果是重复消息,那么就不做处理
- return null;
- }
-
- final List matchRules = new ArrayList<>();
- // 收集匹配的规则
- for (final WxMpMessageRouterRule rule : this.rules) {
- if (rule.test(wxMessage)) {
- matchRules.add(rule);
- if(!rule.isReEnter()) {
- break;
- }
- }
- }
-
- if (matchRules.size() == 0) {
- return null;
- }
-
- WxMpXmlOutMessage res = null;
- final List> futures = new ArrayList<>();
- for (final WxMpMessageRouterRule rule : matchRules) {
- // 返回最后一个非异步的rule的执行结果
- if(rule.isAsync()) {
- futures.add(
- this.executorService.submit(new Runnable() {
- @Override
- public void run() {
- rule.service(wxMessage, WxMpMessageRouter.this.wxMpService, WxMpMessageRouter.this.sessionManager, WxMpMessageRouter.this.exceptionHandler);
- }
- })
- );
- } else {
- res = rule.service(wxMessage, this.wxMpService, this.sessionManager, this.exceptionHandler);
- // 在同步操作结束,session访问结束
- this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUser());
- sessionEndAccess(wxMessage);
- }
- }
-
- if (futures.size() > 0) {
- this.executorService.submit(new Runnable() {
- @Override
- public void run() {
- for (Future> future : futures) {
- try {
- future.get();
- WxMpMessageRouter.this.log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUser());
- // 异步操作结束,session访问结束
- sessionEndAccess(wxMessage);
- } catch (InterruptedException e) {
- WxMpMessageRouter.this.log.error("Error happened when wait task finish", e);
- } catch (ExecutionException e) {
- WxMpMessageRouter.this.log.error("Error happened when wait task finish", e);
- }
- }
- }
- });
- }
- return res;
- }
-
- protected boolean isDuplicateMessage(WxMpXmlMessage wxMessage) {
-
- StringBuffer messageId = new StringBuffer();
- if (wxMessage.getMsgId() == null) {
- messageId.append(wxMessage.getCreateTime())
- .append("-").append(wxMessage.getFromUser())
- .append("-").append(wxMessage.getEventKey() == null ? "" : wxMessage.getEventKey())
- .append("-").append(wxMessage.getEvent() == null ? "" : wxMessage.getEvent())
- ;
- } else {
- messageId.append(wxMessage.getMsgId());
- }
-
- return this.messageDuplicateChecker.isDuplicate(messageId.toString());
-
- }
-
- /**
- * 对session的访问结束
- * @param wxMessage
- */
- protected void sessionEndAccess(WxMpXmlMessage wxMessage) {
-
- InternalSession session = ((InternalSessionManager)this.sessionManager).findSession(wxMessage.getFromUser());
- if (session != null) {
- session.endAccess();
- }
-
- }
-}
+package me.chanjar.weixin.mp.api;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import me.chanjar.weixin.common.api.WxErrorExceptionHandler;
+import me.chanjar.weixin.common.api.WxMessageDuplicateChecker;
+import me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker;
+import me.chanjar.weixin.common.session.InternalSession;
+import me.chanjar.weixin.common.session.InternalSessionManager;
+import me.chanjar.weixin.common.session.StandardSessionManager;
+import me.chanjar.weixin.common.session.WxSessionManager;
+import me.chanjar.weixin.common.util.LogExceptionHandler;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+
+/**
+ *
+ * 微信消息路由器,通过代码化的配置,把来自微信的消息交给handler处理
+ *
+ * 说明:
+ * 1. 配置路由规则时要按照从细到粗的原则,否则可能消息可能会被提前处理
+ * 2. 默认情况下消息只会被处理一次,除非使用 {@link WxMpMessageRouterRule#next()}
+ * 3. 规则的结束必须用{@link WxMpMessageRouterRule#end()}或者{@link WxMpMessageRouterRule#next()},否则不会生效
+ *
+ * 使用方法:
+ * WxMpMessageRouter router = new WxMpMessageRouter();
+ * router
+ * .rule()
+ * .msgType("MSG_TYPE").event("EVENT").eventKey("EVENT_KEY").content("CONTENT")
+ * .interceptor(interceptor, ...).handler(handler, ...)
+ * .end()
+ * .rule()
+ * // 另外一个匹配规则
+ * .end()
+ * ;
+ *
+ * // 将WxXmlMessage交给消息路由器
+ * router.route(message);
+ *
+ *
+ * @author Daniel Qian
+ *
+ */
+public class WxMpMessageRouter {
+
+ protected final Logger log = LoggerFactory.getLogger(WxMpMessageRouter.class);
+
+ private static final int DEFAULT_THREAD_POOL_SIZE = 100;
+
+ private final List rules = new ArrayList<>();
+
+ private final WxMpService wxMpService;
+
+ private ExecutorService executorService;
+
+ private WxMessageDuplicateChecker messageDuplicateChecker;
+
+ private WxSessionManager sessionManager;
+
+ private WxErrorExceptionHandler exceptionHandler;
+
+ public WxMpMessageRouter(WxMpService wxMpService) {
+ this.wxMpService = wxMpService;
+ this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE);
+ this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker();
+ this.sessionManager = new StandardSessionManager();
+ this.exceptionHandler = new LogExceptionHandler();
+ }
+
+ /**
+ *
+ * 设置自定义的 {@link ExecutorService}
+ * 如果不调用该方法,默认使用 Executors.newFixedThreadPool(100)
+ *
+ * @param executorService
+ */
+ public void setExecutorService(ExecutorService executorService) {
+ this.executorService = executorService;
+ }
+
+ /**
+ *
+ * 设置自定义的 {@link me.chanjar.weixin.common.api.WxMessageDuplicateChecker}
+ * 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.api.WxMessageInMemoryDuplicateChecker}
+ *
+ * @param messageDuplicateChecker
+ */
+ public void setMessageDuplicateChecker(WxMessageDuplicateChecker messageDuplicateChecker) {
+ this.messageDuplicateChecker = messageDuplicateChecker;
+ }
+
+ /**
+ *
+ * 设置自定义的{@link me.chanjar.weixin.common.session.WxSessionManager}
+ * 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.session.StandardSessionManager}
+ *
+ * @param sessionManager
+ */
+ public void setSessionManager(WxSessionManager sessionManager) {
+ this.sessionManager = sessionManager;
+ }
+
+ /**
+ *
+ * 设置自定义的{@link me.chanjar.weixin.common.api.WxErrorExceptionHandler}
+ * 如果不调用该方法,默认使用 {@link me.chanjar.weixin.common.util.LogExceptionHandler}
+ *
+ * @param exceptionHandler
+ */
+ public void setExceptionHandler(WxErrorExceptionHandler exceptionHandler) {
+ this.exceptionHandler = exceptionHandler;
+ }
+
+ List getRules() {
+ return this.rules;
+ }
+
+ /**
+ * 开始一个新的Route规则
+ */
+ public WxMpMessageRouterRule rule() {
+ return new WxMpMessageRouterRule(this);
+ }
+
+ /**
+ * 处理微信消息
+ * @param wxMessage
+ */
+ public WxMpXmlOutMessage route(final WxMpXmlMessage wxMessage) {
+ if (isDuplicateMessage(wxMessage)) {
+ // 如果是重复消息,那么就不做处理
+ return null;
+ }
+
+ final List matchRules = new ArrayList<>();
+ // 收集匹配的规则
+ for (final WxMpMessageRouterRule rule : this.rules) {
+ if (rule.test(wxMessage)) {
+ matchRules.add(rule);
+ if(!rule.isReEnter()) {
+ break;
+ }
+ }
+ }
+
+ if (matchRules.size() == 0) {
+ return null;
+ }
+
+ WxMpXmlOutMessage res = null;
+ final List> futures = new ArrayList<>();
+ for (final WxMpMessageRouterRule rule : matchRules) {
+ // 返回最后一个非异步的rule的执行结果
+ if(rule.isAsync()) {
+ futures.add(
+ this.executorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ rule.service(wxMessage, WxMpMessageRouter.this.wxMpService, WxMpMessageRouter.this.sessionManager, WxMpMessageRouter.this.exceptionHandler);
+ }
+ })
+ );
+ } else {
+ res = rule.service(wxMessage, this.wxMpService, this.sessionManager, this.exceptionHandler);
+ // 在同步操作结束,session访问结束
+ this.log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUser());
+ sessionEndAccess(wxMessage);
+ }
+ }
+
+ if (futures.size() > 0) {
+ this.executorService.submit(new Runnable() {
+ @Override
+ public void run() {
+ for (Future> future : futures) {
+ try {
+ future.get();
+ WxMpMessageRouter.this.log.debug("End session access: async=true, sessionId={}", wxMessage.getFromUser());
+ // 异步操作结束,session访问结束
+ sessionEndAccess(wxMessage);
+ } catch (InterruptedException e) {
+ WxMpMessageRouter.this.log.error("Error happened when wait task finish", e);
+ } catch (ExecutionException e) {
+ WxMpMessageRouter.this.log.error("Error happened when wait task finish", e);
+ }
+ }
+ }
+ });
+ }
+ return res;
+ }
+
+ protected boolean isDuplicateMessage(WxMpXmlMessage wxMessage) {
+
+ StringBuffer messageId = new StringBuffer();
+ if (wxMessage.getMsgId() == null) {
+ messageId.append(wxMessage.getCreateTime())
+ .append("-").append(wxMessage.getFromUser())
+ .append("-").append(wxMessage.getEventKey() == null ? "" : wxMessage.getEventKey())
+ .append("-").append(wxMessage.getEvent() == null ? "" : wxMessage.getEvent())
+ ;
+ } else {
+ messageId.append(wxMessage.getMsgId());
+ }
+
+ return this.messageDuplicateChecker.isDuplicate(messageId.toString());
+
+ }
+
+ /**
+ * 对session的访问结束
+ * @param wxMessage
+ */
+ protected void sessionEndAccess(WxMpXmlMessage wxMessage) {
+
+ InternalSession session = ((InternalSessionManager)this.sessionManager).findSession(wxMessage.getFromUser());
+ if (session != null) {
+ session.endAccess();
+ }
+
+ }
+}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java
index 317303b84..6859b7d77 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpMessageRouterRule.java
@@ -3,8 +3,8 @@ package me.chanjar.weixin.mp.api;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.common.api.WxErrorExceptionHandler;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java
index 36c2525cf..228351fda 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/kefu/WxMpKefuMessage.java
@@ -4,14 +4,14 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-import me.chanjar.weixin.mp.bean.custombuilder.ImageBuilder;
-import me.chanjar.weixin.mp.bean.custombuilder.MpNewsBuilder;
-import me.chanjar.weixin.mp.bean.custombuilder.MusicBuilder;
-import me.chanjar.weixin.mp.bean.custombuilder.NewsBuilder;
-import me.chanjar.weixin.mp.bean.custombuilder.TextBuilder;
-import me.chanjar.weixin.mp.bean.custombuilder.VideoBuilder;
-import me.chanjar.weixin.mp.bean.custombuilder.VoiceBuilder;
-import me.chanjar.weixin.mp.bean.custombuilder.WxCardBuilder;
+import me.chanjar.weixin.mp.builder.kefu.ImageBuilder;
+import me.chanjar.weixin.mp.builder.kefu.MpNewsBuilder;
+import me.chanjar.weixin.mp.builder.kefu.MusicBuilder;
+import me.chanjar.weixin.mp.builder.kefu.NewsBuilder;
+import me.chanjar.weixin.mp.builder.kefu.TextBuilder;
+import me.chanjar.weixin.mp.builder.kefu.VideoBuilder;
+import me.chanjar.weixin.mp.builder.kefu.VoiceBuilder;
+import me.chanjar.weixin.mp.builder.kefu.WxCardBuilder;
import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder;
/**
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
similarity index 99%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
index 864b0d984..baca66986 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
@@ -1,4 +1,14 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
+
+import com.thoughtworks.xstream.annotations.XStreamAlias;
+import com.thoughtworks.xstream.annotations.XStreamConverter;
+import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
+import me.chanjar.weixin.mp.api.WxMpConfigStorage;
+import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil;
+import me.chanjar.weixin.mp.util.xml.XStreamTransformer;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.IOException;
import java.io.InputStream;
@@ -6,18 +16,6 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-
-import com.thoughtworks.xstream.annotations.XStreamAlias;
-import com.thoughtworks.xstream.annotations.XStreamConverter;
-
-import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
-import me.chanjar.weixin.mp.api.WxMpConfigStorage;
-import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil;
-import me.chanjar.weixin.mp.util.xml.XStreamTransformer;
-
/**
*
* 微信推送过来的消息,xml格式
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutImageMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessage.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutImageMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessage.java
index 18204a514..62852ca8f 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutImageMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutImageMessage.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
@@ -9,7 +9,7 @@ import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
public class WxMpXmlOutImageMessage extends WxMpXmlOutMessage {
/**
- *
+ *
*/
private static final long serialVersionUID = -2684778597067990723L;
@XStreamAlias("Image")
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java
similarity index 96%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java
index 2eb6818b3..5b8b81e56 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMessage.java
@@ -1,10 +1,10 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
-import me.chanjar.weixin.mp.bean.outxmlbuilder.*;
+import me.chanjar.weixin.mp.builder.outxml.*;
import me.chanjar.weixin.mp.util.crypto.WxMpCryptUtil;
import me.chanjar.weixin.mp.util.xml.XStreamTransformer;
@@ -18,14 +18,14 @@ public abstract class WxMpXmlOutMessage implements Serializable {
@XStreamAlias("ToUserName")
@XStreamConverter(value=XStreamCDataConverter.class)
protected String toUserName;
-
+
@XStreamAlias("FromUserName")
@XStreamConverter(value=XStreamCDataConverter.class)
protected String fromUserName;
-
+
@XStreamAlias("CreateTime")
protected Long createTime;
-
+
@XStreamAlias("MsgType")
@XStreamConverter(value=XStreamCDataConverter.class)
protected String msgType;
@@ -61,7 +61,7 @@ public abstract class WxMpXmlOutMessage implements Serializable {
public void setMsgType(String msgType) {
this.msgType = msgType;
}
-
+
public String toXml() {
return XStreamTransformer.toXml((Class) this.getClass(), this);
}
@@ -95,28 +95,28 @@ public abstract class WxMpXmlOutMessage implements Serializable {
public static VoiceBuilder VOICE() {
return new VoiceBuilder();
}
-
+
/**
* 获得视频消息builder
*/
public static VideoBuilder VIDEO() {
return new VideoBuilder();
}
-
+
/**
* 获得音乐消息builder
*/
public static MusicBuilder MUSIC() {
return new MusicBuilder();
}
-
+
/**
* 获得图文消息builder
*/
public static NewsBuilder NEWS() {
return new NewsBuilder();
}
-
+
/**
* 获得客服消息builder
*/
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMusicMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessage.java
similarity index 97%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMusicMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessage.java
index ec71167c4..a5b48619a 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutMusicMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessage.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
@@ -9,7 +9,7 @@ import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
/**
- *
+ *
*/
private static final long serialVersionUID = -4159937804975448945L;
@XStreamAlias("Music")
@@ -34,7 +34,7 @@ public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
public void setDescription(String description) {
this.music.setDescription(description);
}
-
+
public String getThumbMediaId() {
return this.music.getThumbMediaId();
}
@@ -58,10 +58,10 @@ public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
public void setHqMusicUrl(String hqMusicUrl) {
this.music.setHqMusicUrl(hqMusicUrl);
}
-
+
@XStreamAlias("Music")
public static class Music {
-
+
@XStreamAlias("Title")
@XStreamConverter(value=XStreamCDataConverter.class)
private String title;
@@ -73,15 +73,15 @@ public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
@XStreamAlias("ThumbMediaId")
@XStreamConverter(value=XStreamCDataConverter.class)
private String thumbMediaId;
-
+
@XStreamAlias("MusicUrl")
@XStreamConverter(value=XStreamCDataConverter.class)
private String musicUrl;
-
+
@XStreamAlias("HQMusicUrl")
@XStreamConverter(value=XStreamCDataConverter.class)
private String hqMusicUrl;
-
+
public String getTitle() {
return this.title;
}
@@ -121,7 +121,7 @@ public class WxMpXmlOutMusicMessage extends WxMpXmlOutMessage {
public void setHqMusicUrl(String hqMusicUrl) {
this.hqMusicUrl = hqMusicUrl;
}
-
+
}
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutNewsMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessage.java
similarity index 96%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutNewsMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessage.java
index 170023a3c..413a6d7c0 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutNewsMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessage.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
@@ -12,16 +12,16 @@ import java.util.List;
public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage {
/**
- *
+ *
*/
private static final long serialVersionUID = -4604402850905714772L;
@XStreamAlias("ArticleCount")
protected int articleCount;
-
+
@XStreamAlias("Articles")
protected final List- articles = new ArrayList<>();
-
+
public WxMpXmlOutNewsMessage() {
this.msgType = WxConsts.XML_MSG_NEWS;
}
@@ -34,15 +34,15 @@ public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage {
this.articles.add(item);
this.articleCount = this.articles.size();
}
-
+
public List
- getArticles() {
return this.articles;
}
-
-
+
+
@XStreamAlias("item")
public static class Item {
-
+
@XStreamAlias("Title")
@XStreamConverter(value=XStreamCDataConverter.class)
private String Title;
@@ -54,11 +54,11 @@ public class WxMpXmlOutNewsMessage extends WxMpXmlOutMessage {
@XStreamAlias("PicUrl")
@XStreamConverter(value=XStreamCDataConverter.class)
private String PicUrl;
-
+
@XStreamAlias("Url")
@XStreamConverter(value=XStreamCDataConverter.class)
private String Url;
-
+
public String getTitle() {
return this.Title;
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTextMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessage.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTextMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessage.java
index 4c439a7c1..0719b1ede 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTextMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessage.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
@@ -7,9 +7,9 @@ import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
@XStreamAlias("xml")
public class WxMpXmlOutTextMessage extends WxMpXmlOutMessage {
-
+
/**
- *
+ *
*/
private static final long serialVersionUID = -3972786455288763361L;
@XStreamAlias("Content")
@@ -19,7 +19,7 @@ public class WxMpXmlOutTextMessage extends WxMpXmlOutMessage {
public WxMpXmlOutTextMessage() {
this.msgType = WxConsts.XML_MSG_TEXT;
}
-
+
public String getContent() {
return this.content;
}
@@ -28,5 +28,5 @@ public class WxMpXmlOutTextMessage extends WxMpXmlOutMessage {
this.content = content;
}
-
+
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferKefuMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessage.java
similarity index 96%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferKefuMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessage.java
index 3022e70db..b0eece704 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferKefuMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessage.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutVideoMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessage.java
similarity index 97%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutVideoMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessage.java
index a8f751cfc..3c042f6d2 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutVideoMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessage.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
@@ -9,7 +9,7 @@ import me.chanjar.weixin.common.util.xml.XStreamCDataConverter;
public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage {
/**
- *
+ *
*/
private static final long serialVersionUID = 1745902309380113978L;
@XStreamAlias("Video")
@@ -42,11 +42,11 @@ public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage {
public void setDescription(String description) {
this.video.setDescription(description);
}
-
+
@XStreamAlias("Video")
public static class Video {
-
+
@XStreamAlias("MediaId")
@XStreamConverter(value=XStreamCDataConverter.class)
private String mediaId;
@@ -82,7 +82,7 @@ public class WxMpXmlOutVideoMessage extends WxMpXmlOutMessage {
public void setDescription(String description) {
this.description = description;
}
-
+
}
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutVoiceMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessage.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutVoiceMessage.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessage.java
index a47766dcd..ec354ddfe 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/WxMpXmlOutVoiceMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessage.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamConverter;
@@ -9,7 +9,7 @@ import me.chanjar.weixin.common.util.xml.XStreamMediaIdConverter;
public class WxMpXmlOutVoiceMessage extends WxMpXmlOutMessage {
/**
- *
+ *
*/
private static final long serialVersionUID = 240367390249860551L;
@XStreamAlias("Voice")
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/BaseBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/BaseBuilder.java
similarity index 88%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/BaseBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/BaseBuilder.java
index 911e3f62f..c5285d6f7 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/BaseBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/BaseBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/ImageBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/ImageBuilder.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/ImageBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/ImageBuilder.java
index 85855d259..9533f5b35 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/ImageBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/ImageBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/MpNewsBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/MpNewsBuilder.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/MpNewsBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/MpNewsBuilder.java
index 4ab90dce5..615802b31 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/MpNewsBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/MpNewsBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/MusicBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/MusicBuilder.java
similarity index 97%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/MusicBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/MusicBuilder.java
index 3555f7a90..8d23bacd4 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/MusicBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/MusicBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/NewsBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/NewsBuilder.java
similarity index 94%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/NewsBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/NewsBuilder.java
index d909eb7d6..900babb5b 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/NewsBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/NewsBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/TextBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/TextBuilder.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/TextBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/TextBuilder.java
index 770675f54..9e5f93840 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/TextBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/TextBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/VideoBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/VideoBuilder.java
similarity index 96%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/VideoBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/VideoBuilder.java
index f9740e2f7..13ade68ca 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/VideoBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/VideoBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/VoiceBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/VoiceBuilder.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/VoiceBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/VoiceBuilder.java
index 7686a56d8..c9cb32b2f 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/VoiceBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/VoiceBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/WxCardBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/WxCardBuilder.java
similarity index 93%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/WxCardBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/WxCardBuilder.java
index fb5e81c2e..e600df6cb 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/custombuilder/WxCardBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/kefu/WxCardBuilder.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean.custombuilder;
+package me.chanjar.weixin.mp.builder.kefu;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/BaseBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java
similarity index 83%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/BaseBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java
index 77db2617c..e594565cb 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/BaseBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/BaseBuilder.java
@@ -1,29 +1,29 @@
-package me.chanjar.weixin.mp.bean.outxmlbuilder;
+package me.chanjar.weixin.mp.builder.outxml;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
public abstract class BaseBuilder {
-
+
protected String toUserName;
-
+
protected String fromUserName;
-
+
public BuilderType toUser(String touser) {
this.toUserName = touser;
return (BuilderType) this;
}
-
+
public BuilderType fromUser(String fromusername) {
this.fromUserName = fromusername;
return (BuilderType) this;
}
public abstract ValueType build();
-
+
public void setCommon(WxMpXmlOutMessage m) {
m.setToUserName(this.toUserName);
m.setFromUserName(this.fromUserName);
m.setCreateTime(System.currentTimeMillis() / 1000l);
}
-
+
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/ImageBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/ImageBuilder.java
similarity index 80%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/ImageBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/ImageBuilder.java
index ee265bf3c..0bf441bf9 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/ImageBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/ImageBuilder.java
@@ -1,6 +1,6 @@
-package me.chanjar.weixin.mp.bean.outxmlbuilder;
+package me.chanjar.weixin.mp.builder.outxml;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
/**
* 图片消息builder
@@ -22,5 +22,5 @@ public final class ImageBuilder extends BaseBuilder {
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/NewsBuilder.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/NewsBuilder.java
similarity index 84%
rename from weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/NewsBuilder.java
rename to weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/NewsBuilder.java
index 1014c452c..1936c5f59 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/outxmlbuilder/NewsBuilder.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/builder/outxml/NewsBuilder.java
@@ -1,6 +1,6 @@
-package me.chanjar.weixin.mp.bean.outxmlbuilder;
+package me.chanjar.weixin.mp.builder.outxml;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutNewsMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutNewsMessage;
import java.util.ArrayList;
import java.util.List;
@@ -12,12 +12,12 @@ import java.util.List;
public final class NewsBuilder extends BaseBuilder {
protected final List articles = new ArrayList<>();
-
+
public NewsBuilder addArticle(WxMpXmlOutNewsMessage.Item item) {
this.articles.add(item);
return this;
}
-
+
@Override
public WxMpXmlOutNewsMessage build() {
WxMpXmlOutNewsMessage m = new WxMpXmlOutNewsMessage();
@@ -27,5 +27,5 @@ public final class NewsBuilder extends BaseBuilder"
+ ""
@@ -23,7 +23,7 @@ public class WxMpXmlOutImageMessageTest {
System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
}
-
+
public void testBuild() {
WxMpXmlOutImageMessage m = WxMpXmlOutMessage.IMAGE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build();
String expected = ""
@@ -38,11 +38,11 @@ public class WxMpXmlOutImageMessageTest {
m
.toXml()
.replaceAll("\\s", "")
- .replaceAll(".*?", ""),
+ .replaceAll(".*?", ""),
expected
.replaceAll("\\s", "")
.replaceAll(".*?", "")
);
-
+
}
}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutMusicMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessageTest.java
similarity index 94%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutMusicMessageTest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessageTest.java
index 4397a677d..3e7a96f0a 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutMusicMessageTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutMusicMessageTest.java
@@ -1,10 +1,10 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import org.testng.Assert;
import org.testng.annotations.Test;
@Test
-public class WxXmlOutMusicMessageTest {
+public class WxMpXmlOutMusicMessageTest {
public void test() {
WxMpXmlOutMusicMessage m = new WxMpXmlOutMusicMessage();
@@ -16,7 +16,7 @@ public class WxXmlOutMusicMessageTest {
m.setCreateTime(1122l);
m.setFromUserName("fromUser");
m.setToUserName("toUser");
-
+
String expected = ""
+ ""
+ ""
@@ -33,7 +33,7 @@ public class WxXmlOutMusicMessageTest {
System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
}
-
+
public void testBuild() {
WxMpXmlOutMusicMessage m = WxMpXmlOutMessage.MUSIC()
.fromUser("fromUser")
@@ -62,11 +62,11 @@ public class WxXmlOutMusicMessageTest {
m
.toXml()
.replaceAll("\\s", "")
- .replaceAll(".*?", ""),
+ .replaceAll(".*?", ""),
expected
.replaceAll("\\s", "")
.replaceAll(".*?", "")
);
}
-
+
}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutNewsMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java
similarity index 95%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutNewsMessageTest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java
index 5e2da0b0d..60d8571af 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutNewsMessageTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutNewsMessageTest.java
@@ -1,17 +1,17 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import org.testng.Assert;
import org.testng.annotations.Test;
@Test
-public class WxXmlOutNewsMessageTest {
+public class WxMpXmlOutNewsMessageTest {
public void test() {
WxMpXmlOutNewsMessage m = new WxMpXmlOutNewsMessage();
m.setCreateTime(1122l);
m.setFromUserName("fromUser");
m.setToUserName("toUser");
-
+
WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
item.setDescription("description");
item.setPicUrl("picUrl");
@@ -43,14 +43,14 @@ public class WxXmlOutNewsMessageTest {
System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
}
-
+
public void testBuild() {
WxMpXmlOutNewsMessage.Item item = new WxMpXmlOutNewsMessage.Item();
item.setDescription("description");
item.setPicUrl("picUrl");
item.setTitle("title");
item.setUrl("url");
-
+
WxMpXmlOutNewsMessage m = WxMpXmlOutMessage.NEWS()
.fromUser("fromUser")
.toUser("toUser")
@@ -83,11 +83,11 @@ public class WxXmlOutNewsMessageTest {
m
.toXml()
.replaceAll("\\s", "")
- .replaceAll(".*?", ""),
+ .replaceAll(".*?", ""),
expected
.replaceAll("\\s", "")
.replaceAll(".*?", "")
);
}
-
+
}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutTextMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java
similarity index 90%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutTextMessageTest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java
index 2a7520514..566589671 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutTextMessageTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTextMessageTest.java
@@ -1,10 +1,10 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import org.testng.Assert;
import org.testng.annotations.Test;
@Test
-public class WxXmlOutTextMessageTest {
+public class WxMpXmlOutTextMessageTest {
public void test() {
WxMpXmlOutTextMessage m = new WxMpXmlOutTextMessage();
@@ -12,7 +12,7 @@ public class WxXmlOutTextMessageTest {
m.setCreateTime(1122l);
m.setFromUserName("from");
m.setToUserName("to");
-
+
String expected = ""
+ ""
+ ""
@@ -23,7 +23,7 @@ public class WxXmlOutTextMessageTest {
System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
}
-
+
public void testBuild() {
WxMpXmlOutTextMessage m = WxMpXmlOutMessage.TEXT().content("content").fromUser("from").toUser("to").build();
String expected = ""
@@ -38,13 +38,13 @@ public class WxXmlOutTextMessageTest {
m
.toXml()
.replaceAll("\\s", "")
- .replaceAll(".*?", ""),
+ .replaceAll(".*?", ""),
expected
.replaceAll("\\s", "")
.replaceAll(".*?", "")
);
-
+
}
-
+
}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferKefuMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessageTest.java
similarity index 98%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferKefuMessageTest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessageTest.java
index ad167738c..222f563f2 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxMpXmlOutTransferKefuMessageTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutTransferKefuMessageTest.java
@@ -1,4 +1,4 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import org.testng.Assert;
import org.testng.annotations.Test;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutVideoMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java
similarity index 92%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutVideoMessageTest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java
index 19fbe62af..0c53b28ad 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutVideoMessageTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVideoMessageTest.java
@@ -1,10 +1,10 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import org.testng.Assert;
import org.testng.annotations.Test;
@Test
-public class WxXmlOutVideoMessageTest {
+public class WxMpXmlOutVideoMessageTest {
public void test() {
WxMpXmlOutVideoMessage m = new WxMpXmlOutVideoMessage();
@@ -14,7 +14,7 @@ public class WxXmlOutVideoMessageTest {
m.setCreateTime(1122l);
m.setFromUserName("fromUser");
m.setToUserName("toUser");
-
+
String expected = ""
+ ""
+ ""
@@ -29,7 +29,7 @@ public class WxXmlOutVideoMessageTest {
System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
}
-
+
public void testBuild() {
WxMpXmlOutVideoMessage m = WxMpXmlOutMessage.VIDEO()
.mediaId("media_id")
@@ -54,11 +54,11 @@ public class WxXmlOutVideoMessageTest {
m
.toXml()
.replaceAll("\\s", "")
- .replaceAll(".*?", ""),
+ .replaceAll(".*?", ""),
expected
.replaceAll("\\s", "")
.replaceAll(".*?", "")
);
}
-
+
}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutVoiceMessageTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java
similarity index 90%
rename from weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutVoiceMessageTest.java
rename to weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java
index 0eb848cdc..343143904 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/WxXmlOutVoiceMessageTest.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/bean/message/WxMpXmlOutVoiceMessageTest.java
@@ -1,10 +1,10 @@
-package me.chanjar.weixin.mp.bean;
+package me.chanjar.weixin.mp.bean.message;
import org.testng.Assert;
import org.testng.annotations.Test;
@Test
-public class WxXmlOutVoiceMessageTest {
+public class WxMpXmlOutVoiceMessageTest {
public void test() {
WxMpXmlOutVoiceMessage m = new WxMpXmlOutVoiceMessage();
@@ -12,7 +12,7 @@ public class WxXmlOutVoiceMessageTest {
m.setCreateTime(1122l);
m.setFromUserName("from");
m.setToUserName("to");
-
+
String expected = ""
+ ""
+ ""
@@ -23,7 +23,7 @@ public class WxXmlOutVoiceMessageTest {
System.out.println(m.toXml());
Assert.assertEquals(m.toXml().replaceAll("\\s", ""), expected.replaceAll("\\s", ""));
}
-
+
public void testBuild() {
WxMpXmlOutVoiceMessage m = WxMpXmlOutMessage.VOICE().mediaId("ddfefesfsdfef").fromUser("from").toUser("to").build();
String expected = ""
@@ -38,11 +38,11 @@ public class WxXmlOutVoiceMessageTest {
m
.toXml()
.replaceAll("\\s", "")
- .replaceAll(".*?", ""),
+ .replaceAll(".*?", ""),
expected
.replaceAll("\\s", "")
.replaceAll(".*?", "")
);
}
-
+
}
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoGuessNumberHandler.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoGuessNumberHandler.java
index 604531b11..69636d0bd 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoGuessNumberHandler.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoGuessNumberHandler.java
@@ -11,8 +11,8 @@ import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpMessageMatcher;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.kefu.WxMpKefuMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMatcher {
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java
index cd7332104..3d07437b3 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoImageHandler.java
@@ -6,9 +6,9 @@ import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutImageMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutImageMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import java.io.IOException;
import java.util.Map;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoLogHandler.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoLogHandler.java
index 5245bc035..8e38b3f78 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoLogHandler.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoLogHandler.java
@@ -3,8 +3,8 @@ package me.chanjar.weixin.mp.demo;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import java.util.Map;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoOAuth2Handler.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoOAuth2Handler.java
index 5dc5437d2..820464527 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoOAuth2Handler.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoOAuth2Handler.java
@@ -4,8 +4,8 @@ import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
import java.util.Map;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoTextHandler.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoTextHandler.java
index 9ee15a283..5934eff24 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoTextHandler.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/DemoTextHandler.java
@@ -3,9 +3,9 @@ package me.chanjar.weixin.mp.demo;
import me.chanjar.weixin.common.session.WxSessionManager;
import me.chanjar.weixin.mp.api.WxMpMessageHandler;
import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutTextMessage;
import java.util.Map;
diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpEndpointServlet.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpEndpointServlet.java
index 63052f8bd..c560f3975 100644
--- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpEndpointServlet.java
+++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/demo/WxMpEndpointServlet.java
@@ -10,8 +10,8 @@ import me.chanjar.weixin.common.util.StringUtils;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
-import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
-import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage;
/**
* @author Daniel Qian
diff --git a/weixin-java-mp/src/test/resources/testng.xml b/weixin-java-mp/src/test/resources/testng.xml
index addf7be46..d14999835 100644
--- a/weixin-java-mp/src/test/resources/testng.xml
+++ b/weixin-java-mp/src/test/resources/testng.xml
@@ -18,13 +18,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+