Authentication

Guide

  • Alchemy Pay will issue a pair of appId&appSecret for each partner once onboarded with Alchemy Pay. The appId is used to identify the partner, while appSecret is for signature purposes.

  • appId&appSecrety will be delivered to the partner upon request from Alchemy Pay's operation team. There is currently no online service for self-apply.

  • Please do not expose the appSecret in any API request.

Signature

Mutual authentication is implemented. For requests, the caller needs to compute a digital signature and add the signature as part of the HTTP body. Conversely, for responses, Alchemy Pay provides its signature in the HTTP body in the response. The request signature is generated as follows:

Sign demo for Page integration

Assemble string in ascending alphabetical order

package com.example;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.util.TreeMap;
import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.util.Random;
public class nft {

    private final static String CHARSET = "UTF-8";

    public static String sign(String s, String key) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA1");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(CHARSET), mac.getAlgorithm());
        mac.init(secretKeySpec);
        byte[] hash = mac.doFinal(s.getBytes(CHARSET));
        return DatatypeConverter.printBase64Binary(hash);
    }

    public static void main(String[] args) throws Exception {
        final String APP_ID = "ahzxh0klegv1fzol";
        final String APP_SECRET = "py2bwighth62ajq6";
				String signStr = "amount=3000&appId=ahzxh0klegv1fzol&callbackUrl=https://alchemypay.org&fiat=USD&merchantName=merchantName&merchantOrderNo=ACH100001234&name=nftname&nonce=1862325104&picture=https://download.bit.store/official/BitStore/pic/user_portrait/20.jpeg&redirectUrl=https://alchemypay.org&targetFiat=SGD&timeout=1675394255000&timestamp=1675417608&type=MARKET&uniqueId=1113"
        String signture = sign(signStr, APP_SECRET); 
				System.out.println("signture is: " + signture);

    }
}
//node v14.15.1
const crypto = require('crypto');

function encrypt(plainText, secretKeyData) {
  try {
    var hmac = crypto.createHmac("sha1", secretKeyData);
    var signed = hmac.update(Buffer.from(plainText, 'utf-8')).digest("base64");
    return signed;
  } catch (e) {
    console.log(`HmacSHA1 encrypting exception, msg is ${e.toString()}`);
  }
  return null;
}

let key = "py2bwighth62ajq6";
const plaintext = "amount=3000&appId=ahzxh0klegv1fzol&callbackUrl=https://alchemypay.org&fiat=USD&merchantName=merchantName&merchantOrderNo=ACH100001234&name=nftname&nonce=28518016&picture=https://download.bit.store/official/BitStore/pic/user_portrait/20.jpeg&redirectUrl=https://alchemypay.org&targetFiat=SGD&timeout=1675394255000&timestamp=1676525212&type=MARKET&uniqueId=1113";
const ciphertext = encrypt(plaintext,"py2bwighth62ajq6"); //appSecret
console.log("sign is ",ciphertext);
const urlEncodeText = encodeURIComponent(ciphertext)
console.log("encode sign is ",urlEncodeText);
#Python 3.7.4 
import base64
import urllib
import requests
import base64
import hashlib
import hmac

def encrypt(key, s, method):
    hmac_str = hmac.new(key.encode("utf8"), s.encode("utf8"), method).digest()
    return base64.b64encode(hmac_str)


secret_key="py2bwighth62ajq6"
rawdata = rawData = "amount=3000&appId=ahzxh0klegv1fzol&callbackUrl=https://alchemypay.org&fiat=USD&merchantName=merchantName&merchantOrderNo=ACH100001234&name=nftname&nonce=28518016&picture=https://download.bit.store/official/BitStore/pic/user_portrait/20.jpeg&redirectUrl=https://alchemypay.org&targetFiat=SGD&timeout=1675394255000&timestamp=1676525212&type=MARKET&uniqueId=1113"
sign = encrypt(secret_key, rawData, hashlib.sha1)
print("sign is:", sign)
urlEncodeData = urllib.parse.quote_plus(sign)
print("encode sign is: ", urlEncodeData)
//PHP 8.0.7
<?php
function encrypt($plaintext,$secretKey){
    $plaintextData = utf8_encode($plaintext);
    $secretKeyData = utf8_encode($secretKey);
    $ciphertext = hash_hmac('sha1', $plaintextData, $secretKeyData,true);
    return base64_encode($ciphertext);
}

$data = "amount=3000&appId=ahzxh0klegv1fzol&callbackUrl=https://alchemypay.org&fiat=USD&merchantName=merchantName&merchantOrderNo=ACH100001234&name=nftname&nonce=28518016&picture=https://download.bit.store/official/BitStore/pic/user_portrait/20.jpeg&redirectUrl=https://alchemypay.org&targetFiat=SGD&timeout=1675394255000&timestamp=1676525212&type=MARKET&uniqueId=1113";
$key = 'py2bwighth62ajq6';
$sign = encrypt($data,$key);
printf("sign is: %s\n",$sign);
$urlEncodeData = urlencode($sign);
printf("encode sign is:: %s",$urlEncodeData);
?>
//go version go1.18.2
package main

import (
	"crypto/hmac"
	"crypto/sha1"
	"encoding/base64"
	"fmt"
	"net/url"
)

func encrypt(message string, secret string) string {
	key := []byte(secret)
	h := hmac.New(sha1.New, key)
	h.Write([]byte(message))
	return base64.StdEncoding.EncodeToString([]byte(h.Sum(nil)))
}

func main() {
	rawData := "amount=3000&appId=ahzxh0klegv1fzol&callbackUrl=https://alchemypay.org&fiat=USD&merchantName=merchantName&merchantOrderNo=ACH100001234&name=nftname&nonce=28518016&picture=https://download.bit.store/official/BitStore/pic/user_portrait/20.jpeg&redirectUrl=https://alchemypay.org&targetFiat=SGD&timeout=1675394255000&timestamp=1676525212&type=MARKET&uniqueId=1113"
	key := "py2bwighth62ajq6"
	sign := encrypt(rawData, key)
	fmt.Printf("sign is %s \n", sign)
	encodeSign := url.QueryEscape(sign)
	fmt.Printf("encode sign is %s \n", encodeSign)
}

Sign demo for API

public class APISignCheckUtil {

    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();
    }
}
//node v14.15.1
const sha1 = require('js-sha1');


function getMerSign(appId, appSecret, timestamp) {
  return sha1(appId + appSecret + String(timestamp));
}
#Python 3.7.4 
import hashlib
from time import time


def getMerSign(appId, appSecret, timestamp):
    strr = appId + appSecret + str(timestamp)
    encoded_str = strr.encode()
    hash_obj = hashlib.sha1(encoded_str)
    hexa_value = hash_obj.hexdigest()
    return hexa_value


timestamp = int(time() * 1000)
print("timestamp = ", timestamp)
print("\n")
res = getMerSign("f83Is2**********", "4Yn*************", timestamp)
print(res)
//PHP 8.0.7
<?php
function getMerSign($appId, $appSecret, $timestamp){
  $str = $appId.$appSecret.strval($timestamp);
  return sha1($str);
}
$timestamp = floor(microtime(true) * 1000);
printf("timestamp = %d\n", $timestamp);
$res = getMerSign("f83Is2**********", "4Yn*************", $timestamp);
print($res);
 ?>
//go version go1.18.2
package main

import (
    "crypto/sha1"
    "encoding/hex"
    "strconv"
)

func getMerSign(appId string, appSecret string, timestamp int64) string {
    s := appId + appSecret + strconv.FormatInt(timestamp, 10)
    h := sha1.New()
    h.Write([]byte(s))
    //io.WriteString(h, s)
    return hex.EncodeToString(h.Sum(nil))
}