-----> 金蝶实名认证接口文档下载地址 <-----
(请先留意金蝶实名认证接口文档(涉及加解密、偏移量、签名秘钥))
3DES加解密Util
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class Cipher3DES {
//private final static Logger log = LoggerFactory.getLogger(Cipher3DES.class);
public static String encrypt(String toEncode, String key, String vector){
try {
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
DESedeKeySpec dks = new DESedeKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory
.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
IvParameterSpec iv = new IvParameterSpec(vector.getBytes(), 0,
cipher.getBlockSize());
cipher.init(1, securekey, iv);
byte[] encoded = cipher.doFinal(toEncode.getBytes("UTF-8"));
return CipherBase64.encryptBASE64(encoded);
} catch (NoSuchAlgorithmException | NoSuchPaddingException
| InvalidKeyException | InvalidKeySpecException
| InvalidAlgorithmParameterException
| IllegalBlockSizeException | BadPaddingException
| UnsupportedEncodingException e) {
//log.error(e.getMessage());
}
return null;
}
public static String decrypt(String toDecode, String key, String vector) {
try {
Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
DESedeKeySpec dks = new DESedeKeySpec(key.getBytes());
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey securekey = keyFactory.generateSecret(dks);
IvParameterSpec iv = new IvParameterSpec(vector.getBytes(), 0,
cipher.getBlockSize());
cipher.init(2, securekey, iv);
byte[] todecodeBytes = CipherBase64.decryptBASE64(toDecode);
String decoded = new String(cipher.doFinal(todecodeBytes), "utf-8");
return decoded;
} catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | InvalidKeySpecException | InvalidAlgorithmParameterException | UnsupportedEncodingException | IllegalBlockSizeException | BadPaddingException e) {
//log.error(e.getMessage());
}
return null;
}
}
Base64加解密
public class CipherBase64 {
private static final byte[] base64Alphabet = new byte[''];
private static final char[] lookUpBase64Alphabet = new char[64];
public static byte[] decryptBASE64(String encoded) {
if (encoded == null) {
return null;
}
char[] base64Data = encoded.toCharArray();
int len = removeWhiteSpace(base64Data);
if (len % 4 != 0) {
return null;
}
int numberQuadruple = len / 4;
if (numberQuadruple == 0) {
return new byte[0];
}
byte[] decodedData = null;
byte b1 = 0;
byte b2 = 0;
byte b3 = 0;
byte b4 = 0;
char d1 = '\000';
char d2 = '\000';
char d3 = '\000';
char d4 = '\000';
int i = 0;
int encodedIndex = 0;
int dataIndex = 0;
decodedData = new byte[numberQuadruple * 3];
for (; i < numberQuadruple - 1; i++) {
if ((!isData(d1 = base64Data[(dataIndex++)]))
|| (!isData(d2 = base64Data[(dataIndex++)]))
|| (!isData(d3 = base64Data[(dataIndex++)]))
|| (!isData(d4 = base64Data[(dataIndex++)]))) {
return null;
}
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[(encodedIndex++)] = ((byte) (b1 << 2 | b2 >> 4));
decodedData[(encodedIndex++)] = ((byte) ((b2 & 0xF) << 4 | b3 >> 2 & 0xF));
decodedData[(encodedIndex++)] = ((byte) (b3 << 6 | b4));
}
if ((!isData(d1 = base64Data[(dataIndex++)]))
|| (!isData(d2 = base64Data[(dataIndex++)]))) {
return null;
}
b1 = base64Alphabet[d1];
b2 = base64Alphabet[d2];
d3 = base64Data[(dataIndex++)];
d4 = base64Data[(dataIndex++)];
if ((!isData(d3)) || (!isData(d4))) {
if ((isPad(d3)) && (isPad(d4))) {
if ((b2 & 0xF) != 0) {
return null;
}
byte[] tmp = new byte[i * 3 + 1];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[encodedIndex] = ((byte) (b1 << 2 | b2 >> 4));
return tmp;
}
if ((!isPad(d3)) && (isPad(d4))) {
b3 = base64Alphabet[d3];
if ((b3 & 0x3) != 0) {
return null;
}
byte[] tmp = new byte[i * 3 + 2];
System.arraycopy(decodedData, 0, tmp, 0, i * 3);
tmp[(encodedIndex++)] = ((byte) (b1 << 2 | b2 >> 4));
tmp[encodedIndex] = ((byte) ((b2 & 0xF) << 4 | b3 >> 2 & 0xF));
return tmp;
}
return null;
}
b3 = base64Alphabet[d3];
b4 = base64Alphabet[d4];
decodedData[(encodedIndex++)] = ((byte) (b1 << 2 | b2 >> 4));
decodedData[(encodedIndex++)] = ((byte) ((b2 & 0xF) << 4 | b3 >> 2 & 0xF));
decodedData[(encodedIndex++)] = ((byte) (b3 << 6 | b4));
return decodedData;
}
public static String encryptBASE64(byte[] binaryData) {
if (binaryData == null) {
return null;
}
int lengthDataBits = binaryData.length * 8;
if (lengthDataBits == 0) {
return "";
}
int fewerThan24bits = lengthDataBits % 24;
int numberTriplets = lengthDataBits / 24;
int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1
: numberTriplets;
char[] encodedData = null;
encodedData = new char[numberQuartet * 4];
byte k = 0;
byte l = 0;
byte b1 = 0;
byte b2 = 0;
byte b3 = 0;
int encodedIndex = 0;
int dataIndex = 0;
for (int i = 0; i < numberTriplets; i++) {
b1 = binaryData[(dataIndex++)];
b2 = binaryData[(dataIndex++)];
b3 = binaryData[(dataIndex++)];
l = (byte) (b2 & 0xF);
k = (byte) (b1 & 0x3);
byte val1 = (b1 & 0xFFFFFF80) == 0 ? (byte) (b1 >> 2)
: (byte) (b1 >> 2 ^ 0xC0);
byte val2 = (b2 & 0xFFFFFF80) == 0 ? (byte) (b2 >> 4)
: (byte) (b2 >> 4 ^ 0xF0);
byte val3 = (b3 & 0xFFFFFF80) == 0 ? (byte) (b3 >> 6)
: (byte) (b3 >> 6 ^ 0xFC);
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[val1];
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[(val2 | k << 4)];
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[(l << 2 | val3)];
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[(b3 & 0x3F)];
}
if (fewerThan24bits == 8) {
b1 = binaryData[dataIndex];
k = (byte) (b1 & 0x3);
byte val1 = (b1 & 0xFFFFFF80) == 0 ? (byte) (b1 >> 2)
: (byte) (b1 >> 2 ^ 0xC0);
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[val1];
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[(k << 4)];
encodedData[(encodedIndex++)] = '=';
encodedData[(encodedIndex++)] = '=';
} else if (fewerThan24bits == 16) {
b1 = binaryData[dataIndex];
b2 = binaryData[(dataIndex + 1)];
l = (byte) (b2 & 0xF);
k = (byte) (b1 & 0x3);
byte val1 = (b1 & 0xFFFFFF80) == 0 ? (byte) (b1 >> 2)
: (byte) (b1 >> 2 ^ 0xC0);
byte val2 = (b2 & 0xFFFFFF80) == 0 ? (byte) (b2 >> 4)
: (byte) (b2 >> 4 ^ 0xF0);
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[val1];
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[(val2 | k << 4)];
encodedData[(encodedIndex++)] = lookUpBase64Alphabet[(l << 2)];
encodedData[(encodedIndex++)] = '=';
}
return new String(encodedData);
}
private static int removeWhiteSpace(char[] data) {
if (data == null) {
return 0;
}
int newSize = 0;
int len = data.length;
for (int i = 0; i < len; i++) {
if (!isWhiteSpace(data[i])) {
data[(newSize++)] = data[i];
}
}
return newSize;
}
private static boolean isWhiteSpace(char octect) {
return (octect == ' ') || (octect == '\r') || (octect == '\n')
|| (octect == '\t');
}
private static boolean isPad(char octect) {
return octect == '=';
}
private static boolean isData(char octect) {
return (octect < '') && (base64Alphabet[octect] != -1);
}
static {
for (int i = 0; i < 128; i++) {
base64Alphabet[i] = -1;
}
for (int i = 90; i >= 65; i--) {
base64Alphabet[i] = ((byte) (i - 65));
}
for (int i = 122; i >= 97; i--) {
base64Alphabet[i] = ((byte) (i - 97 + 26));
}
for (int i = 57; i >= 48; i--) {
base64Alphabet[i] = ((byte) (i - 48 + 52));
}
base64Alphabet[43] = 62;
base64Alphabet[47] = 63;
for (int i = 0; i <= 25; i++) {
lookUpBase64Alphabet[i] = ((char) (65 + i));
}
int i = 26;
for (int j = 0; i <= 51; j++) {
lookUpBase64Alphabet[i] = ((char) (97 + j));
i++;
}
i = 52;
for (int j = 0; i <= 61; j++) {
lookUpBase64Alphabet[i] = ((char) (48 + j));
i++;
}
lookUpBase64Alphabet[62] = '+';
lookUpBase64Alphabet[63] = '/';
}
}
签名方式
根据用户自己的签名私钥对加密报文进行签名
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
public class RsaSignCoder {
//private static final Logger log = LoggerFactory.getLogger(Cipher3DES.class);
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Map<String, Object> initKey() {
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(512);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map keyMap = new HashMap();
keyMap.put("RSAPublicKey", publicKey);
keyMap.put("RSAPrivateKey", privateKey);
return keyMap;
} catch (NoSuchAlgorithmException e) {
//log.error(e.getMessage());
}
return null;
}
public static String sign(String datas, String privates) {
byte[] data = datas.getBytes();
byte[] privateKey = CipherBase64.decryptBASE64(privates);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(privateKey);
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initSign(priKey);
signature.update(data);
return CipherBase64.encryptBASE64(signature.sign());
} catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException | InvalidKeySpecException e) {
//log.error(e.getMessage());
}
return null;
}
public static boolean verify(String datas, String publicKeys, String signs) {
byte[] data = datas.getBytes();
byte[] publicKey = CipherBase64.decryptBASE64(publicKeys);
byte[] sign = CipherBase64.decryptBASE64(signs);
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(publicKey);
PublicKey pubKey = keyFactory.generatePublic(x509KeySpec);
Signature signature = Signature.getInstance("MD5withRSA");
signature.initVerify(pubKey);
signature.update(data);
return signature.verify(sign);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | InvalidKeyException | SignatureException e) {
//log.error(e.getMessage());
}
return false;
}
public static String getPrivateKey(Map<String, Object> keyMap) {
Key key = (Key) keyMap.get("RSAPrivateKey");
return CipherBase64.encryptBASE64(key.getEncoded());
}
public static String getPublicKey(Map<String, Object> keyMap) {
Key key = (Key) keyMap.get("RSAPublicKey");
return CipherBase64.encryptBASE64(key.getEncoded());
}
}
四要素
其中涉及到的client_id(云平台id),client_secret ( 云平台秘钥 ),publicKey(公钥),PrivateKey(私钥)需要联系金蝶提供。
import java.util.Map;
import java.util.TreeMap;
import java.util.UUID;
import javax.inject.Singleton;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.ningze.entity.ReqDate;
@Singleton
@Path("")
public class FourElements {
private static final Logger LOGGER = LogManager.getLogger(FourElements.class.getName());
private final static String client_id = "******";
private final static String client_secret = "1a0b365*********************";
private final static String PRIVATE_KEY = "*******************************";
private final static String PUBLIC_KEY = "********************************";
@Autowired
private ReqDate req = new ReqDate();
@POST
@Path("/realName")
@Produces(MediaType.APPLICATION_JSON)
public Response identification2(/*@Context UriInfo uri, @Context HttpHeaders headers,*/ String requestJson) {
JSONObject request = JSONObject.parseObject(requestJson);
String realName = request.getString("realName");
String bankCard = request.getString("bankCard");
// 偏移量
String vector = UUID.randomUUID().toString().substring(0, 8);
JSONObject responseJSON = new JSONObject();
responseJSON.put("realName", realName);
responseJSON.put("bankCard", bankCard);
responseJSON.put("client_id", client_id);
responseJSON.put("client_secret", client_secret);
StringBuffer strBuff = new StringBuffer();
// 利用fastjson将jsonobject对象转为map类型
TreeMap<String, String> jsonMap = JSONObject.parseObject(responseJSON.toJSONString(),
new TypeReference<TreeMap<String, String>>() {});
// 所有需签名字段按key的字典序连接,组成key1=value1&key2=value2的方式
for (Map.Entry<String, String> entry : jsonMap.entrySet()) {
strBuff.append(entry.getKey() + "=" + entry.getValue() + "&");
}
// 签名
String signature = RsaSignCoder.sign(strBuff.substring(0, strBuff.length() - 1), PRIVATE_KEY);
responseJSON.put("sign", signature);
// 加密
String encrData = Cipher3DES.encrypt(responseJSON.toJSONString(), PUBLIC_KEY, vector);
// 加密后输入
req.setAppid(client_id);
req.setData(encrData);
req.setVector(vector);
String url = "https://www.bigdataxy.com/api/v2/verify/bankcard/check2";
// 模拟客户端请求
Response resp = ClientBuilder.newClient().target(url).request()
.post(Entity.entity(JSONObject.toJSONString(req), MediaType.APPLICATION_JSON));
JSONObject responseJson = JSONObject.parseObject(resp.readEntity(String.class));
// JSONObject jData=responseJson.getJSONObject("data");
return Response.status(200).entity(responseJson.toString()).type(new MediaType("application", "json", "UTF-8"))
.build();
}
public static void main(String[] args) {
FourElements four = new FourElements();
String requestJson = "{\"realName\":\"***\",\"bankCard\":\"*******\"}";
Response res = four.identification2(requestJson);
//res.getEntity().
System.out.println(res.getEntity());
}
}
返回结果:
{
"msg": "操作成功",
"data": {
"result": "HgZ/NySGpVe4k/CWSetm71DlEpjOibEBffW7iIUEL86VxEv4F9cv2Rzw+lDPHEmIVrAVH+ZrK/9+yzNIuwMyTc2BvHN6XdnXrvNefSflm5T81FqUHf8UAtCHeQQPaLa4Zbl/igcHQyvADNvsqjvDb4rrIRosVNMnld1CnjcAiShzvyeejltQomjITHJD+OlqYOIU+TumOb4=",
"sign": "COZ5+y4ArU7de4xi5RYdtHExU5UAobcg0VVMUnNxTLpkT91bfg6pbtwPv5bz6wa7daTelABPBA0UDitndMHbB0gxjSxvu/TcYaY90WJ/4dMjC38XIvkyuVVYPSpSchDQnaZ3RkjlAMtEuZTqWmXZ946woxVKYjtojX9otnUqNho=",
"vector": "8a53a4cd"
},
"status": 200
}