0123456789/-**--------------///////////124714256588996

/*-+._百度知道
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。
我有更好的答案
采纳率:27%
为您推荐:
换一换
回答问题,赢新手礼包/ weichat1
项目语言:JAVA
权限:read-only(如需更高权限请先加入项目)
Index: com/allywll/weichat/core/weichat/web/MsgInterceptor.java
===================================================================
--- com/allywll/weichat/core/weichat/web/MsgInterceptor.java (revision 0)
+++ com/allywll/weichat/core/weichat/web/MsgInterceptor.java (revision 2)
@@ -0,0 +1,115 @@
+package com.allywll.weichat.core.weichat.
+import com.allywll.weichat.core.api.ApiConfigK
+import com.allywll.weichat.core.util.ConstD
+import com.allywll.weichat.core.util.SignatureCheckK
+import com.jfinal.aop.I
+import com.jfinal.core.ActionI
+import com.jfinal.core.C
+import com.jfinal.kit.StrK
+import com.jfinal.log.L
+ * Msg 拦截器
+ * 1:通过 MsgController.getApiConfig() 得到 ApiConfig 对象,并将其绑定到当前线程之上(利用了 ApiConfigKit 中的 ThreadLocal 对象)
+ * 2:响应开发者中心服务器配置 URL 与 Token 请求
+ * 3:签名检测
+ * 注意: MsgController 的继承类如果覆盖了 index 方法,则需要对该 index 方法声明该拦截器
因为子类覆盖父类方法会使父类方法配置的拦截器失效,从而失去本拦截器的功能
+public class MsgInterceptor implements Interceptor {
+ private static final Logger log =
Logger.getLogger(MsgInterceptor.class);
+ public void intercept(ActionInvocation paramActionInvocation) {
// TODO Auto-generated method stub
Controller controller=paramActionInvocation.getController();
if (controller instanceof MsgController == false)
log.error(&控制器需要继承 MsgController&);
throw new RuntimeException(&控制器需要继承 MsgController&);
// 将 ApiConfig 对象与当前线程绑定,以便在后续操作中方便获取该对象: ApiConfigKit.getApiConfig();
ApiConfigKit.setThreadLocalApiConfig(((MsgController)controller).getApiConfig());
// 如果是服务器配置请求,则配置服务器并返回
if (isConfigServerRequest(controller)) {
(&【msgInterceptor微信服务器配置】&);
configServer(controller);
// 签名检测
if (checkSignature(controller)) {
(&【msgInterceptor签名检测通过】&);
paramActionInvocation.invoke();
(&【msgInterceptor签名检测错误】&);
controller.setAttr(ConstDefine.Errors.ErrorInfoKey, ConstDefine.Errors.ErrorSign);
controller.renderFreeMarker(&error&);
ApiConfigKit.removeThreadLocalApiConfig();
* 是否为开发者中心保存服务器配置的请求
* 保存请求时会有echostr(并且确认不为空)
+ private boolean isConfigServerRequest(Controller controller) {
return StrKit.notBlank(controller.getPara(&echostr&));
* 验证服务器配置
* @param c
* @see http://mp./wiki/17/2d08cd170ad.html
+ public void configServer(Controller c) {
// 通过 echostr 判断请求是否为配置微信服务器回调所需的 url 与 token
String echostr = c.getPara(&echostr&);
boolean isOk = SignatureCheckKit.checkSignature(c);
c.renderText(echostr);
log.error(&【configServer】验证失败:微信配置签名不正确&);
* 检测签名
+ private boolean checkSignature(Controller controller) {
String signature = controller.getPara(&signature&);
String timestamp = controller.getPara(&timestamp&);
String nonce = controller.getPara(&nonce&);
if (StrKit.isBlank(signature) || StrKit.isBlank(timestamp) || StrKit.isBlank(nonce)) {
controller.renderText(&check signature failure&);
if (SignatureCheckKit.checkSignature(controller)) {
log.error(&check signature failure: & +
& signature = & + controller.getPara(&signature&) +
& timestamp = & + controller.getPara(&timestamp&) +
& nonce = & + controller.getPara(&nonce&));
Index: com/allywll/weichat/core/weichat/web/MsgController.java
===================================================================
--- com/allywll/weichat/core/weichat/web/MsgController.java (revision 0)
+++ com/allywll/weichat/core/weichat/web/MsgController.java (revision 2)
@@ -0,0 +1,89 @@
+package com.allywll.weichat.core.weichat.
+import com.allywll.weichat.core.api.ApiC
+import com.allywll.weichat.core.api.ApiConfigK
+import com.allywll.weichat.core.util.MsgEncryptK
+import com.allywll.weichat.core.weichat.msg.in.InM
+import com.jfinal.aop.B
+import com.jfinal.core.C
+import com.jfinal.ext.interceptor.NotA
+import com.jfinal.kit.HttpK
+import com.jfinal.log.L
+ * 接收微信服务器消息,自动解析成 InMsg 并分发到相应的处理方法
+public abstract class MsgController extends Controller {
+ private static final Logger log =
Logger.getLogger(MsgController.class);
+ private String inMsgXml =
// 本次请求 xml数据
+ private InMsg inMsg =
// 本次请求 xml 解析后的 InMsg 对象
+ public abstract ApiConfig getApiConfig();
* weixin 公众号服务器调用唯一入口,即在开发者中心输入的 URL 必须要指向此 action
+ @Before(MsgInterceptor.class)
+ public void index() {
// 开发模式输出微信服务发送过来的
if (ApiConfigKit.isDevMode()) {
(&接收消息:&);
(getInMsgXml());
// 解析消息并根据消息类型分发到相应的处理方法
InMsg msg = getInMsg();
/*if (msg instanceof InTextMsg)
processInTextMsg((InTextMsg)msg);
else if (msg instanceof InImageMsg)
processInImageMsg((InImageMsg)msg);
else if (msg instanceof InVoiceMsg)
processInVoiceMsg((InVoiceMsg)msg);
else if (msg instanceof InVideoMsg)
processInVideoMsg((InVideoMsg)msg);
else if (msg instanceof InLocationMsg)
processInLocationMsg((InLocationMsg)msg);
else if (msg instanceof InLinkMsg)
processInLinkMsg((InLinkMsg)msg);
else if (msg instanceof InFollowEvent)
processInFollowEvent((InFollowEvent)msg);
else if (msg instanceof InQrCodeEvent)
processInQrCodeEvent((InQrCodeEvent)msg);
else if (msg instanceof InLocationEvent)
processInLocationEvent((InLocationEvent)msg);
else if (msg instanceof InMenuEvent)
processInMenuEvent((InMenuEvent)msg);
else if (msg instanceof InSpeechRecognitionResults)
processInSpeechRecognitionResults((InSpeechRecognitionResults)msg);
else if (msg instanceof InTemplateMsgEvent)
processInTemplateMsgEvent((InTemplateMsgEvent)msg);
log.error(&未能识别的消息类型。 消息 xml 内容为:\n& + getInMsgXml());*/
+ @Before(NotAction.class)
* 获取微信request中的信息
+ public String getInMsgXml() {
if (inMsgXml == null) {
inMsgXml = HttpKit.readIncommingRequestData(getRequest());
// 是否需要解密消息
if (ApiConfigKit.getApiConfig().isEncryptMessage()) {
inMsgXml = MsgEncryptKit.decrypt(inMsgXml, getPara(&timestamp&), getPara(&nonce&), getPara(&msg_signature&));
return inMsgX
+ @Before(NotAction.class)
+ public InMsg getInMsg() {
/*if (inMsg == null)
//inMsg = InMsgParaser.parse(getInMsgXml());
return inM
Index: com/allywll/weichat/core/weichat/encrypt/AesException.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/AesException.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/AesException.java (revision 2)
@@ -0,0 +1,59 @@
+package com.allywll.weichat.core.weichat.
+@SuppressWarnings(&serial&)
+public class AesException extends Exception {
+ public final static int OK = 0;
+ public final static int ValidateSignatureError = -40001;
+ public final static int ParseXmlError = -40002;
+ public final static int ComputeSignatureError = -40003;
+ public final static int IllegalAesKey = -40004;
+ public final static int ValidateAppidError = -40005;
+ public final static int EncryptAESError = -40006;
+ public final static int DecryptAESError = -40007;
+ public final static int IllegalBuffer = -40008;
+ //public final static int EncodeBase64Error = -40009;
+ //public final static int DecodeBase64Error = -40010;
+ //public final static int GenReturnXmlError = -40011;
+ private static String getMessage(int code) {
switch (code) {
case ValidateSignatureError:
return &签名验证错误&;
case ParseXmlError:
return &xml解析失败&;
case ComputeSignatureError:
return &sha加密生成签名失败&;
case IllegalAesKey:
return &SymmetricKey非法&;
case ValidateAppidError:
return &appid校验失败&;
case EncryptAESError:
return &aes加密失败&;
case DecryptAESError:
return &aes解密失败&;
case IllegalBuffer:
return &解密后得到的buffer非法&;
case EncodeBase64Error:
return &base64加密错误&;
case DecodeBase64Error:
return &base64解密错误&;
case GenReturnXmlError:
return &xml生成失败&;
// cannot be
+ public int getCode() {
+ AesException(int code) {
super(getMessage(code));
this.code =
Index: com/allywll/weichat/core/weichat/encrypt/PKCS7Encoder.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/PKCS7Encoder.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/PKCS7Encoder.java (revision 2)
@@ -0,0 +1,67 @@
+ * 对公众平台发送给公众账号的消息加解密示例代码.
+ * @copyright Copyright (c)
Tencent Inc.
+// ------------------------------------------------------------------------
+package com.allywll.weichat.core.weichat.
+import java.nio.charset.C
+import java.util.A
+ * 提供基于PKCS7算法的加解密接口.
+class PKCS7Encoder {
+ static Charset CHARSET = Charset.forName(&utf-8&);
+ static int BLOCK_SIZE = 32;
* 获得对明文进行补位填充的字节.
* @param count 需要进行填充补位操作的明文字节个数
* @return 补齐用的字节数组
+ static byte[] encode(int count) {
// 计算需要填充的位数
int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
if (amountToPad == 0) {
amountToPad = BLOCK_SIZE;
// 获得补位所用的字符
char padChr = chr(amountToPad);
String tmp = new String();
for (int index = 0; index & amountToP index++) {
tmp += padC
return tmp.getBytes(CHARSET);
* 删除解密后明文的补位字符
* @param decrypted 解密后的明文
* @return 删除补位字符后的明文
+ static byte[] decode(byte[] decrypted) {
int pad = (int) decrypted[decrypted.length - 1];
if (pad & 1 || pad & 32) {
return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
* 将数字转化成ASCII码对应的字符,用于对明文进行补码
* @param a 需要转化的数字
* @return 转化得到的字符
+ static char chr(int a) {
byte target = (byte) (a & 0xFF);
return (char)
Index: com/allywll/weichat/core/weichat/encrypt/Program.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/Program.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/Program.java (revision 2)
@@ -0,0 +1,60 @@
+package com.allywll.weichat.core.weichat.
+import java.io.StringR
+import javax.xml.parsers.DocumentB
+import javax.xml.parsers.DocumentBuilderF
+import org.w3c.dom.D
+import org.w3c.dom.E
+import org.w3c.dom.NodeL
+import org.xml.sax.InputS
+public class Program {
+ public static void main(String[] args) throws Exception {
// 第三方回复公众平台
// 需要加密的明文
String encodingAesKey = &abcdefghijklmnopqrstuvwxyzABCDEFG&;
String token = &pamtest&;
String timestamp = &&;
String nonce = &xxxxxx&;
String appId = &wxbcb6&;
String replyMsg = & 中文&xml&&ToUserName&&![CDATA[oia2TjjewbmiOUlr6X-1crbLOvLw]]&&/ToUserName&&FromUserName&&![CDATA[gh_7fa]]&&/FromUserName&&CreateTime&&/CreateTime&&MsgType&&![CDATA[video]]&&/MsgType&&Video&&MediaId&&![CDATA[eYJ1MbwPRJtOvIEabaxHs7TX2D-HV71s79GUxqdUkjm6Gs2Ed1KF3ulAOA9H1xG0]]&&/MediaId&&Title&&![CDATA[testCallBackReplyVideo]]&&/Title&&Description&&![CDATA[testCallBackReplyVideo]]&&/Description&&/Video&&/xml&&;
WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
String mingwen = pc.encryptMsg(replyMsg, timestamp, nonce);
System.out.println(&加密后: & + mingwen);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(mingwen);
InputSource is = new InputSource(sr);
Document document = db.parse(is);
Element root = document.getDocumentElement();
NodeList nodelist1 = root.getElementsByTagName(&Encrypt&);
NodeList nodelist2 = root.getElementsByTagName(&MsgSignature&);
String encrypt = nodelist1.item(0).getTextContent();
String msgSignature = nodelist2.item(0).getTextContent();
String format = &&xml&&ToUserName&&![CDATA[toUser]]&&/ToUserName&&Encrypt&&![CDATA[%1$s]]&&/Encrypt&&/xml&&;
String fromXML = String.format(format, encrypt);
// 公众平台发送消息给第三方,第三方处理
// 第三方收到公众号平台发送的消息
String result2 = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML);
System.out.println(&解密后明文: & + result2);
//pc.verifyUrl(null, null, null, null);
Index: com/allywll/weichat/core/weichat/encrypt/XMLParse.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/XMLParse.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/XMLParse.java (revision 2)
@@ -0,0 +1,72 @@
+ * 对公众平台发送给公众账号的消息加解密示例代码.
+ * @copyright Copyright (c)
Tencent Inc.
+// ------------------------------------------------------------------------
+package com.allywll.weichat.core.weichat.
+import java.io.StringR
+import javax.xml.parsers.DocumentB
+import javax.xml.parsers.DocumentBuilderF
+import org.w3c.dom.D
+import org.w3c.dom.E
+import org.w3c.dom.NodeL
+import org.xml.sax.InputS
+ * XMLParse class
+ * 提供提取消息格式中的密文及生成回复消息格式的接口.
+class XMLParse {
* 提取出xml数据包中的加密消息
* @param xmltext 待提取的xml字符串
* @return 提取出的加密消息字符串
* @throws AesException
+ public static Object[] extract(String xmltext) throws AesException
Object[] result = new Object[3];
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(xmltext);
InputSource is = new InputSource(sr);
Document document = db.parse(is);
Element root = document.getDocumentElement();
NodeList nodelist1 = root.getElementsByTagName(&Encrypt&);
NodeList nodelist2 = root.getElementsByTagName(&ToUserName&);
result[0] = 0;
result[1] = nodelist1.item(0).getTextContent();
result[2] = nodelist2.item(0).getTextContent();
} catch (Exception e) {
e.printStackTrace();
throw new AesException(AesException.ParseXmlError);
* 生成xml消息
* @param encrypt 加密后的消息密文
* @param signature 安全签名
* @param timestamp 时间戳
* @param nonce 随机字符串
* @return 生成的xml字符串
+ public static String generate(String encrypt, String signature, String timestamp, String nonce) {
String format = &&xml&\n& + &&Encrypt&&![CDATA[%1$s]]&&/Encrypt&\n&
+ &&MsgSignature&&![CDATA[%2$s]]&&/MsgSignature&\n&
+ &&TimeStamp&%3$s&/TimeStamp&\n& + &&Nonce&&![CDATA[%4$s]]&&/Nonce&\n& + &&/xml&&;
return String.format(format, encrypt, signature, timestamp, nonce);
Index: com/allywll/weichat/core/weichat/encrypt/readme.txt
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/readme.txt (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/readme.txt (revision 2)
@@ -0,0 +1,21 @@
+ * 针对mons.codec.binary.Base64,
+ * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
+ * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
+ * 提供接收和推送给公众平台消息的加解密接口(UTF8编码的字符串).
&li&第三方回复加密消息给公众平台&/li&
&li&第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。&/li&
+ * 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案
&li&在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:
/technetwork/java/javase/downloads/jce-7-download-432124.html&/li&
&li&下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt&/li&
&li&如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件&/li&
&li&如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件&/li&
Index: com/allywll/weichat/core/weichat/encrypt/SHA1.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/SHA1.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/SHA1.java (revision 2)
@@ -0,0 +1,61 @@
+ * 对公众平台发送给公众账号的消息加解密示例代码.
+ * @copyright Copyright (c)
Tencent Inc.
+// ------------------------------------------------------------------------
+package com.allywll.weichat.core.weichat.
+import java.security.MessageD
+import java.util.A
+ * SHA1 class
+ * 计算公众平台的消息签名接口.
+class SHA1 {
* 用SHA1算法生成安全签名
* @param token 票据
* @param timestamp 时间戳
* @param nonce 随机字符串
* @param encrypt 密文
* @return 安全签名
* @throws AesException
+ public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException
String[] array = new String[] { token, timestamp, nonce, encrypt };
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i & 4; i++) {
sb.append(array[i]);
String str = sb.toString();
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance(&SHA-1&);
md.update(str.getBytes());
byte[] digest = md.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = &&;
for (int i = 0; i & digest. i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() & 2) {
hexstr.append(0);
hexstr.append(shaHex);
return hexstr.toString();
} catch (Exception e) {
e.printStackTrace();
throw new puteSignatureError);
Index: com/allywll/weichat/core/weichat/encrypt/WXBizMsgCrypt.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/WXBizMsgCrypt.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/WXBizMsgCrypt.java (revision 2)
@@ -0,0 +1,289 @@
+ * 对公众平台发送给公众账号的消息加解密示例代码.
+ * @copyright Copyright (c)
Tencent Inc.
+// ------------------------------------------------------------------------
+ * 针对mons.codec.binary.Base64,
+ * 需要导入架包commons-codec-1.9(或commons-codec-1.8等其他版本)
+ * 官方下载地址:http://commons.apache.org/proper/commons-codec/download_codec.cgi
+package com.allywll.weichat.core.weichat.
+import java.nio.charset.C
+import java.util.A
+import java.util.R
+import javax.crypto.C
+import javax.crypto.spec.IvParameterS
+import javax.crypto.spec.SecretKeyS
+import mons.codec.binary.Base64;
+ * 提供接收和推送给公众平台消息的加解密接口(UTF8编码的字符串).
&li&第三方回复加密消息给公众平台&/li&
&li&第三方收到公众平台发送的消息,验证消息的安全性,并对消息进行解密。&/li&
+ * 说明:异常java.security.InvalidKeyException:illegal Key Size的解决方案
&li&在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:
/technetwork/java/javase/downloads/jce-7-download-432124.html&/li&
&li&下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt&/li&
&li&如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件&/li&
&li&如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件&/li&
+public class WXBizMsgCrypt {
+ static Charset CHARSET = Charset.forName(&utf-8&);
+ Base64 base64 = new Base64();
+ byte[] aesK
+ String appId;
* 构造函数
* @param token 公众平台上,开发者设置的token
* @param encodingAesKey 公众平台上,开发者设置的EncodingAESKey
* @param appId 公众平台appid
* @throws com.jfinal.weixin.sdk.encrypt.AesException 执行失败,请查看该异常的错误码和具体的错误信息
+ public WXBizMsgCrypt(String token, String encodingAesKey, String appId) throws AesException {
if (encodingAesKey.length() != 43) {
throw new AesException(AesException.IllegalAesKey);
this.token =
this.appId = appId;
aesKey = Base64.decodeBase64(encodingAesKey + &=&);
+ // 生成4个字节的网络字节序
+ byte[] getNetworkBytesOrder(int sourceNumber) {
byte[] orderBytes = new byte[4];
orderBytes[3] = (byte) (sourceNumber & 0xFF);
orderBytes[2] = (byte) (sourceNumber && 8 & 0xFF);
orderBytes[1] = (byte) (sourceNumber && 16 & 0xFF);
orderBytes[0] = (byte) (sourceNumber && 24 & 0xFF);
return orderB
+ // 还原4个字节的网络字节序
+ int recoverNetworkBytesOrder(byte[] orderBytes) {
int sourceNumber = 0;
for (int i = 0; i & 4; i++) {
sourceNumber &&= 8;
sourceNumber |= orderBytes[i] & 0
return sourceN
+ // 随机生成16位字符串
+ String getRandomStr() {
String base = &ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&;
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();
* 对明文进行加密.
* @param text 需要加密的明文
* @return 加密后base64编码的字符串
* @throws com.jfinal.weixin.sdk.encrypt.AesException aes加密失败
+ String encrypt(String randomStr, String text) throws AesException {
ByteGroup byteCollector = new ByteGroup();
byte[] randomStrBytes = randomStr.getBytes(CHARSET);
byte[] textBytes = text.getBytes(CHARSET);
byte[] networkBytesOrder = getNetworkBytesOrder(textBytes.length);
byte[] appidBytes = appId.getBytes(CHARSET);
// randomStr + networkBytesOrder + text + appid
byteCollector.addBytes(randomStrBytes);
byteCollector.addBytes(networkBytesOrder);
byteCollector.addBytes(textBytes);
byteCollector.addBytes(appidBytes);
// ... + pad: 使用自定义的填充方式对明文进行补位填充
byte[] padBytes = PKCS7Encoder.encode(byteCollector.size());
byteCollector.addBytes(padBytes);
// 获得最终的字节流, 未加密
byte[] unencrypted = byteCollector.toBytes();
// 设置加密模式为AES的CBC模式
Cipher cipher = Cipher.getInstance(&AES/CBC/NoPadding&);
SecretKeySpec keySpec = new SecretKeySpec(aesKey, &AES&);
IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv);
byte[] encrypted = cipher.doFinal(unencrypted);
// 使用BASE64对加密后的字符串进行编码
String base64Encrypted = base64.encodeToString(encrypted);
return base64E
} catch (Exception e) {
e.printStackTrace();
throw new AesException(AesException.EncryptAESError);
* 对密文进行解密.
* @param text 需要解密的密文
* @return 解密得到的明文
* @throws com.jfinal.weixin.sdk.encrypt.AesException aes解密失败
+ String decrypt(String text) throws AesException {
// 设置解密模式为AES的CBC模式
Cipher cipher = Cipher.getInstance(&AES/CBC/NoPadding&);
SecretKeySpec key_spec = new SecretKeySpec(aesKey, &AES&);
IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
cipher.init(Cipher.DECRYPT_MODE, key_spec, iv);
// 使用BASE64对密文进行解码
byte[] encrypted = Base64.decodeBase64(text);
original = cipher.doFinal(encrypted);
} catch (Exception e) {
e.printStackTrace();
throw new AesException(AesException.DecryptAESError);
String xmlContent, from_
// 去除补位字符
byte[] bytes = PKCS7Encoder.decode(original);
// 分离16位随机字符串,网络字节序和AppId
byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20);
int xmlLength = recoverNetworkBytesOrder(networkOrder);
xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), CHARSET);
from_appid = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length),
} catch (Exception e) {
e.printStackTrace();
throw new AesException(AesException.IllegalBuffer);
// appid不相同的情况
if (!from_appid.equals(appId)) {
throw new AesException(AesException.ValidateAppidError);
return xmlC
* 将公众平台回复用户的消息加密打包.
&li&对要发送的消息进行AES-CBC加密&/li&
&li&生成安全签名&/li&
&li&将消息密文和安全签名打包成xml格式&/li&
* @param replyMsg 公众平台待回复用户的消息,xml格式的字符串
* @param timeStamp 时间戳,可以自己生成,也可以用URL参数的timestamp
* @param nonce 随机串,可以自己生成,也可以用URL参数的nonce
* @return 加密后的可以直接回复用户的密文,包括msg_signature, timestamp, nonce, encrypt的xml格式的字符串
* @throws com.jfinal.weixin.sdk.encrypt.AesException 执行失败,请查看该异常的错误码和具体的错误信息
+ public String encryptMsg(String replyMsg, String timeStamp, String nonce) throws AesException {
String encrypt = encrypt(getRandomStr(), replyMsg);
// 生成安全签名
if (timeStamp == &&) {
timeStamp = Long.toString(System.currentTimeMillis());
String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt);
// System.out.println(&发送给平台的签名是: & + signature[1].toString());
// 生成发送的xml
String result = XMLParse.generate(encrypt, signature, timeStamp, nonce);
* 检验消息的真实性,并且获取解密后的明文.
&li&利用收到的密文生成安全签名,进行签名验证&/li&
&li&若验证通过,则提取xml中的加密消息&/li&
&li&对消息进行解密&/li&
* @param msgSignature 签名串,对应URL参数的msg_signature
* @param timeStamp 时间戳,对应URL参数的timestamp
* @param nonce 随机串,对应URL参数的nonce
* @param postData 密文,对应POST请求的数据
* @return 解密后的原文
* @throws com.jfinal.weixin.sdk.encrypt.AesException 执行失败,请查看该异常的错误码和具体的错误信息
+ public String decryptMsg(String msgSignature, String timeStamp, String nonce, String postData)
throws AesException {
// 密钥,公众账号的app secret
// 提取密文
Object[] encrypt = XMLParse.extract(postData);
// 验证安全签名
String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString());
// 和URL中的签名比较是否相等
// System.out.println(&第三方收到URL中的签名:& + msg_sign);
// System.out.println(&第三方校验签名:& + signature);
if (!signature.equals(msgSignature)) {
throw new AesException(AesException.ValidateSignatureError);
String result = decrypt(encrypt[1].toString());
* @param msgSignature 签名串,对应URL参数的msg_signature
* @param timeStamp 时间戳,对应URL参数的timestamp
* @param nonce 随机串,对应URL参数的nonce
* @param echoStr 随机串,对应URL参数的echostr
* @return 解密之后的echostr
* @throws com.jfinal.weixin.sdk.encrypt.AesException 执行失败,请查看该异常的错误码和具体的错误信息
+ public String verifyUrl(String msgSignature, String timeStamp, String nonce, String echoStr)
throws AesException {
String signature = SHA1.getSHA1(token, timeStamp, nonce, echoStr);
if (!signature.equals(msgSignature)) {
throw new AesException(AesException.ValidateSignatureError);
String result = decrypt(echoStr);
\ No newline at end of file
Index: com/allywll/weichat/core/weichat/encrypt/WXBizMsgCryptTest.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/WXBizMsgCryptTest.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/WXBizMsgCryptTest.java (revision 2)
@@ -0,0 +1,129 @@
+package com.allywll.weichat.core.weichat.
+/*import static org.junit.Assert.*;*/
+import java.io.IOE
+import java.io.StringR
+import javax.xml.parsers.DocumentB
+import javax.xml.parsers.DocumentBuilderF
+import javax.xml.parsers.ParserConfigurationE
+/*import org.junit.A
+import org.junit.AfterC
+import org.junit.B
+import org.junit.BeforeC
+import org.junit.T*/
+import org.w3c.dom.D
+import org.w3c.dom.E
+import org.w3c.dom.NodeL
+import org.xml.sax.InputS
+import org.xml.sax.SAXE
+public class WXBizMsgCryptTest {
+ String encodingAesKey = &abcdefghijklmnopqrstuvwxyzABCDEFG&;
+ String token = &pamtest&;
+ String timestamp = &&;
+ String nonce = &xxxxxx&;
+ String appId = &wxbcb6&;
+ String replyMsg = &我是中文abcd123&;
+ String xmlFormat = &&xml&&ToUserName&&![CDATA[toUser]]&&/ToUserName&&Encrypt&&![CDATA[%1$s]]&&/Encrypt&&/xml&&;
+ String afterAesEncrypt = &jn1L23DB+6ELqJ+6bruv21Y6MD7KeIfP82D6gU39rmkgczbWwt5+3bnyg5K55bgVtVzd832WzZGMhkP72vVOfg==&;
+ String randomStr = &aaaabbbbccccdddd&;
+ String replyMsg2 = &&xml&&ToUserName&&![CDATA[oia2Tj我是中文jewbmiOUlr6X-1crbLOvLw]]&&/ToUserName&&FromUserName&&![CDATA[gh_7fa]]&&/FromUserName&&CreateTime&&/CreateTime&&MsgType&&![CDATA[video]]&&/MsgType&&Video&&MediaId&&![CDATA[eYJ1MbwPRJtOvIEabaxHs7TX2D-HV71s79GUxqdUkjm6Gs2Ed1KF3ulAOA9H1xG0]]&&/MediaId&&Title&&![CDATA[testCallBackReplyVideo]]&&/Title&&Description&&![CDATA[testCallBackReplyVideo]]&&/Description&&/Video&&/xml&&;
+ 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 {
WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
String afterEncrpt = pc.encryptMsg(replyMsg, timestamp, nonce);
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&);
NodeList nodelist2 = root.getElementsByTagName(&MsgSignature&);
String encrypt = nodelist1.item(0).getTextContent();
String msgSignature = nodelist2.item(0).getTextContent();
String fromXML = String.format(xmlFormat, encrypt);
// 第三方收到公众号平台发送的消息
String afterDecrpt = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML);
// assertEquals(replyMsg, afterDecrpt);
} catch (AesException e) {
// fail(&正常流程,怎么就抛出异常了??????&);
+ public void testAesEncrypt() {
WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
// assertEquals(afterAesEncrypt, pc.encrypt(randomStr, replyMsg));
} catch (AesException e) {
e.printStackTrace();
// fail(&no异常&);
+ public void testAesEncrypt2() {
WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
// assertEquals(afterAesEncrypt2, pc.encrypt(randomStr, replyMsg2));
} catch (AesException e) {
e.printStackTrace();
// fail(&no异常&);
+ public void testIllegalAesKey() {
new WXBizMsgCrypt(token, &abcde&, appId);
} catch (AesException e) {
// assertEquals(AesException.IllegalAesKey, e.getCode());
// fail(&错误流程不抛出异常???&);
+ public void testValidateSignatureError() throws ParserConfigurationException, SAXException,
IOException {
WXBizMsgCrypt pc = new WXBizMsgCrypt(token, encodingAesKey, appId);
String afterEncrpt = pc.encryptMsg(replyMsg, timestamp, nonce);
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(xmlFormat, encrypt);
pc.decryptMsg(&12345&, timestamp, nonce, fromXML); // 这里签名错误
} catch (AesException e) {
// assertEquals(AesException.ValidateSignatureError, e.getCode());
// fail(&错误流程不抛出异常???&);
+ public void testVerifyUrl() throws AesException {
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(&QDG6eK&,
&jWmYm7qr5nMoAUwZRjGtBxmz3KA1tkAj3ykkR6q2B2C&, &wxbd56c7&);
String verifyMsgSig = &5c45ff5e21c57e6ad56bacd9ac89fd3&;
String timeStamp = &&;
String nonce = &&;
String echoStr = &P9nAzCzyDtyTWESHep1vC5X9xho/qYX3Zpb4yKa9SKld1DsH3Iyt3tP3zNdtp+4RPcs8TgAE7OaBO+FZXvnaqQ==&;
wxcpt.verifyUrl(verifyMsgSig, timeStamp, nonce, echoStr);
// 只要不抛出异常就好
Index: com/allywll/weichat/core/weichat/encrypt/ByteGroup.java
===================================================================
--- com/allywll/weichat/core/weichat/encrypt/ByteGroup.java (revision 0)
+++ com/allywll/weichat/core/weichat/encrypt/ByteGroup.java (revision 2)
@@ -0,0 +1,26 @@
+package com.allywll.weichat.core.weichat.
+import java.util.ArrayL
+class ByteGroup {
+ ArrayList&Byte& byteContainer = new ArrayList&Byte&();
+ public byte[] toBytes() {
byte[] bytes = new byte[byteContainer.size()];
for (int i = 0; i & byteContainer.size(); i++) {
bytes[i] = byteContainer.get(i);
+ public ByteGroup addBytes(byte[] bytes) {
for (byte b : bytes) {
byteContainer.add(b);
+ public int size() {
return byteContainer.size();
Index: com/allywll/weichat/core/weichat/msg/in/InMsg.java
===================================================================
--- com/allywll/weichat/core/weichat/msg/in/InMsg.java (revision 0)
+++ com/allywll/weichat/core/weichat/msg/in/InMsg.java (revision 2)
@@ -0,0 +1,76 @@
+package com.allywll.weichat.core.weichat.msg.
+接收消息,以下是接收文本消息的例子
+接收文本消息
+ &ToUserName&&![CDATA[toUser]]&&/ToUserName&
+ &FromUserName&&![CDATA[fromUser]]&&/FromUserName&
+ &CreateTime&&/CreateTime&
+ &MsgType&&![CDATA[text]]&&/MsgType&
+ &Content&&![CDATA[this is a test]]&&/Content&
+ &MsgId&3456&/MsgId&
+public abstract class InMsg {
+ // 开发者微信号
+ protected String toUserN
+ // 发送方帐号(一个OpenID)
+ protected String fromUserN
+ // 消息创建时间 (整型)
+ protected Integer createT
* 消息类型
* 1:text 文本消息
* 2:image 图片消息
* 3:voice 语音消息
* 4:video 视频消息
* 5:location 地址位置消息
* 6:link 链接消息
* 7:event 事件
+ protected String msgT
+ public InMsg(String toUserName, String fromUserName, Integer createTime, String msgType) {
this.toUserName = toUserN
this.fromUserName = fromUserN
this.createTime = createT
this.msgType = msgT
+ public String getToUserName() {
return toUserN
+ public void setToUserName(String toUserName) {
this.toUserName = toUserN
+ public String getFromUserName() {
return fromUserN
+ public void setFromUserName(String fromUserName) {
this.fromUserName = fromUserN
+ public Integer getCreateTime() {
return createT
+ public void setCreateTime(Integer createTime) {
this.createTime = createT
+ public String getMsgType() {
return msgT
+ public void setMsgType(String msgType) {
this.msgType = msgT
Index: com/allywll/weichat/core/api/ApiConfigKit.java
===================================================================
--- com/allywll/weichat/core/api/ApiConfigKit.java (revision 0)
+++ com/allywll/weichat/core/api/ApiConfigKit.java (revision 2)
@@ -0,0 +1,32 @@
+package com.allywll.weichat.core.
+public class ApiConfigKit {
+private static final ThreadLocal&ApiConfig& tl = new ThreadLocal&ApiConfig&();
+ // 开发模式将输出消息交互 xml 到控制台
+ private static boolean devMode =
+ public static void setDevMode(boolean devMode) {
ApiConfigKit.devMode = devM
+ public static boolean isDevMode() {
return devM
+ public static void setThreadLocalApiConfig(ApiConfig apiConfig) {
tl.set(apiConfig);
+ public static void removeThreadLocalApiConfig() {
tl.remove();
+ public static ApiConfig getApiConfig() {
ApiConfig result = tl.get();
if (result == null)
throw new IllegalStateException(&需要事先使用 ApiConfigKit.setThreadLocalApiConfig(apiConfig) 将 ApiConfig对象存入,才可以调用 ApiConfigKit.getApiConfig() 方法&);
Index: com/allywll/weichat/core/api/ApiConfig.java
===================================================================
--- com/allywll/weichat/core/api/ApiConfig.java (revision 0)
+++ com/allywll/weichat/core/api/ApiConfig.java (revision 2)
@@ -0,0 +1,96 @@
+package com.allywll.weichat.core.
+ * 存放 Weixin 服务号需要用到的各个参数
+public class ApiConfig {
+ private String token =// 授权码
+ private String appId =// 公众号唯一标识账号
+ private String appSecret =// 密码
+ private String encodingAesKey =
+ private boolean messageEncrypt = // 消息加密与否
+ public ApiConfig() {
+ public ApiConfig(String token) {
setToken(token);
+ public ApiConfig(String token, String appId, String appSecret) {
setToken(token);
setAppId(appId);
setAppSecret(appSecret);
+ public ApiConfig(String token, String appId, String appSecret,
boolean messageEncrypt, String encodingAesKey) {
setToken(token);
setAppId(appId);
setAppSecret(appSecret);
setEncryptMessage(messageEncrypt);
setEncodingAesKey(encodingAesKey);
+ public String getToken() {
if (token == null)
throw new IllegalStateException(&token 未被赋值&);
+ public void setToken(String token) {
if (token == null)
throw new IllegalArgumentException(&token 值不能为 null&);
this.token =
+ public String getAppId() {
if (appId == null)
throw new IllegalStateException(&appId 未被赋值&);
return appId;
+ public void setAppId(String appId) {
if (appId == null)
throw new IllegalArgumentException(&appId 值不能为 null&);
this.appId = appId;
+ public String getAppSecret() {
if (appSecret == null)
throw new IllegalStateException(&appSecret 未被赋值&);
return appS
+ public void setAppSecret(String appSecret) {
if (appSecret == null)
throw new IllegalArgumentException(&appSecret 值不能为 null&);
this.appSecret = appS
+ public String getEncodingAesKey() {
if (encodingAesKey == null)
throw new IllegalStateException(&encodingAesKey 未被赋值&);
return encodingAesK
+ public void setEncodingAesKey(String encodingAesKey) {
if (encodingAesKey == null)
throw new IllegalArgumentException(&encodingAesKey 值不能为 null&);
this.encodingAesKey = encodingAesK
+ public boolean isEncryptMessage() {
return messageE
* 是否对消息进行加密,对应于微信平台的消息加解密方式: 1:true进行加密且必须配置 encodingAesKey
* 2:false采用明文模式,同时也支持混合模式
+ public void setEncryptMessage(boolean messageEncrypt) {
this.messageEncrypt = messageE
Index: com/allywll/weichat/core/util/ConstDefine.java
===================================================================
--- com/allywll/weichat/core/util/ConstDefine.java (revision 0)
+++ com/allywll/weichat/core/util/ConstDefine.java (revision 2)
@@ -0,0 +1,16 @@
+package com.allywll.weichat.core.
+public interface ConstDefine {
+ //定义错误信息相关常量
+ public interface Errors{
//错误信息key值
public String ErrorInfoKey=&errorInfo&;
//错误的签名信息
public String ErrorSign=&错误的签名信息&;
Index: com/allywll/weichat/core/util/MsgEncryptKit.java
===================================================================
--- com/allywll/weichat/core/util/MsgEncryptKit.java (revision 0)
+++ com/allywll/weichat/core/util/MsgEncryptKit.java (revision 2)
@@ -0,0 +1,83 @@
+package com.allywll.weichat.core.
+import java.io.StringR
+import javax.xml.parsers.DocumentB
+import javax.xml.parsers.DocumentBuilderF
+import org.w3c.dom.D
+import org.w3c.dom.E
+import org.w3c.dom.NodeL
+import org.xml.sax.InputS
+import com.allywll.weichat.core.api.ApiC
+import com.allywll.weichat.core.api.ApiConfigK
+import com.allywll.weichat.core.weichat.encrypt.WXBizMsgC
+ * 对微信平台官方给出的加密解析代码进行再次封装
+ * 异常java.security.InvalidKeyException:illegal Key Size的解决方案:
+ * 1:在官方网站下载JCE无限制权限策略文件(JDK7的下载地址:
/technetwork/java/javase/downloads/jce-7-download-432124.html
+ * 2:下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt
+ * 3:如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件
+ * 4:如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件
+ * 设置为消息加密模式后 JFinal Action Report 中有如下参数:
+ * timestamp=
+ * encrypt_type=aes
+ * nonce=
+ * msg_signature=8ed2ac0d28eaf30a323
+ * signature=1a3fad9aa73faf4c8054b7eeda2463d3
+public class MsgEncryptKit {
+ private static final String format = &&xml&&ToUserName&&![CDATA[toUser]]&&/ToUserName&&Encrypt&&![CDATA[%1$s]]&&/Encrypt&&/xml&&;
+ public static String encrypt(String msg, String timestamp, String nonce) {
ApiConfig ac = ApiConfigKit.getApiConfig();
WXBizMsgCrypt pc = new WXBizMsgCrypt(ac.getToken(), ac.getEncodingAesKey(), ac.getAppId());
return pc.encryptMsg(msg, timestamp, nonce);
catch (Exception e) {
throw new RuntimeException(e);
+ public static String decrypt(String encryptedMsg, String timestamp, String nonce, String msgSignature) {
ApiConfig ac = ApiConfigKit.getApiConfig();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
StringReader sr = new StringReader(encryptedMsg);
InputSource is = new InputSource(sr);
Document document = db.parse(is);
Element root = document.getDocumentElement();
NodeList nodelist1 = root.getElementsByTagName(&Encrypt&);
// NodeList nodelist2 = root.getElementsByTagName(&MsgSignature&);
String encrypt = nodelist1.item(0).getTextContent();
// String msgSignature = nodelist2.item(0).getTextContent();
String fromXML = String.format(format, encrypt);
String encodingAesKey = ac.getEncodingAesKey();
if (encodingAesKey == null)
throw new IllegalStateException(&encodingAesKey can not be null, config encodingAesKey first.&);
WXBizMsgCrypt pc = new WXBizMsgCrypt(ac.getToken(), encodingAesKey, ac.getAppId());
return pc.decryptMsg(msgSignature, timestamp, nonce, fromXML); // 此处 timestamp 如果与加密前的不同则报签名不正确的异常
catch (Exception e) {
throw new RuntimeException(e);
Index: com/allywll/weichat/core/util/SignatureCheckKit.java
===================================================================
--- com/allywll/weichat/core/util/SignatureCheckKit.java (revision 0)
+++ com/allywll/weichat/core/util/SignatureCheckKit.java (revision 2)
@@ -0,0 +1,29 @@
+package com.allywll.weichat.core.
+import java.util.A
+import com.allywll.weichat.core.api.ApiConfigK
+import com.jfinal.core.C
+import com.jfinal.kit.EncryptionK
+public class SignatureCheckKit {
+ private static boolean checkSignature(String signature, String timestamp, String nonce) {
String TOKEN = ApiConfigKit.getApiConfig().getToken();
String array[] = {TOKEN, timestamp, nonce};
Arrays.sort(array);
String tempStr = new StringBuilder().append(array[0] + array[1] + array[2]).toString();
tempStr = EncryptionKit.sha1Encrypt(tempStr);
return tempStr.equalsIgnoreCase(signature);
* 检查微信接入签名
* @param c
+ public static boolean checkSignature(Controller c)
return checkSignature(c.getPara(&signature&), c.getPara(&timestamp&), c.getPara(&nonce&));
Index: com/allywll/weichat/synergy/WeiChatMsgController.java
===================================================================
--- com/allywll/weichat/synergy/WeiChatMsgController.java (revision 0)
+++ com/allywll/weichat/synergy/WeiChatMsgController.java (revision 2)
@@ -0,0 +1,33 @@
+package com.allywll.weichat.
+import com.allywll.weichat.core.api.ApiC
+import com.allywll.weichat.core.weichat.web.MsgC
+import com.jfinal.kit.PropK
+public class WeiChatMsgController extends MsgController {
* 如果要支持多公众账号,只需要在此返回各个公众号对应的
ApiConfig 对象即可
* 可以通过在请求 url 中挂参数来动态从数据库中获取 ApiConfig 属性值
+ public ApiConfig getApiConfig() {
ApiConfig ac = new ApiConfig();
// 配置微信 API 相关常量
ac.setToken(PropKit.get(&token&));
ac.setAppId(PropKit.get(&appId&));
ac.setAppSecret(PropKit.get(&appSecret&));
是否对消息进行加密,对应于微信平台的消息加解密方式:
1:true进行加密且必须配置 encodingAesKey
2:false采用明文模式,同时也支持混合模式
ac.setEncryptMessage(PropKit.getBoolean(&encryptMessage&, false));
ac.setEncodingAesKey(PropKit.get(&encodingAesKey&));
Index: com/allywll/weichat/synergy/WeiChatConfig.java
===================================================================
--- com/allywll/weichat/synergy/WeiChatConfig.java (revision 0)
+++ com/allywll/weichat/synergy/WeiChatConfig.java (revision 2)
@@ -0,0 +1,74 @@
+package com.allywll.weichat.
+import java.io.F
+import java.util.P
+import com.allywll.weichat.core.api.ApiConfigK
+import com.jfinal.config.C
+import com.jfinal.config.H
+import com.jfinal.config.I
+import com.jfinal.config.JFinalC
+import com.jfinal.config.P
+import com.jfinal.config.R
+import com.jfinal.ext.handler.ContextPathH
+import com.jfinal.kit.PropK
+import com.jfinal.render.FreeMarkerR
+public class WeiChatConfig extends JFinalConfig {
* 配置参数
* -- 启动filter会init执行 序号1
* @param paramConstants
+ public void configConstant(Constants paramConstants) {
//加载默认配置文件
loadPropertyFile(&weichat.properties&);
//设置开发模式
paramConstants.setDevMode(PropKit.getBoolean(&devMode&, false));
// ApiConfigKit 设为开发模式可以在开发阶段输出请求交互的 xml 与 json 数据
ApiConfigKit.setDevMode(paramConstants.getDevMode());
//设置freemarket配置
paramConstants.setBaseViewPath(&freemarket&);//页面模板根路径
paramConstants.setFreeMarkerViewExtension(&.htm&);//freemarker 模板后缀名
* 配置路由映射
* --启动filter在init执行 序号2
* @param paramRoutes
+ public void configRoute(Routes paramRoutes) {
paramRoutes.add(&/msg&, WeiChatMsgController.class);
+ public void configHandler(Handlers paramHandlers) {
//设置默认webRoot路径为contextPath
paramHandlers.add(new ContextPathHandler(&contextPath&));
+ public void configInterceptor(Interceptors paramInterceptors) {
+ public void configPlugin(Plugins paramPlugins) {
* 启动成功后
* 加载freemarker配置
+ public void afterJFinalStart() {
Properties p = loadPropertyFile(&freemarker.properties&);//由于我们用到freemarker,所以在此进行freemarker配置文件的装载
FreeMarkerRender.setProperties(p);
Index: freemarker.properties
===================================================================
--- freemarker.properties (revision 0)
+++ freemarker.properties (revision 2)
@@ -0,0 +1,9 @@
+#freemarker配置文件
+default_encoding=utf-8
+#for testing
+template_exception_handler=DEBUG
+template_update_delay=5
+datetime_format=yyyy-MM-dd HH:mm:ss
+date_format=yyyy-MM-dd
+number_format=#.##
\ No newline at end of file
Index: weichat.properties
===================================================================
--- weichat.properties (revision 0)
+++ weichat.properties (revision 2)
@@ -0,0 +1,43 @@
+#weichat项目配置文件
+##############开发模式######################
+#设置为true会输出默认请求的参数
+devMode=true
+#########################################
+###############微信公众号配置#################
+# 微信服务器回调所用的 token
+token=zhongfang
+#微信用的账号
+appId=wx7b7cb0e9378ab88e
+appSecret=96c3abdd6730749fbc0d84bc24eaa18c
+#是否对消息进行加密,是否对消息进行加密,对应于微信平台的消息加解密方式,false支持明文模式及兼容模式,true支持安全模式及兼容模式
+encryptMessage=false
+encodingAesKey=p6iKdZGISEnDjuoZfaIo44Bt8wJTSGHRCQgnyFONLVH
+#########################################
+##########用于与微信通讯的接口#################
+#######################################
(C)&&2013&&Alibaba&&Inc.&&All&&rights&&resvered.
Powered by

我要回帖

更多关于 a0123456789 的文章

 

随机推荐