嗨森逛服务
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hai-server/hai-service/src/main/java/com/hai/common/utils/WxUtils.java

582 lines
20 KiB

package com.hai.common.utils;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Maps;
import com.hai.common.pay.util.sdk.WXPayConstants;
import com.hai.common.pay.util.sdk.WXPayXmlUtil;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.naming.NoNameCoder;
import com.thoughtworks.xstream.io.xml.XppDriver;
import net.sf.cglib.beans.BeanMap;
import org.apache.commons.lang3.StringUtils;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.*;
public class WxUtils {
private static final Random RANDOM = new SecureRandom();
private static final String SYMBOLS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
/**
* 生成签名
*
* @param signMaps
* @return
* @throws Exception
*/
public static String generateSign(SortedMap<String, String> signMaps, String mchKey) {
StringBuffer sb = new StringBuffer();
// 字典序
for (Map.Entry signMap : signMaps.entrySet()) {
String key = (String) signMap.getKey();
String value = (String) signMap.getValue();
// 为空不参与签名、参数名区分大小写
if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) {
sb.append(key).append("=").append(value).append("&");
}
}
// 拼接key
sb.append("key=").append(mchKey);
// MD5加密
String sign = MD5Encode(sb.toString(), "UTF-8").toUpperCase();
return sign;
}
public static String generateSignSHA256(SortedMap<String, String> signMaps,String mchKey)throws Exception{
StringBuffer sb = new StringBuffer();
// 字典序
for (Map.Entry signMap : signMaps.entrySet()) {
String key = (String) signMap.getKey();
String value = (String) signMap.getValue();
// 为空不参与签名、参数名区分大小写
if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) {
sb.append(key).append("=").append(value).append("&");
}
}
// 拼接key
sb.append("key=").append(mchKey);
// HMACSHA256加密
String sign = HMACSHA256(sb.toString(), mchKey).toUpperCase();
return sign;
}
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
private static final String[] hexDigits = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
private static HashMap<String, String> sortAsc(Map<String, String> map) {
HashMap<String, String> tempMap = new LinkedHashMap<String, String>();
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
//排序
infoIds.sort(new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return o1.getKey().compareTo(o2.getKey());
}
});
for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, String> item = infoIds.get(i);
tempMap.put(item.getKey(), item.getValue());
}
return tempMap;
}
/**
* 生成 HMACSHA256
* @param data 待处理数据
* @param key 密钥
* @return 加密结果
* @throws Exception
*/
public static String HMACSHA256(String data, String key) throws Exception {
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");
sha256_HMAC.init(secret_key);
byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
/**
* 获取随机字符串 Nonce Str
*
* @return String 随机字符串
*/
public static String makeNonStr() {
char[] nonceChars = new char[32];
for (int index = 0; index < nonceChars.length; ++index) {
nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
}
return new String(nonceChars);
}
/**
* 拼接签名数据
*
*/
public static String makeSign(BeanMap beanMap, String mchKey, String signType)throws Exception {
SortedMap<String, String> signMaps = Maps.newTreeMap();
for (Object key : beanMap.keySet()) {
Object value = beanMap.get(key);
// 排除空数据
if (value == null) {
continue;
}
signMaps.put(key + "", String.valueOf(value));
}
if(signType.equals("MD5")) {
// 生成签名
return generateSign(signMaps, mchKey);
}else if(signType.equals("SHA256")){
return generateSignSHA256(signMaps, mchKey);
}else{
return null;
}
}
/**
* 数据转换为xml格式
*
* @param object
* @param obj
* @return
*/
public static String truncateDataToXML(Class<?> object, Object obj) {
XStream xStream = new XStream(new XppDriver(new NoNameCoder()));
xStream.alias("xml", object);
return xStream.toXML(obj);
}
/**
* 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
*
* @param data 待签名数据
* @param key API密钥
* @param signType 签名方式
* @return 签名
*/
public static String generateSignature(final Map<String, String> data, String key, WXPayConstants.SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
sb.append("key=").append(key);
if (WXPayConstants.SignType.MD5.equals(signType)) {
return MD5(sb.toString() , true);
}
else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
public static String generateSignatureAppSecret(final Map<String, Object> data, String key, WXPayConstants.SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (StringUtils.isBlank(sb.toString())) {
sb.append(k).append("=").append(data.get(k));
} else {
sb.append("&").append(k).append("=").append(data.get(k));
}
}
sb.append("&app_secret=").append(key);
if (WXPayConstants.SignType.MD5.equals(signType)) {
return MD5(sb.toString() , false);
}
else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
public static String generateSignature(final Map<String, Object> data) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (StringUtils.isBlank(sb.toString())) {
sb.append(k).append("=").append(data.get(k));
} else {
sb.append("&").append(k).append("=").append(data.get(k));
}
}
return sb.toString();
}
public static String generateSignature2(final Map<String, Object> data, String sign, String key) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (data.get(k) != null) // 参数值为空,则不参与签名
sb.append(k).append("=").append(data.get(k)).append("&");
}
if (key != null) {
sb.append("app_secret=").append(key);
}
return sb.toString();
}
/**
* 生成 MD5
*
* @param data 待处理数据
* @return MD5结果
*/
public static String MD5(String data , Boolean isUpperCase) throws Exception {
java.security.MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
if (isUpperCase) {
return sb.toString().toUpperCase();
} else {
return sb.toString();
}
}
/**
* 将Map转换为XML格式的字符串
*
* @param data Map类型数据
* @return XML格式的字符串
* @throws Exception
*/
public static String mapToXml(Map<String, String> data) throws Exception {
org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key: data.keySet()) {
String value = data.get(key);
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString(); //.replaceAll("|\r", "");
try {
writer.close();
}
catch (Exception ex) {
}
return output;
}
/**
* 千猪生成签名。
*
* @param data 待签名数据
* @param secret API密钥
* @param signType 签名方式
* @return 签名
*/
public static String generateSignaturePig(final Map<String, String> data, String secret, WXPayConstants.SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
String s = sb.substring(0, sb.length() - 1) + secret;
if (WXPayConstants.SignType.MD5.equals(signType)) {
return MD5(sb.toString() , false);
}
else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(s, secret);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
/**
* 生成龙阅签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
*
* @param data 待签名数据
* @param key API密钥
* @param signType 签名方式
* @return 签名
*/
public static String generateSignatureLy(final Map<String, Object> data, String key, WXPayConstants.SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (data.get(k) != null) // 参数值为空,则不参与签名
sb.append(k).append("=").append(data.get(k)).append("&");
}
sb.append("apikey=").append(key);
if (WXPayConstants.SignType.MD5.equals(signType)) {
return MD5(sb.toString() , true);
}
else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
/**
* 生成龙阅签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
*
* @param data 待签名数据
* @param key API密钥
* @param signType 签名方式
* @return 签名
*/
public static String generateSignatureCy(final Map<String, Object> data, String key, WXPayConstants.SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN)) {
continue;
}
if (data.get(k) != null) // 参数值为空,则不参与签名
sb.append(k).append("=").append(data.get(k)).append("&");
}
sb.append("appsecret=").append(key);
if (WXPayConstants.SignType.MD5.equals(signType)) {
return MD5(sb.toString() , true);
}
else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
/**
* 生成签名.
*
* @param data 待签名数据
* @param key API密钥
* @param signType 签名方式
* @return 签名
*/
public static String generateSignApi(final Map<String, Object> data, String key, WXPayConstants.SignType signType) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals(WXPayConstants.FIELD_SIGN) || k.equals("apiKey")) {
continue;
}
if (data.get(k) != null) // 参数值为空,则不参与签名
{
sb.append(k).append("=").append(data.get(k)).append("&");
}
}
sb.append("apiKey=").append(key);
if (WXPayConstants.SignType.MD5.equals(signType)) {
return MD5(sb.toString() , true);
}
else if (WXPayConstants.SignType.HMACSHA256.equals(signType)) {
return HMACSHA256(sb.toString(), key);
}
else {
throw new Exception(String.format("Invalid sign_type: %s", signType));
}
}
/**
* 用SHA1算法生成安全签名
* @param token 票据
* @param timestamp 时间戳
* @param nonce 随机字符串
* @return 安全签名
* @throws Exception
*/
public static String getSHA1(String token, String timestamp, String nonce) throws Exception
{
try {
String[] array = new String[] { token, timestamp, nonce};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 3; i++) {
sb.append(array[i]);
}
String str = sb.toString();
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
return hexstr.toString();
} catch (Exception e) {
e.printStackTrace();
throw new Exception(String.format("Invalid sign_type: %s"));
}
}
/**
* 用SHA1算法生成安全签名
* @param data 数据
* @param key key
* @return 安全签名
* @throws Exception
*/
public static String getSHA1(final Map<String, Object> data, String key) throws Exception
{
try {
String[] array = new String[] { token, timestamp, nonce};
StringBuffer sb = new StringBuffer();
// 字符串排序
Arrays.sort(array);
for (int i = 0; i < 3; i++) {
sb.append(array[i]);
}
String str = sb.toString();
// SHA1签名生成
MessageDigest md = MessageDigest.getInstance("SHA-1");
md.update(str.getBytes());
byte[] digest = md.digest();
StringBuffer hexstr = new StringBuffer();
String shaHex = "";
for (int i = 0; i < digest.length; i++) {
shaHex = Integer.toHexString(digest[i] & 0xFF);
if (shaHex.length() < 2) {
hexstr.append(0);
}
hexstr.append(shaHex);
}
return hexstr.toString();
} catch (Exception e) {
e.printStackTrace();
throw new Exception(String.format("Invalid sign_type: %s"));
}
}
}