Authentication

Guide

  • Alchemy Pay will issue a pair of appId & appSecret for each partner once a partner has been on-boarded with Alchemy Pay. appId is used to identify partner, appSecret is for sign purpose.
  • appId & appSecret will be delivered to partner upon request from Alchemy Pay’s operation. There is currently no online service for self-apply.
  • In any circumstances, never expose appSecret in any API request.
  • The authentication mechanism has two methods one for Page mode another for Initiate API.

Sign demo for Page mode

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class AESUtil {
    public static String encrypt(String plainText, String secretKeyData)  {
        try {
            byte[] plainTextData = plainText.getBytes(StandardCharsets.UTF_8);
            byte[] secretKey = secretKeyData.getBytes(StandardCharsets.UTF_8);
            String iv = new String(secretKey).substring(0, 16);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");

            byte[] dataBytes = plainTextData;
            int plaintextLength = dataBytes.length;
            byte[] plaintext = new byte[plaintextLength];
            System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);

            SecretKeySpec keyspec = new SecretKeySpec(secretKey, "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

            cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
            byte[] encrypted = cipher.doFinal(plaintext);

            return new String(Base64.getEncoder().encode(encrypted));

        } catch (Exception e) {
            System.out.println("AES encrypting exception , msg is {}" + e.toString());
        }
        return null;
    }

    public static String decrypt(String cipherText, String secretKeyData) {
        try {

            byte[] cipherTextData = cipherText.getBytes(StandardCharsets.UTF_8);
            byte[] secretKey = secretKeyData.getBytes(StandardCharsets.UTF_8);
            String iv = new String(secretKey).substring(0, 16);

            byte[] encrypted = Base64.getDecoder().decode(cipherTextData);

            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
            SecretKeySpec keyspec = new SecretKeySpec(secretKey, "AES");
            IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());

            cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec);

            byte[] original = cipher.doFinal(encrypted);
            String originalString = new String(original);
            return originalString;
        } catch (Exception e) {
            System.out.println("AES decrypting exception: msg is {}" + e.toString());
        }
        return null;
    }


public static void main(String[] args) throws UnsupportedEncodingException {
    String rawData = "address=0x755CA9224E613252c06ae9C20825113Dda1971aa11660287337793&appId=jcudotl1hwyvxhdp";
    String sign = encrypt(rawData, "syw7mcauglkkhiov");
    System.out.println("sign is: " + sign);
    System.out.println("\n");
    String urlEncodeData = URLEncoder.encode(sign, "UTF-8");
    System.out.println("encode sign is: " +urlEncodeData);

}


}

Sign demo for Initiate API

public class MerSignCheckUtil {

    private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5',
        '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };

    public static String getMerSign(String appId, String appSecret, String timestamp) {
        return encode("sha1", appId  + appSecret + timestamp);
    }


    private static String encode(String algorithm, String value) {
        if (value == null) {
            return null;
        }
        try {
            MessageDigest messageDigest
                = MessageDigest.getInstance(algorithm);
            messageDigest.update(value.getBytes());
            return getFormattedText(messageDigest.digest());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    private static String getFormattedText(byte[] bytes) {
        int len = bytes.length;
        StringBuilder buf = new StringBuilder(len * 2);
        for (int j = 0; j < len; j++) {
            buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);
            buf.append(HEX_DIGITS[bytes[j] & 0x0f]);
        }
        return buf.toString();
    }
}