支付系统中的常用工具
- StringUtils.java
处理常用字符串:判断是否为空isEmpty(String value);
按字典排序并拼接参数:createLinkString(Map<String,String> params);
1 import java.util.ArrayList; 2 import java.util.Collections; 3 import java.util.List; 4 import java.util.Map; 5 6 public class StringUtils { 7 /** 8 * 判断字符数组是否为空 9 */ 10 public static boolean areNotEmpty(String... values) { 11 boolean result = true; 12 if (values == null || values.length == 0) { 13 result = false; 14 } else { 15 for (String value : values) { 16 result &= !isEmpty(value); 17 } 18 } 19 return result; 20 } 21 22 /** 23 * 把数组所有元素排序,并按照"name1=value1&name2=value2..."字符拼接成字符串 24 * 25 * @param params 26 * 需要排序并参与字符拼接的参数组 27 * @return 拼接后字符串 28 */ 29 public static String createLinkString(Map<String, String> params) { 30 31 List<String> keys = new ArrayList<String>(params.keySet()); 32 Collections.sort(keys); 33 34 String prestr = ""; 35 36 for (int i = 0; i < keys.size(); i++) { 37 String key = keys.get(i); 38 String value = params.get(key); 39 40 if (i == keys.size() - 1) { 41 prestr = prestr + key + "=" + value; 42 } else { 43 prestr = prestr + key + "=" + value + "&"; 44 } 45 } 46 47 return prestr; 48 } 49 50 /** 51 * 判断字符串是否为空 52 * <ul> 53 * <li>isEmpty(null) = true</li> 54 * <li>isEmpty("") = true</li> 55 * <li>isEmpty(" ") = true</li> 56 * <li>isEmpty("abc") = false</li> 57 * </ul> 58 * 59 * @param value 60 * 目标字符串 61 * @return true/false 62 */ 63 public static boolean isEmpty(String value) { 64 int strLen; 65 if (value == null || (strLen = value.length()) == 0) { 66 return true; 67 } 68 for (int i = 0; i < strLen; i++) { 69 if ((Character.isWhitespace(value.charAt(i)) == false)) { 70 return false; 71 } 72 } 73 return true; 74 } 75 }
- 支付系统中的签名和验签SignUtils.java
1 import java.io.InputStream; 2 import java.security.KeyStore; 3 import java.security.PrivateKey; 4 import java.security.PublicKey; 5 import java.security.cert.Certificate; 6 import java.security.cert.CertificateFactory; 7 import java.util.ArrayList; 8 import java.util.Collections; 9 import java.util.Enumeration; 10 import java.util.HashMap; 11 import java.util.List; 12 import java.util.Map; 13 import org.apache.commons.codec.binary.Base64; 14 15 /** 16 * 17 */ 18 public class SignUtils { 19 20 /** */ 21 // 缓存公钥和私钥 22 public static Map<String, Object> certMap = new java.util.concurrent.ConcurrentHashMap<String, Object>(); 23 24 /** 25 * 26 * 27 * @param sArray 28 * @return 29 */ 30 public static Map<String, String> paraFilter(Map<String, String> sArray) { 31 32 Map<String, String> result = new HashMap<String, String>(); 33 34 if (sArray == null || sArray.size() <= 0) { 35 return result; 36 } 37 38 for (String key : sArray.keySet()) { 39 String value = sArray.get(key); 40 if (value == null || StringUtils.isEmpty(value) 41 || key.equalsIgnoreCase("sign")) { 42 continue; 43 } 44 result.put(key, value); 45 } 46 47 return result; 48 } 49 50 51 /** 52 * 53 * 54 * @param sortedParams 55 * @return 56 */ 57 public static String getSignContent(Map<String, String> sortedParams) { 58 StringBuffer content = new StringBuffer(); 59 List<String> keys = new ArrayList<String>(sortedParams.keySet()); 60 Collections.sort(keys); 61 int index = 0; 62 for (int i = 0; i < keys.size(); i++) { 63 String key = keys.get(i); 64 String value = sortedParams.get(key); 65 if (StringUtils.areNotEmpty(key, value)) { 66 content.append((index == 0 ? "" : "&") + key + "=" + value); 67 index++; 68 } 69 } 70 return content.toString(); 71 } 72 73 74 /** 75 * 76 * 签名 77 * @param params 业务参数 78 * @param charset 编码 79 * @param pfxCertFileInputStream 证书输入流 80 * @param rsaPassword 私钥pkcs12证书密码 81 * @param algorithmName rsa算法名 82 * @return 83 * @throws Exception 84 */ 85 public static String rsaSign(Map<String, String> params, String charset, 86 InputStream pfxCertFileInputStream,String rsaPassword, String algorithmName) throws Exception { 87 String signContent = getSignContent(params); 88 89 return rsaSign(signContent, charset, pfxCertFileInputStream,rsaPassword, algorithmName); 90 } 91 92 /** 93 * 94 * 95 * @param content 96 * @param charset 97 * @param pfxCertFileInputStream 98 * @param rsaPassword 99 * @param algorithmName 100 * @return 101 * @throws Exception 102 */ 103 public static String rsaSign(String content, String charset, 104 InputStream pfxCertFileInputStream,String rsaPassword, String algorithmName) throws Exception { 105 try { 106 PrivateKey priKey = getPrivateKeyFromPKCS12( 107 rsaPassword, 108 pfxCertFileInputStream); 109 110 java.security.Signature signature = java.security.Signature 111 .getInstance(algorithmName); 112 113 signature.initSign(priKey); 114 115 if (StringUtils.isEmpty(charset)) { 116 signature.update(content.getBytes()); 117 } else { 118 signature.update(content.getBytes(charset)); 119 } 120 121 byte[] signed = signature.sign(); 122 123 String sign = new String(Base64.encodeBase64(signed), charset); 124 125 126 return sign; 127 } catch (Exception e) { 128 throw new Exception("RSAcontent = " + content + "; charset = " 129 + charset, e); 130 } 131 } 132 133 /** 134 * 135 * 136 * @param publicCertFileInputStream 137 * @param params 138 * @param sign 139 * @param charset 140 * @param algorithmName 141 * @return 142 * @throws Exception 143 */ 144 public static boolean rsaCheckContent( 145 InputStream publicCertFileInputStream, Map<String, String> params, 146 String sign, String charset,String algorithmName) throws Exception { 147 String content = StringUtils.createLinkString(SignUtils 148 .paraFilter(params)); 149 150 return rsaCheckContent(publicCertFileInputStream, content, sign, 151 charset, algorithmName); 152 } 153 154 155 /** 156 * 157 * 158 * @param publicCertFileInputStream 159 * @param content 160 * @param sign 161 * @param charset 162 * @param algorithmName 163 * @return 164 * @throws Exception 165 */ 166 public static boolean rsaCheckContent( 167 InputStream publicCertFileInputStream, String content, String sign, 168 String charset, String algorithmName) throws Exception { 169 boolean bFlag = false; 170 try { 171 java.security.Signature signetcheck = java.security.Signature 172 .getInstance(algorithmName); 173 signetcheck 174 .initVerify(getPublicKeyFromCert(publicCertFileInputStream)); 175 signetcheck.update(content.getBytes(charset)); 176 if (signetcheck.verify(Base64.decodeBase64(sign.getBytes(charset)))) { 177 bFlag = true; 178 System.out.println("签名成功!"); 179 }else{ 180 System.out.println("签名失败!"); 181 } 182 } catch (Exception e) { 183 throw new Exception("验证签名异常"); 184 } 185 186 return bFlag; 187 } 188 189 /** 190 * 读取公钥,x509格式. 191 * 192 * @param ins 193 * @return 194 * @throws Exception 195 */ 196 public static PublicKey getPublicKeyFromCert(InputStream ins) 197 throws Exception { 198 PublicKey pubKey = (PublicKey) certMap.get("PublicKey"); 199 if (pubKey != null) { 200 return pubKey; 201 } 202 203 try { 204 CertificateFactory cf = CertificateFactory.getInstance("X.509"); 205 Certificate cac = cf.generateCertificate(ins); 206 pubKey = cac.getPublicKey(); 207 certMap.put("PublicKey", pubKey); 208 } catch (Exception e) { 209 if (ins != null) 210 ins.close(); 211 throw e; 212 } finally { 213 if (ins != null) { 214 ins.close(); 215 } 216 } 217 218 return pubKey; 219 } 220 221 /** 222 * 读取PKCS12格式的key(私钥)pfx格式. 223 * 224 * @param rsaPassword 225 * @param ins 226 * @return 227 * @throws Exception 228 */ 229 public static PrivateKey getPrivateKeyFromPKCS12(String rsaPassword, 230 InputStream ins) throws Exception { 231 PrivateKey priKey = (PrivateKey) certMap.get("PrivateKey"); 232 if (priKey != null) { 233 return priKey; 234 } 235 236 KeyStore keystoreCA = KeyStore.getInstance("PKCS12"); 237 try { 238 // 读取CA根证书 239 keystoreCA.load(ins, rsaPassword.toCharArray()); 240 241 Enumeration<?> aliases = keystoreCA.aliases(); 242 String keyAlias = null; 243 if (aliases != null) { 244 while (aliases.hasMoreElements()) { 245 keyAlias = (String) aliases.nextElement(); 246 // 获取CA私钥 247 priKey = (PrivateKey) (keystoreCA.getKey(keyAlias, 248 rsaPassword.toCharArray())); 249 if (priKey != null) { 250 certMap.put("PrivateKey", priKey); 251 break; 252 } 253 } 254 } 255 } catch (Exception e) { 256 if (ins != null) 257 ins.close(); 258 throw e; 259 } finally { 260 if (ins != null) { 261 ins.close(); 262 } 263 } 264 265 return priKey; 266 } 267 268 }