API Signature Generate
# Unified signature generation rules
Only the parameter value participates in the signature, the Key (parameter name) is only sorted and does not participate in the signature calculation
- Sort the Key (parameter name) of all non-empty parameters according to
ASCII
- According to the order of Key (parameter name), take the parameter values one by one for parallel splicing, and use the
RSA
algorithm to calculate the string to calculate the signature string
# Example description
- Example Parameters
Parameters | Example |
---|---|
merchantCode | S82023000000000000001 |
orderType | 0 |
method | qrPay |
orderNum | T13748238583 |
payMoney | 100 |
notifyUrl | http://notifyUrl |
dateTime | 2099-99-99 01:01:01 |
- Splicing strings
- First sort the Key (parameter name) according to ASCII
- Then sort the values according to Key (parameter name) and concatenate them into a string.
StrA = 2099-99-99 01:01:01S82023000000000000001qrPayhttp://notifyUrlT137482385830100
- Calculate Signature
- Use the key pair you configured in TopPay Merchant Backend
- Use your private key to perform encryption calculation RSA(StrA) to obtain the final signature string
Sign = IMLn23c4orM+7pZhHoRmbjrol4X33jeAqFxbZuQ+pnznBIGhb6 ...
# Code Example
import com.google.gson.JsonObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* <p>
* TopPay RSA signatureToolClass
* </p>
*
* @author TopPay
*/
public class TopPayRequestUtil {
/**
* VERIFY SIGNATURE
* @param params
* @return
*/
public static boolean verifySign(JsonObject params, String publickey) throws InvalidKeySpecException, NoSuchAlgorithmException {
String platSign = params.remove("platSign").getAsString(); // sign
List<String> paramNameList = new ArrayList<>(params.keySet());
Collections.sort(paramNameList);
StringBuilder stringBuilder = new StringBuilder();
for (String name : paramNameList) {
stringBuilder.append(params.get(name).getAsString());
}
System.out.println("keys:" + stringBuilder);
String decryptSign = publicDecrypt(platSign, getPublicKey(publickey));
System.out.println("decryptSign:" + decryptSign);
return stringBuilder.toString().equals(decryptSign);
}
/**
* PRIVATE KEY ENCRYPTION
* @param data
* @param privateKey
* @return
*/
public static String privateEncrypt(String data, RSAPrivateKey privateKey){
try{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return Base64.encodeBase64String(rsaSplitCodec(cipher, Cipher.ENCRYPT_MODE, data.getBytes("UTF-8"), privateKey.getModulus().bitLength()));
}catch(Exception e){
throw new RuntimeException("ENCRYPTED STRING[" + data + "]Encountered an exception", e);
}
}
/**
* PUBLIC KEY DECRYPTION
* @param data
* @param publicKey
* @return
*/
public static String publicDecrypt(String data, RSAPublicKey publicKey){
try{
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return new String(rsaSplitCodec(cipher, Cipher.DECRYPT_MODE, Base64.decodeBase64(data), publicKey.getModulus().bitLength()), "UTF-8");
}catch(Exception e){
throw new RuntimeException("When attempting to encrypt the string [" + data + "], an exception occurred.", e);
}
}
/**
* GET PRIVATE KEY
* @param privateKey KEY STRING (BASE 64 ENCODED)
*/
public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//Obtain the private key object through the Key command encoded by PKCS 8
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
return key;
}
/**
* GET PUBLIC KEY
* @param publicKey KEY STRING (BASE 64 ENCODED)
*/
public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
//Obtain the public key object through the Key command encoded by X509
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(Base64.decodeBase64(publicKey));
RSAPublicKey key = (RSAPublicKey) keyFactory.generatePublic(x509KeySpec);
return key;
}
private static byte[] rsaSplitCodec(Cipher cipher, int opmode, byte[] datas, int keySize){
int maxBlock = 0;
if(opmode == Cipher.DECRYPT_MODE){
maxBlock = keySize / 8;
}else{
maxBlock = keySize / 8 - 11;
}
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] buff;
int i = 0;
try{
while(datas.length > offSet){
if(datas.length-offSet > maxBlock){
buff = cipher.doFinal(datas, offSet, maxBlock);
}else{
buff = cipher.doFinal(datas, offSet, datas.length-offSet);
}
out.write(buff, 0, buff.length);
i++;
offSet = i * maxBlock;
}
}catch(Exception e){
throw new RuntimeException("An exception occurred while encrypting or decrypting data with a threshold of [" + maxBlock + "].", e);
}
byte[] resultDatas = out.toByteArray();
IOUtils.closeQuietly(out);
return resultDatas;
}
public static String doPost(String url,String json) throws IOException {
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
StringEntity s = new StringEntity(json);
s.setContentEncoding("UTF-8");
s.setContentType("application/json");//SENDING JSON DATA NEEDS TO SET CONTENT TYPE
post.setEntity(s);
HttpResponse res = client.execute(post);
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
return EntityUtils.toString(res.getEntity());// RETURN JSON FORMAT
}
return null;
}
}