33333333333
This commit is contained in:
@@ -128,6 +128,7 @@ public enum TrdPayTypeEnum {
|
||||
* 支付宝 8 微信 4
|
||||
*/
|
||||
V11("http://bgxa.peiqi.zhifusg.com","/Pay_Index.html","/Pay_Trade_query.html","/api/pay/trd/notify/v11","OK"),
|
||||
V12("https://cashapi.sandpay.com.cn","/gateway/trade","/Pay_Trade_query.html","/api/pay/trd/notify/v11","OK"),
|
||||
|
||||
;
|
||||
private final String gatewayUrl;
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.ruoyi.cai.trdpay.handle;
|
||||
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.ruoyi.cai.domain.PayTrdConfig;
|
||||
import com.ruoyi.cai.pay.PayManager;
|
||||
import com.ruoyi.cai.pay.PayOrderInfoDTO;
|
||||
import com.ruoyi.cai.pay.PayReturnResp;
|
||||
import com.ruoyi.cai.service.OrderLogsService;
|
||||
import com.ruoyi.cai.trdpay.PayTrdService;
|
||||
import com.ruoyi.cai.trdpay.TrdPayTypeEnum;
|
||||
import com.ruoyi.cai.trdpay.dto.NotifyResp;
|
||||
import com.ruoyi.cai.trdpay.handle.v12.SandPayClient;
|
||||
import com.ruoyi.cai.trdpay.handle.v12.SandPayConfig;
|
||||
import com.ruoyi.cai.trdpay.handle.v12.SandpayConfigUtil;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.utils.ServletUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class PayTrdV12Service implements PayTrdService {
|
||||
|
||||
@Autowired
|
||||
private OrderLogsService orderLogsService;
|
||||
@Autowired
|
||||
private PayManager payManager;
|
||||
|
||||
private SandPayClient sandPayClient = null;
|
||||
|
||||
public synchronized void init(String accessMid){
|
||||
if(sandPayClient == null){
|
||||
// 初始化sandpay参数(全局设置一次)
|
||||
SandPayConfig config = new SandPayConfig();
|
||||
// 接入商户号
|
||||
config.setAccessMid(accessMid);
|
||||
// 加签 加密参数设置
|
||||
config.setEncryptType(SandpayConfigUtil.AES_STR);
|
||||
config.setPrivateKeyPath("D:\\mmm\\6888806128148.pfx");//存放目录:src\main\resources\cert\prod
|
||||
config.setPrivateKeyPassword("926645");
|
||||
config.setSandPublicKeyPath("D:\\mmm\\sand_pro.cer");//存放目录:src\main\resources\cert\prod
|
||||
// 请求版本号
|
||||
config.setVersion("4.0.0");
|
||||
sandPayClient = new SandPayClient(config);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TrdPayTypeEnum getType() {
|
||||
return TrdPayTypeEnum.V12;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayReturnResp createOrderAli(PayOrderInfoDTO payOrderInfoDTO, PayTrdConfig payTrdConfig,boolean wx) {
|
||||
init(payTrdConfig.getMchId());
|
||||
TrdPayTypeEnum type = getType();
|
||||
JSONObject bizData = new JSONObject();
|
||||
bizData.put("mid","6888806128148");
|
||||
bizData.put("outOrderNo",payOrderInfoDTO.getOrderNo());
|
||||
bizData.put("description","知予-"+payOrderInfoDTO.getSubject());
|
||||
bizData.put("goodsClass","99");
|
||||
bizData.put("amount", payOrderInfoDTO.getPrice());
|
||||
JSONArray payExtra = new JSONArray();
|
||||
if(wx){
|
||||
bizData.put("funcCodeList", new String[]{"02010005"});
|
||||
/**
|
||||
* subAppId : wxe78b5fdab7ddebbc
|
||||
* ghOriId : gh_40fd947b7d3f
|
||||
* pathUrl : pages/zf/index?
|
||||
* miniProgramType : 0
|
||||
*/
|
||||
JSONObject exPayExtra = new JSONObject();
|
||||
exPayExtra.put("funcCode","02010005");
|
||||
exPayExtra.put("subAppId","wxe78b5fdab7ddebbc");
|
||||
exPayExtra.put("ghOriId","gh_40fd947b7d3f");
|
||||
exPayExtra.put("pathUrl","pages/zf/index?");
|
||||
exPayExtra.put("miniProgramType","0");
|
||||
payExtra.add(exPayExtra);
|
||||
}else{
|
||||
bizData.put("funcCodeList", new String[]{"02020004"});
|
||||
}
|
||||
String notifyUrl = type.getNotifyUrl(payTrdConfig.getNotifyUrl(), wx);
|
||||
JSONObject payerInfo = new JSONObject();
|
||||
payerInfo.put("frontUrl", notifyUrl);
|
||||
payerInfo.put("payExtra",payExtra);
|
||||
bizData.put("payerInfo",payerInfo);
|
||||
bizData.put("notifyUrl", notifyUrl);
|
||||
JSONObject reqReserved = new JSONObject();
|
||||
reqReserved.put("sourceIp", ServletUtils.getClientIP());
|
||||
bizData.put("sdCashierType", "SDK");
|
||||
bizData.put("metaOption", "[{\"s\":\"Android\",\"n\":\"\",\"id\":\"\",\"sc\":\"\"},{\"s\":\"IOS\",\"n\":\"\",\"id\":\"\",\"sc\":\"\"}]");
|
||||
bizData.put("reqReserved",reqReserved);
|
||||
|
||||
String gatewayUrl = getGatewayUrl(payTrdConfig);
|
||||
String createOrderUrl = gatewayUrl + type.getCreateOrderUrl();
|
||||
JSONObject responseJson = sandPayClient.execute(createOrderUrl, bizData);
|
||||
if(responseJson == null || !"accept".equals(responseJson.getString("resultStatus"))){
|
||||
orderLogsService.createAliPayLogs(payOrderInfoDTO.getOrderNo(), createOrderUrl+JSON.toJSONString(responseJson), com.alibaba.fastjson2.JSONObject.from(responseJson), false, type, getStepName(wx));
|
||||
log.info("第三方支付失败 V12 统一支付失败失败 url={} params={} body={}, payTrdConfig={}", createOrderUrl, JSON.toJSONString(bizData), JSON.toJSONString(responseJson), JSON.toJSONString(payTrdConfig));
|
||||
throw new ServiceException("调用支付失败");
|
||||
}else{
|
||||
orderLogsService.createAliPayLogs(payOrderInfoDTO.getOrderNo(), createOrderUrl+JSON.toJSONString(responseJson), com.alibaba.fastjson2.JSONObject.from(responseJson), true, type, getStepName(wx));
|
||||
}
|
||||
return PayReturnResp.createH5(responseJson.getString("cashierUrl"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public NotifyResp getNotifyResp(Map<String, String> sourceData) {
|
||||
String mchOrderNo = sourceData.get("orderid");
|
||||
String payOrderId = sourceData.get("transaction_id");
|
||||
String status = sourceData.get("returncode");
|
||||
NotifyResp resp = new NotifyResp();
|
||||
resp.setOrderNo(mchOrderNo);
|
||||
resp.setTrdOrderNo(payOrderId);
|
||||
resp.setPayTypeEnum(getType());
|
||||
resp.setSourceData(sourceData);
|
||||
resp.setSuccess("00".equals(status));
|
||||
return resp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.alibaba.fastjson2.JSONObject queryOrder(String orderNo, PayTrdConfig payTrdConfig) {
|
||||
throw new RuntimeException("暂时不支持订单查询");
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.alibaba.fastjson2.JSONObject resetOrder(String orderNo, PayTrdConfig payTrdConfig, boolean updateData) {
|
||||
throw new RuntimeException("暂时不支持订单充值");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public class PayTrdV7Service implements PayTrdService {
|
||||
boolean success = checkSuccess(jsonObject);
|
||||
orderLogsService.createAliPayLogs(payOrderInfoDTO.getOrderNo(), createOrderUrl+JSON.toJSONString(map), jsonObject, success, type, getStepName(wx));
|
||||
if(!success){
|
||||
log.info("第三方支付失败 V7 统一支付失败失败 url={} params={} body={}, payTrdConfig={}, typeEnum={}", createOrderUrl,JSON.toJSONString(map), body, JSON.toJSONString(payTrdConfig), JSON.toJSONString(jsonObject));
|
||||
log.info("第三方支付失败 V7 统一支付失败失败 url={} params={} body={}, payTrdConfig={}", createOrderUrl,JSON.toJSONString(map), body, JSON.toJSONString(payTrdConfig));
|
||||
throw new ServiceException("调用支付失败");
|
||||
}
|
||||
String payUrl = jsonObject.getJSONObject("data").getString("payUrl");
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
|
||||
public class AESUtils {
|
||||
private static final String KEY_ALGORITHM = "AES";
|
||||
private static final String CIPHER_ALGORITHM = "AES/ECB/PKCS5Padding";
|
||||
|
||||
public AESUtils() {
|
||||
}
|
||||
|
||||
public static byte[] encrypt(byte[] plainBytes, byte[] keyBytes, String IV) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
||||
SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
|
||||
if (StringUtils.isNotBlank(IV)) {
|
||||
IvParameterSpec ips = new IvParameterSpec(IV.getBytes());
|
||||
cipher.init(1, secretKey, ips);
|
||||
} else {
|
||||
cipher.init(1, secretKey);
|
||||
}
|
||||
|
||||
return cipher.doFinal(plainBytes);
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] encryptedBytes, byte[] keyBytes, String IV) throws Exception {
|
||||
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
|
||||
SecretKey secretKey = new SecretKeySpec(keyBytes, "AES");
|
||||
if (StringUtils.isNotBlank(IV)) {
|
||||
IvParameterSpec ips = new IvParameterSpec(IV.getBytes());
|
||||
cipher.init(2, secretKey, ips);
|
||||
} else {
|
||||
cipher.init(2, secretKey);
|
||||
}
|
||||
|
||||
return cipher.doFinal(encryptedBytes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class FileUtils {
|
||||
|
||||
public static final Logger logger = LoggerFactory.getLogger(FileUtils.class);
|
||||
|
||||
public FileUtils() {
|
||||
}
|
||||
|
||||
public static InputStream loadFile(String fileName) {
|
||||
if (StringUtils.isNotBlank(fileName)) {
|
||||
return loadFromAbsoluteFile(fileName);
|
||||
// return absolutePathStart(fileName) ? loadFromAbsoluteFile(fileName) : loadFromClasspathFile(fileName);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream loadFromAbsoluteFile(String fileName) {
|
||||
try {
|
||||
File f = new File(fileName);
|
||||
return !f.exists() ? null : new FileInputStream(f);
|
||||
} catch (Throwable var3) {
|
||||
logger.warn("load file[" + fileName + "] fail", var3);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean absolutePathStart(String path) {
|
||||
File[] files = File.listRoots();
|
||||
File[] var2 = files;
|
||||
int var3 = files.length;
|
||||
|
||||
for(int var4 = 0; var4 < var3; ++var4) {
|
||||
File file = var2[var4];
|
||||
if (path.startsWith(file.getPath())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static InputStream loadFromClasspathFile(String fileName) {
|
||||
try {
|
||||
// return ClassLoader.getSystemResourceAsStream(fileName);
|
||||
return FileUtils.class.getClassLoader().getResourceAsStream(fileName);
|
||||
} catch (Throwable var2) {
|
||||
logger.warn("load file[" + fileName + "] fail", var2);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static InputStream loadFromRelativeFile(String fileName) {
|
||||
String userDir = System.getProperty("user.dir");
|
||||
String realFilePath = addSeparator(userDir) + fileName;
|
||||
return loadFromAbsoluteFile(realFilePath);
|
||||
}
|
||||
|
||||
private static String addSeparator(String dir) {
|
||||
if (!dir.endsWith(File.separator)) {
|
||||
dir = dir + File.separator;
|
||||
}
|
||||
|
||||
return dir;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
|
||||
public class HttpClientUtils {
|
||||
public static final Logger logger = LoggerFactory.getLogger(HttpClientUtils.class);
|
||||
|
||||
public HttpClientUtils() {
|
||||
}
|
||||
|
||||
public static String sendPost(String url, String param, int connectTimeout, int readTimeout) {
|
||||
PrintWriter out = null;
|
||||
BufferedReader in = null;
|
||||
|
||||
try {
|
||||
URL realUrl = new URL(url);
|
||||
URLConnection conn = realUrl.openConnection();
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("accept", "*/*");
|
||||
conn.setRequestProperty("connection", "Keep-Alive");
|
||||
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
|
||||
conn.setDoOutput(true);
|
||||
conn.setDoInput(true);
|
||||
conn.setConnectTimeout(connectTimeout);
|
||||
conn.setReadTimeout(readTimeout);
|
||||
out = new PrintWriter(conn.getOutputStream());
|
||||
out.print(param);
|
||||
out.flush();
|
||||
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line = null;
|
||||
|
||||
while((line = in.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
|
||||
String var10 = sb.toString();
|
||||
return var10;
|
||||
} catch (Exception var19) {
|
||||
throw new SandPayException("请求服务器失败,url:" + url + " err:" + var19.getMessage(), var19);
|
||||
} finally {
|
||||
try {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
} catch (IOException var18) {
|
||||
logger.error("发送POST方法的请求,关闭流异常:", var18);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.Base64;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RSAUtils {
|
||||
|
||||
private static final String ALGORITHM = "RSA/ECB/PKCS1Padding";
|
||||
private static final int KEY_LENGTH = 2048;
|
||||
private static final int RESERVE_SIZE = 11;
|
||||
|
||||
public RSAUtils() {
|
||||
}
|
||||
|
||||
public static String encryptToBase64Text(String plainTextBytes, PublicKey publicKey) throws Exception {
|
||||
byte[] aesKeyBytes = plainTextBytes.getBytes();
|
||||
byte[] encryptKeyBytes = encrypt(aesKeyBytes, publicKey);
|
||||
return Base64.getEncoder().encodeToString(encryptKeyBytes);
|
||||
}
|
||||
|
||||
public static String decryptBase64ToText(String encText, PrivateKey privateKey) throws Exception {
|
||||
byte[] encTextBytes = Base64.getDecoder().decode(encText);
|
||||
byte[] contentBytes = decrypt(encTextBytes, privateKey);
|
||||
String decryptText = new String(contentBytes, StandardCharsets.UTF_8);
|
||||
return decryptText;
|
||||
}
|
||||
|
||||
public static byte[] encrypt(byte[] plainTextBytes, PublicKey publicKey) throws Exception {
|
||||
boolean keyByteSize = true;
|
||||
boolean encryptBlockSize = true;
|
||||
int nBlock = plainTextBytes.length / 245;
|
||||
if (plainTextBytes.length % 245 != 0) {
|
||||
++nBlock;
|
||||
}
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(1, publicKey);
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(nBlock * 256);
|
||||
|
||||
for(int offset = 0; offset < plainTextBytes.length; offset += 245) {
|
||||
int inputLen = plainTextBytes.length - offset;
|
||||
if (inputLen > 245) {
|
||||
inputLen = 245;
|
||||
}
|
||||
|
||||
byte[] decryptedBlock = cipher.doFinal(plainTextBytes, offset, inputLen);
|
||||
byteArrayOutputStream.write(decryptedBlock);
|
||||
}
|
||||
|
||||
byteArrayOutputStream.flush();
|
||||
byteArrayOutputStream.close();
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
public static byte[] decrypt(byte[] cipherTextBytes, PrivateKey privateKey) throws Exception {
|
||||
boolean keyByteSize = true;
|
||||
boolean decryptBlockSize = true;
|
||||
int nBlock = cipherTextBytes.length / 256;
|
||||
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
|
||||
cipher.init(2, privateKey);
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(nBlock * 245);
|
||||
|
||||
for(int offset = 0; offset < cipherTextBytes.length; offset += 256) {
|
||||
int inputLen = cipherTextBytes.length - offset;
|
||||
if (inputLen > 256) {
|
||||
inputLen = 256;
|
||||
}
|
||||
|
||||
byte[] decryptedBlock = cipher.doFinal(cipherTextBytes, offset, inputLen);
|
||||
byteArrayOutputStream.write(decryptedBlock);
|
||||
}
|
||||
|
||||
byteArrayOutputStream.flush();
|
||||
byteArrayOutputStream.close();
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
}
|
||||
|
||||
public static String generateSign(String content, PrivateKey privateKey, String signType, String charset) throws Exception {
|
||||
Signature signature = null;
|
||||
if (!"RSA".equals(signType) && !"SHA256WithRSA".equals(signType)) {
|
||||
throw new SandPayException("不是支持的签名类型 : signType=" + signType);
|
||||
} else {
|
||||
signature = Signature.getInstance("SHA256WithRSA");
|
||||
signature.initSign(privateKey);
|
||||
if (StringUtils.isBlank(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
return Base64.getEncoder().encodeToString(signed);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @Description: 验签
|
||||
* @param content 响应报文bizData
|
||||
* @param sign 响应报文中的sign
|
||||
* @param signType 响应报文中的signType
|
||||
* @param publicKey 杉德公钥
|
||||
* @param charset 编码格式
|
||||
* @return: boolean
|
||||
*/
|
||||
public static boolean verifySign(String content, String sign, String signType, PublicKey publicKey, String charset) throws Exception {
|
||||
Signature signature = Signature.getInstance(signType);
|
||||
signature.initVerify(publicKey);
|
||||
if (StringUtils.isBlank(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
return signature.verify(Base64.getDecoder().decode(sign.getBytes()));
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKeyByStr(String publicKeyStr) throws Exception {
|
||||
return loadPublicKey(new ByteArrayInputStream(publicKeyStr.getBytes()));
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKeyByStr(String priKeyStr) throws Exception {
|
||||
return loadPrivateKey(new ByteArrayInputStream(priKeyStr.getBytes()), (String)null);
|
||||
}
|
||||
|
||||
public static PrivateKey loadPrivateKey(InputStream ins, String password) throws Exception {
|
||||
KeyStore ks = KeyStore.getInstance("PKCS12");
|
||||
char[] nPassword;
|
||||
if (password != null && !password.trim().equals("")) {
|
||||
nPassword = password.toCharArray();
|
||||
} else {
|
||||
nPassword = null;
|
||||
}
|
||||
|
||||
ks.load(ins, nPassword);
|
||||
Enumeration<String> enumas = ks.aliases();
|
||||
String keyAlias = null;
|
||||
if (enumas.hasMoreElements()) {
|
||||
keyAlias = (String)enumas.nextElement();
|
||||
}
|
||||
|
||||
return (PrivateKey)ks.getKey(keyAlias, nPassword);
|
||||
}
|
||||
|
||||
|
||||
public static PublicKey getSandPublicKey(String sandPublicKeyPath) throws Exception {
|
||||
InputStream publicIns = FileUtils.loadFile(sandPublicKeyPath);
|
||||
if (Objects.isNull(publicIns)) {
|
||||
throw new SandPayException("获取公钥失败");
|
||||
} else {
|
||||
return RSAUtils.loadPublicKey(publicIns);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static PublicKey loadPublicKey(InputStream ins) throws Exception {
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509");
|
||||
X509Certificate oCert = (X509Certificate)cf.generateCertificate(ins);
|
||||
PublicKey publicKey = oCert.getPublicKey();
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
|
||||
public class RandomV12Util {
|
||||
|
||||
public static String genRandomString(int length) {
|
||||
return RandomUtil.randomString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,305 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @ClassName : SandPayClient
|
||||
* @Description : 加密、签名、验签
|
||||
**/
|
||||
@Slf4j
|
||||
public class SandPayClient {
|
||||
|
||||
private SandpayConfigUtil sandpayConfigUtil = new SandpayConfigUtil();
|
||||
|
||||
public SandPayClient() {
|
||||
}
|
||||
|
||||
public SandPayClient(SandPayConfig sandPayConfig) {
|
||||
if (sandPayConfig != null) {
|
||||
try {
|
||||
this.sandpayConfigUtil.setBaseUrl(sandPayConfig.getBaseUrl());
|
||||
this.sandpayConfigUtil.setAccessMid(sandPayConfig.getAccessMid());
|
||||
this.sandpayConfigUtil.setMid(sandPayConfig.getMid());
|
||||
this.sandpayConfigUtil.setPlMid(sandPayConfig.getPlMid());
|
||||
this.sandpayConfigUtil.setVersion(sandPayConfig.getVersion());
|
||||
// this.sandpayConfigUtil.setCertNo(sandPayConfig.getCertNo());//预留
|
||||
String privateKeyPath = sandPayConfig.getPrivateKeyPath();
|
||||
String sandPublicKeyPath = sandPayConfig.getSandPublicKeyPath();
|
||||
if (!StringUtils.isBlank(privateKeyPath) || !StringUtils.isBlank(sandPublicKeyPath)) {
|
||||
this.sandpayConfigUtil.setPrivateKey(this.sandpayConfigUtil.getPrivateKey(sandPayConfig.getPrivateKeyPath(), sandPayConfig.getPrivateKeyPassword()));
|
||||
this.sandpayConfigUtil.setSandPublicKey(this.sandpayConfigUtil.getSandPublicKey(sandPayConfig.getSandPublicKeyPath()));
|
||||
this.sandpayConfigUtil.setEncryptType(sandPayConfig.getEncryptType());
|
||||
this.sandpayConfigUtil.setSignType(sandPayConfig.getSignType());
|
||||
Integer connectTimeout = sandPayConfig.getConnectTimeout();
|
||||
if (Objects.nonNull(connectTimeout)) {
|
||||
this.sandpayConfigUtil.setConnectTimeout(connectTimeout);
|
||||
}
|
||||
Integer readTimeout = sandPayConfig.getReadTimeout();
|
||||
if (Objects.nonNull(readTimeout)) {
|
||||
this.sandpayConfigUtil.setReadTimeout(readTimeout);
|
||||
}
|
||||
}
|
||||
} catch (Exception var6) {
|
||||
log.error(var6.getMessage());
|
||||
throw new SandPayException("初始化SandPayClient异常", var6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public JSONObject execute(String url, JSONObject bizData) {
|
||||
return (JSONObject) this.requestCoreReturnObject(url, bizData, JSONObject.class);
|
||||
}
|
||||
|
||||
public JSONObject execute(String url, JSONObject bizData, String encryptType) {
|
||||
return (JSONObject) this.requestCoreReturnObject(url, bizData, JSONObject.class, encryptType);
|
||||
}
|
||||
|
||||
private <T> T requestCoreReturnObject(String url, Object bizRequest, Class<T> returnClass, String encryptType) {
|
||||
String bizRequestJson = JSON.toJSONString(bizRequest);
|
||||
JSONObject sandPayCommonRequest = this.buildRequest(bizRequestJson, encryptType);
|
||||
log.info("请求Sand报文:{}", sandPayCommonRequest);
|
||||
String responseStr = HttpClientUtils.sendPost(url, JSON.toJSONString(sandPayCommonRequest), this.sandpayConfigUtil.getConnectTimeout(), this.sandpayConfigUtil.getReadTimeout());
|
||||
log.info("Sand返回报文:{}", responseStr);
|
||||
return this.handleResponse(responseStr, returnClass, encryptType);
|
||||
}
|
||||
|
||||
private <T> T requestCoreReturnObject(String url, Object bizRequest, Class<T> returnClass) throws SandPayException {
|
||||
String encryptType = this.sandpayConfigUtil.getEncryptType();
|
||||
return this.requestCoreReturnObject(url, bizRequest, returnClass, encryptType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 加密、签名接口请求报文并组装公共请求报文
|
||||
* @param content 接口请求报文明文
|
||||
* @param encryptType 加密方式
|
||||
* @return: JSONObject 公共请求报文
|
||||
*/
|
||||
public JSONObject buildRequest(String content, String encryptType) throws SandPayException {
|
||||
String signType = "RSA";
|
||||
String encryptKey;
|
||||
String bizData;
|
||||
String sign;
|
||||
if (StringUtils.isBlank(content)) {
|
||||
throw new SandPayException("签名内容为空 : content=" + content);
|
||||
} else if (!"AES".equals(encryptType)) {
|
||||
throw new SandPayException("不是支持的加密类型 : encryptType=" + encryptType);
|
||||
} else {
|
||||
//1.生成一个16位的随机字符串aesKey,该字符串仅包含大小写字母及数字。
|
||||
String aesKey = RandomV12Util.genRandomString(16);
|
||||
//2.将随机字符串转为byte数组aesKeyBytes,编码格式为UTF_8。
|
||||
//3.将请求报文中明文bizData域转为byte数组,编码格式为UTF_8,并用aesKeyBytes用AES算法(AES/ECB/PKCS5Padding)对其加密,并对结果进行base64转码,得到加密报文体bizData。
|
||||
bizData = this.aesEncrypt(content, aesKey);
|
||||
//4.将随机字符串byte数组aesKeyBytes使用杉德公钥进行RSA算法(RSA/ECB/PKCS1Padding)加密,并将结果进行base64转码即得到encryptKey。
|
||||
encryptKey = rsaEncrypt(aesKey, this.sandpayConfigUtil.getSandPublicKey());
|
||||
//5.将加密报文体使用商户私钥进行RSA算法(SHA256WithRSA)签名,得到sign。
|
||||
sign = this.generateSign(bizData, signType, this.sandpayConfigUtil.getPrivateKey());
|
||||
|
||||
}
|
||||
|
||||
//6.组装公共请求报文并返回
|
||||
JSONObject commonRequest = new JSONObject();
|
||||
commonRequest.put("accessMid", this.sandpayConfigUtil.getAccessMid());
|
||||
commonRequest.put("encryptType", encryptType);
|
||||
commonRequest.put("encryptKey", encryptKey);
|
||||
// commonRequest.put("certNo", this.sandpayConfigUtil.getCertNo());//预留
|
||||
commonRequest.put("version", this.sandpayConfigUtil.getVersion());
|
||||
commonRequest.put("timestamp", this.getTimestamp());
|
||||
commonRequest.put("signType", signType);
|
||||
commonRequest.put("sign", sign);
|
||||
commonRequest.put("bizData", bizData);
|
||||
return commonRequest;
|
||||
}
|
||||
|
||||
//解析响应报文
|
||||
public JSONObject parseResponse(String content, String encryptType) throws SandPayException {
|
||||
return (JSONObject) this.handleResponse(content, JSONObject.class, encryptType);
|
||||
}
|
||||
|
||||
//验签回调
|
||||
public boolean verifySign(String data, String sign, String signType, String charset) throws SandPayException {
|
||||
try {
|
||||
return RSAUtils.verifySign(data, sign, signType, this.sandpayConfigUtil.getSandPublicKey(), charset);
|
||||
} catch (Exception var6) {
|
||||
throw new SandPayException("验证回调签名异常", var6);
|
||||
}
|
||||
}
|
||||
|
||||
//处理响应报文
|
||||
private <T> T handleResponse(String responseStr, Class<T> returnClass, String encryptType) throws SandPayException {
|
||||
JSONObject commonResponse = (JSONObject) JSON.parseObject(responseStr, JSONObject.class);
|
||||
String respCode = (String) commonResponse.get("respCode");
|
||||
if (respCode == null) {
|
||||
throw new SandPayException("处理返回报文失败,原始报文" + responseStr);
|
||||
} else {
|
||||
String bizData;
|
||||
if (!"success".equals(respCode)) {
|
||||
bizData = (String) commonResponse.get("respDesc");
|
||||
throw new SandPayException(respCode, bizData, responseStr);
|
||||
} else {
|
||||
bizData = commonResponse.get("bizData").toString();
|
||||
String sign = (String) commonResponse.get("sign");
|
||||
String signType = (String) commonResponse.get("signType");
|
||||
this.verifySign(bizData, sign, signType, this.sandpayConfigUtil.getSandPublicKey());
|
||||
if (!"AES".equals(encryptType)) {
|
||||
throw new SandPayException("不是支持的加密类型: encryptType=" + encryptType);
|
||||
} else {
|
||||
String encryptKey = (String) commonResponse.get("encryptKey");
|
||||
String respAesKey = this.rsaDecrypt(encryptKey, this.sandpayConfigUtil.getPrivateKey());
|
||||
bizData = this.aesDecrypt(bizData, respAesKey);
|
||||
|
||||
if (returnClass == String.class) {
|
||||
return (T) bizData;
|
||||
} else {
|
||||
try {
|
||||
return JSON.parseObject(bizData, returnClass);
|
||||
} catch (Exception var11) {
|
||||
throw new SandPayException("解析报文失败," + responseStr, var11);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//AES加密
|
||||
private String aesEncrypt(String content, String aesKey) {
|
||||
byte[] aesKeyBytes = aesKey.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
try {
|
||||
byte[] encryptValueBytes = AESUtils.encrypt(content.getBytes(StandardCharsets.UTF_8), aesKeyBytes, (String) null);
|
||||
return Base64.getEncoder().encodeToString(encryptValueBytes);
|
||||
} catch (Exception var5) {
|
||||
throw new SandPayException("AES加密异常", var5);
|
||||
}
|
||||
}
|
||||
|
||||
//RSA加密
|
||||
public static String rsaEncrypt(String content, PublicKey publicKey) {
|
||||
try {
|
||||
byte[] aesKeyBytes = content.getBytes();
|
||||
byte[] encryptKeyBytes = RSAUtils.encrypt(aesKeyBytes, publicKey);
|
||||
return Base64.getEncoder().encodeToString(encryptKeyBytes);
|
||||
} catch (Exception var4) {
|
||||
throw new SandPayException("RSA加密异常", var4);
|
||||
}
|
||||
}
|
||||
|
||||
//RSA解密响应参数
|
||||
private String rsaDecrypt(String content, PrivateKey privateKey) {
|
||||
byte[] decryptKeyBytes = Base64.getDecoder().decode(content);
|
||||
|
||||
try {
|
||||
byte[] contentBytes = RSAUtils.decrypt(decryptKeyBytes, privateKey);
|
||||
String decryptKey = new String(contentBytes, StandardCharsets.UTF_8);
|
||||
return decryptKey;
|
||||
} catch (Exception var6) {
|
||||
throw new SandPayException("RSA解密随机加密串失败", var6);
|
||||
}
|
||||
}
|
||||
|
||||
//AES解密响应参数
|
||||
private String aesDecrypt(String content, String aesKey) {
|
||||
byte[] decryptDataBase64 = Base64.getDecoder().decode(content);
|
||||
|
||||
try {
|
||||
byte[] decryptDataBytes = AESUtils.decrypt(decryptDataBase64, aesKey.getBytes(StandardCharsets.UTF_8), (String) null);
|
||||
String decryptData = new String(decryptDataBytes);
|
||||
return decryptData;
|
||||
} catch (Exception var6) {
|
||||
throw new SandPayException("AES解密返回参数失败", var6);
|
||||
}
|
||||
}
|
||||
|
||||
//签名
|
||||
public String generateSign(String content, String signType, PrivateKey privateKey) {
|
||||
try {
|
||||
if ("RSA".equals(signType)) {
|
||||
signType = "SHA256WithRSA";
|
||||
}
|
||||
|
||||
return RSAUtils.generateSign(content, privateKey, signType, "UTF-8");
|
||||
} catch (Exception var5) {
|
||||
throw new SandPayException("请求签名异常", var5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description: 验签响应报文
|
||||
* @param content 响应报文中的bizData
|
||||
* @param sign 响应报文中的sign
|
||||
* @param signType 响应报文中的signType
|
||||
* @param publicKey 杉德公钥
|
||||
* @return: boolean 验签结果
|
||||
*/
|
||||
private boolean verifySign(String content, String sign, String signType, PublicKey publicKey) {
|
||||
try {
|
||||
if ("RSA".equals(signType)) {
|
||||
signType = "SHA256WithRSA";
|
||||
}
|
||||
return RSAUtils.verifySign(content, sign, signType, publicKey, "UTF-8");
|
||||
} catch (Exception var6) {
|
||||
throw new SandPayException("验证响应报文签名异常", var6);
|
||||
}
|
||||
}
|
||||
|
||||
//生成时间戳 yyyy-MM-dd HH:mm:ss
|
||||
private String getTimestamp() {
|
||||
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
||||
return df.format(new Date(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
//请求时间 yyyyMMddHHmmss
|
||||
public String getCurrentTime() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
||||
return sdf.format(new Date());
|
||||
}
|
||||
|
||||
//获取当前时间*小时后的时间 yyyyMMddHHmmss
|
||||
public String getTimeOutTime(int hour) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.add(Calendar.HOUR, hour);
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
||||
return sdf.format(calendar.getTime());
|
||||
}
|
||||
|
||||
//生成订单号
|
||||
public String getOutOrderNo() {
|
||||
return this.getOutOrderNo("", 25);
|
||||
}
|
||||
|
||||
public String getOutOrderNo(String prefix, int length) {
|
||||
if (prefix == null) {
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
if (length < 25) {
|
||||
length = 25;
|
||||
}
|
||||
|
||||
DateFormat df = new SimpleDateFormat("yyyyMMddHHmmsss");
|
||||
df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
|
||||
String currentTime = df.format(new Date(System.currentTimeMillis()));
|
||||
String outOrderNo = prefix.concat(currentTime);
|
||||
int randomLen = length - outOrderNo.length();
|
||||
outOrderNo = prefix.concat(currentTime).concat(RandomV12Util.genRandomString(randomLen));
|
||||
return outOrderNo;
|
||||
}
|
||||
|
||||
public SandpayConfigUtil getSandpayConfigUtil() {
|
||||
return this.sandpayConfigUtil;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
|
||||
@Data
|
||||
public class SandPayConfig {
|
||||
private String baseUrl;
|
||||
private String version = "4.0.0";
|
||||
private String accessMid;
|
||||
private String plMid;
|
||||
private String mid;
|
||||
private PrivateKey privateKey;
|
||||
private String privateKeyPassword;
|
||||
private String privateKeyPath;
|
||||
private String certNo;
|
||||
private PublicKey sandPublicKey;
|
||||
private String sandPublicKeyPath;
|
||||
private String signType = "RSA";
|
||||
private String encryptType = "AES";
|
||||
private int connectTimeout = 5000;
|
||||
private int readTimeout = 5000;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
|
||||
|
||||
public class SandPayException extends RuntimeException {
|
||||
private String respCode;
|
||||
private String respDesc;
|
||||
private String responseMsg;
|
||||
|
||||
public SandPayException() {
|
||||
}
|
||||
|
||||
public SandPayException(String message) {
|
||||
super(message);
|
||||
this.respDesc = message;
|
||||
}
|
||||
|
||||
public SandPayException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.respDesc = message;
|
||||
}
|
||||
|
||||
public SandPayException(String respCode, String respDesc, String responseMsg) {
|
||||
super(respCode + ":" + respDesc);
|
||||
this.respCode = respCode;
|
||||
this.respDesc = respDesc;
|
||||
this.responseMsg = responseMsg;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.toJSON().toString();
|
||||
}
|
||||
|
||||
public JSONObject toJSON() {
|
||||
JSONObject sandResp = new JSONObject();
|
||||
sandResp.put("respCode", this.getRespCode());
|
||||
sandResp.put("respDesc", this.getRespDesc());
|
||||
if (this.getResponseMsg() != null && this.getResponseMsg().length() > 0) {
|
||||
JSONObject responseMsg = (JSONObject) JSON.parseObject(this.getResponseMsg(), JSONObject.class);
|
||||
sandResp.put("responseMsg", responseMsg);
|
||||
}
|
||||
|
||||
return sandResp;
|
||||
}
|
||||
|
||||
public String getRespCode() {
|
||||
return this.respCode;
|
||||
}
|
||||
|
||||
public String getRespDesc() {
|
||||
return this.respDesc;
|
||||
}
|
||||
|
||||
public String getResponseMsg() {
|
||||
return this.responseMsg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package com.ruoyi.cai.trdpay.handle.v12;
|
||||
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SandpayConfigUtil {
|
||||
public static final Logger logger = LoggerFactory.getLogger(SandpayConfigUtil.class);
|
||||
private String baseUrl;
|
||||
private String version;
|
||||
private String accessMid;
|
||||
private String plMid;
|
||||
private String mid;
|
||||
private PrivateKey privateKey;
|
||||
private String certNo;
|
||||
private PublicKey sandPublicKey;
|
||||
private String signType = "SHA256WithRSA";
|
||||
private String encryptType = "AES";
|
||||
private int connectTimeout = 10000;
|
||||
private int readTimeout = 10000;
|
||||
public static final String CHARSET = "UTF-8";
|
||||
public static final String AES_STR = "AES";
|
||||
public static final String RSA_STR = "RSA";
|
||||
public static final String SHA_256_WITH_RSA = "SHA256WithRSA";
|
||||
public static final String SUCCESS_STR = "success";
|
||||
public static final String RESP_CODE_STR = "respCode";
|
||||
public static final String RESP_DESC_STR = "respDesc";
|
||||
public static final String BIZ_DATA_STR = "bizData";
|
||||
public static final String SIGN_STR = "sign";
|
||||
public static final String SIGN_TYPE_STR = "signType";
|
||||
public static final String ENCRYPT_TYPE_STR = "encryptType";
|
||||
public static final String ENCRYPT_KEY_STR = "encryptKey";
|
||||
|
||||
public SandpayConfigUtil() {
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey(String privateKeyPath, String privateKeyPassword) throws Exception {
|
||||
logger.debug("商户私钥路径 => "+privateKeyPath);
|
||||
logger.debug("商户私钥密码 => "+privateKeyPassword);
|
||||
InputStream privateIns = FileUtils.loadFile(privateKeyPath);
|
||||
if (Objects.isNull(privateIns)) {
|
||||
throw new SandPayException("获取私钥失败");
|
||||
} else {
|
||||
return RSAUtils.loadPrivateKey(privateIns, privateKeyPassword);
|
||||
}
|
||||
}
|
||||
|
||||
public PublicKey getSandPublicKey(String sandPublicKeyPath) throws Exception {
|
||||
logger.debug("杉德公钥路径 => "+ sandPublicKeyPath);
|
||||
InputStream publicIns = FileUtils.loadFile(sandPublicKeyPath);
|
||||
if (Objects.isNull(publicIns)) {
|
||||
throw new SandPayException("获取公钥失败");
|
||||
} else {
|
||||
return RSAUtils.loadPublicKey(publicIns);
|
||||
}
|
||||
}
|
||||
|
||||
public String getBaseUrl() {
|
||||
return this.baseUrl;
|
||||
}
|
||||
|
||||
public void setBaseUrl(String baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getAccessMid() {
|
||||
return this.accessMid;
|
||||
}
|
||||
|
||||
public void setAccessMid(String accessMid) {
|
||||
this.accessMid = accessMid;
|
||||
}
|
||||
|
||||
public String getPlMid() {
|
||||
return this.plMid;
|
||||
}
|
||||
|
||||
public void setPlMid(String plMid) {
|
||||
this.plMid = plMid;
|
||||
}
|
||||
|
||||
public String getMid() {
|
||||
return this.mid;
|
||||
}
|
||||
|
||||
public void setMid(String mid) {
|
||||
this.mid = mid;
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey() {
|
||||
return this.privateKey;
|
||||
}
|
||||
|
||||
public void setPrivateKey(PrivateKey privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String getCertNo() {
|
||||
return this.certNo;
|
||||
}
|
||||
|
||||
public void setCertNo(String certNo) {
|
||||
this.certNo = certNo;
|
||||
}
|
||||
|
||||
public PublicKey getSandPublicKey() {
|
||||
return this.sandPublicKey;
|
||||
}
|
||||
|
||||
public void setSandPublicKey(PublicKey sandPublicKey) {
|
||||
this.sandPublicKey = sandPublicKey;
|
||||
}
|
||||
|
||||
public String getSignType() {
|
||||
return this.signType;
|
||||
}
|
||||
|
||||
public void setSignType(String signType) {
|
||||
this.signType = signType;
|
||||
}
|
||||
|
||||
public String getEncryptType() {
|
||||
return this.encryptType;
|
||||
}
|
||||
|
||||
public void setEncryptType(String encryptType) {
|
||||
this.encryptType = encryptType;
|
||||
}
|
||||
|
||||
public int getConnectTimeout() {
|
||||
return this.connectTimeout;
|
||||
}
|
||||
|
||||
public void setConnectTimeout(int connectTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
public int getReadTimeout() {
|
||||
return this.readTimeout;
|
||||
}
|
||||
|
||||
public void setReadTimeout(int readTimeout) {
|
||||
this.readTimeout = readTimeout;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user