介绍:由于本公司是做B端的接口开发,涉及到很多和用户对接的问题。签名、访问、加验签的过程,比较耗时且容易出错。所以封装成了一个工具包。
功能:
1.外部用户调用,数据整理+签名+请求+验签+返回数据整理
2.内部开发组使用,数据整理+请求+返回数据整理
代码如下:
package com.lianjin.common;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lianjin.other.RSA;
/** * 联金开放平台API接口请求及处理工具类 * * @author 北国 * */
public class OpenApiUtil {
private static final String CHARSET = "UTF-8";
private static final String CODE = "code";
private static final String MSG = "msg";
private static final String RETURN_MSG_202 = "服务器已接受请求,但尚未处理。";
private static final String RETURN_MSG_400 = "交易失败。可能原因:参数格式等不符合接口要求。";
private static final String RETURN_MSG_401 = "验证失败。可能原因:商户签名数据校验失败。";
private static final String RETURN_MSG_403 = "禁止访问。可能原因:商户未开通相应接口权限。";
private static final String RETURN_MSG_404 = "请求失败。可能原因:服务器未提供该接口。";
private static final String RETURN_MSG_500 = "内部错误。可能原因:联金服务器与金融机构服务器之间通讯出现异常,交易最终处理状态未知。这种情况的交易需要通过流水查询来确定交易最终处理状态。";
private static final String RETURN_MSG_DEFAULT = "请求消息未到达。";
private static final String RETURN_MSG_DEPARAMERERROR = "参数异常,请检查传送参数。";
private static final String RETURN_MSG_VERIFY = "返回值验签失败。可能原因:公私钥不匹配,或者消息体被拦截。";
/** * 不需要签名和验签的方法调用 * * @param params 需要上传的字段 * @param url 访问路径 * @return json格式字符串 * @throws Exception 处理异常 */
public static String operate(Map<String, Object> params, String url) throws Exception {
return operate(params, url, CHARSET);
}
/** * 不需要签名和验签的方法调用 * * @param params 需要上传的字段 * @param url 访问路径 * @param charset 编码格式 * @return json格式字符串 * @throws Exception 处理异常 */
public static String operate(Map<String, Object> params, String url, String charset) throws Exception {
return operate(params, null, null, url, charset);
}
/** * 需要签名和验签的方法调用 * * @param params 需要上传的字段 * @param privateKey 商户私钥 * @param publicKey 开放平台公钥 * @param url 访问路径 * @return json格式字符串 * @throws Exception 处理异常 */
public static String operate(Map<String, Object> params, String privateKey, String publicKey, String url)
throws Exception {
return operate(params, privateKey, publicKey, url, CHARSET);
}
/** * 需要签名和验签的方法调用 * * @param params 需要上传的字段 * @param privateKey 商户私钥 * @param publicKey 开放平台公钥 * @param url 访问路径 * @param charset 编码格式 * @return json格式字符串 * @throws Exception 处理异常 */
public static String operate(Map<String, Object> params, String privateKey, String publicKey, String url,
String charset) throws Exception {
boolean flag = true;
if (privateKey == null || publicKey == null) {
flag = false;
}
return operate(params, flag, privateKey, publicKey, url, charset);
}
//=======================================================私有方法调用=====================================================
/** * 私有方法处理 * @param params * @param flag * @param privateKey * @param publicKey * @param url * @param charset * @return * @throws Exception */
@SuppressWarnings("deprecation")
private static String operate(Map<String, Object> params, boolean flag, String privateKey, String publicKey,
String url, String charset) throws Exception {
// 1.参数验证
boolean bl = checkNull(url);
if (bl)
throw new ParamsErrorException(RETURN_MSG_DEPARAMERERROR);
// 2.参数整理
if (charset == null || charset.length() == 0) {
charset = CHARSET;
}
JSONObject jsonObject = new JSONObject();
if (params != null && params.size() > 0) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
jsonObject.put(entry.getKey(), entry.getValue());
}
}
String msg = jsonObject.toJSONString();
// 3.参数签名
String sign = null;
if (flag) {
msg = Base64.encodeBase64String(msg.getBytes());
sign = RSA.sign(msg, privateKey, charset);
}
// 4.请求
HttpClient client = new HttpClient();
PostMethod pm = new PostMethod(url);
pm.addParameter("MSG", msg);
if (flag) {
pm.addParameter("SIGN", sign);
}
HttpMethodParams param = pm.getParams();
param.setContentCharset(charset);
client.executeMethod(pm);
// 5.返回值处理
int statusCode = pm.getStatusCode();
JSONObject reponseData = JSON.parseObject(pm.getResponseBodyAsString());
String returnErrorMsg = "";
try {
switch (statusCode) {
case 200:
InputStream stream = pm.getResponseBodyAsStream();
BufferedReader br = new BufferedReader(new InputStreamReader(stream, charset));
StringBuffer buf = new StringBuffer();
String line;
while (null != (line = br.readLine())) {
buf.append(line);
}
String json = buf.toString();
JSONObject parseObject = JSON.parseObject(json);
String rMsg = parseObject.getString("MSG");
if (flag) {
String rSign = parseObject.getString("SIGN");
// 解签
boolean verifyFlag = RSA.verify(rMsg, URLDecoder.decode(rSign), publicKey, charset);
if (!verifyFlag) {
throw new VerifyException(RETURN_MSG_VERIFY);
}
rMsg = URLDecoder.decode(rMsg);
rMsg = new String(Base64.decodeBase64(rMsg));
}
jsonObject.clear();
jsonObject.put(CODE, statusCode);
jsonObject.put(MSG, rMsg);
return jsonObject.toJSONString();
case 202:
returnErrorMsg = "{\"errorCode\":\"" + statusCode + "\",\"errorMsg\":\"" + reponseData.get("msg")
+ "\",\"description\":\"" + RETURN_MSG_202 + "\"}";
throw new AcceptException(returnErrorMsg);
case 400:
returnErrorMsg = "{\"errorCode\":\"" + statusCode + "\",\"errorMsg\":\"" + reponseData.get("msg")
+ "\",\"description\":\"" + RETURN_MSG_400 + "\"}";
throw new BadRequestException(returnErrorMsg);
case 401:
returnErrorMsg = "{\"errorCode\":\"" + statusCode + "\",\"errorMsg\":\"" + reponseData.get("msg")
+ "\",\"description\":\"" + RETURN_MSG_401 + "\"}";
throw new UnauthorizedException(returnErrorMsg);
case 403:
returnErrorMsg = "{\"errorCode\":\"" + statusCode + "\",\"errorMsg\":\"" + reponseData.get("msg")
+ "\",\"description\":\"" + RETURN_MSG_403 + "\"}";
throw new ForbiddenException(returnErrorMsg);
case 404:
returnErrorMsg = "{\"errorCode\":\"" + statusCode + "\",\"errorMsg\":\"" + reponseData.get("msg")
+ "\",\"description\":\"" + RETURN_MSG_404 + "\"}";
throw new NotFoundException(returnErrorMsg);
case 500:
returnErrorMsg = "{\"errorCode\":\"" + statusCode + "\",\"errorMsg\":\"" + reponseData.get("msg")
+ "\",\"description\":\"" + RETURN_MSG_500 + "\"}";
throw new InternalServerErrorException(returnErrorMsg);
default:
returnErrorMsg = "{\"errorCode\":\"" + statusCode + "\",\"errorMsg\":\"" + reponseData.get("msg")
+ "\",\"description\":\"" + RETURN_MSG_DEFAULT + "\"}";
throw new OtherException(returnErrorMsg);
}
} finally {
// 释放连接
pm.releaseConnection();
}
}
/** * 判断是否非空 * @param params * @return */
private static boolean checkNull(String... params) {
boolean bl = false;
if (params == null || params.length == 0) {
return bl;
}
for (int i = 0, len = params.length; i < len; i++) {
if (params[i] == null || params[i].length() == 0) {
bl = true;
break;
}
}
return bl;
}
}
/** * paramsError 参数错误异常。 */
class ParamsErrorException extends Exception {
private static final long serialVersionUID = 6263654286719942595L;
public ParamsErrorException(String msg) {
super(msg);
}
}
/** * 返回值验签失败。 */
class VerifyException extends Exception {
private static final long serialVersionUID = 217444837037724136L;
public VerifyException(String msg) {
super(msg);
}
}
/** * 202 服务器已接受请求,但尚未处理。 */
class AcceptException extends Exception {
private static final long serialVersionUID = 7928277023391853822L;
public AcceptException(String msg) {
super(msg);
}
}
/** * 400 交易失败。可能原因:参数格式等不符合接口要求。 */
class BadRequestException extends Exception {
private static final long serialVersionUID = -9221710431564471515L;
public BadRequestException(String msg) {
super(msg);
}
}
/** * 401 验证失败。可能原因:商户签名数据校验失败。 */
class UnauthorizedException extends Exception {
private static final long serialVersionUID = -753392976403114549L;
public UnauthorizedException(String msg) {
super(msg);
}
}
/** * 403 禁止访问。可能原因:商户未开通相应接口权限。 */
class ForbiddenException extends Exception {
private static final long serialVersionUID = -7917058639724657007L;
public ForbiddenException(String msg) {
super(msg);
}
}
/** * 404 请求失败。可能原因:服务器未提供该接口。 */
class NotFoundException extends Exception {
private static final long serialVersionUID = -793287866605198176L;
public NotFoundException(String msg) {
super(msg);
}
}
/** * 500 内部错误。可能原因:联金服务器与金融机构服务器之间通讯出现异常,交易最终处理状态未知。这种情况的交易需要通过流水查询来确定交易最终处理状态。 */
class InternalServerErrorException extends Exception {
private static final long serialVersionUID = -2490506788240801922L;
public InternalServerErrorException(String msg) {
super(msg);
}
}
/** * other 可能原因:请求消息未到达 */
class OtherException extends Exception {
private static final long serialVersionUID = -5685237491673646459L;
public OtherException(String msg) {
super(msg);
}
}
RSA工具类使用
package com.lianjin.other;
import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
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.cert.Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
/** * RSA签名,加解密处理核心文件,注意:密钥长�?024 */
public class RSA {
/** * 签名算法 */
public static final String SIGNATURE_ALGORITHM = "SHA1withRSA";
/** * 加密算法RSA */
public static final String KEY_ALGORITHM = "RSA";
/** * RSA�?��加密明文大小 */
private static final int MAX_ENCRYPT_BLOCK = 117;
/** * RSA�?��解密密文大小 */
private static final int MAX_DECRYPT_BLOCK = 128;
/** * 获取公钥的key */
private static final String PUBLIC_KEY = "RSAPublicKey";
/** * 获取私钥的key */
private static final String PRIVATE_KEY = "RSAPrivateKey";
/** * <p> * 生成密钥�?公钥和私�? * </p> * * @throws Exception */
public static Map<String, Object> genKeyPair() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
Map<String, Object> keyMap = new HashMap<String, Object>(2);
keyMap.put(PUBLIC_KEY, publicKey);
keyMap.put(PRIVATE_KEY, privateKey);
return keyMap;
}
public static void main(String[] args) throws Exception {
Map<String, Object> genKeyPair = RSA.genKeyPair();
System.out.println(RSA.getPublicKey(genKeyPair));
System.out.println(RSA.getPrivateKey(genKeyPair));
}
/** * 签名字符�? * * @param text * �?��签名的字符串 * @param privateKey * 私钥(BASE64编码) * * @param charset * 编码格式 * @return 签名结果(BASE64编码) */
public static String sign(String text, String privateKey, String charset) throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PrivateKey privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateK);
signature.update(getContentBytes(text, charset));
byte[] result = signature.sign();
return Base64.encodeBase64String(result);
}
public static String sign(String text, PrivateKey privateKey, String charset)
throws SignatureException, InvalidKeyException {
try {
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(privateKey);
signature.update(getContentBytes(text, charset));
byte[] result = signature.sign();
return Base64.encodeBase64String(result);
} catch (NoSuchAlgorithmException e) {
// 不可能发生,
return null;
}
}
/** * 签名字符�? * * @param text * �?��签名的字符串 * @param sign * 客户签名结果 * @param publicKey * 公钥(BASE64编码) * @param charset * 编码格式 * @return 验签结果 */
public static boolean verify(String text, String sign, String publicKey, String charset) throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
PublicKey publicK = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(publicK);
signature.update(getContentBytes(text, charset));
return signature.verify(Base64.decodeBase64(sign));
}
/** * <P> * 私钥解密 * </p> * * @param encryptedData * 已加密数�? * @param privateKey * 私钥(BASE64编码) * @throws Exception */
public static byte[] decryptByPrivateKey(byte[] encryptedData, String privateKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解�?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** * <p> * 公钥解密 * </p> * * @param encryptedData * 已加密数�? * @param publicKey * 公钥(BASE64编码) * @throws Exception */
public static byte[] decryptByPublicKey(byte[] encryptedData, String publicKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicK);
int inputLen = encryptedData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段解�?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
}
/** * <p> * 公钥加密 * </p> * * @param data * 源数�? * @param publicKey * 公钥(BASE64编码) * @throws Exception */
public static byte[] encryptByPublicKey(byte[] data, String publicKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(publicKey);
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicK = keyFactory.generatePublic(x509KeySpec);
// 对数据加�?
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加�?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** * <p> * 公钥加密 * </p> * * @param data * 源数�? * @param cert * 证书 * @throws Exception */
public static byte[] encryptByPublicKey(byte[] data, Certificate cert) throws Exception {
// 对数据加�?
PublicKey uk = cert.getPublicKey();
Cipher cipher = Cipher.getInstance(uk.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, uk);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加�?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** * <p> * 私钥加密 * </p> * * @param data * 源数�? * @param privateKey * 私钥(BASE64编码) * @throws Exception */
public static byte[] encryptByPrivateKey(byte[] data, String privateKey) throws Exception {
byte[] keyBytes = Base64.decodeBase64(privateKey);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateK = keyFactory.generatePrivate(pkcs8KeySpec);
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateK);
int inputLen = data.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
// 对数据分段加�?
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
} else {
cache = cipher.doFinal(data, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_ENCRYPT_BLOCK;
}
byte[] encryptedData = out.toByteArray();
out.close();
return encryptedData;
}
/** * @param content * @param charset * @throws SignatureException * @throws UnsupportedEncodingException */
private static byte[] getContentBytes(String content, String charset) {
if (charset == null || "".equals(charset)) {
return content.getBytes();
}
try {
return content.getBytes(charset);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException("签名过程中出现错�?指定的编码集不对,您目前指定的编码集是:" + charset);
}
}
/** * <p> * 获取私钥 * </p> * * @param keyMap * 密钥�? * @return String * @throws Exception */
public static String getPrivateKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return Base64.encodeBase64String(key.getEncoded());
}
/** * <p> * 获取公钥 * </p> * * @param keyMap * 密钥�? * @throws Exception */
public static String getPublicKey(Map<String, Object> keyMap) throws Exception {
Key key = (Key) keyMap.get(PUBLIC_KEY);
return Base64.encodeBase64String(key.getEncoded());
}
// public static void main(String[] args) throws Exception {
// Map<String, Object> genKeyPair = genKeyPair();
// String 公钥 = CFS_ConfOA.openApiPublicKey;
// String 私钥 = CFS_ConfOA.cfsPrivateKey;
//
// String base64publicKey = getPublicKey(genKeyPair);
// base64publicKey = 公钥;
// System.out.println("公钥 \n" + base64publicKey);
// String base64privateKey = getPrivateKey(genKeyPair);
// base64privateKey = 私钥;
// System.out.println("私钥\n" + base64privateKey);
//
// String passwd = "曹杰";
// String charsetName = "utf-8";
//
// String sign = RSA.sign(passwd, 私钥, charsetName);
// System.out.println("签名�? + sign);
// System.out.println("验签�? + RSA.verify(passwd, sign, 公钥, charsetName));
//
// System.out.println("以下为公钥加密,私钥解密-------------------------------------\n");
//
// String encryptByPublicKey = Base64
// .encodeBase64String((encryptByPublicKey(passwd.getBytes(charsetName),
// base64publicKey)));
// System.out.println("加密\n" + encryptByPublicKey);
//
// byte[] decryptByPrivateKey =
// decryptByPrivateKey(Base64.decodeBase64(encryptByPublicKey),
// base64privateKey);
// String string = new String(decryptByPrivateKey, "utf-8");
// System.out.println("解密后\n" + string);
//
// System.out.println("以下为私钥加密,公钥解密-------------------------------------\n");
//
// encryptByPublicKey = Base64
// .encodeBase64String(encryptByPrivateKey(passwd.getBytes(charsetName),
// base64privateKey));
// System.out.println("加密\n" + encryptByPublicKey);
//
// decryptByPrivateKey =
// decryptByPublicKey(Base64.decodeBase64(encryptByPublicKey),
// base64publicKey);
// string = new String(decryptByPrivateKey, "utf-8");
// System.out.println("解密后\n" + string);
// }
}