package com.allinpay.syb.lib;
|
|
import java.io.UnsupportedEncodingException;
|
import java.security.KeyFactory;
|
import java.security.MessageDigest;
|
import java.security.NoSuchAlgorithmException;
|
import java.security.PrivateKey;
|
import java.security.PublicKey;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
import java.util.List;
|
import java.util.Map;
|
import java.util.Random;
|
import java.util.TreeMap;
|
|
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.TypeReference;
|
import com.doumee.dao.business.dto.PayOrderNotifyParam;
|
import org.apache.commons.codec.binary.Base64;
|
|
public class SybUtil {
|
/**
|
* js转化为实体
|
*
|
* @param <T>
|
* @param jsonstr
|
* @param cls
|
* @return
|
*/
|
public static <T> T json2Obj(String jsonstr, Class<T> cls) {
|
TypeReference<T> type = new TypeReference<T>() { };
|
T obj = JSONObject.parseObject(jsonstr, type.getType());
|
// JSONObject jo = JSONObject.fromObject(jsonstr);
|
// T obj = (T) JSONObject.toBean(jo, cls);
|
return obj;
|
}
|
public static Map json2ObjMap(String jsonstr ) {
|
TypeReference<Map> type = new TypeReference<Map>() { };
|
Map obj = JSONObject.parseObject(jsonstr, type.getType());
|
// JSONObject jo = JSONObject.fromObject(jsonstr);
|
// T obj = (T) JSONObject.toBean(jo, cls);
|
return obj;
|
}
|
|
/**
|
* md5
|
*
|
* @param b
|
* @return
|
*/
|
public static String md5(byte[] b) {
|
try {
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
md.reset();
|
md.update(b);
|
byte[] hash = md.digest();
|
StringBuffer outStrBuf = new StringBuffer(32);
|
for (int i = 0; i < hash.length; i++) {
|
int v = hash[i] & 0xFF;
|
if (v < 16) {
|
outStrBuf.append('0');
|
}
|
outStrBuf.append(Integer.toString(v, 16).toLowerCase());
|
}
|
return outStrBuf.toString();
|
} catch (NoSuchAlgorithmException e) {
|
e.printStackTrace();
|
return new String(b);
|
}
|
}
|
|
/**
|
* 判断字符串是否为空
|
*
|
* @param s
|
* @return
|
*/
|
public static boolean isEmpty(String s) {
|
if (s == null || "".equals(s.trim()))
|
return true;
|
return false;
|
}
|
|
/**
|
* 生成随机码
|
*
|
* @param n
|
* @return
|
*/
|
public static String getValidatecode(int n) {
|
Random random = new Random();
|
String sRand = "";
|
n = n == 0 ? 4 : n;// default 4
|
for (int i = 0; i < n; i++) {
|
String rand = String.valueOf(random.nextInt(10));
|
sRand += rand;
|
}
|
return sRand;
|
}
|
|
|
|
public static boolean validSign(TreeMap<String, String> param,
|
String appkey, String signType) throws Exception {
|
if (param != null && !param.isEmpty()) {
|
if (!param.containsKey("sign"))
|
return false;
|
String sign = param.remove("sign");
|
if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序
|
param.put("key", appkey);
|
}
|
StringBuilder sb = new StringBuilder();
|
for (Map.Entry<String, String> entry : param.entrySet()) {
|
if (entry.getValue() != null && entry.getValue().length() > 0) {
|
sb.append(entry.getKey()).append("=")
|
.append(entry.getValue()).append("&");
|
}
|
}
|
if (sb.length() > 0) {
|
sb.deleteCharAt(sb.length() - 1);
|
}
|
if ("MD5".equals(signType)) {
|
return sign.toLowerCase().equals(
|
md5(sb.toString().getBytes("UTF-8")).toLowerCase());
|
} else if("SM2".equals(signType)){
|
PublicKey publicKey = SmUtil.pubKeySM2FromBase64Str(appkey);
|
return SmUtil.verifySM3SM2(publicKey, "Allinpay", Base64.decodeBase64(sign), sb.toString().getBytes("UTF-8"));
|
}else {
|
return rsaVerifyPublickey(sb.toString(), sign, appkey, "UTF-8");
|
}
|
}
|
return false;
|
}
|
|
public static boolean rsaVerifyPublickey(String content, String sign,
|
String publicKey, String charset) throws Exception {
|
try {
|
PublicKey pubKey = getPublicKeyFromX509("RSA",
|
Base64.decodeBase64(publicKey.getBytes()));
|
return rsaVerifyPublickey(content, sign, pubKey, charset);
|
} catch (Exception e) {
|
e.printStackTrace();
|
throw new Exception("RSAcontent = " + content + ",sign=" + sign
|
+ ",charset = " + charset, e);
|
}
|
}
|
|
public static boolean rsaVerifyPublickey(String content, String sign,
|
PublicKey pubKey, String charset) throws Exception {
|
try {
|
java.security.Signature signature = java.security.Signature
|
.getInstance("SHA1WithRSA");
|
|
signature.initVerify(pubKey);
|
|
if (charset == null || "".equals(charset)) {
|
signature.update(content.getBytes());
|
} else {
|
signature.update(content.getBytes(charset));
|
}
|
|
return signature.verify(Base64.decodeBase64(sign.getBytes()));
|
} catch (Exception e) {
|
throw e;
|
}
|
}
|
public static String unionSign(TreeMap<String, String> params,String appkey,
|
String signType) throws Exception {
|
// TODO Auto-generated method stub
|
|
params.remove("sign");
|
if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序
|
params.put("key", appkey);
|
}
|
StringBuilder sb = new StringBuilder();
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
if (entry.getValue() != null && entry.getValue().length() > 0) {
|
sb.append(entry.getKey()).append("=").append(entry.getValue())
|
.append("&");
|
}
|
}
|
if (sb.length() > 0) {
|
sb.deleteCharAt(sb.length() - 1);
|
}
|
String sign = "";
|
if ("MD5".equals(signType)) {
|
System.out.println(sb.toString());
|
sign = md5(sb.toString().getBytes("UTF-8"));// 记得是md5编码的加签
|
params.remove("key");
|
} else if("SM2".equals(signType)){
|
System.out.println(sb.toString());
|
PrivateKey privkey = SmUtil.privKeySM2FromBase64Str(appkey);
|
sign = SmUtil.signSM3SM2RetBase64(privkey, params.get("appid"), sb.toString().getBytes("UTF-8"));//签名
|
} else {
|
System.out.println(sb.toString());
|
sign = rsaSign(sb.toString(), appkey, "UTF-8");
|
}
|
return sign;
|
}
|
|
public static String rsaSign(String content, String privateKey,
|
String charset) throws Exception {
|
PrivateKey priKey = getPrivateKeyFromPKCS8("RSA",
|
Base64.decodeBase64(privateKey.getBytes()));
|
return rsaSign(content, priKey, charset);
|
}
|
|
public static String rsaSign(String content, byte[] privateKey,
|
String charset) throws Exception {
|
PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", privateKey);
|
return rsaSign(content, priKey, charset);
|
}
|
|
public static String rsaSign(String content, PrivateKey priKey,
|
String charset) throws Exception {
|
java.security.Signature signature = java.security.Signature
|
.getInstance("SHA1WithRSA");
|
signature.initSign(priKey);
|
if (charset == null || "".equals(charset)) {
|
signature.update(content.getBytes());
|
} else {
|
signature.update(content.getBytes(charset));
|
}
|
byte[] signed = signature.sign();
|
|
return new String(Base64.encodeBase64(signed));
|
}
|
|
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
|
byte[] encodedKey) throws Exception {
|
|
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
|
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
|
}
|
|
public static PublicKey getPublicKeyFromX509(String algorithm,
|
byte[] encodedKey) throws Exception {
|
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
|
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
|
}
|
public static String getPayInfoByStatus(PayOrderNotifyParam map) {
|
/**
|
* 0000:交易成功
|
* 1001:交易不存在
|
* 2008或者2000 : 交易处理中,请查询交易,如果是实时交易(例如刷卡支付,交易撤销,退货),建议每隔一段时间(10秒)查询交易
|
* 3开头的错误码代表交易失败
|
* 3888-流水号重复
|
* 3889-交易控制失败,具体原因看errmsg
|
* 3099-渠道商户错误
|
* 3014-交易金额小于应收手续费
|
* 3024-退款频率限制,建议30秒后再发起退款
|
* 3031-校验实名信息失败
|
* 3088-交易未支付(在查询时间区间内未成功支付,如已影响资金24小时内会做差错退款处理)
|
* 3089-撤销异常,如已影响资金24小时内会做差错退款处理
|
* 3045-其他错误,具体原因看errmsg
|
* 3050-交易已被撤销
|
* 3999-其他错误,具体原因看errmsg
|
* 3008-商户余额不足
|
*/
|
String info = "交易失败";
|
switch (map.getTrxstatus()){
|
case "0000":
|
info="交易成功";
|
break;
|
case "1001":
|
info="交易不存在";
|
break;
|
case "2008":
|
info="交易处理中,请查询交易,如果是实时交易(例如刷卡支付,交易撤销,退货),建议每隔一段时间(10秒)查询交易";
|
break;
|
case "2000":
|
info="交易处理中,请查询交易,如果是实时交易(例如刷卡支付,交易撤销,退货),建议每隔一段时间(10秒)查询交易";
|
break;
|
case "3888":
|
info="流水号重复";
|
break;
|
case "3889":
|
info="交易控制失败,具体原因看errmsg";
|
break;
|
case "3099":
|
info="渠道商户错误";
|
break;
|
case "3014":
|
info="退款频率限制,建议30秒后再发起退款";
|
break;
|
case "3024":
|
info="交易金额小于应收手续费";
|
break;
|
case "3031":
|
info="校验实名信息失败";
|
break;
|
case "3088":
|
info="交易未支付(在查询时间区间内未成功支付,如已影响资金24小时内会做差错退款处理)";
|
break;
|
case "3089":
|
info="撤销异常,如已影响资金24小时内会做差错退款处理";
|
break;
|
case "3045":
|
info="其他错误,具体原因看errmsg";
|
break;
|
case "3050":
|
info="交易已被撤销";
|
break;
|
case "3999":
|
info= "其他错误1,具体原因看errmsg";
|
break;
|
case "3008":
|
info="商户余额不足";
|
break;
|
default:
|
break;
|
}
|
|
return map.getTrxstatus() + info ;
|
}
|
public static String getPayTypeByCode(PayOrderNotifyParam map) {
|
/**
|
VSP501 微信支付
|
VSP502 微信支付撤销
|
VSP503 微信支付退款
|
VSP511 支付宝支付
|
VSP512 支付宝支付撤销
|
VSP513 支付宝支付退款
|
VSP551 银联扫码支付
|
VSP552 银联扫码撤销
|
VSP553 银联扫码退货
|
*/
|
String info = "交易失败";
|
switch (map.getTrxcode()){
|
case "VSP501":
|
info="微信支付";
|
break;
|
case "VSP502":
|
info="微信支付撤销";
|
break;
|
case "VSP511":
|
info="付宝支付";
|
break;
|
case "VSP512":
|
info="支付宝支付撤销";
|
break;
|
case "VSP513":
|
info="支付宝支付退款";
|
break;
|
case "VSP551":
|
info="银联扫码支付";
|
break;
|
case "VSP552":
|
info="银联扫码撤销";
|
break;
|
case "VSP553":
|
info="银联扫码退货";
|
break;
|
default:
|
break;
|
}
|
|
return info ;
|
}
|
|
}
|