import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.Map.Entry;
/**
* 工具类
*/
public class PayCommonUtil {
private static Logger logger = LoggerFactory.getLogger(PayCommonUtil.class);
/**
* 自定义长度随机字符串
* @param length
* @return
*/
public static String createConceStr(int length) {
String strs = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String str = "";
for (int i = 0; i < length; i++) {
// str +=strs.substring(0, new Random().nextInt(strs.length()));
char achar = strs.charAt(new Random().nextInt(strs.length() - 1));
str += achar;
}
return str;
}
/**
* 获取时间戳
* 时间戳从1970年1月1日00:00:00至今的秒数
*/
public static long getTimeStamp() {
Date d = new Date();
long timeStamp = d.getTime() / 1000; //getTime()得到的是微秒, 需要换算成秒
return timeStamp;
}
/**
* 默认16 位随机字符串
* @return
*/
public static String CreateNoncestr() {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
for (int i = 0; i < 16; i++) {
Random rd = new Random();
res += chars.charAt(rd.nextInt(chars.length() - 1));
}
return res;
}
/**
* 签名工具
* @Description:sign签名
* @param characterEncoding
* 编码格式 UTF-8
* @param parameters
* 请求参数
* @return
*/
public static String createSign(String characterEncoding, Map parameters) {
StringBuffer sb = new StringBuffer();
//对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
Map params = sortMap(parameters);
Iterator> it = params.entrySet().iterator();
while (it.hasNext()) {
Entry entry = (Entry) it.next();
String key = (String) entry.getKey();
Object value = entry.getValue();//去掉带sign的项
if (null != value && !"".equals(value) && !"sign".equals(key)
&& !"key".equals(key)) {
sb.append(key + "=" + value + "&");
}
}
sb.append("key=" + WXPayConstant.KEY);
//注意sign转为大写
return MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
}
/**
* 对map根据key进行排序 ASCII 顺序
*
* @param map(无序的)
* @return
*/
public static Map sortMap(Map map) {
List> infoIds = new ArrayList>(
map.entrySet());
Collections.sort(infoIds, new Comparator>() {
public int compare(Entry o1,
Entry o2) {
// return (o2.getValue() - o1.getValue());//value处理
return (o1.getKey()).toString().compareTo(o2.getKey());
}
});
Map sortmap = new TreeMap();
for (int i = 0; i < infoIds.size(); i++) {
String[] split = infoIds.get(i).toString().split("=");
sortmap.put(split[0], split[1]);
}
return sortmap;
}
/**
* @date
* @Description:将请求参数转换为xml格式的string
* @param parameters
* 请求参数
* @return
*/
public static String getRequestXml(Map parameters) {
StringBuffer sb = new StringBuffer();
sb.append("");
Iterator> iterator = parameters.entrySet().iterator();
while (iterator.hasNext()) {
Entry entry = (Entry) iterator.next();
String key = (String) entry.getKey();
String value = (String) entry.getValue().toString();
sb.append("<" + key + ">" + value + "" + key + ">");
}
sb.append(" ");
return sb.toString();
}
public static String setXML(String return_code, String return_msg) {
return " ";
}
/**
* 检验API返回的数据里面的签名是否合法
*
* @param responseString API返回的XML数据字符串
* @return API签名是否合法
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
public static boolean checkIsSignValidFromResponseString(String responseString) {
try {
Map map = doXMLParse(responseString);
logger.debug(map.toString());
String signFromAPIResponse = map.get("sign").toString();
if ("".equals(signFromAPIResponse) || signFromAPIResponse == null) {
logger.debug("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
return false;
}
logger.debug("服务器回包里面的签名是:" + signFromAPIResponse);
map.put("sign", "");
String signForAPIResponse = PayCommonUtil.createSign("UTF-8", map);
if (!signForAPIResponse.equals(signFromAPIResponse)) {
logger.debug("数据签名验证不通过");
return false;
}
logger.debug("恭喜,数据签名验证通过!!!");
return true;
} catch (Exception e) {
return false;
}
}
/**
* 解析xml,返回第一级元素键值对。
* 如果第一级元素有子节点,
* 则此节点的值是子节点的xml数据。
*
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml)
throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if (null == strxml || "".equals(strxml)) {
return null;
}
Map map = new TreeMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String key = e.getName();
String value = "";
List children = e.getChildren();
if (children.isEmpty()) {
value = e.getTextNormalize();
} else {
value = getChildrenText(children);
}
map.put(key, value);
}
// 关闭流
in.close();
return map;
}
/**
* 获取子结点的xml
* @param children
* @return
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if (!children.isEmpty()) {
Iterator it = children.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if (!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("" + name + ">");
}
}
return sb.toString();
}
}