{"agetId":"61000000103774","pdata":"Ocn4bo++jxEG/6mnCmVCSxYKgbqYrP1+gyxE9T9ADq3rPRg
WU9o9aMUpFEY5oOTQkzj1dumFodqHWtI1O7AG5Mhm/yAU6uZEU2gRI6h921jzpUd3hvAyOTEj5vGlq5/tVIdoTXQ3hSyRShsqHA+Mg3nYgXOHIIT6mDRWXnUXVl+9fQ04vSViTOWHZvmHGcoCC1KviopKY/DM+O5MctN0WH2piolwnLP2rqPGLy
iP0Rx58owAQEm6A2kLH3gIe29GgLUhD0/DJofupFlTsYeOFaKVI48loUhtOM+dxmAg9IaD7oKfSihTWqMoI8KUPj8dQFYZ0jSFFRdghu+xq82ayQbUo7yUCjo3mkEStCn6shv6cIZj/gBkNU3VUuwLRJ69YT4sDAOI9XfIWEGgnaG+ekbJFsoTV
nRAexbT4kB3LIyAtYco14IWNzzIfZqFf5iCVaRnXzSFpyIASvNwL6HEt842iPJx89R4HpoSVbZvmQisxk1tsN49AGSr+9iV1pcMd250AZnFJGuyUYWCPQl0OXm5lPholzbF0a5ChSLFeVt0b0Azsk8/BxjAZVSC/UnFOAJuqkKIArkCom0oN57x
CkQ/PJAhR/KU6XyN4kUWn3RILc8x05CQBvIbJfEBstevhIXGKA81WOwncIDNZbe2Ms4GyDcGYukVQtrarzLMgI2GS+vr2/I+GWPCtLPjCAYovKy7xVKCqOS0FT2UGuRVJbUzyTXekjtU2XxzuOxkjEI6XoFrAY/jbKtlVzM5Ji7YZOQcqiShjwH
/3HjNc6UmGr+nhRXbUduCul7wkxna14BGIkVts/zXPwZ6STAneXNYCgc10OcTofI6JybtfCg1hyJHLgEbZO6QsNN5UmQy5ZnMXZgYYbAabKDq1OuPGg2amuP3qFtMY4AHnYtP2BkZPiQC64VuMRHYN3fMVOVsOw5VlxXm7qFGpnBff7d2O+REaB
SwKQCQ8v3K3AsjL+FS17SYSAwVAkz/Q5qXYHQdqyl35o7cniYqhzjKb+3CXS3bg3Xyg734HjAWEmxHHQrLTmiPBbDJhyDbyjE23Ld2CGSMfct6Yh+SfHx8P11P3uh5R4AM5uT1fMEnI3hBvjzAEqXe0qQiiIJXQf8C7GztUrqRkiuPhOiQHjipq
q4dtaDoOKLtaYquxBgkPMgF+SkZi6WNSfi5f3QiPLAuerIO87vu0OdZ69ObczCTiozU0V1Ir8eXUYf6TvsiDyB3grBjXhKFHlhaxk25V0Hv2euCJoEvWCEUnXpuj5CgYCxah4QLEdqwq1iCHam9TwuJLVMWxhKythzisQS0ze5q1Knw3X4xET5X
6M3rzSHzsMinYQlcXCEGN2U0kX+0yEfbKdro9XVE0B4MqkI9kqqt3wDtcFEjkcOhBX031UJsgGkJimcH/dP+i05mRu2N1z0JOgNlnN9EsZdCS5Mo7Q7uR4F7yn/JbQkqDplIV2tMERFfjAT3SwSDcDWhYbDMG8yshvc8pmINPFSJ0NgyJx1IHDA
jMOitJIbU6rCJp9pk92CH9CZ/sHxDW75eLDh+yHGY7z+t+MYWLW8wO7jUViUhL5z7C1QvpnN6cP5mz0Q8ACg1HVYHratS2GeAKbZf0ZMXAKognkiGwesV65n02UwRRUvv+T2ANVJxFTC6Th13HL+afru7YCkI3gRpihuQgefyjLeLWeUJfUMYXa
Fal7hVVLHU8FQ="}
{"auditRemark":null,"auditStatus":"1","authId":"8496379813794816000","custId":"2
0000000001203","customerId":"20000000001203","isManage":"0","mainCustId":"60000001057073","operationType":"0","sign":"d9FmeZoeoRblzvbqYywCQWBmuXR5x5B1oTS/csZx0L3OWBZK7NYccFSo3GXIGjr9I
NU5V8ZdSfTf157P4SWk81AJyieJ9WRAYuhMkcLBweofyPqv1coox4lHF/1wYNwun8fBo7jxjs/fCOEaGFRfm0BIO1nDduID8ciaPB1QUYDYpajeZanql7y/epBKucMW5Hy/C5v6gtNVUEz/rk2yuTkSUkk5ttjDC6ZYeDSBWRQ4SjTm4Wkb53G/
VegJzm0Z6hqS8YNNHMstzd94eC8/5acA4iMs4gTXAvHdulEiiz7KZYQzmfAjToVquh+Bf/23U6szDkcNV0jpBI0RK6S4MA==","signId":"8496379815405428736"}
auditStatus=1&authId=8496379813794816000&custId=20000000001203&customerId=20000000001203&isManage=0&mainCustId=60000001057073&operationType=0&signId=8496379815405428736
a35dbed9438c7fd11ce196b522318dc9ad745a4b9403adca577ba022fd7a07c0
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.ArrayUtils;
import sun.misc.BASE64Decoder;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.TreeMap;
/**
* 公钥解签
*/
@Log4j2
public class RUtil {
/**
* 公钥解密过程
*
* @param key 公钥
* @param data 密文数据
* @return 明文
* @throws Exception 解密过程中的异常信息
*/
public static String decrypt(String key, String data) throws Exception {
if (key == null) {
throw new Exception("解密公钥为空, 请设置");
}
PublicKey publicKey = getPublicKey(key);
byte[] cipherData = Base64Util.decode(data);
Cipher cipher = null;
try {
// 使用默认RSA
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
byte[] buf = (byte[]) null;
for (int i = 0; i < cipherData.length; i += 256) {
byte[] doFinal = cipher.doFinal(ArrayUtils.subarray(cipherData, i, i + 256));
if(buf == null) {
buf = doFinal;
} else {
buf = addBytes(buf,doFinal);
}
}
return new String(buf);
} catch (NoSuchAlgorithmException e) {
throw new Exception("无此解密算法");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new Exception("解密公钥非法,请检查");
} catch (IllegalBlockSizeException e) {
throw new Exception("密文长度非法");
} catch (BadPaddingException e) {
throw new Exception("密文数据已损坏");
}
}
/**
* 数组拼接
* @param data1 数组1
* @param data2 数组2
* @return
*/
public static byte[] addBytes(byte[] data1, byte[] data2) {
byte[] data3 = new byte[data1.length + data2.length];
System.arraycopy(data1, 0, data3, 0, data1.length);
System.arraycopy(data2, 0, data3, data1.length, data2.length);
return data3;
}
/**
* 验证sign
* plainText 返回数据报文
* publicKey 公钥
* @return
*/
public static boolean checkSign(String plainText,String publicKey) throws Exception {
TreeMap<String ,Object> map = JSONObject.parseObject(plainText, new TypeReference<TreeMap<String, Object>>(){});
System.out.println(JSONObject.toJSONString(map));
StringBuilder sb = new StringBuilder();
String sign = "";
for (String key : map.keySet()){
if("sign".equals(key)){
sign =(String) map.get(key);
continue;
}
sb.append(key).append("=").append(map.get(key)).append("&");
}
String res = sb.substring(0,sb.lastIndexOf("&"));
log.info("拼接字符串:"+res);
String sha256 = SHA256.getSHA256(res);
log.info("拼接串的SHA256:"+sha256);
String decodeSha256 = decrypt(publicKey,sign);
log.info("sign解密的SHA256:"+decodeSha256);
return sha256.equals(decodeSha256);
}
/**
* 得到公钥
*
* @param key 密钥字符串(经过base64编码)
* @throws Exception
*/
public static PublicKey getPublicKey(String key) throws Exception {
byte[] keyBytes;
keyBytes = new BASE64Decoder().decodeBuffer(key);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey publicKey = keyFactory.generatePublic(keySpec);
return publicKey;
}
}{
"type": "object",
"properties": {
"agetId": {
"type": "string",
"description": "机构号"
},
"pdata": {
"type": "object",
"properties": {
"batchId": {
"type": "string",
"description": "批次号"
},
"otherOrderNo": {
"type": "string",
"description": "三方订单号"
},
"tradeDate": {
"type": "string",
"description": "交易时间yyyymmdd"
},
"splitTradeLogs": {
"type": "array",
"items": {
"type": "object",
"properties": {
"tradeId": {
"type": "string",
"description": "分账流水号"
},
"txAmt": {
"type": "number",
"description": "分账金额:元"
},
"fee": {
"type": "number",
"description": "手续费:元"
},
"feeOut": {
"type": "number",
"description": "出款方承担手续费:元"
},
"feeIn": {
"type": "number",
"description": "接收方承担手续费:元"
},
"tradeStatus": {
"type": "number",
"description": "交易状态:0-待执行 1-交易成功 2-交易失败 3-处理中 4-交易异常 "
},
"cashStatus": {
"type": "number",
"description": "结算状态:0-不结算 1-待结算 2-结算中 3-结算成功 4-结算失败 "
},
"inCustomerId": {
"type": "string",
"description": "接收方客户号"
},
"outCustId": {
"type": "string",
"description": "分账出款方商户号,600商户在星驿付的唯一代码"
},
"inCustId": {
"type": "string",
"description": "分账出款方商户号,600商户在星驿付的唯一代码"
},
"withId": {
"type": "string",
"description": "提现订单号:【结算状态 2-结算中 3-结算成功 】时返回"
},
"splitTime": {
"type": "string",
"description": "分账交易完成时间:yyyyMMddHHmmss"
},
"withTime": {
"type": "string",
"description": "结算完成时间: 需结算的订单,结算成功后返回yyyyMMddHHmmss"
},
"returnStatus": {
"type": "string",
"description": "订单退回状态 0-未退回 1-已回退 2-退回中 3-退回失败"
},
"revokeStatus": {
"type": "string",
"description": "订单撤销状态 0-未撤销 1-已撤销 2-撤销中 3-撤销失败"
}
},
"x-apifox-orders": [
"tradeId",
"outCustId",
"inCustId",
"inCustomerId",
"txAmt",
"fee",
"feeOut",
"feeIn",
"tradeStatus",
"cashStatus",
"withId",
"splitTime",
"withTime",
"returnStatus",
"revokeStatus"
],
"required": [
"tradeId",
"outCustId",
"inCustomerId",
"txAmt",
"fee",
"feeOut",
"feeIn",
"tradeStatus",
"cashStatus",
"inCustId",
"returnStatus",
"revokeStatus",
"withId"
]
},
"description": "分账详情"
},
"sign": {
"type": "string",
"description": "签名"
}
},
"required": [
"batchId",
"otherOrderNo",
"tradeDate",
"splitTradeLogs",
"sign"
],
"x-apifox-orders": [
"batchId",
"otherOrderNo",
"tradeDate",
"splitTradeLogs",
"sign"
]
}
},
"required": [
"agetId",
"pdata"
],
"x-apifox-orders": [
"agetId",
"pdata"
]
}