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);
}
}
微信 request请求解析验证 与 response 返回消息组装 工具类
最新推荐文章于 2022-11-10 23:21:24 发布