引言:更多相关请看 Java其它
代码:
package com.lebaoxun.allinpay;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.lebaoxun.commons.utils.Date8Util;
import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import java.io.IOException;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* @Auther: Administrator
* @Date: 2020/1/16 10:46
* @Description: 通联支付工具类
*/
@Slf4j
public class AllInPayUtils {
// 当前类名
private static String currentClassName = Thread.currentThread().getStackTrace()[1].getClassName();
// 分配的系统编号
public static String sysid = "100000000002";
public static String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA18UsDXe3kEFk5bAV2NVmdpiTtc/ayoa8xeboL312fiOKhhP9YukApmSkZCyiVUhGSjcY8JHE6TUZgyTpUMlrtEGZmt593YuVjG81VB0GXFE9J0mzOjdkIzy+h8b0HNNZYuz1athm65aDVB8aOw3SIBPQxHK7j9X0VEwdr+dSLJlYxkimKrRBXEQUPxrt/MLhnSRXDJTN09g3zNaPhDqHAGP8GP59fQb6/QwN4UgDUhtpjEbgzbgbzZplVRkedsSM6781WlkXrjne0kJrPE0cfEAJDpohZOc/flnBa0To7JuWgEz/2o24ROjfdnFOY0+hByTzs4oZNkgY6cWJ+rQmUwIDAQAB";
public static String privateKey = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDXxSwNd7eQQWTlsBXY1WZ2mJO1z9rKhrzF5ugvfXZ+I4qGE/1i6QCmZKRkLKJVSEZKNxjwkcTpNRmDJOlQyWu0QZma3n3di5WMbzVUHQZcUT0nSbM6N2QjPL6HxvQc01li7PVq2GbrloNUHxo7DdIgE9DEcruP1fRUTB2v51IsmVjGSKYqtEFcRBQ/Gu38wuGdJFcMlM3T2DfM1o+EOocAY/wY/n19Bvr9DA3hSANSG2mMRuDNuBvNmmVVGR52xIzrvzVaWReuOd7SQms8TRx8QAkOmiFk5z9+WcFrROjsm5aATP/ajbhE6N92cU5jT6EHJPOzihk2SBjpxYn6tCZTAgMBAAECggEAP4EcEJCqGY5tnD5hh7JzGDeazblxuwbB23s03flOnRxnwkNy4aATHWXkjkkms/P0IBasQ+2bJ0oGCreb5beKeACQrWiLYd+Zsb3vU6TBQP12ArCpy9oOomJX701KfotjtP5p0rsDO5ZOa71FspjEPcWnPZJJCrHdWcwXNrTd1hr3jksV+XNz3ToAMgoW16wxMVVIJm/pP5PqBkqylBuUXGn7tfBSF3XDUipHfbLUQ5N55zOGF96Y9Fd1kuCIsZlTB3XdPNQze5hS3jwQSABYOUSHckWnYzzVKp4Ol9SGgONc2W5n1tkKRhoG1jqItQvlbyOjMgrBPvCjOJTklo7yOQKBgQDuaySeBgvuGqJQYJXirI1a9N6/ckZPuAmoKXr1RBagEuiKb4U//BSOongiMBeUVH214cgnjdB/aG8rog0UfZ7iBvAewqX4wdhZiFx8IdnDiJRaE9s+cLBSyOicv7wv9BGMV0gtN0mPNR4tld5vhAC4eOxCVva3tFAl1e11bZ30WQKBgQDnrnmIvJQHJRJu+SxNLfdqAk98n8s4zTNLn0l2Er9TeV29P3tS1cBX+2Usj2Msazbc36oL8ymfUN0Ufjqi9am3mRzTyNxOijj+nzgaCbMOtmjeXs9LogYXTL3YzR/UCK/DPI8HYMEi1BpXhFqVj/4RZm/tVgvlF4cDvOByNO0KiwKBgQCA8FruR1DeZXMQyxtkanNMFI/+s5uI83vtgPlpeXhO+8rdS3Ch6P9pID6eJqop4wPVgJTRp2Vx8hXlYA943HM3xA7KY/SEsrkBurhhvaDamZu5l3GDtEf3jYYXd64btQBkiLOVGIhktZJrjtisMJR/L45+Vi+5q/+IZsi0MCMziQKBgQCrwQv2U58F4PTWckDmgqI947KbuDbHSFCzykWClAlkz7+vkcVSNoaecw+hRjeGcYE9o06EB2Oe6SrMi3va3XZRVuApHWo9i3kPQmgr3W7yBEagO/c/ocEUOt8vP3pODZaHjXiXRqJHuKhCoysoX5RBwAhQEY9F6fg8zCQ0ZoooWwKBgQCOqp9sTBEWpd0cXdD5rORxuLJTvfM6xZEPjx71RGgamX2z4nWkVWhVcX7y+6z4E+Sp9lTmQlhmkqcTo/eKkuvjIcI6SWPqcyjoRdORaQLKN++x4NBx7wFfG/0gHAnLtpQHAZYaqlryQ6CzJwP8S42KSDyE/LEJXfVWAX5D4v15rw==";
public static Provider provider = new com.sun.security.sasl.Provider();
// 测试环境接口地址:http://116.228.64.55:6900/service/soa
public static String testInterfaceURL = "http://116.228.64.55:6900/service/soa";
// 测试环境网关地址:http://116.228.64.55:6900/yungateway/frontTrans.do
public static String testGatewayURL = "http://116.228.64.55:6900/yungateway/frontTrans.do";
// 测试环境门户地址:http://116.228.64.55:6901/portal
public static String testPortalURL = "http://116.228.64.55:6901/portal";
// 生产环境接口地址:https://fintech.allinpay.com/service/soa
public static String procInterfaceURL = "https://fintech.allinpay.com/service/soa";
// 生产环境网关地址:https://fintech.allinpay.com /yungateway/frontTrans.do
public static String procGatewayURL = "http://fintech.allinpay.com/yungateway/frontTrans.do";
// 生产环境门户地址:https://fintech.allinpay.com/portal
public static String procPortalURL = "https://fintech.allinpay.com/portal";
/**
* 签名
* 步骤 1:先对签名源串用 MD5 算法进行摘要计算;
* 步骤 2:对步骤 1 的返回数据进行 Base64 编码;
* 步骤 3:对步骤 2 的返回数据使用商户私钥进行 SHA1WithRSA 算法签名;
* 步骤 4:对步骤 3 的返回数据进行 Base64 编码。
*
* @param text 签名源串:sysid(系统编号) + req(服务请求的JSON对象) + timestamp(请求时间戳)
* @return
* @throws Exception
*/
public static String sign(String text) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
String encode = null;
try {
// Signature signature = Signature.getInstance("SHA1WithRSA", provider);
Signature signature = Signature.getInstance("SHA1WithRSA");
// 步骤1和2
text = md5(text);
signature.initSign(getPrivateKey());
// 步骤 3:对步骤2的返回数据使用商户私钥进行SHA1WithRSA算法签名; ==> Signature.getInstance("SHA1WithRSA")
signature.update(text.getBytes(Charset.forName("UTF-8")));
byte[] data = signature.sign();
// 步骤 4:对步骤 3 的返回数据进行 Base64 编码。
encode = new BASE64Encoder().encode(data);
} catch (Exception e) {
e.printStackTrace();
}
return encode;
}
/**
* MD5验签
*
* @param src
* @return
*/
public static String md5(String src) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
String result = "";
try {
// 步骤 1:先对签名源串用 MD5 算法进行摘要计算;
MessageDigest md = MessageDigest.getInstance("MD5");
// result = Base64.encode(md.digest(src.getBytes("utf-8")));
// 步骤 2:对步骤 1 的返回数据进行 Base64 编码;
result = new BASE64Encoder().encode(md.digest(src.getBytes("utf-8")));
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* 验签
* 步骤 1:先对签名源串用 MD5 算法进行摘要计算;
* 步骤 2:对步骤 1 的返回数据进行 Base64 编码;
* 步骤 3:对响应报文中的签名串 sign 进行 Base64 解码;
* 步骤 4:对步骤 2、3 的返回数据使用通联公钥进行 SHA1WithRSA 算法验签。
* 验签结果为 true 则说明验证签名成功,否则验证签名失败。
* 注:验签前需要 urldecode 解码,部分语言在获取参数时会自动解码,请注意。
*
* @param publicKey
* @param text
* @param sign
* @return
* @throws Exception
*/
public static boolean verify(PublicKey publicKey, String text, String sign) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
boolean flag = false;
try {
// Signature signature = Signature.getInstance("SHA1WithRSA", provider);
Signature signature = Signature.getInstance("SHA1WithRSA");
signature.initVerify(publicKey);
// 步骤1和2
text = md5(text);
signature.update(text.getBytes("UTF-8"));
// 步骤 3:对响应报文中的签名串 sign 进行 Base64 解码;
byte[] signed = new BASE64Decoder().decodeBuffer(sign);
// 步骤 4:对步骤 2、3 的返回数据使用通联公钥进行 SHA1WithRSA 算法验签。==> Signature.getInstance("SHA1WithRSA")
flag = signature.verify(signed);
} catch (Exception e) {
e.printStackTrace();
}
log.info("验证状态:{}", flag);
return flag;
}
/**
* JSON转字符串
*
* @param object
* @return
*/
public static String jsonToStr(Object object) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
return JSON.toJSONString(object);
}
/**
* 字符串转json
*
* @param str
* @return
*/
public static Map<String, Object> strToJson(String str) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
return JSON.parseObject(str, new TypeReference<TreeMap<String, Object>>() {});
// return JSON.parseObject(str, TreeMap.class);
}
/**
* 获取公钥对象
*
* @return
*/
public static PublicKey getPublicKey() {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
PublicKey publicKeyObj = null;
X509EncodedKeySpec keySpec = null;
try {
keySpec = new X509EncodedKeySpec(new BASE64Decoder().decodeBuffer(publicKey));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
publicKeyObj = keyFactory.generatePublic(keySpec);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return publicKeyObj;
}
/**
* 获取私钥对象
*
* @return
*/
public static PrivateKey getPrivateKey() {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
PrivateKey privateKeyObj = null;
PKCS8EncodedKeySpec priPKCS8 = null;
try {
priPKCS8 = new PKCS8EncodedKeySpec(new BASE64Decoder().decodeBuffer(privateKey));
KeyFactory keyf = KeyFactory.getInstance("RSA");
privateKeyObj = keyf.generatePrivate(priPKCS8);
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return privateKeyObj;
}
/**
* String 转换为publickey
*
* @param key
* @return
* @throws Exception
*/
public static PublicKey gettoPublicKey(String key) throws Exception {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
/**
* String转私钥PrivateKey
*
* @param key
* @return
* @throws Exception
*/
public static PrivateKey gettoPrivateKey(String key) throws Exception {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
byte[] keyBytes;
keyBytes = (new BASE64Decoder()).decodeBuffer(key);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
return privateKey;
}
// ==========================接口定义三连杀==============================
// 请求报文reqMsg --> 服务请求的JSON req --> 请求参数param
/**
* 初始化请求报文
*
* @return
*/
public static Map<String, Object> reqMsg(Map<String, Object> req) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
Map<String, Object> result = new HashMap<>();
String timestamp = Date8Util.datetimeFormat(new Date());
// 分配的系统编号
result.put("sysid", sysid);
// text签名源串:sysid(系统编号) + req(服务请求的JSON对象) + timestamp(请求时间戳)
// String text = AllInPayUtils.sysid + req + timestamp;
// req应该要从Map转为JSON字符串
String text = sysid + jsonToStr(req) + timestamp;
log.info("text签名源串:{}", text);
// 签名
String sign = sign(text);
// 验签
boolean verify = verify(getPublicKey(), text, sign);
if (verify == false) {
throw new RuntimeException("验签失败");
}
log.info("签名sign:{}", sign);
result.put("sign", sign);
// 请求时间戳 格式:yyyy-MM-ddHH:mm:ss
result.put("timestamp", timestamp);
// 接口版本(现为 2.0)
result.put("v", "2.0");
// 服务请求的 JSON 对象
result.put("req", req);
Map<String, Object> reqmap = (Map<String, Object>) result.get("req");
log.info("sysid:{},sign:{},timestamp:{},v:{},req:{},param:{}",
result.get("sysid"), result.get("sign"), result.get("timestamp"),
result.get("v"), result.get("req"), reqmap.get("param"));
log.info("result:{}", result);
return result;
}
/**
* 构建服务请求的 JSON req对象,参与签名
*
* @param service 服务对象
* @param method 调用方法
* @param param 请求参数
* @return
*/
public static Map<String, Object> req(String service, String method, Map<String, Object> param) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
// 服务请求的 JSON 对象,参与签名
Map<String, Object> req = new HashMap<>();
// 服务对象
req.put("service", service);
// 调用方法
req.put("method", method);
// 请求参数
req.put("param", param);
log.info("service:{},method:{},param:{}", service, method, param);
log.info("req:{}", req);
return req;
}
/**
* 请求参数,嵌套的 JSON 对象
*
* @param bizUserId 商户系统用户标识,商户系统中唯一编号。注意:1.不能输入“中文” 2.不要使用系统保留用户标识:#yunBizUserId_B2C#
* @return
*/
public static Map<String, Object> param(String bizUserId) {
log.info("当前类名:{}", currentClassName);
log.info("当前方法名称:{}", Thread.currentThread().getStackTrace()[1].getMethodName());
// 请求参数,嵌套的 JSON 对象
Map<String, Object> param = new HashMap<>();
// 商户系统用户标识,商户系统中唯一编号
param.put("bizUserId", bizUserId);
log.info("param:{}", param);
return param;
}
}