Regarding Signature

  • Currently, the secret is obtained through offline methods or the merchant management platform.
  • Secret:The secret is used to digest and sign the input parameters for API requests. It should be kept by the merchant themselves, and it is essential to ensure strict security measures to prevent its disclosure to external parties.
  • To generate a signature string:all the parameters that need to be verified should be assembled into an array and sorted in ascending order based on the parameter names' dictionary order using ASCII code. It's important to note that only the parameter keys are sorted, and the values are not involved in the sorting process.
  • All required field values participate in the signature calculation (excluding "sign").
Signature String Example:
  • For example, given the parameters:

    {
      "email": "[email protected]",
      "appId": "qmamnbodyqzbdr0w"
    }
    
  • To prepare the string for signing, convert the format of each parameter to "parameter_name=parameter_value" and join them using the "&" symbol. Finally, append the key (secret) at the end. The resulting string would be as follows:

    appId=qmamnbodyqzbdr0w&[email protected]&key=6fdbaac29eb94bc6b36547ad705e9298
    
  • Next, apply the SHA-512 algorithm to the prepared signing string to generate the final signature. The signature result is as follows:

     8979EEB59CF15246A04E033962CA4084973A9D0F2F5CC08F07B99E9D0338F4486ED7700CF78F6365C2E399ED593B3EF9059F2EC808B5107CED8CC17BA0475962
     
    
Java Signature Generation Code Example:
	package io.alchemytech.virtualcard.center.utils;
	import io.alchemytech.basics.shared.common.utils.SHA512Utils;
	import java.util.SortedMap;
	import java.util.TreeMap;

	public class SignUtils {
		/**
		 * @param appId Merchant ID
		 * @param email      email
		 * @param secrete    Secret Key
		 * @return
		 */
		public static String getSign(String appId, String email, String secrete) {
			SortedMap<Object, Object> map = new TreeMap<>();
			if (email != null && !email.equals("")) {
				map.put("email", email);
			}
			map.put("appId", appId);
			String sign = SHA512Utils.SHAEncrypt(map, secrete);
			return sign;
		}

		public static void main(String[] args) {
			System.out.println(getSign("qmamnbodyqzbdr0w","[email protected]","6fdbaac29eb94bc6b36547ad705e9298"));
		}
	}
Encryption Utility Class:
	import org.slf4j.Logger;
	import org.slf4j.LoggerFactory;
	import java.io.UnsupportedEncodingException;
	import java.security.MessageDigest;
	import java.security.NoSuchAlgorithmException;
	import java.util.Iterator;
	import java.util.Map;
	import java.util.Set;
	import java.util.SortedMap;
	public class SHA512Utils {
		public static final String ENCODE = "UTF-8";
		private static Logger logger = LoggerFactory.getLogger(SHA512Utils.class);

		/**
		 * Sign the message using SHA algorithm
		 *
		 * @param signParams Signature Parameter
		 * @param key        Encryption Key
		 * @return
		 */
		public static String SHAEncrypt(SortedMap<Object, Object> signParams, String key) {
			String sign = null;
			StringBuffer sb = new StringBuffer();
			Set es = signParams.entrySet();
			Iterator it = es.iterator();
			while (it.hasNext()) {
				Map.Entry entry = (Map.Entry) it.next();
				String k = (String) entry.getKey();
				String v = (String) entry.getValue();
				if (null != v && !"".equals(v) && !v.equals("null") && !"sign".equals(k) && !"key".equals(k)) {
					sb.append(k + "=" + v + "&");
				}
			}
			sb.append("key=" + key);
			logger.info("signStr: {}", sb);
			sign = encrypt(sb.toString(), ENCODE).toUpperCase();
			logger.info("sign: {}", sign);
			return sign;
		}

		public static String encrypt(String aValue, String encoding) {
			aValue = aValue.trim();
			byte value[];
			try {
				value = aValue.getBytes(encoding);
			} catch (UnsupportedEncodingException e) {
				value = aValue.getBytes();
			}
			MessageDigest md = null;
			try {
				md = MessageDigest.getInstance("SHA-512");
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
				return null;
			}
			return toHex(md.digest(value));
		}

		public static String toHex(byte input[]) {
			if (input == null) return null;
			StringBuffer output = new StringBuffer(input.length * 2);
			for (int i = 0; i < input.length; i++) {
				int current = input[i] & 0xff;
				if (current < 16) output.append("0");
				output.append(Integer.toString(current, 16));
			}
			return output.toString();
		}

		/**
		 * Verify Signature
		 *
		 * @param signParams Signature Parameter
		 * @param key        Encryption Key
		 * @return
		 */
		public static boolean verifySHA(SortedMap<Object, Object> signParams, String key) {
			String verifySign = (String) signParams.get("sign");
			String sign = SHAEncrypt(signParams, key);
			if (sign.equalsIgnoreCase(verifySign)) {
				return true;
			}
			return false;
		}
	}