首页 > 代码库 > 微信公众平台消息体签名及加解密实例(Java)

微信公众平台消息体签名及加解密实例(Java)

前言:

      最近在研究微信公众平台的开发,玩得不亦乐乎。基本的回复功能已经实现了,而且回复用到了图灵机器人的接口。其实图灵机器人已经有微信接口可以直接调用。如果项目的需要,想要做个性化需求的话,用这种方式是行不通的。我现在的解决方案是,我开发的应用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目录下覆盖原来文件
我用的是jdk1.6.0_31,所以需要下载相关的文件并进行了覆盖,下载地址:http://www.oracle.com/technetwork/java/javase/downloads/jce-6-download-429243.html


微信公众平台消息体签名及加解密实例(Java)