前言:
最近在研究微信公众平台的开发,玩得不亦乐乎。基本的回复功能已经实现了,而且回复用到了图灵机器人的接口。其实图灵机器人已经有微信接口可以直接调用。如果项目的需要,想要做个性化需求的话,用这种方式是行不通的。我现在的解决方案是,我开发的应用A作为中间层,连接微信接口与图灵机器人接口。有点扯远了,如题,微信官方为了更高的安全性,10月份推出了消息体签名验证。网上关于此项的实例不多,其实根据官方的例子,重新封装一下,就可以了。
一、准备工作:
1.已申请了相关的订阅号或者服务号(可以用虚拟器,具体的方式没试过,百度一下,有很多介绍);
2.已经有了原来的公众平台交互应用A;
3.按照官网提示下载相关的示例代码;
4.保证应用的JDK是1.6以上;
二、具体实现:
1.去官网设置消息加密方式,点击“开发者中心”-》“修改配置”,这里为了调试,设置为“兼容模式”:
2.将官网下载的示例代码导入应用中,我们只需关注其中重要的接口类:WXBizMsgCrypt以及它的具体应用展示Program类;
3.根据自己的代码应用场景,将WXBizMsgCrypt重新封装一下:
AuthProcess.java
package cn.qtone.xxt.base.wechat.utils; import javax.servlet.http.HttpServletRequest; import cn.qtone.xxt.base.wechat.utils.aes.AesException; import cn.qtone.xxt.base.wechat.utils.aes.WXBizMsgCrypt; public class AuthProcess { public final static String Token = "xxxx";//公众平台上面自己填写的Token public final static String EncodingAESKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//公众平台上面自己填写的43位EncodingAESKey public final static String AppID = "wx488885e67d6c19e2";//应用的appid(微信生成的) /** * 将加密后的原文进行解密重新封装 * @param request * @param originalXml 原xml * @return 重新解密后的xml */ public static String decryptMsg(HttpServletRequest request,String originalXml) { // 微信加密签名 //String sVerifyMsgSig = request.getParameter("signature"); String msgSignature = request.getParameter("msg_signature"); // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); try { WXBizMsgCrypt pc = new WXBizMsgCrypt(Token, EncodingAESKey, AppID); return pc.decryptMsg(msgSignature, timestamp, nonce, originalXml); } catch (AesException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } /** * 对需要回复的原文进行加密重新封装 * @param request * @param replyXml 需要回复的xml * @return 重新加密后的xml */ public static String encryptMsg(HttpServletRequest request,String replyXml) { // 时间戳 String timestamp = request.getParameter("timestamp"); // 随机数 String nonce = request.getParameter("nonce"); try { WXBizMsgCrypt pc = new WXBizMsgCrypt(Token, EncodingAESKey, AppID); return pc.encryptMsg(replyXml, timestamp, nonce); } catch (AesException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
4.找到原来自动回复接口的流程代码,在处理数据前后,加上请求数据解密,回复数据加密的流程(下面为关键代码部分):
//加密消息处理 String encrypt_type =request.getParameter("encrypt_type"); if (StringTools.nil(encrypt_type) || encrypt_type.equals("raw")) {//不用加密 // 正常的微信处理流程 result = weChatService.processWechatMag(xml); } else {//需走加解密流程 //解密请求消息体 String nXmlString = AuthProcess.decryptMsg(request, xml); //执行原处理 String originalResult = weChatService.processWechatMag(nXmlString); //加密回复消息体 result = AuthProcess.encryptMsg(request, originalResult); }总结:经测试,以上流程是成功的,但中间出现一点小状况,需要特别说明一下,这里引述一下官方FAQ的其中一个我遇到的问题及他们的解决方案:
- 异常java.security.InvalidKeyException:illegal Key Size的解决方案:在官方网站下载JCE无限制权限策略文件(请到官网下载对应的版本, 例如JDK7的下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt,如果安装了JRE,将两个jar文件放到%JRE_HOME%\lib\security目录下覆盖原来的文件;如果安装了JDK,将两个jar文件放到%JDK_HOME%\jre\lib\security目录下覆盖原来文件