| | |
| | | <version>3.15.6</version> <!-- 确保使用与你的 Spring Boot 版本兼容的 Redisson 版本 --> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>net.sf.json-lib</groupId> |
| | | <artifactId>json-lib</artifactId> |
| | | <version>2.4</version> |
| | | <classifier>jdk15</classifier> |
| | | </dependency> |
| | | |
| | | </dependencies> |
| | | |
| | | <build> |
对比新文件 |
| | |
| | | package com.mzl.flower.pay; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.DataOutputStream; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.net.HttpURLConnection; |
| | | import java.net.URL; |
| | | import java.net.URLConnection; |
| | | import java.net.URLEncoder; |
| | | import java.util.Map; |
| | | |
| | | import javax.net.ssl.HostnameVerifier; |
| | | import javax.net.ssl.HttpsURLConnection; |
| | | import javax.net.ssl.SSLSession; |
| | | |
| | | import org.apache.commons.logging.Log; |
| | | |
| | | public class HttpConnectionUtil { |
| | | private HttpURLConnection conn; |
| | | private String connectUrl; |
| | | |
| | | public HttpConnectionUtil(String connectUrl){ |
| | | this.connectUrl = connectUrl; |
| | | } |
| | | |
| | | public void init() throws Exception{ |
| | | URL url = new URL(connectUrl); |
| | | System.setProperty("java.protocol.handler.pkgs", "javax.net.ssl"); |
| | | HostnameVerifier hv = new HostnameVerifier() { |
| | | public boolean verify(String urlHostName, SSLSession session) { |
| | | return urlHostName.equals(session.getPeerHost()); |
| | | } |
| | | }; |
| | | HttpsURLConnection.setDefaultHostnameVerifier(hv); |
| | | URLConnection conn = url.openConnection(); |
| | | conn.setDoInput(true); |
| | | conn.setDoOutput(true); |
| | | conn.setReadTimeout(60000); |
| | | conn.setConnectTimeout(30000); |
| | | if (conn instanceof HttpsURLConnection){ |
| | | HttpsURLConnection httpsConn = (HttpsURLConnection)conn; |
| | | httpsConn.setSSLSocketFactory(SSLUtil.getInstance().getSSLSocketFactory()); |
| | | } else if (conn instanceof HttpURLConnection){ |
| | | HttpURLConnection httpConn = (HttpURLConnection)conn; |
| | | } else { |
| | | throw new Exception("不是http/https协议的url"); |
| | | } |
| | | this.conn = (HttpURLConnection)conn; |
| | | initDefaultPost(); |
| | | } |
| | | |
| | | public void destory(){ |
| | | try{ |
| | | if(this.conn!=null){ |
| | | this.conn.disconnect(); |
| | | } |
| | | }catch(Exception e){ |
| | | |
| | | } |
| | | } |
| | | |
| | | private void initDefaultPost() throws Exception{ |
| | | conn.setDoOutput(true); |
| | | conn.setDoInput(true); |
| | | conn.setRequestMethod("POST"); |
| | | conn.setUseCaches(false); |
| | | conn.setInstanceFollowRedirects(true); |
| | | conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); |
| | | } |
| | | |
| | | public byte[] postParams(Map<String, String> params,boolean readreturn) throws IOException { |
| | | StringBuilder outBuf = new StringBuilder(); |
| | | boolean isNotFirst = false; |
| | | for (Map.Entry<String, String> entry: params.entrySet()){ |
| | | if (isNotFirst) |
| | | outBuf.append('&'); |
| | | isNotFirst = true; |
| | | outBuf |
| | | .append(entry.getKey()) |
| | | .append('=') |
| | | .append(URLEncoder.encode(entry.getValue(), "UTF-8")); |
| | | } |
| | | System.out.println("参数:"+outBuf.toString()); |
| | | return postParams(outBuf.toString(),readreturn); |
| | | } |
| | | |
| | | public byte[] postParams(String message,boolean readreturn) throws IOException { |
| | | DataOutputStream out = new DataOutputStream(conn.getOutputStream()); |
| | | out.write(message.getBytes("UTF-8")); |
| | | out.close(); |
| | | if(readreturn){ |
| | | return readBytesFromStream(conn.getInputStream()); |
| | | }else{ |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | public byte[] postParams(byte[] message,boolean readreturn) throws IOException { |
| | | DataOutputStream out = new DataOutputStream(conn.getOutputStream()); |
| | | out.write(message); |
| | | out.close(); |
| | | if(readreturn){ |
| | | return readBytesFromStream(conn.getInputStream()); |
| | | }else{ |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private byte[] readBytesFromStream(InputStream is) throws IOException{ |
| | | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| | | int readLen; |
| | | byte[] tmpBuf = new byte[4096]; |
| | | while ((readLen = is.read(tmpBuf)) > 0) |
| | | baos.write(tmpBuf, 0, readLen); |
| | | is.close(); |
| | | return baos.toByteArray(); |
| | | } |
| | | |
| | | public HttpURLConnection getConn() { |
| | | return conn; |
| | | } |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.mzl.flower.pay; |
| | | |
| | | import java.security.KeyManagementException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.cert.CertificateException; |
| | | import java.security.cert.X509Certificate; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.net.ssl.SSLSocketFactory; |
| | | import javax.net.ssl.TrustManager; |
| | | import javax.net.ssl.X509TrustManager; |
| | | |
| | | /** |
| | | * SSL管理助手类 |
| | | * @author Administrator |
| | | * |
| | | */ |
| | | public class SSLUtil implements X509TrustManager { |
| | | private SSLSocketFactory sslFactory = null; |
| | | |
| | | private SSLUtil(){ |
| | | } |
| | | |
| | | public void checkClientTrusted(X509Certificate[] arg0, String arg1) |
| | | throws CertificateException { |
| | | } |
| | | |
| | | public void checkServerTrusted(X509Certificate[] arg0, String arg1) |
| | | throws CertificateException { |
| | | } |
| | | |
| | | public X509Certificate[] getAcceptedIssuers() { |
| | | return null; |
| | | } |
| | | |
| | | /** 获取SSL Socket工厂 */ |
| | | public SSLSocketFactory getSSLSocketFactory(){ |
| | | return sslFactory; |
| | | } |
| | | |
| | | private static SSLUtil _instance = null; |
| | | |
| | | /** 获取SSL管理助手类实例 */ |
| | | synchronized public static SSLUtil getInstance() throws NoSuchAlgorithmException, KeyManagementException { |
| | | if (_instance == null){ |
| | | _instance = new SSLUtil(); |
| | | SSLContext sc = SSLContext.getInstance("SSLv3"); |
| | | sc.init(null, new TrustManager[]{new SSLUtil()}, null); |
| | | _instance.sslFactory = sc.getSocketFactory(); |
| | | } |
| | | return _instance; |
| | | } |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.mzl.flower.pay; |
| | | |
| | | import java.io.IOException; |
| | | import java.math.BigInteger; |
| | | import java.security.KeyFactory; |
| | | import java.security.PrivateKey; |
| | | import java.security.PublicKey; |
| | | import java.security.SecureRandom; |
| | | import java.security.Security; |
| | | import java.security.Signature; |
| | | import java.security.spec.PKCS8EncodedKeySpec; |
| | | import java.security.spec.X509EncodedKeySpec; |
| | | import java.util.Arrays; |
| | | |
| | | import org.apache.commons.codec.binary.Base64; |
| | | import org.bouncycastle.asn1.ASN1EncodableVector; |
| | | import org.bouncycastle.asn1.ASN1Integer; |
| | | import org.bouncycastle.asn1.ASN1Sequence; |
| | | import org.bouncycastle.asn1.DERSequence; |
| | | import org.bouncycastle.jcajce.spec.SM2ParameterSpec; |
| | | import org.bouncycastle.jce.provider.BouncyCastleProvider; |
| | | import org.bouncycastle.util.encoders.Hex; |
| | | |
| | | public class SmUtil { |
| | | static{ |
| | | Security.addProvider(new BouncyCastleProvider()); |
| | | } |
| | | /**算法常量:SM3withSM2*/ |
| | | public static final String ALGORITHM_SM3SM2_BCPROV = "SM3withSM2"; |
| | | private final static int SM3withSM2_RS_LEN=32; |
| | | |
| | | public static void main(String[] args) throws Exception { |
| | | /**商户平台分配的appid,也是签名的certid**/ |
| | | String appid = "00000156"; |
| | | /**商户sm2私钥,用于向通联发起请求前进行签名**/ |
| | | String cusPrivateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgjj4Rk+b0YjwO+UwXofnHf4bK+kaaY5Btkd8nMP2VimmgCgYIKoEcz1UBgi2hRANCAAQqlALW4qGC3bP1x3wo5QsKxaCMEZJ2ODTTwOQ+d8UGU7GoK/y/WMBQWf5upMnFU06p5FxGooXYYoBtldgm03hq"; |
| | | /**商户sm2公钥,需要配置到通联商户平台**/ |
| | | String cusPubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEKpQC1uKhgt2z9cd8KOULCsWgjBGSdjg008DkPnfFBlOxqCv8v1jAUFn+bqTJxVNOqeRcRqKF2GKAbZXYJtN4ag=="; |
| | | |
| | | /**通联平台sm2公钥,用于请求返回或者通联通知的验签**/ |
| | | String tlPubKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE/BnA8BawehBtH0ksPyayo4pmzL/u1FQ2sZcqwOp6bjVqQX4tjo930QAvHZPJ2eez8sCz/RYghcqv4LvMq+kloQ=="; |
| | | |
| | | String blankStr = "请求待签名数据"; |
| | | PrivateKey privkey = privKeySM2FromBase64Str(cusPrivateKey); |
| | | String sign = signSM3SM2RetBase64(privkey, appid, blankStr.getBytes("UTF-8"));//签名 |
| | | System.out.println(sign); |
| | | |
| | | String rspBlankStr = "返回待验签数据";//通联返回的明文 |
| | | String rspSign = "AovBKQGUe0xuJ0ox7FgIIX+yB3DzbudgUsnNvJmDV0IdHZtU2Y8vdeUY1pd2vmPUf08hNgdkoz+4WP/D/ktOcA==";//通联返回的签名 |
| | | PublicKey publicKey = pubKeySM2FromBase64Str(tlPubKey); |
| | | boolean isOk = verifySM3SM2(publicKey, "Allinpay", Base64.decodeBase64(rspSign), rspBlankStr.getBytes("UTF-8")); |
| | | System.out.println("验签结果:"+isOk); |
| | | |
| | | |
| | | } |
| | | |
| | | /**签名并BASE64编码-SM3WithSM2 */ |
| | | public static String signSM3SM2RetBase64(final PrivateKey privateKey,String certid,final byte[] data) throws Exception{ |
| | | return Base64.encodeBase64String(signSM3SM2(privateKey, certid, data)); |
| | | } |
| | | |
| | | /**签名-SM3WithSM2 */ |
| | | public static byte[] signSM3SM2(final PrivateKey privateKey,String certid,final byte[] data) throws Exception{ |
| | | SM2ParameterSpec parameterSpec = new SM2ParameterSpec(certid.getBytes()); |
| | | Signature signer = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC"); |
| | | signer.setParameter(parameterSpec); |
| | | signer.initSign(privateKey, new SecureRandom()); |
| | | signer.update(data); |
| | | return byteAsn12BytePlain(signer.sign()); |
| | | } |
| | | |
| | | /** 验证签名-SM3WithSM2*/ |
| | | public static boolean verifySM3SM2(final PublicKey publicKey,String certid,final byte[] signData, final byte[] srcData) throws Exception { |
| | | SM2ParameterSpec parameterSpec = new SM2ParameterSpec(certid.getBytes()); |
| | | Signature verifier = Signature.getInstance(ALGORITHM_SM3SM2_BCPROV, "BC"); |
| | | verifier.setParameter(parameterSpec); |
| | | verifier.initVerify(publicKey); |
| | | verifier.update(srcData); |
| | | return verifier.verify(bytePlain2ByteAsn1(signData)); |
| | | } |
| | | |
| | | /**从字符串读取私钥-目前支持PKCS8(keystr为BASE64格式)*/ |
| | | public static PrivateKey privKeySM2FromBase64Str(String keystr) throws Exception { |
| | | KeyFactory keyFactory = KeyFactory.getInstance("EC"); |
| | | return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(keystr))); |
| | | } |
| | | |
| | | /**从字符串读取RSA公钥(keystr为BASE64格式)*/ |
| | | public static PublicKey pubKeySM2FromBase64Str(String keystr) throws Exception { |
| | | KeyFactory keyFactory = KeyFactory.getInstance("EC"); |
| | | return keyFactory.generatePublic(new X509EncodedKeySpec(Base64.decodeBase64(keystr))); |
| | | } |
| | | |
| | | /** |
| | | * 将普通字节数组转换为ASN1字节数组 适用于SM3withSM2验签时验签明文转换 |
| | | */ |
| | | private static byte[] bytePlain2ByteAsn1(byte[] data) { |
| | | if (data.length != SM3withSM2_RS_LEN * 2) throw new RuntimeException("err data. "); |
| | | BigInteger r = new BigInteger(1, Arrays.copyOfRange(data, 0, SM3withSM2_RS_LEN)); |
| | | BigInteger s = new BigInteger(1, Arrays.copyOfRange(data, SM3withSM2_RS_LEN, SM3withSM2_RS_LEN * 2)); |
| | | ASN1EncodableVector v = new ASN1EncodableVector(); |
| | | v.add(new ASN1Integer(r)); |
| | | v.add(new ASN1Integer(s)); |
| | | try { |
| | | return new DERSequence(v).getEncoded("DER"); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | /** |
| | | * 将ASN1字节数组转换为普通字节数组 适用于SM3withSM2签名时签名结果转换 |
| | | */ |
| | | private static byte[] byteAsn12BytePlain(byte[] dataAsn1) { |
| | | ASN1Sequence seq = ASN1Sequence.getInstance(dataAsn1); |
| | | byte[] r = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(0)).getValue()); |
| | | byte[] s = bigIntToFixexLengthBytes(ASN1Integer.getInstance(seq.getObjectAt(1)).getValue()); |
| | | byte[] result = new byte[SM3withSM2_RS_LEN * 2]; |
| | | System.arraycopy(r, 0, result, 0, r.length); |
| | | System.arraycopy(s, 0, result, SM3withSM2_RS_LEN, s.length); |
| | | return result; |
| | | } |
| | | |
| | | private static byte[] bigIntToFixexLengthBytes(BigInteger rOrS) { |
| | | byte[] rs = rOrS.toByteArray(); |
| | | if (rs.length == SM3withSM2_RS_LEN) return rs; |
| | | else if (rs.length == SM3withSM2_RS_LEN + 1 && rs[0] == 0) |
| | | return Arrays.copyOfRange(rs, 1, SM3withSM2_RS_LEN + 1); |
| | | else if (rs.length < SM3withSM2_RS_LEN) { |
| | | byte[] result = new byte[SM3withSM2_RS_LEN]; |
| | | Arrays.fill(result, (byte) 0); |
| | | System.arraycopy(rs, 0, result, SM3withSM2_RS_LEN - rs.length, rs.length); |
| | | return result; |
| | | } else { |
| | | throw new RuntimeException("err rs: " + Hex.toHexString(rs)); |
| | | } |
| | | } |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.mzl.flower.pay; |
| | | |
| | | public class SybConstants { |
| | | // 测试环境测试参数 |
| | | // public static final String SYB_ORGID = "";//集团/机构模式下该参数不为空,且appid与key是与次参数对应 |
| | | // public static final String SYB_CUSID = "990581007426001"; |
| | | // public static final String SYB_APPID = "00000051"; |
| | | // public static final String SYB_MD5_APPKEY = "allinpay888"; |
| | | // public static final String SYB_APIURL = "http://172.16.1.10/apiweb"; |
| | | /**商户RSA私钥,用于向通联发起请求前进行签名**/ |
| | | // public static final String SYB_RSACUSPRIKEY = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAK5aIo+E1eyWwEIgMB8ZEZRAaWjSAglmfKVhzy8N1eLjAlqPjJgOCqXGEYt/r61AyIjCCJiYVDTHzcqstmbBU7HKpYjTsquCLjRWcL/fhMwMGBSg2bP5mqw5locSOz1gtRujmd3kZo9OIJuWtfG2+wgPPdKUdGZS+5K8WtWCF4z1AgMBAAECgYAPvvqvkPzb9tpqrmsCJ/qvM6kBazP9Ytjfe8ehFYQLT1qrUJsPMXdzNMHpYhD82eSyeymZFGrIcIIMq4/2lD+pYOMQTMGGjoVb2wnQhZFqPdgjXgOQ90E43X69jD3p5F8CuKVNa13I4l3iyfzlVIL780JPdJdug7yKEFdSeOQZUQJBAONlFpIqz87pbnwzfgO5kRTbbI7DcyObb8OEeCK3VlGB3r9P4NoMEDaXm+HnIdv53gnFq+xgbREWUt2nFq9dSUUCQQDESOIdSvIBc3KQTYR+cnlQTH0SOvm0Tlx4KekBCLxTFAFyBqnOBLdVyQb6Z1wxGz855AjnNbHy1rFhUYQ6hPfxAkAIRZUcnBITJMqwGe9rk0SDzbeVOebmVLEsG5WDLcgmDuNbcjxrsiSk178D6LSCnARHtrkaUCenh3hcN8fLeUlBAkABNP2G9pYEYkRbFM7yxBtw3feK7Cfq7uxspL1VD0uxKxdTLy1OIgNKmMDdO1N6zdMWtQtE+LSObLmMgqbQgU7RAkBFX5kl4+B3k+/aCYB/ndqd1nQIr4SNAtLFJDtlW2xah9W2lQL/7KQDT4o4dUMY51m7Bu61SAmKtralv7Hf25yf"; |
| | | // /**通联平台RSA公钥,用于请求返回或者通联通知的验签**/ |
| | | // public static final String SYB_RSATLPUBKEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYXfu4b7xgDSmEGQpQ8Sn3RzFgl5CE4gL4TbYrND4FtCYOrvbgLijkdFgIrVVWi2hUW4K0PwBsmlYhXcbR+JSmqv9zviVXZiym0lK3glJGVCN86r9EPvNTusZZPm40TOEKMVENSYaUjCxZ7JzeZDfQ4WCeQQr2xirqn6LdJjpZ5wIDAQAB"; |
| | | // |
| | | // /**商户sm2私钥,用于向通联发起请求前进行签名**/ |
| | | // public static final String SYB_SM2PPRIVATEKEY = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgjj4Rk+b0YjwO+UwXofnHf4bK+kaaY5Btkd8nMP2VimmgCgYIKoEcz1UBgi2hRANCAAQqlALW4qGC3bP1x3wo5QsKxaCMEZJ2ODTTwOQ+d8UGU7GoK/y/WMBQWf5upMnFU06p5FxGooXYYoBtldgm03hq"; |
| | | // /**通联平台sm2公钥,用于请求返回或者通联通知的验签**/ |
| | | // public static final String SYB_SM2TLPUBKEY = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE/BnA8BawehBtH0ksPyayo4pmzL/u1FQ2sZcqwOp6bjVqQX4tjo930QAvHZPJ2eez8sCz/RYghcqv4LvMq+kloQ=="; |
| | | |
| | | // 正式环境测试参数 |
| | | public static final String SYB_ORGID = "";//集团/机构模式下该参数不为空,且appid与key是与次参数对应 |
| | | public static final String SYB_CUSID = "660731051932PAJ"; |
| | | public static final String SYB_APPID = "00324494"; |
| | | public static final String SYB_MD5_APPKEY = "666888"; |
| | | public static final String SYB_APIURL = "https://vsp.allinpay.com/apiweb";//生产环境 |
| | | public static final String SYB_RSACUSPRIKEY = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDcvMSSSSyjeIFXpoc/aFScXgp1o9qbAO6fIGPRGFtwexSO4g3oP7sse8lL80bUNtj5Q7ysAEjVKW0fDpe/iJ0/jtqJ2CEL5aXDr6Fu7YR7zMLhbCDa531t64Iw4l0ADg3c+5jDSY3ck2rp5pX3RxYLpBb5VB2P005nMNJpG5oRuIRTMa0og07/cFMjhV3Q10eN6pBMnZ4jlXRjUUcftZhMCVUS9zAH16bcnbf6X6HJpBghuPEeIXKEwb+p8usvm4ZVcPh7Ha5dEdHeUGP7bCY9360plVfv20bZvucwlR4GuP6lDmMgqLF11jrEeGa+Fu+2e8wD0LnIfZjeenKLvlqFAgMBAAECggEAA2zmfAKor6y6DRsndCNxVK/c57BwPwGHsm51PhRrrtYqHoGBh74dcHZHTGdtDPQA7/VOIzkp6CzpZZb7YdyD3C2iVItHEAEzTlMWZTtIWAd4arkb1WnMN311Gr8YhFyzeF9rInSsv+SFvzV11E2FGQ8l0B6vCsFTsSQ/z6O/A1FbT3IaW5LTcsd6oysQr7ShT5yuCtuBuBypXI/7lmFoOn4O0/o5WFtqXr1295rpjv10WTycqZyfKh8W7CW7AKwT3SfuEodLBhmVHtu9TD+RNJRhu6ekv58vrnFAaRI7YUh/Kg3SfkvE0+Csp9meDGJJB6pbRwF8jdvTVd2kuWeM4QKBgQD+Ax/rxLRIGhc22cdw11c7anK7JkMU6J/K7i/zFJ6FJTixaz+zWOAxwyDPYSkyVeA555CSKAsXAtWd9vJHjFjgA4avPeF96C5WSZu26K+6pAz9VfyRYXw/2pZ060M+iBIinlTKu/B9SiYoiB5Y86Me9xFag4FrQvcghmV4zzhuyQKBgQDedvtm2hI7Gfna7fBOcr/69eiwxEvKhZ/1K0oRv9O2Sr0tFfUT0kSNejC1/CtRhaJN0TM4ZET7ajJZxfgK/lzyB3Utr60Sp5Vk0KaKVrwN7H3HOjQ8zE+YlbQwPRphgTM0/y0/wgq8sTmg1FKHHrHi4k7EusS4KEsD4AQ2pAl/3QKBgQCiIJBxRb3j/3MtuVcI+QlejRTpywQqBkhnmBvWxSRgy18iLtgbuvBuEqOQee13iURy8RBfmVtqto5uIr6FWFkpslZ258JTQKzCuny/BEmVkTwRPp7UlCpf/z7lJXxoHyWkHvbz530aGwe7+xWTpP5Kt1vGMAWc1sMxaVa/A1R7sQKBgQCkBZXWf3JxoPVXNZe4P2LM5gJqUlCPQXZujTxPWd/+x5wzYb0QoDdrGGxRwVsvABhqx5O8QDGcLPBywEPh1ykwSc9bn+s7ldPQQQaJeOmuWm9iNMfPC9Sj67yu1F5fBaN7r6jtGWRRO1oB+onelgMSBUmOQyZHoW2trb1tjAR1AQKBgQCJ7wwrATqy+4/1kcm1zWrwjI39Db27lyLb1TR5jPdmdOHmCMMoLrsB4fkpZhnlXIA7uIzkZX5+rNMAkGrV84ZWZ0Q5QXCCMtFypFlZPxh9q8Jb1aB1Abn3UTKgJfUalDo4H8Q+h1COlNPU/6YuWPl8gU489NI/rkopt25j0GhFqQ=="; |
| | | public static final String SYB_RSATLPUBKEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3LzEkkkso3iBV6aHP2hUnF4KdaPamwDunyBj0RhbcHsUjuIN6D+7LHvJS/NG1DbY+UO8rABI1SltHw6Xv4idP47aidghC+Wlw6+hbu2Ee8zC4Wwg2ud9beuCMOJdAA4N3PuYw0mN3JNq6eaV90cWC6QW+VQdj9NOZzDSaRuaEbiEUzGtKINO/3BTI4Vd0NdHjeqQTJ2eI5V0Y1FHH7WYTAlVEvcwB9em3J23+l+hyaQYIbjxHiFyhMG/qfLrL5uGVXD4ex2uXRHR3lBj+2wmPd+tKZVX79tG2b7nMJUeBrj+pQ5jIKixddY6xHhmvhbvtnvMA9C5yH2Y3npyi75ahQIDAQAB"; |
| | | |
| | | |
| | | |
| | | public static final String VERSION = "12"; |
| | | public static final String RET_URL = "https://test.allinpaygd.com/JWeb/reccomparams.jsp"; |
| | | public static final String NOTFIY_URL = "https://test.allinpaygd.com/JWeb/NotifyServlet"; |
| | | public static final String VALID_TIME = "5"; |
| | | public static final String SIGN_TYPE = "RSA";// |
| | | // /**商户sm2私钥,用于向通联发起请求前进行签名**/ |
| | | public static final String SYB_SM2PPRIVATEKEY = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgjj4Rk+b0YjwO+UwXofnHf4bK+kaaY5Btkd8nMP2VimmgCgYIKoEcz1UBgi2hRANCAAQqlALW4qGC3bP1x3wo5QsKxaCMEZJ2ODTTwOQ+d8UGU7GoK/y/WMBQWf5upMnFU06p5FxGooXYYoBtldgm03hq"; |
| | | // /**通联平台sm2公钥,用于请求返回或者通联通知的验签**/ |
| | | public static final String SYB_SM2TLPUBKEY = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEBQicgWm0KAMqhO3bdqMUEDrKQvYg8cCXHhdGwq7CGE6oJDzJ1P/94HpuVdBf1KidmPxr7HOH+0DAnpeCcx9TcQ=="; |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.mzl.flower.pay; |
| | | |
| | | import java.net.URLEncoder; |
| | | import java.util.Map; |
| | | import java.util.TreeMap; |
| | | |
| | | public class SybPayService { |
| | | |
| | | |
| | | /** |
| | | * 封装订单信息 |
| | | * @param trxamt 订单金额单位为分 |
| | | * @param reqsn 商户订单号 |
| | | * @param unireqsn 商户唯一订单号 |
| | | * @param body 订单标题,订单描述信息,展示在收银台 |
| | | * @param remark 备注 |
| | | * @param notifyUrl 服务器异步通知页面路径,交易完成后,平台会将交易结果以后台通知的方式发送到该地址,商户需要以此通知判断用户订单交易是否成功。 |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public TreeMap<String,String> createOrder(long trxamt, |
| | | String reqsn, |
| | | String unireqsn, |
| | | String body, |
| | | String remark, |
| | | String notifyUrl) throws Exception{ |
| | | TreeMap<String,String> params = new TreeMap<String,String>(); |
| | | if(!SybUtil.isEmpty(SybConstants.SYB_ORGID)) |
| | | params.put("orgid", SybConstants.SYB_ORGID); |
| | | params.put("cusid", SybConstants.SYB_CUSID); |
| | | params.put("appid", SybConstants.SYB_APPID); |
| | | params.put("version", "12"); |
| | | params.put("trxamt", String.valueOf(trxamt)); |
| | | params.put("reqsn", reqsn); |
| | | params.put("unireqsn", unireqsn); |
| | | params.put("notify_url", notifyUrl); |
| | | params.put("body", body); |
| | | params.put("remark", remark); |
| | | params.put("paytype", "W06"); |
| | | params.put("randomstr", SybUtil.getValidatecode(8)); |
| | | params.put("signtype", SybConstants.SIGN_TYPE); |
| | | String appkey = ""; |
| | | if(SybConstants.SIGN_TYPE.equals("RSA")) |
| | | appkey = SybConstants.SYB_RSACUSPRIKEY; |
| | | else if(SybConstants.SIGN_TYPE.equals("SM2")) |
| | | appkey = SybConstants.SYB_SM2PPRIVATEKEY; |
| | | else |
| | | appkey = SybConstants.SYB_MD5_APPKEY; |
| | | params.put("sign", SybUtil.unionSign(params,appkey,SybConstants.SIGN_TYPE)); |
| | | return params; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 撤销订单 |
| | | * @param trxamt 原订单金额 |
| | | * @param reqsn 商户的退款交易订单号 |
| | | * @param oldtrxid 原交易的收银宝平台流水 |
| | | * @param oldreqsn 原交易的商户交易单号 |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public Map<String,String> cancel(long trxamt,String reqsn,String oldtrxid,String oldreqsn) throws Exception{ |
| | | HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL+"/tranx/cancel"); |
| | | http.init(); |
| | | TreeMap<String,String> params = new TreeMap<String,String>(); |
| | | if(!SybUtil.isEmpty(SybConstants.SYB_ORGID)) |
| | | params.put("orgid", SybConstants.SYB_ORGID); |
| | | params.put("cusid", SybConstants.SYB_CUSID); |
| | | params.put("appid", SybConstants.SYB_APPID); |
| | | params.put("version", "11"); |
| | | params.put("trxamt", String.valueOf(trxamt)); |
| | | params.put("reqsn", reqsn); |
| | | params.put("oldtrxid", oldtrxid); |
| | | params.put("oldreqsn", oldreqsn); |
| | | params.put("randomstr", SybUtil.getValidatecode(8)); |
| | | params.put("signtype", SybConstants.SIGN_TYPE); |
| | | String appkey = ""; |
| | | if(SybConstants.SIGN_TYPE.equals("RSA")) |
| | | appkey = SybConstants.SYB_RSACUSPRIKEY; |
| | | else if(SybConstants.SIGN_TYPE.equals("SM2")) |
| | | appkey = SybConstants.SYB_SM2PPRIVATEKEY; |
| | | else |
| | | appkey = SybConstants.SYB_MD5_APPKEY; |
| | | params.put("sign", SybUtil.unionSign(params,appkey,SybConstants.SIGN_TYPE)); |
| | | byte[] bys = http.postParams(params, true); |
| | | String result = new String(bys,"UTF-8"); |
| | | Map<String,String> map = handleResult(result); |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * 退款 |
| | | * @param trxamt 退款金额单位为分 |
| | | * @param reqsn 商户的退款交易订单号 |
| | | * @param oldtrxid 原交易的收银宝平台流水 |
| | | * @param oldreqsn 原交易的商户订单号 |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public Map<String,String> refund(long trxamt,String reqsn,String oldtrxid,String oldreqsn) throws Exception{ |
| | | HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL+"/tranx/refund"); |
| | | http.init(); |
| | | TreeMap<String,String> params = new TreeMap<String,String>(); |
| | | if(!SybUtil.isEmpty(SybConstants.SYB_ORGID)) |
| | | params.put("orgid", SybConstants.SYB_ORGID); |
| | | params.put("cusid", SybConstants.SYB_CUSID); |
| | | params.put("appid", SybConstants.SYB_APPID); |
| | | params.put("version", "11"); |
| | | params.put("trxamt", String.valueOf(trxamt)); |
| | | params.put("reqsn", reqsn); |
| | | params.put("oldreqsn", oldreqsn); |
| | | params.put("oldtrxid", oldtrxid); |
| | | params.put("randomstr", SybUtil.getValidatecode(8)); |
| | | params.put("signtype", SybConstants.SIGN_TYPE); |
| | | String appkey = ""; |
| | | if(SybConstants.SIGN_TYPE.equals("RSA")) |
| | | appkey = SybConstants.SYB_RSACUSPRIKEY; |
| | | else if(SybConstants.SIGN_TYPE.equals("SM2")) |
| | | appkey = SybConstants.SYB_SM2PPRIVATEKEY; |
| | | else |
| | | appkey = SybConstants.SYB_MD5_APPKEY; |
| | | params.put("sign", SybUtil.unionSign(params,appkey,SybConstants.SIGN_TYPE)); |
| | | byte[] bys = http.postParams(params, true); |
| | | String result = new String(bys,"UTF-8"); |
| | | Map<String,String> map = handleResult(result); |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * 关闭订单 |
| | | * @param oldtrxid 原通联平台交易流水 |
| | | * @param oldreqsn 原商户订单号 |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public Map<String,String> close(String oldtrxid,String oldreqsn) throws Exception{ |
| | | HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL+"/tranx/close"); |
| | | http.init(); |
| | | TreeMap<String,String> params = new TreeMap<String,String>(); |
| | | if(!SybUtil.isEmpty(SybConstants.SYB_ORGID)) |
| | | params.put("orgid", SybConstants.SYB_ORGID); |
| | | params.put("cusid", SybConstants.SYB_CUSID); |
| | | params.put("appid", SybConstants.SYB_APPID); |
| | | params.put("version", "12"); |
| | | params.put("oldreqsn", oldreqsn); |
| | | params.put("oldtrxid", oldtrxid); |
| | | params.put("randomstr", SybUtil.getValidatecode(8)); |
| | | params.put("signtype", SybConstants.SIGN_TYPE); |
| | | String appkey = ""; |
| | | if(SybConstants.SIGN_TYPE.equals("RSA")) |
| | | appkey = SybConstants.SYB_RSACUSPRIKEY; |
| | | else if(SybConstants.SIGN_TYPE.equals("SM2")) |
| | | appkey = SybConstants.SYB_SM2PPRIVATEKEY; |
| | | else |
| | | appkey = SybConstants.SYB_MD5_APPKEY; |
| | | params.put("sign", SybUtil.unionSign(params,appkey,SybConstants.SIGN_TYPE)); |
| | | byte[] bys = http.postParams(params, true); |
| | | String result = new String(bys,"UTF-8"); |
| | | Map<String,String> map = handleResult(result); |
| | | return map; |
| | | } |
| | | |
| | | public Map<String,String> query(String reqsn,String trxid) throws Exception{ |
| | | HttpConnectionUtil http = new HttpConnectionUtil(SybConstants.SYB_APIURL+"/tranx/query"); |
| | | http.init(); |
| | | TreeMap<String,String> params = new TreeMap<String,String>(); |
| | | if(!SybUtil.isEmpty(SybConstants.SYB_ORGID)) |
| | | params.put("orgid", SybConstants.SYB_ORGID); |
| | | params.put("cusid", SybConstants.SYB_CUSID); |
| | | params.put("appid", SybConstants.SYB_APPID); |
| | | params.put("version", "11"); |
| | | params.put("reqsn", reqsn); |
| | | params.put("trxid", trxid); |
| | | params.put("randomstr", SybUtil.getValidatecode(8)); |
| | | params.put("signtype", SybConstants.SIGN_TYPE); |
| | | String appkey = ""; |
| | | if(SybConstants.SIGN_TYPE.equals("RSA")) |
| | | appkey = SybConstants.SYB_RSACUSPRIKEY; |
| | | else if(SybConstants.SIGN_TYPE.equals("SM2")) |
| | | appkey = SybConstants.SYB_SM2PPRIVATEKEY; |
| | | else |
| | | appkey = SybConstants.SYB_MD5_APPKEY; |
| | | params.put("sign", SybUtil.unionSign(params,appkey,SybConstants.SIGN_TYPE)); |
| | | byte[] bys = http.postParams(params, true); |
| | | String result = new String(bys,"UTF-8"); |
| | | Map<String,String> map = handleResult(result); |
| | | return map; |
| | | } |
| | | |
| | | |
| | | public static Map<String,String> handleResult(String result) throws Exception{ |
| | | System.out.println("ret:"+result); |
| | | Map map = SybUtil.json2Obj(result, Map.class); |
| | | if(map == null){ |
| | | throw new Exception("返回数据错误"); |
| | | } |
| | | if("SUCCESS".equals(map.get("retcode"))){ |
| | | TreeMap tmap = new TreeMap(); |
| | | tmap.putAll(map); |
| | | String appkey = ""; |
| | | if(SybConstants.SIGN_TYPE.equals("RSA")) |
| | | appkey = SybConstants.SYB_RSATLPUBKEY; |
| | | else if(SybConstants.SIGN_TYPE.equals("SM2")) |
| | | appkey = SybConstants.SYB_SM2TLPUBKEY; |
| | | else |
| | | appkey = SybConstants.SYB_MD5_APPKEY; |
| | | if(SybUtil.validSign(tmap, appkey, SybConstants.SIGN_TYPE)){ |
| | | System.out.println("签名成功"); |
| | | return map; |
| | | }else{ |
| | | throw new Exception("验证签名失败"); |
| | | } |
| | | |
| | | }else{ |
| | | throw new Exception(map.get("retmsg").toString()); |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
对比新文件 |
| | |
| | | package com.mzl.flower.pay; |
| | | |
| | | import java.io.UnsupportedEncodingException; |
| | | import java.security.KeyFactory; |
| | | import java.security.MessageDigest; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.PrivateKey; |
| | | import java.security.PublicKey; |
| | | import java.security.spec.PKCS8EncodedKeySpec; |
| | | import java.security.spec.X509EncodedKeySpec; |
| | | import java.util.Map; |
| | | import java.util.Random; |
| | | import java.util.TreeMap; |
| | | import org.apache.commons.codec.binary.Base64; |
| | | import net.sf.json.JSONObject; |
| | | |
| | | public class SybUtil { |
| | | /** |
| | | * js转化为实体 |
| | | * |
| | | * @param <T> |
| | | * @param jsonstr |
| | | * @param cls |
| | | * @return |
| | | */ |
| | | public static <T> T json2Obj(String jsonstr, Class<T> cls) { |
| | | JSONObject jo = JSONObject.fromObject(jsonstr); |
| | | T obj = (T) JSONObject.toBean(jo, cls); |
| | | return obj; |
| | | } |
| | | |
| | | /** |
| | | * md5 |
| | | * |
| | | * @param b |
| | | * @return |
| | | */ |
| | | public static String md5(byte[] b) { |
| | | try { |
| | | MessageDigest md = MessageDigest.getInstance("MD5"); |
| | | md.reset(); |
| | | md.update(b); |
| | | byte[] hash = md.digest(); |
| | | StringBuffer outStrBuf = new StringBuffer(32); |
| | | for (int i = 0; i < hash.length; i++) { |
| | | int v = hash[i] & 0xFF; |
| | | if (v < 16) { |
| | | outStrBuf.append('0'); |
| | | } |
| | | outStrBuf.append(Integer.toString(v, 16).toLowerCase()); |
| | | } |
| | | return outStrBuf.toString(); |
| | | } catch (NoSuchAlgorithmException e) { |
| | | e.printStackTrace(); |
| | | return new String(b); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 判断字符串是否为空 |
| | | * |
| | | * @param s |
| | | * @return |
| | | */ |
| | | public static boolean isEmpty(String s) { |
| | | if (s == null || "".equals(s.trim())) |
| | | return true; |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * 生成随机码 |
| | | * |
| | | * @param n |
| | | * @return |
| | | */ |
| | | public static String getValidatecode(int n) { |
| | | Random random = new Random(); |
| | | String sRand = ""; |
| | | n = n == 0 ? 4 : n;// default 4 |
| | | for (int i = 0; i < n; i++) { |
| | | String rand = String.valueOf(random.nextInt(10)); |
| | | sRand += rand; |
| | | } |
| | | return sRand; |
| | | } |
| | | |
| | | |
| | | |
| | | public static boolean validSign(TreeMap<String, String> param, |
| | | String appkey, String signType) throws Exception { |
| | | if (param != null && !param.isEmpty()) { |
| | | if (!param.containsKey("sign")) |
| | | return false; |
| | | String sign = param.remove("sign"); |
| | | if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序 |
| | | param.put("key", appkey); |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (Map.Entry<String, String> entry : param.entrySet()) { |
| | | if (entry.getValue() != null && entry.getValue().length() > 0) { |
| | | sb.append(entry.getKey()).append("=") |
| | | .append(entry.getValue()).append("&"); |
| | | } |
| | | } |
| | | if (sb.length() > 0) { |
| | | sb.deleteCharAt(sb.length() - 1); |
| | | } |
| | | if ("MD5".equals(signType)) { |
| | | return sign.toLowerCase().equals( |
| | | md5(sb.toString().getBytes("UTF-8")).toLowerCase()); |
| | | } else if("SM2".equals(signType)){ |
| | | PublicKey publicKey = SmUtil.pubKeySM2FromBase64Str(appkey); |
| | | return SmUtil.verifySM3SM2(publicKey, "Allinpay", Base64.decodeBase64(sign), sb.toString().getBytes("UTF-8")); |
| | | }else { |
| | | return rsaVerifyPublickey(sb.toString(), sign, appkey, "UTF-8"); |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | public static boolean rsaVerifyPublickey(String content, String sign, |
| | | String publicKey, String charset) throws Exception { |
| | | try { |
| | | PublicKey pubKey = getPublicKeyFromX509("RSA", |
| | | Base64.decodeBase64(publicKey.getBytes())); |
| | | return rsaVerifyPublickey(content, sign, pubKey, charset); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | throw new Exception("RSAcontent = " + content + ",sign=" + sign |
| | | + ",charset = " + charset, e); |
| | | } |
| | | } |
| | | |
| | | public static boolean rsaVerifyPublickey(String content, String sign, |
| | | PublicKey pubKey, String charset) throws Exception { |
| | | try { |
| | | java.security.Signature signature = java.security.Signature |
| | | .getInstance("SHA1WithRSA"); |
| | | |
| | | signature.initVerify(pubKey); |
| | | |
| | | if (charset == null || "".equals(charset)) { |
| | | signature.update(content.getBytes()); |
| | | } else { |
| | | signature.update(content.getBytes(charset)); |
| | | } |
| | | |
| | | return signature.verify(Base64.decodeBase64(sign.getBytes())); |
| | | } catch (Exception e) { |
| | | throw e; |
| | | } |
| | | } |
| | | public static String unionSign(TreeMap<String, String> params,String appkey, |
| | | String signType) throws Exception { |
| | | // TODO Auto-generated method stub |
| | | |
| | | params.remove("sign"); |
| | | if ("MD5".equals(signType)) {// 如果是md5则需要把md5的key加入到排序 |
| | | params.put("key", appkey); |
| | | } |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (Map.Entry<String, String> entry : params.entrySet()) { |
| | | if (entry.getValue() != null && entry.getValue().length() > 0) { |
| | | sb.append(entry.getKey()).append("=").append(entry.getValue()) |
| | | .append("&"); |
| | | } |
| | | } |
| | | if (sb.length() > 0) { |
| | | sb.deleteCharAt(sb.length() - 1); |
| | | } |
| | | String sign = ""; |
| | | if ("MD5".equals(signType)) { |
| | | System.out.println(sb.toString()); |
| | | sign = md5(sb.toString().getBytes("UTF-8"));// 记得是md5编码的加签 |
| | | params.remove("key"); |
| | | } else if("SM2".equals(signType)){ |
| | | System.out.println(sb.toString()); |
| | | PrivateKey privkey = SmUtil.privKeySM2FromBase64Str(appkey); |
| | | sign = SmUtil.signSM3SM2RetBase64(privkey, params.get("appid"), sb.toString().getBytes("UTF-8"));//签名 |
| | | } else { |
| | | System.out.println(sb.toString()); |
| | | sign = rsaSign(sb.toString(), appkey, "UTF-8"); |
| | | } |
| | | return sign; |
| | | } |
| | | |
| | | public static String rsaSign(String content, String privateKey, |
| | | String charset) throws Exception { |
| | | PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", |
| | | Base64.decodeBase64(privateKey.getBytes())); |
| | | return rsaSign(content, priKey, charset); |
| | | } |
| | | |
| | | public static String rsaSign(String content, byte[] privateKey, |
| | | String charset) throws Exception { |
| | | PrivateKey priKey = getPrivateKeyFromPKCS8("RSA", privateKey); |
| | | return rsaSign(content, priKey, charset); |
| | | } |
| | | |
| | | public static String rsaSign(String content, PrivateKey priKey, |
| | | String charset) throws Exception { |
| | | java.security.Signature signature = java.security.Signature |
| | | .getInstance("SHA1WithRSA"); |
| | | signature.initSign(priKey); |
| | | if (charset == null || "".equals(charset)) { |
| | | signature.update(content.getBytes()); |
| | | } else { |
| | | signature.update(content.getBytes(charset)); |
| | | } |
| | | byte[] signed = signature.sign(); |
| | | |
| | | return new String(Base64.encodeBase64(signed)); |
| | | } |
| | | |
| | | public static PrivateKey getPrivateKeyFromPKCS8(String algorithm, |
| | | byte[] encodedKey) throws Exception { |
| | | |
| | | KeyFactory keyFactory = KeyFactory.getInstance(algorithm); |
| | | |
| | | return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey)); |
| | | } |
| | | |
| | | public static PublicKey getPublicKeyFromX509(String algorithm, |
| | | byte[] encodedKey) throws Exception { |
| | | KeyFactory keyFactory = KeyFactory.getInstance(algorithm); |
| | | |
| | | return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey)); |
| | | } |
| | | } |