Scroll to top

To safeguard the interactions between your backend systems and the Luxon API, we employ a robust authentication system. This authentication method employs a specific signing mechanism to ensure that the API calls originated from authentic sources and haven’t been tampered with during transit. Below is a step-by-step guide on how to create this authentication signature.

SIGNATURE FORMAT

AAA.BBB

Generate signature header part one: AAA

1. Header Creation:

Construct a header object with the following fields:

  • Algorithm (alg)
  • Key
  • Timestamp

Java Example

SignatureHeader header = new SignatureHeader();
header.setAlg("HS512");
header.setKey(keyId);
header.setTimestamp(Instant.now().getEpochSecond());

2. Encoding the Header (AAA):

Convert the header to a Base64 encoded string.

Java

Base64.getEncoder().encodeToString(objectMapper.writeValueAsString(header).getBytes())


Generate signature header part two: BBB

3. Preparing the Payload (Request Body - after removeEscapeSequenceAndWhiteSpace):

Make sure the request body does not have any white spaces or escape sequences.

{
"merchantTransactionId":"[value]",
"merchantUserId":"[value]",
"redirectUrl":"string",
"comment":"[value]",
"amount":[value],
"currency":"[value]"
}

4. SHA-512 Hashing of Payload (X):

Compute the SHA-512 hash of the request body, even if it is empty and then Base64 encode it.

Base64(Sha-512 hashed request body)

5. Double Base64 Encoding (Y):

Base64 encode the previously obtained value (X) from step 4.

Base64(Base64(Sha-512 hashed request body))

Java

var payloadHashedBase64Base64 = Base64.getEncoder().encodeToString(encodeWithSha(requestBody).getBytes());

where encodeWithSha(String requestBody) ->
public static String encodeWithSha(String requestBody) throws NoSuchAlgorithmException {
	String unEscaped = StringUtils.removeEscapeSequenceAndWhitespace(requestBody);
	MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
	messageDigest.update(unEscaped.getBytes());
	return Base64.getEncoder().encodeToString(messageDigest.digest());
}

6. Constructing the Signature String:

Concatenate the HTTP Method, API endpoint, timestamp and ‘Y’ from step 5.

Java Example

String requestMethod = "POST";
String requestPath = "/api/v1/merchant/payment";
String requestQueryString = requestQueryString == null ? "" : requestQueryString;
String timestampValue = header.getTimestamp();

String stringSignature = POST/api/v1/merchant/payment[timestampValue][Y];

Java Example

String requestMethod = "POST";
String requestPath = "/api/v1/merchant/payment";
String requestQueryString = requestQueryString == null ? "" : requestQueryString;
String timestampValue = header.getTimestamp();

String stringSignature = POST/api/v1/merchant/payment[timestampValue][Y];

7. Generating HMAC and Encoding (BBB):

Using the merchant’s key and the HMAC SHA-512 algorithm, compute the HMAC of the signature string from step 6 and then Base64 to encode the result.

Java Example for how to create BBB

String B = signWithHmac(keyValue, stringSignature, header.getAlg());

where ->
public static String signWithHmac(String keyValue, String stringSignature, String algorithm) throws NoSuchAlgorithmException, InvalidKeyException {
String alg = "HmacSHA512"; // algorithm is HS512
Key signingKey = new SecretKeySpec(keyValue.getBytes(), alg);
Mac mac = Mac.getInstance(alg);
mac.init(signingKey);
byte[] encoded = mac.doFinal(stringSignature.getBytes());
return Base64.getEncoder().encodeToString(encoded);
}


8. Final Signature (AAA.BBB):

Concatenate AAA from step 2 and BBB from step 7, separated by a dot ‘.’.

This signature is then added to the headers of the HTTP request when making a call to the Luxon API, allowing Luxon to validate the authenticity and integrity of the incoming request.

Always ensure to include the Content-type: APPLICATION-JSON header in the API request.

Note: Care should be taken to keep the key confidential and to ensure that the timestamp used in the signature is synchronized with the server time for accuracy.


Auth Process Example

The provided example shows how this process should look at each step.

Header

alg=“HS512”
key=“AYO8AXQW5Fwjz0qSpKixnavUfhwc87kF”
timestamp = 1635934687

Request body

{
"amount": 10000,
"currency": "EUR"
}

1. SignatureHeader:
(alg=HS512, key=AYO8AXQW5Fwjz0qSpKixnavUfhwc87kF,
timestamp= 1635934687)

2. Base64 encoded header:
eyJhbGciOiJIUzUxMiIsImtleSI6IkFZTzhBWFFXNUZ3anowcVNwS2l4bmF2VWZod2M4N2tGIiwidGltZXN0YW1wIjoxNjM1OTM0Njg3fQ==

3. Request body after removeEscapeSequenceAndWhiteSpace:
requestBody ={"amount":10000,"currency":"EUR"}

4. Base64(Sha hashed request body):
“W1k4yX8MwyWOxS+KxvdjnCeMmYv6E8U/XzYiCkbOfGz+Qauo/sHgUJHUduzUH7j38MRSk8BC3+ESasbGy++kog==“

5. Base64(Base64(Sha hashed request body)):
“VzFrNHlYOE13eVdPeFMrS3h2ZGpuQ2VNbVl2NkU4VS9YellpQ2tiT2ZHeitRYXVvL3NIZ1VKSFVkdXpVSDdqMzhNUlNrOEJDMytFU2FzYkd5Kytrb2c9PQ==”

6. String signature:
“POST/api/v1/merchant/payment1635934687VzFrNHlYOE13eVdPeFMrS3h2ZGpuQ2VNbVl2NkU4VS9YellpQ2tiT2ZHeitRYXVvL3NIZ1VKSFVkdXpVSDdqMzhNUlNrOEJDMytFU2FzYkd5Kytrb2c9PQ==“

7. Base64 encoded HMAC encoded signature:
"1EVBn9oETR04ITdAcGajQYjVHY9L1J4336BJlWF5JQ6rNzhv/CmdfxoGSmzsHYsQaTTo4+WuPNUkRqeLohpMUg=="

8. X-signature:
“eyJhbGciOiJIUzUxMiIsImtleSI6IkFZTzhBWFFXNUZ3anowcVNwS2l4bmF2VWZod2M4N2tGIiwidGltZXN0YW1wIjoxNjM1OTM0Njg3fQ==.1EVBn9oETR04ITdAcGajQYjVHY9L1J4336BJlWF5JQ6rNzhv/CmdfxoGmzsHYsQaTTo4+WuPNUkRqeLohpMUg==”

Content-type: APPLICATION-JSON