mirror of
https://gitee.com/durcframework/SOP.git
synced 2025-08-11 12:56:28 +08:00
5.0
This commit is contained in:
@@ -4,15 +4,13 @@
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-parent</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>com.gitee.sop</groupId>
|
||||
<artifactId>sop-test</artifactId>
|
||||
<version>5.0.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
@@ -42,7 +40,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.6</version>
|
||||
<version>1.18.34</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -60,7 +58,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.3</version>
|
||||
<version>3.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
|
@@ -1,8 +1,8 @@
|
||||
package com.gitee.sop.test;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.sop.test.alipay.AlipayApiException;
|
||||
import com.gitee.sop.test.alipay.AlipaySignature;
|
||||
import com.gitee.sop.test.sign.AlipayApiException;
|
||||
import com.gitee.sop.test.sign.AlipaySignature;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.File;
|
||||
@@ -10,7 +10,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -296,7 +295,8 @@ public class Client {
|
||||
|
||||
/**
|
||||
* 添加系统参数
|
||||
* @param name 参数名
|
||||
*
|
||||
* @param name 参数名
|
||||
* @param value 参数值
|
||||
* @return 返回RequestBuilder
|
||||
*/
|
||||
|
@@ -1,611 +0,0 @@
|
||||
/**
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.test.alipay;
|
||||
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class AlipaySignature {
|
||||
|
||||
/** RSA最大加密明文大小 */
|
||||
private static final int MAX_ENCRYPT_BLOCK = 117;
|
||||
|
||||
/** RSA最大解密密文大小 */
|
||||
private static final int MAX_DECRYPT_BLOCK = 128;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param sortedParams
|
||||
* @return
|
||||
*/
|
||||
public static String getSignContent(Map<String, String> sortedParams) {
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(sortedParams.keySet());
|
||||
Collections.sort(keys);
|
||||
int index = 0;
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = sortedParams.get(key);
|
||||
if (StringUtils.areNotEmpty(key, value)) {
|
||||
content.append((index == 0 ? "" : "&") + key + "=" + value);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* rsa内容签名
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaSign(String content, String privateKey, String charset,
|
||||
String signType) throws AlipayApiException {
|
||||
|
||||
if (AlipayConstants.SIGN_TYPE_RSA.equals(signType)) {
|
||||
|
||||
return rsaSign(content, privateKey, charset);
|
||||
} else if (AlipayConstants.SIGN_TYPE_RSA2.equals(signType)) {
|
||||
|
||||
return rsa256Sign(content, privateKey, charset);
|
||||
} else {
|
||||
|
||||
throw new AlipayApiException("Sign Type is Not Support : signType=" + signType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256WithRsa 加签
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsa256Sign(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_SHA256RSA_ALGORITHMS);
|
||||
|
||||
signature.initSign(priKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
|
||||
return new String(Base64.encodeBase64(signed));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("RSAcontent = " + content + "; charset = " + charset, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1WithRsa 加签
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaSign(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_ALGORITHMS);
|
||||
|
||||
signature.initSign(priKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
|
||||
return new String(Base64.encodeBase64(signed));
|
||||
} catch (InvalidKeySpecException ie) {
|
||||
throw new AlipayApiException("RSA私钥格式不正确,请检查是否正确配置了PKCS8格式的私钥", ie);
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("RSAcontent = " + content + "; charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String rsaSign(Map<String, String> params, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String signContent = getSignContent(params);
|
||||
|
||||
return rsaSign(signContent, privateKey, charset);
|
||||
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
|
||||
InputStream ins) throws Exception {
|
||||
if (ins == null || StringUtils.isEmpty(algorithm)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
byte[] encodedKey = StreamUtil.readText(ins).getBytes();
|
||||
|
||||
encodedKey = Base64.decodeBase64(encodedKey);
|
||||
|
||||
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
|
||||
}
|
||||
|
||||
public static String getSignCheckContentV1(Map<String, String> params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
params.remove("sign");
|
||||
params.remove("sign_type");
|
||||
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = params.get(key);
|
||||
content.append((i == 0 ? "" : "&") + key + "=" + value);
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public static String getSignCheckContentV2(Map<String, String> params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
params.remove("sign");
|
||||
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = params.get(key);
|
||||
content.append((i == 0 ? "" : "&") + key + "=" + value);
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV1(params);
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
|
||||
String charset,String signType) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV1(params);
|
||||
|
||||
return rsaCheck(content, sign, publicKey, charset,signType);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV2(params);
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
|
||||
String charset,String signType) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV2(params);
|
||||
|
||||
return rsaCheck(content, sign, publicKey, charset,signType);
|
||||
}
|
||||
|
||||
public static boolean rsaCheck(String content, String sign, String publicKey, String charset,
|
||||
String signType) throws AlipayApiException {
|
||||
|
||||
if (AlipayConstants.SIGN_TYPE_RSA.equals(signType)) {
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
|
||||
} else if (AlipayConstants.SIGN_TYPE_RSA2.equals(signType)) {
|
||||
|
||||
return rsa256CheckContent(content, sign, publicKey, charset);
|
||||
|
||||
} else {
|
||||
|
||||
throw new AlipayApiException("Sign Type is Not Support : signType=" + signType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean rsa256CheckContent(String content, String sign, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509("RSA",
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_SHA256RSA_ALGORITHMS);
|
||||
|
||||
signature.initVerify(pubKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
return signature.verify(Base64.decodeBase64(sign.getBytes()));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException(
|
||||
"RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean rsaCheckContent(String content, String sign, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509("RSA",
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_ALGORITHMS);
|
||||
|
||||
signature.initVerify(pubKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
return signature.verify(Base64.decodeBase64(sign.getBytes()));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException(
|
||||
"RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKeyFromX509(String algorithm,
|
||||
InputStream ins) throws Exception {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamUtil.io(new InputStreamReader(ins), writer);
|
||||
|
||||
byte[] encodedKey = writer.toString().getBytes();
|
||||
|
||||
encodedKey = Base64.decodeBase64(encodedKey);
|
||||
|
||||
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签并解密
|
||||
* <p>
|
||||
* <b>目前适用于公众号</b><br>
|
||||
* params参数示例:
|
||||
* <br>{
|
||||
* <br>biz_content=M0qGiGz+8kIpxe8aF4geWJdBn0aBTuJRQItLHo9R7o5JGhpic/MIUjvXo2BLB++BbkSq2OsJCEQFDZ0zK5AJYwvBgeRX30gvEj6eXqXRt16/IkB9HzAccEqKmRHrZJ7PjQWE0KfvDAHsJqFIeMvEYk1Zei2QkwSQPlso7K0oheo/iT+HYE8aTATnkqD/ByD9iNDtGg38pCa2xnnns63abKsKoV8h0DfHWgPH62urGY7Pye3r9FCOXA2Ykm8X4/Bl1bWFN/PFCEJHWe/HXj8KJKjWMO6ttsoV0xRGfeyUO8agu6t587Dl5ux5zD/s8Lbg5QXygaOwo3Fz1G8EqmGhi4+soEIQb8DBYanQOS3X+m46tVqBGMw8Oe+hsyIMpsjwF4HaPKMr37zpW3fe7xOMuimbZ0wq53YP/jhQv6XWodjT3mL0H5ACqcsSn727B5ztquzCPiwrqyjUHjJQQefFTzOse8snaWNQTUsQS7aLsHq0FveGpSBYORyA90qPdiTjXIkVP7mAiYiAIWW9pCEC7F3XtViKTZ8FRMM9ySicfuAlf3jtap6v2KPMtQv70X+hlmzO/IXB6W0Ep8DovkF5rB4r/BJYJLw/6AS0LZM9w5JfnAZhfGM2rKzpfNsgpOgEZS1WleG4I2hoQC0nxg9IcP0Hs+nWIPkEUcYNaiXqeBc=,
|
||||
* <br>sign=rlqgA8O+RzHBVYLyHmrbODVSANWPXf3pSrr82OCO/bm3upZiXSYrX5fZr6UBmG6BZRAydEyTIguEW6VRuAKjnaO/sOiR9BsSrOdXbD5Rhos/Xt7/mGUWbTOt/F+3W0/XLuDNmuYg1yIC/6hzkg44kgtdSTsQbOC9gWM7ayB4J4c=,
|
||||
* sign_type=RSA,
|
||||
* <br>charset=UTF-8
|
||||
* <br>}
|
||||
* </p>
|
||||
* @param params
|
||||
* @param alipayPublicKey 平台公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param isCheckSign 是否验签
|
||||
* @param isDecrypt 是否解密
|
||||
* @return 解密后明文,验签失败则异常抛出
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String checkSignAndDecrypt(Map<String, String> params, String alipayPublicKey,
|
||||
String cusPrivateKey, boolean isCheckSign,
|
||||
boolean isDecrypt) throws AlipayApiException {
|
||||
String charset = params.get("charset");
|
||||
String bizContent = params.get("biz_content");
|
||||
if (isCheckSign) {
|
||||
if (!rsaCheckV2(params, alipayPublicKey, charset)) {
|
||||
throw new AlipayApiException("rsaCheck failure:rsaParams=" + params);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDecrypt) {
|
||||
return rsaDecrypt(bizContent, cusPrivateKey, charset);
|
||||
}
|
||||
|
||||
return bizContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验签并解密
|
||||
* <p>
|
||||
* <b>目前适用于公众号</b><br>
|
||||
* params参数示例:
|
||||
* <br>{
|
||||
* <br>biz_content=M0qGiGz+8kIpxe8aF4geWJdBn0aBTuJRQItLHo9R7o5JGhpic/MIUjvXo2BLB++BbkSq2OsJCEQFDZ0zK5AJYwvBgeRX30gvEj6eXqXRt16/IkB9HzAccEqKmRHrZJ7PjQWE0KfvDAHsJqFIeMvEYk1Zei2QkwSQPlso7K0oheo/iT+HYE8aTATnkqD/ByD9iNDtGg38pCa2xnnns63abKsKoV8h0DfHWgPH62urGY7Pye3r9FCOXA2Ykm8X4/Bl1bWFN/PFCEJHWe/HXj8KJKjWMO6ttsoV0xRGfeyUO8agu6t587Dl5ux5zD/s8Lbg5QXygaOwo3Fz1G8EqmGhi4+soEIQb8DBYanQOS3X+m46tVqBGMw8Oe+hsyIMpsjwF4HaPKMr37zpW3fe7xOMuimbZ0wq53YP/jhQv6XWodjT3mL0H5ACqcsSn727B5ztquzCPiwrqyjUHjJQQefFTzOse8snaWNQTUsQS7aLsHq0FveGpSBYORyA90qPdiTjXIkVP7mAiYiAIWW9pCEC7F3XtViKTZ8FRMM9ySicfuAlf3jtap6v2KPMtQv70X+hlmzO/IXB6W0Ep8DovkF5rB4r/BJYJLw/6AS0LZM9w5JfnAZhfGM2rKzpfNsgpOgEZS1WleG4I2hoQC0nxg9IcP0Hs+nWIPkEUcYNaiXqeBc=,
|
||||
* <br>sign=rlqgA8O+RzHBVYLyHmrbODVSANWPXf3pSrr82OCO/bm3upZiXSYrX5fZr6UBmG6BZRAydEyTIguEW6VRuAKjnaO/sOiR9BsSrOdXbD5Rhos/Xt7/mGUWbTOt/F+3W0/XLuDNmuYg1yIC/6hzkg44kgtdSTsQbOC9gWM7ayB4J4c=,
|
||||
* sign_type=RSA,
|
||||
* <br>charset=UTF-8
|
||||
* <br>}
|
||||
* </p>
|
||||
* @param params
|
||||
* @param alipayPublicKey 平台公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param isCheckSign 是否验签
|
||||
* @param isDecrypt 是否解密
|
||||
* @return 解密后明文,验签失败则异常抛出
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String checkSignAndDecrypt(Map<String, String> params, String alipayPublicKey,
|
||||
String cusPrivateKey, boolean isCheckSign,
|
||||
boolean isDecrypt, String signType) throws AlipayApiException {
|
||||
String charset = params.get("charset");
|
||||
String bizContent = params.get("biz_content");
|
||||
if (isCheckSign) {
|
||||
if (!rsaCheckV2(params, alipayPublicKey, charset,signType)) {
|
||||
throw new AlipayApiException("rsaCheck failure:rsaParams=" + params);
|
||||
}
|
||||
}
|
||||
|
||||
if (isDecrypt) {
|
||||
return rsaDecrypt(bizContent, cusPrivateKey, charset);
|
||||
}
|
||||
|
||||
return bizContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密并签名<br>
|
||||
* <b>目前适用于公众号</b>
|
||||
* @param bizContent 待加密、签名内容
|
||||
* @param alipayPublicKey 平台公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @param isEncrypt 是否加密,true-加密 false-不加密
|
||||
* @param isSign 是否签名,true-签名 false-不签名
|
||||
* @return 加密、签名后xml内容字符串
|
||||
* <p>
|
||||
* 返回示例:
|
||||
* <alipay>
|
||||
* <response>密文</response>
|
||||
* <encryption_type>RSA</encryption_type>
|
||||
* <sign>sign</sign>
|
||||
* <sign_type>RSA</sign_type>
|
||||
* </alipay>
|
||||
* </p>
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String encryptAndSign(String bizContent, String alipayPublicKey,
|
||||
String cusPrivateKey, String charset, boolean isEncrypt,
|
||||
boolean isSign) throws AlipayApiException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
charset = AlipayConstants.CHARSET_GBK;
|
||||
}
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
|
||||
if (isEncrypt) {// 加密
|
||||
sb.append("<alipay>");
|
||||
String encrypted = rsaEncrypt(bizContent, alipayPublicKey, charset);
|
||||
sb.append("<response>" + encrypted + "</response>");
|
||||
sb.append("<encryption_type>RSA</encryption_type>");
|
||||
if (isSign) {
|
||||
String sign = rsaSign(encrypted, cusPrivateKey, charset);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>RSA</sign_type>");
|
||||
}
|
||||
sb.append("</alipay>");
|
||||
} else if (isSign) {// 不加密,但需要签名
|
||||
sb.append("<alipay>");
|
||||
sb.append("<response>" + bizContent + "</response>");
|
||||
String sign = rsaSign(bizContent, cusPrivateKey, charset);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>RSA</sign_type>");
|
||||
sb.append("</alipay>");
|
||||
} else {// 不加密,不加签
|
||||
sb.append(bizContent);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加密并签名<br>
|
||||
* <b>目前适用于公众号</b>
|
||||
* @param bizContent 待加密、签名内容
|
||||
* @param alipayPublicKey 平台公钥
|
||||
* @param cusPrivateKey 商户私钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @param isEncrypt 是否加密,true-加密 false-不加密
|
||||
* @param isSign 是否签名,true-签名 false-不签名
|
||||
* @return 加密、签名后xml内容字符串
|
||||
* <p>
|
||||
* 返回示例:
|
||||
* <alipay>
|
||||
* <response>密文</response>
|
||||
* <encryption_type>RSA</encryption_type>
|
||||
* <sign>sign</sign>
|
||||
* <sign_type>RSA</sign_type>
|
||||
* </alipay>
|
||||
* </p>
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String encryptAndSign(String bizContent, String alipayPublicKey,
|
||||
String cusPrivateKey, String charset, boolean isEncrypt,
|
||||
boolean isSign,String signType) throws AlipayApiException {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
charset = AlipayConstants.CHARSET_GBK;
|
||||
}
|
||||
sb.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>");
|
||||
if (isEncrypt) {// 加密
|
||||
sb.append("<alipay>");
|
||||
String encrypted = rsaEncrypt(bizContent, alipayPublicKey, charset);
|
||||
sb.append("<response>" + encrypted + "</response>");
|
||||
sb.append("<encryption_type>RSA</encryption_type>");
|
||||
if (isSign) {
|
||||
String sign = rsaSign(encrypted, cusPrivateKey, charset, signType);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>");
|
||||
sb.append(signType);
|
||||
sb.append("</sign_type>");
|
||||
}
|
||||
sb.append("</alipay>");
|
||||
} else if (isSign) {// 不加密,但需要签名
|
||||
sb.append("<alipay>");
|
||||
sb.append("<response>" + bizContent + "</response>");
|
||||
String sign = rsaSign(bizContent, cusPrivateKey, charset, signType);
|
||||
sb.append("<sign>" + sign + "</sign>");
|
||||
sb.append("<sign_type>");
|
||||
sb.append(signType);
|
||||
sb.append("</sign_type>");
|
||||
sb.append("</alipay>");
|
||||
} else {// 不加密,不加签
|
||||
sb.append(bizContent);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 公钥加密
|
||||
*
|
||||
* @param content 待加密内容
|
||||
* @param publicKey 公钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @return 密文内容
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaEncrypt(String content, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
Cipher cipher = Cipher.getInstance(AlipayConstants.SIGN_TYPE_RSA);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
|
||||
byte[] data = StringUtils.isEmpty(charset) ? content.getBytes()
|
||||
: content.getBytes(charset);
|
||||
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 = Base64.encodeBase64(out.toByteArray());
|
||||
out.close();
|
||||
|
||||
return StringUtils.isEmpty(charset) ? new String(encryptedData)
|
||||
: new String(encryptedData, charset);
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("EncryptContent = " + content + ",charset = " + charset,
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 私钥解密
|
||||
*
|
||||
* @param content 待解密内容
|
||||
* @param privateKey 私钥
|
||||
* @param charset 字符集,如UTF-8, GBK, GB2312
|
||||
* @return 明文内容
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaDecrypt(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
Cipher cipher = Cipher.getInstance(AlipayConstants.SIGN_TYPE_RSA);
|
||||
cipher.init(Cipher.DECRYPT_MODE, priKey);
|
||||
byte[] encryptedData = StringUtils.isEmpty(charset)
|
||||
? Base64.decodeBase64(content.getBytes())
|
||||
: Base64.decodeBase64(content.getBytes(charset));
|
||||
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 StringUtils.isEmpty(charset) ? new String(decryptedData)
|
||||
: new String(decryptedData, charset);
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("EncodeContent = " + content + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,171 +0,0 @@
|
||||
package com.gitee.sop.test.alipay;
|
||||
|
||||
/**
|
||||
* 字符串工具类。
|
||||
*
|
||||
* @author carver.gu
|
||||
* @since 1.0, Sep 12, 2009
|
||||
*/
|
||||
public abstract class StringUtils {
|
||||
|
||||
private StringUtils() {}
|
||||
|
||||
/**
|
||||
* 检查指定的字符串是否为空。
|
||||
* <ul>
|
||||
* <li>SysUtils.isEmpty(null) = true</li>
|
||||
* <li>SysUtils.isEmpty("") = true</li>
|
||||
* <li>SysUtils.isEmpty(" ") = true</li>
|
||||
* <li>SysUtils.isEmpty("abc") = false</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param value 待检查的字符串
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean isEmpty(String value) {
|
||||
int strLen;
|
||||
if (value == null || (strLen = value.length()) == 0) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < strLen; i++) {
|
||||
if ((Character.isWhitespace(value.charAt(i)) == false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否为数字型字符串,包含负数开头的。
|
||||
*/
|
||||
public static boolean isNumeric(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
char[] chars = obj.toString().toCharArray();
|
||||
int length = chars.length;
|
||||
if(length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
if(length > 1 && chars[0] == '-') {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
for (; i < length; i++) {
|
||||
if (!Character.isDigit(chars[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查指定的字符串列表是否不为空。
|
||||
*/
|
||||
public static boolean areNotEmpty(String... values) {
|
||||
boolean result = true;
|
||||
if (values == null || values.length == 0) {
|
||||
result = false;
|
||||
} else {
|
||||
for (String value : values) {
|
||||
result &= !isEmpty(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把通用字符编码的字符串转化为汉字编码。
|
||||
*/
|
||||
public static String unicodeToChinese(String unicode) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
if (!isEmpty(unicode)) {
|
||||
for (int i = 0; i < unicode.length(); i++) {
|
||||
out.append(unicode.charAt(i));
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤不可见字符
|
||||
*/
|
||||
public static String stripNonValidXMLCharacters(String input) {
|
||||
if (input == null || ("".equals(input))) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder out = new StringBuilder();
|
||||
char current;
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
current = input.charAt(i);
|
||||
if ((current == 0x9) || (current == 0xA) || (current == 0xD)
|
||||
|| ((current >= 0x20) && (current <= 0xD7FF))
|
||||
|| ((current >= 0xE000) && (current <= 0xFFFD))
|
||||
|| ((current >= 0x10000) && (current <= 0x10FFFF))) {
|
||||
out.append(current);
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public static String leftPad(String str, int size, char padChar) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
} else {
|
||||
int pads = size - str.length();
|
||||
if (pads <= 0) {
|
||||
return str;
|
||||
} else {
|
||||
return pads > 8192 ? leftPad(str, size, String.valueOf(padChar)) : padding(pads, padChar).concat(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String leftPad(String str, int size, String padStr) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (isEmpty(padStr)) {
|
||||
padStr = " ";
|
||||
}
|
||||
|
||||
int padLen = padStr.length();
|
||||
int strLen = str.length();
|
||||
int pads = size - strLen;
|
||||
if (pads <= 0) {
|
||||
return str;
|
||||
} else if (padLen == 1 && pads <= 8192) {
|
||||
return leftPad(str, size, padStr.charAt(0));
|
||||
} else if (pads == padLen) {
|
||||
return padStr.concat(str);
|
||||
} else if (pads < padLen) {
|
||||
return padStr.substring(0, pads).concat(str);
|
||||
} else {
|
||||
char[] padding = new char[pads];
|
||||
char[] padChars = padStr.toCharArray();
|
||||
|
||||
for(int i = 0; i < pads; ++i) {
|
||||
padding[i] = padChars[i % padLen];
|
||||
}
|
||||
|
||||
return (new String(padding)).concat(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
|
||||
if (repeat < 0) {
|
||||
throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
|
||||
} else {
|
||||
char[] buf = new char[repeat];
|
||||
|
||||
for(int i = 0; i < buf.length; ++i) {
|
||||
buf[i] = padChar;
|
||||
}
|
||||
|
||||
return new String(buf);
|
||||
}
|
||||
}
|
||||
}
|
@@ -2,11 +2,11 @@
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.test.alipay;
|
||||
package com.gitee.sop.test.sign;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class AlipayApiException extends Exception {
|
||||
@@ -46,4 +46,4 @@ public class AlipayApiException extends Exception {
|
||||
return this.errMsg;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -2,10 +2,10 @@
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.test.alipay;
|
||||
package com.gitee.sop.test.sign;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class AlipayConstants {
|
@@ -0,0 +1,335 @@
|
||||
/**
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.test.sign;
|
||||
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author runzhi
|
||||
*/
|
||||
public class AlipaySignature {
|
||||
|
||||
/**
|
||||
* RSA最大加密明文大小
|
||||
*/
|
||||
private static final int MAX_ENCRYPT_BLOCK = 117;
|
||||
|
||||
/**
|
||||
* RSA最大解密密文大小
|
||||
*/
|
||||
private static final int MAX_DECRYPT_BLOCK = 128;
|
||||
|
||||
|
||||
/**
|
||||
* @param sortedParams
|
||||
* @return
|
||||
*/
|
||||
public static String getSignContent(Map<String, String> sortedParams) {
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(sortedParams.keySet());
|
||||
Collections.sort(keys);
|
||||
int index = 0;
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = sortedParams.get(key);
|
||||
if (StringUtils.areNotEmpty(key, value)) {
|
||||
content.append((index == 0 ? "" : "&") + key + "=" + value);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* rsa内容签名
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaSign(String content, String privateKey, String charset,
|
||||
String signType) throws AlipayApiException {
|
||||
|
||||
if (AlipayConstants.SIGN_TYPE_RSA.equals(signType)) {
|
||||
|
||||
return rsaSign(content, privateKey, charset);
|
||||
} else if (AlipayConstants.SIGN_TYPE_RSA2.equals(signType)) {
|
||||
|
||||
return rsa256Sign(content, privateKey, charset);
|
||||
} else {
|
||||
|
||||
throw new AlipayApiException("Sign Type is Not Support : signType=" + signType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sha256WithRsa 加签
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsa256Sign(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_SHA256RSA_ALGORITHMS);
|
||||
|
||||
signature.initSign(priKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
|
||||
return new String(Base64.encodeBase64(signed));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("RSAcontent = " + content + "; charset = " + charset, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1WithRsa 加签
|
||||
*
|
||||
* @param content
|
||||
* @param privateKey
|
||||
* @param charset
|
||||
* @return
|
||||
* @throws AlipayApiException
|
||||
*/
|
||||
public static String rsaSign(String content, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PrivateKey priKey = getPrivateKeyFromPKCS8(AlipayConstants.SIGN_TYPE_RSA,
|
||||
new ByteArrayInputStream(privateKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_ALGORITHMS);
|
||||
|
||||
signature.initSign(priKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
|
||||
return new String(Base64.encodeBase64(signed));
|
||||
} catch (InvalidKeySpecException ie) {
|
||||
throw new AlipayApiException("RSA私钥格式不正确,请检查是否正确配置了PKCS8格式的私钥", ie);
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException("RSAcontent = " + content + "; charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static String rsaSign(Map<String, String> params, String privateKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String signContent = getSignContent(params);
|
||||
|
||||
return rsaSign(signContent, privateKey, charset);
|
||||
|
||||
}
|
||||
|
||||
public static PrivateKey getPrivateKeyFromPKCS8(String algorithm,
|
||||
InputStream ins) throws Exception {
|
||||
if (ins == null || StringUtils.isEmpty(algorithm)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
byte[] encodedKey = StreamUtil.readText(ins).getBytes();
|
||||
|
||||
encodedKey = Base64.decodeBase64(encodedKey);
|
||||
|
||||
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
|
||||
}
|
||||
|
||||
public static String getSignCheckContentV1(Map<String, String> params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
params.remove("sign");
|
||||
params.remove("sign_type");
|
||||
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = params.get(key);
|
||||
content.append((i == 0 ? "" : "&") + key + "=" + value);
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public static String getSignCheckContentV2(Map<String, String> params) {
|
||||
if (params == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
params.remove("sign");
|
||||
|
||||
StringBuffer content = new StringBuffer();
|
||||
List<String> keys = new ArrayList<String>(params.keySet());
|
||||
Collections.sort(keys);
|
||||
|
||||
for (int i = 0; i < keys.size(); i++) {
|
||||
String key = keys.get(i);
|
||||
String value = params.get(key);
|
||||
content.append((i == 0 ? "" : "&") + key + "=" + value);
|
||||
}
|
||||
|
||||
return content.toString();
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV1(params);
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV1(Map<String, String> params, String publicKey,
|
||||
String charset, String signType) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV1(params);
|
||||
|
||||
return rsaCheck(content, sign, publicKey, charset, signType);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV2(params);
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
}
|
||||
|
||||
public static boolean rsaCheckV2(Map<String, String> params, String publicKey,
|
||||
String charset, String signType) throws AlipayApiException {
|
||||
String sign = params.get("sign");
|
||||
String content = getSignCheckContentV2(params);
|
||||
|
||||
return rsaCheck(content, sign, publicKey, charset, signType);
|
||||
}
|
||||
|
||||
public static boolean rsaCheck(String content, String sign, String publicKey, String charset,
|
||||
String signType) throws AlipayApiException {
|
||||
|
||||
if (AlipayConstants.SIGN_TYPE_RSA.equals(signType)) {
|
||||
|
||||
return rsaCheckContent(content, sign, publicKey, charset);
|
||||
|
||||
} else if (AlipayConstants.SIGN_TYPE_RSA2.equals(signType)) {
|
||||
|
||||
return rsa256CheckContent(content, sign, publicKey, charset);
|
||||
|
||||
} else {
|
||||
|
||||
throw new AlipayApiException("Sign Type is Not Support : signType=" + signType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static boolean rsa256CheckContent(String content, String sign, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509("RSA",
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_SHA256RSA_ALGORITHMS);
|
||||
|
||||
signature.initVerify(pubKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
return signature.verify(Base64.decodeBase64(sign.getBytes()));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException(
|
||||
"RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean rsaCheckContent(String content, String sign, String publicKey,
|
||||
String charset) throws AlipayApiException {
|
||||
try {
|
||||
PublicKey pubKey = getPublicKeyFromX509("RSA",
|
||||
new ByteArrayInputStream(publicKey.getBytes()));
|
||||
|
||||
java.security.Signature signature = java.security.Signature
|
||||
.getInstance(AlipayConstants.SIGN_ALGORITHMS);
|
||||
|
||||
signature.initVerify(pubKey);
|
||||
|
||||
if (StringUtils.isEmpty(charset)) {
|
||||
signature.update(content.getBytes());
|
||||
} else {
|
||||
signature.update(content.getBytes(charset));
|
||||
}
|
||||
|
||||
return signature.verify(Base64.decodeBase64(sign.getBytes()));
|
||||
} catch (Exception e) {
|
||||
throw new AlipayApiException(
|
||||
"RSAcontent = " + content + ",sign=" + sign + ",charset = " + charset, e);
|
||||
}
|
||||
}
|
||||
|
||||
public static PublicKey getPublicKeyFromX509(String algorithm,
|
||||
InputStream ins) throws Exception {
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
StreamUtil.io(new InputStreamReader(ins), writer);
|
||||
|
||||
byte[] encodedKey = writer.toString().getBytes();
|
||||
|
||||
encodedKey = Base64.decodeBase64(encodedKey);
|
||||
|
||||
return keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
* Alipay.com Inc.
|
||||
* Copyright (c) 2004-2012 All Rights Reserved.
|
||||
*/
|
||||
package com.gitee.sop.test.alipay;
|
||||
package com.gitee.sop.test.sign;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -13,7 +13,7 @@ import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author runzhi
|
||||
*/
|
||||
public class StreamUtil {
|
168
sop-test/src/main/java/com/gitee/sop/test/sign/StringUtils.java
Normal file
168
sop-test/src/main/java/com/gitee/sop/test/sign/StringUtils.java
Normal file
@@ -0,0 +1,168 @@
|
||||
package com.gitee.sop.test.sign;
|
||||
|
||||
/**
|
||||
* 字符串工具类。
|
||||
*/
|
||||
public abstract class StringUtils {
|
||||
|
||||
private StringUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查指定的字符串是否为空。
|
||||
* <ul>
|
||||
* <li>SysUtils.isEmpty(null) = true</li>
|
||||
* <li>SysUtils.isEmpty("") = true</li>
|
||||
* <li>SysUtils.isEmpty(" ") = true</li>
|
||||
* <li>SysUtils.isEmpty("abc") = false</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param value 待检查的字符串
|
||||
* @return true/false
|
||||
*/
|
||||
public static boolean isEmpty(String value) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < value.length(); i++) {
|
||||
if ((!Character.isWhitespace(value.charAt(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查对象是否为数字型字符串,包含负数开头的。
|
||||
*/
|
||||
public static boolean isNumeric(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
char[] chars = obj.toString().toCharArray();
|
||||
int length = chars.length;
|
||||
if (length < 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
if (length > 1 && chars[0] == '-') {
|
||||
i = 1;
|
||||
}
|
||||
|
||||
for (; i < length; i++) {
|
||||
if (!Character.isDigit(chars[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查指定的字符串列表是否不为空。
|
||||
*/
|
||||
public static boolean areNotEmpty(String... values) {
|
||||
boolean result = true;
|
||||
if (values == null || values.length == 0) {
|
||||
result = false;
|
||||
} else {
|
||||
for (String value : values) {
|
||||
result &= !isEmpty(value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把通用字符编码的字符串转化为汉字编码。
|
||||
*/
|
||||
public static String unicodeToChinese(String unicode) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
if (!isEmpty(unicode)) {
|
||||
for (int i = 0; i < unicode.length(); i++) {
|
||||
out.append(unicode.charAt(i));
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 过滤不可见字符
|
||||
*/
|
||||
public static String stripNonValidXMLCharacters(String input) {
|
||||
if (input == null || ("".equals(input))) {
|
||||
return "";
|
||||
}
|
||||
StringBuilder out = new StringBuilder();
|
||||
char current;
|
||||
for (int i = 0; i < input.length(); i++) {
|
||||
current = input.charAt(i);
|
||||
if ((current == 0x9) || (current == 0xA) || (current == 0xD)
|
||||
|| ((current >= 0x20) && (current <= 0xD7FF))
|
||||
|| ((current >= 0xE000) && (current <= 0xFFFD))
|
||||
|| ((current >= 0x10000) && (current <= 0x10FFFF))) {
|
||||
out.append(current);
|
||||
}
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public static String leftPad(String str, int size, char padChar) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
} else {
|
||||
int pads = size - str.length();
|
||||
if (pads <= 0) {
|
||||
return str;
|
||||
} else {
|
||||
return pads > 8192 ? leftPad(str, size, String.valueOf(padChar)) : padding(pads, padChar).concat(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String leftPad(String str, int size, String padStr) {
|
||||
if (str == null) {
|
||||
return null;
|
||||
} else {
|
||||
if (isEmpty(padStr)) {
|
||||
padStr = " ";
|
||||
}
|
||||
|
||||
int padLen = padStr.length();
|
||||
int strLen = str.length();
|
||||
int pads = size - strLen;
|
||||
if (pads <= 0) {
|
||||
return str;
|
||||
} else if (padLen == 1 && pads <= 8192) {
|
||||
return leftPad(str, size, padStr.charAt(0));
|
||||
} else if (pads == padLen) {
|
||||
return padStr.concat(str);
|
||||
} else if (pads < padLen) {
|
||||
return padStr.substring(0, pads).concat(str);
|
||||
} else {
|
||||
char[] padding = new char[pads];
|
||||
char[] padChars = padStr.toCharArray();
|
||||
|
||||
for (int i = 0; i < pads; ++i) {
|
||||
padding[i] = padChars[i % padLen];
|
||||
}
|
||||
|
||||
return (new String(padding)).concat(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String padding(int repeat, char padChar) throws IndexOutOfBoundsException {
|
||||
if (repeat < 0) {
|
||||
throw new IndexOutOfBoundsException("Cannot pad a negative amount: " + repeat);
|
||||
} else {
|
||||
char[] buf = new char[repeat];
|
||||
|
||||
for (int i = 0; i < buf.length; ++i) {
|
||||
buf[i] = padChar;
|
||||
}
|
||||
|
||||
return new String(buf);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
package com.gitee.sop.test.taobao;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
public class Constants {
|
||||
public static final String SIGN_METHOD_HMAC = "hmac";
|
||||
public static final String SIGN_METHOD_MD5 = "md5";
|
||||
public static final String CHARSET_UTF8 = "UTF-8";
|
||||
}
|
@@ -1,95 +0,0 @@
|
||||
package com.gitee.sop.test.taobao;
|
||||
|
||||
import com.gitee.sop.test.alipay.StringUtils;
|
||||
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author 六如
|
||||
*/
|
||||
public class TaobaoSignature {
|
||||
|
||||
|
||||
public static String signTopRequest(Map<String, String> params, String secret, String signMethod) throws IOException {
|
||||
String content = getSignContent(params);
|
||||
return doSign(content, secret, signMethod);
|
||||
}
|
||||
|
||||
public static String getSignContent(Map<String, String> params) {
|
||||
// 第一步:检查参数是否已经排序
|
||||
String[] keys = params.keySet().toArray(new String[0]);
|
||||
Arrays.sort(keys);
|
||||
|
||||
// 第二步:把所有参数名和参数值串在一起
|
||||
StringBuilder query = new StringBuilder();
|
||||
|
||||
for (String key : keys) {
|
||||
String value = params.get(key);
|
||||
if (StringUtils.areNotEmpty(key, value)) {
|
||||
query.append(key).append(value);
|
||||
}
|
||||
}
|
||||
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
public static String doSign(String content,String secret, String signMethod) throws IOException {
|
||||
// 第三步:使用MD5/HMAC加密
|
||||
byte[] bytes;
|
||||
if (Constants.SIGN_METHOD_HMAC.equals(signMethod)) {
|
||||
bytes = encryptHMAC(content, secret);
|
||||
} else {
|
||||
bytes = encryptMD5(secret + content + secret);
|
||||
}
|
||||
|
||||
// 第四步:把二进制转化为大写的十六进制(正确签名应该为32大写字符串,此方法需要时使用)
|
||||
return byte2hex(bytes);
|
||||
}
|
||||
|
||||
public static byte[] encryptHMAC(String data, String secret) throws IOException {
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
SecretKey secretKey = new SecretKeySpec(secret.getBytes(Constants.CHARSET_UTF8), "HmacMD5");
|
||||
Mac mac = Mac.getInstance(secretKey.getAlgorithm());
|
||||
mac.init(secretKey);
|
||||
bytes = mac.doFinal(data.getBytes(Constants.CHARSET_UTF8));
|
||||
} catch (GeneralSecurityException gse) {
|
||||
throw new IOException(gse.toString());
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static byte[] encryptMD5(String data) throws IOException {
|
||||
return encryptMD5(data.getBytes(Constants.CHARSET_UTF8));
|
||||
}
|
||||
|
||||
public static byte[] encryptMD5(byte[] data) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance(Constants.SIGN_METHOD_MD5);
|
||||
return digest.digest(data);
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String byte2hex(byte[] bytes) {
|
||||
StringBuilder sign = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
String hex = Integer.toHexString(bytes[i] & 0xFF);
|
||||
if (hex.length() == 1) {
|
||||
sign.append("0");
|
||||
}
|
||||
sign.append(hex.toUpperCase());
|
||||
}
|
||||
return sign.toString();
|
||||
}
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
package com.gitee.sop.test;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.gitee.sop.test.alipay.AlipaySignature;
|
||||
import com.gitee.sop.test.sign.AlipaySignature;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
Reference in New Issue
Block a user