微信 request请求解析验证 与 response 返回消息组装 工具类

package com.weixin.utils;

import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.util.QuickWriter;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
import com.thoughtworks.xstream.io.xml.XppDriver;
import com.weixin.base.message.TextMessage;

public class MessageUtils {
	
	public final static String REQ_MESSAGE_TYPE_TEXT = "text";
	
	public final static String RESP_MESSAGE_TYPE_TEXT = "text";
	
	//必须与微信后台页面配置的参数保持一致
	private static final String TOKEN = "WeiWinValidation";
	
	/**
	 * 微信请求验证(根据微信请求验证规则进行验证)
	 * 
	 * @param signature:原始的加密的签名字符串
	 * @param timestamp:时间戳信息
	 * @param nonce:随机数
	 * @return
	 */
	public static boolean checkSignature(String signature,String timestamp,String nonce)
	{
		//1. 将token、timestamp、nonce三个参数进行字典序排序
		
		//先构造一个数组
		String[] params = new String[]{TOKEN,timestamp,nonce};
		
		//实现按字典顺序排序
		Arrays.sort(params);
		
		//2. 将三个参数字符串拼接成一个字符串
		StringBuilder builder = new StringBuilder();
		//StringBuffer
		for(int i=0;i<params.length;i++)
		{
			builder.append(params[i]);
		}
		
		System.out.println("拼接后的字符串:"+builder.toString());
		

		MessageDigest md = null;
		String result = "";
		
		try {
			//3. 对拼接后的字符串进行sha1加密
			md = md.getInstance("SHA-1");
			
			byte[] digest = md.digest(builder.toString().getBytes());
			
			//将字节数组转换成为密文字符串
			result = byteToStr(digest);
			
			System.out.println("加密后的密文是:"+result);
			
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		//4.将加密后的字符串与从微信服务器接受到的原始的signature签名字符串进行对比,如果相等就标识该请求来源于微信服务器,否则不认可,
		//请求验证不能通过
		
		return result != null ?(result.equals(signature.toUpperCase())):false;
		
	}
	
	/**
	 * 实现将字节数组转换为十六进制字符串
	 * @param str
	 */
	private static String byteToStr(byte[] str)
	{
		String strDigest = "";
		for(int i=0;i<str.length;i++)
		{
			strDigest += byteToHexStr(str[i]);
		}
		return strDigest;
	}
	
	/**
	 * 将一个字节转换为十六进制字符串
	 * @param mByte
	 * @return
	 */
	private static String byteToHexStr(byte mByte)
	{
		char[] Digit = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
		char[] temp=new char[2];
		
		temp[0] = Digit[(mByte>>>4)& 0X0F];
		temp[1] = Digit[mByte & 0X0F];
		
		String s = new String(temp);
		
		return s;
	}
	
	/**
	 * 解析从请求中获得xml格式串
	 * 采用dom4的方式来进行解析
	 * 
	 * @return
	 * @throws IOException 
	 * @throws DocumentException 
	 */
	public static Map<String, String> parseXML(HttpServletRequest request) throws IOException, Exception{
		//存放解析出来的数据
		Map<String,String> map = new HashMap<String,String>();
		
		//从请求对象中获取输入流对象
		InputStream inputStream = request.getInputStream();
		
		//创建SAX解析器对象
		SAXReader reader = new SAXReader();
		
		//读入流对象,生成文档对象
		Document document = reader.read(inputStream);
		
		//获得根节点
		Element root = document.getRootElement();
		
		//一次性遍历根元素下的所有子元素并以列表形式返回
		List<Element>  elementList = root.elements();
		
		//将list列表中的元素对象分别以元素名、元素值这种键值对的方式放入到map集合中
		
		for(Element e: elementList)
		{
			//       节点名      节点值
			map.put(e.getName(),e.getText());
		}
		
		//关闭流
		inputStream.close();
		
		inputStream = null;
		
		return map;
	}
	
	
	/**
	 * 用于扩展节点数据按照 <ToUserName><![CDATA[toUser]]></ToUserName> ,中间加了 CDATA
	 */
	private static XStream xstream = new XStream(new XppDriver() 
	{
		public HierarchicalStreamWriter createWriter(Writer out) 
		{
			return new PrettyPrintWriter(out) {
				
				boolean cdata = true;

				public void startNode(String name, Class clazz) {
					super.startNode(name, clazz);
				}

				protected void writeText(QuickWriter writer, String text) {
					if (cdata) {
						writer.write("<![CDATA[");
						
						writer.write(text);
						
						writer.write("]]>");
						
					} else {
						writer.write(text);
					}
				}
			};
		}
	});

	/**
	 * 将文本消息转换成 XML 格式 用来发送
	 * 
	 * @return
	 */
	public static String messageToXml(TextMessage textMessage) {
		//给对象取别名
		xstream.alias("xml", textMessage.getClass());

		return xstream.toXML(textMessage);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值