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 a73e01d0d..c36561c2d 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
@@ -14,6 +14,8 @@ import javax.xml.parsers.ParserConfigurationException;
import com.google.common.base.CharMatcher;
import com.google.common.io.BaseEncoding;
+import lombok.AllArgsConstructor;
+import lombok.Data;
import me.chanjar.weixin.common.error.WxRuntimeException;
import org.apache.commons.codec.binary.Base64;
import org.w3c.dom.Document;
@@ -157,6 +159,29 @@ public class WxCryptUtil {
return generateXml(encryptedXml, signature, timeStamp, nonce);
}
+ /**
+ * 将公众平台回复用户的消息加密打包.
+ *
+ * - 对要发送的消息进行AES-CBC加密
+ * - 生成安全签名
+ * - 将消息密文和安全签名打包成xml格式
+ *
+ *
+ * @param plainText 公众平台待回复用户的消息,xml格式的字符串
+ * @return 加密消息所需的值对象
+ */
+ public EncryptContext encryptContext(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);
+ return new EncryptContext(encryptedXml, signature, timeStamp, nonce);
+ }
+
/**
* 对明文进行加密.
*
@@ -211,22 +236,56 @@ public class WxCryptUtil {
* @param msgSignature 签名串,对应URL参数的msg_signature
* @param timeStamp 时间戳,对应URL参数的timestamp
* @param nonce 随机串,对应URL参数的nonce
- * @param encryptedXml 密文,对应POST请求的数据
+ * @param encryptedXml 包含 Encrypt 密文的 xml,对应POST请求的数据
* @return 解密后的原文
*/
- public String decrypt(String msgSignature, String timeStamp, String nonce, String encryptedXml) {
+ public String decryptXml(String msgSignature, String timeStamp, String nonce, String encryptedXml) {
// 密钥,公众账号的app corpSecret
// 提取密文
String cipherText = extractEncryptPart(encryptedXml);
+ return decryptContent(msgSignature, timeStamp, nonce, cipherText);
+ }
+ /**
+ * 检验消息的真实性,并且获取解密后的明文.
+ *
+ * - 利用收到的密文生成安全签名,进行签名验证
+ * - 若验证通过,则提取xml中的加密消息
+ * - 对消息进行解密
+ *
+ *
+ * @param msgSignature 签名串,对应URL参数的msg_signature
+ * @param timeStamp 时间戳,对应URL参数的timestamp
+ * @param nonce 随机串,对应URL参数的nonce
+ * @param encryptedXml 包含 Encrypt 密文的 xml,对应POST请求的数据
+ * @return 解密后的原文
+ */
+ public String decrypt(String msgSignature, String timeStamp, String nonce, String encryptedXml) {
+ return decryptXml(msgSignature, timeStamp, nonce, encryptedXml);
+ }
+
+ /**
+ * 检验消息的真实性,并且获取解密后的明文.
+ *
+ * - 利用收到的密文生成安全签名,进行签名验证
+ * - 若验证通过,则提取xml中的加密消息
+ * - 对消息进行解密
+ *
+ *
+ * @param msgSignature 签名串,对应URL参数的msg_signature
+ * @param timeStamp 时间戳,对应URL参数的timestamp
+ * @param nonce 随机串,对应URL参数的nonce
+ * @param encryptedContent 加密文本体
+ * @return 解密后的原文
+ */
+ public String decryptContent(String msgSignature, String timeStamp, String nonce, String encryptedContent) {
// 验证安全签名
- String signature = SHA1.gen(this.token, timeStamp, nonce, cipherText);
+ String signature = SHA1.gen(this.token, timeStamp, nonce, encryptedContent);
if (!signature.equals(msgSignature)) {
throw new WxRuntimeException("加密消息签名校验失败");
}
-
// 解密
- return decrypt(cipherText);
+ return decrypt(encryptedContent);
}
/**
@@ -271,12 +330,20 @@ public class WxCryptUtil {
}
// appid不相同的情况 暂时忽略这段判断
-// if (!fromAppid.equals(this.appidOrCorpid)) {
-// throw new WxRuntimeException("AppID不正确,请核实!");
-// }
+ // if (!fromAppid.equals(this.appidOrCorpid)) {
+ // throw new WxRuntimeException("AppID不正确,请核实!");
+ // }
return xmlContent;
}
+ @Data
+ @AllArgsConstructor
+ public static class EncryptContext {
+ private String encrypt;
+ private String signature;
+ private String timeStamp;
+ private String nonce;
+ }
}
diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
index d144b63af..063938d27 100644
--- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
+++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/message/WxMpXmlMessage.java
@@ -506,7 +506,6 @@ public class WxMpXmlMessage implements Serializable {
@JacksonXmlProperty(localName = "ReceiptInfo")
private String receiptInfo;
-
///////////////////////////////////////
// 门店审核事件推送
///////////////////////////////////////
@@ -797,6 +796,12 @@ public class WxMpXmlMessage implements Serializable {
@JacksonXmlProperty(localName = "nsrsbh")
private String nsrsbh;
+ /**
+ * 加密消息
+ */
+ @XStreamAlias("Encrypt")
+ @JacksonXmlProperty(localName = "Encrypt")
+ private String encrypt;
public static WxMpXmlMessage fromXml(String xml) {
//修改微信变态的消息内容格式,方便解析
@@ -836,6 +841,14 @@ public class WxMpXmlMessage implements Serializable {
}
}
+ public WxMpXmlMessage decryptField(WxMpConfigStorage wxMpConfigStorage,
+ String timestamp, String nonce, String msgSignature) {
+ WxMpCryptUtil cryptUtil = new WxMpCryptUtil(wxMpConfigStorage);
+ String plainText = cryptUtil.decryptContent(msgSignature, timestamp, nonce, this.encrypt);
+ log.debug("解密后的原始xml消息内容:{}", plainText);
+ return fromXml(plainText);
+ }
+
/**
*
* 当接受用户消息时,可能会获得以下值: