GenerateAnInterfaceSignature

# UnifiedSignatureGenerationRules

onlyParameterValuesParticipateInTheSignature, Key(theNameOfTheParameter) Only the sorting is performed, and it does not participate in the signature calculation

  1. replaceAllNonNullParameters Key(theNameOfTheParameter) follow ASCII sort
  2. According to the order of the key (parameter name), the parameter values are taken one by one and concatenated in parallel, and the signature string is calculated by using the 'RSA' algorithm to calculate the signature string

# IllustratedByExample

  • ExampleParameters
parameters type required describe example
mchNo string(32) Y The merchant ID can be obtained from the merchant platform - personal account - personal information S820211021094748000001
method string(16) N paymentMethods BCA
orderNum string(64) Y merchantOrderNumber T1642592278863
amount int(10) Y theAmountOfThePayment 10000
productDetail string(100) Y paymentDescription Test Pay
customerName string(64) Y theNameOfTheBusiness JackMa
expiryPeriod int(5) Y orderExpirationTime 1440
customeEmail string(64) Y merchantEmailAddress [email protected]
customerPhone string(32) Y merchantSMobilePhoneNumber 082122965511
  • ConcatenateStrings
  1. firstSortTheKeysParameterNamesByASCII
  2. Then, according to the key (parameter name), the values are sorted in order and concatenated into a string

StrA = 2022-01-01 10:55:[email protected] notify urlT1642593166888150.60082122965511Test Pay

  • CalculateTheSignature
  1. Use the key pair you configured in the TopPay Merchant Portal
  2. Use your privateKey to perform cryptographic calculations, RSA (StrA) to obtain the final signature string

sign = IMLn23c4orM+7pZhHoRmbjrol4X33jeAqFxbZuQ+pnznBIGhb6Ail3qQPmKwcuhNCt536nmldpbWI72 k1lDxd0zZ95ZHElcNzwTFHFKtd8063uy6rFaxaW6DQ47t4U/95dpGfHAZe0GiIFAQ6xQquaoLINyQa4QqL+cpB JFEg1dyW6GYLFSdJnx7ycQvFYllmOpGZmdPLny62GvrCWvkiIARUsmc9fpkpTx5UQEDTgmhwdCKBkhHVsx2AiQ bYDxZ5WBuU1GZeiJjPuzSxvzWP6VoQBsfpwTI5kdJs6aQCekGO2/YScD+tGgrm2J89Pc/axPcb1xZzsi5SxpWh feabQ\u003d\u003d

# CodeSamples

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 signatureUtilityClass
 * </p>
 *
 * @author TopPay
 */
public class TopPayRequestUtil {

    /**
     * verifyTheSignature
     * @param params
     * @return
     */
    public static boolean verifySign(JsonObject params, String publickey) throws InvalidKeySpecException, NoSuchAlgorithmException {
        String platSign = params.remove("platSign").getAsString(); // signature
        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);
    }

    /**
     * privateKeyEncryption
     * @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("encryptStrings[" + data + "]anExceptionWasEncountered", e);
        }
    }

    /**
     * publicKeyDecryption
     * @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("decryptTheString[" + data + "]anExceptionWasEncountered", e);
        }
    }

    /**
     * getThePrivateKey
     * @param privateKey keyString(base64Encoded)
     */
    public static RSAPrivateKey getPrivateKey(String privateKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //The private key object is obtained through the PKCS#8 encoded Key instruction
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey));
        RSAPrivateKey key = (RSAPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
        return key;
    }

    /**
     * getThePublicKey
     * @param publicKey keyStringBase64Encoded
     */
    public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
        //The public key object is obtained through the X509 encoded Key instruction
        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("theEncryptionAndDecryptionThresholdsAre["+maxBlock+"]anExceptionOccurredWhileTheDataWasInPlace", 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");//toSendJsonDataYouNeedToSetContentType
        post.setEntity(s);
        HttpResponse res = client.execute(post);
        if(res.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
            return EntityUtils.toString(res.getEntity());// returnInJsonFormat

        }
        return null;
    }
}