Generating the Signature

Generating the signature #

The formula for calculating the signature is signature = HMAC-SHAx-HEX(secret_key, signing_string).

In order to generate the signature, two parameters, secret_key and signing_string are required. The secret_key is configured by a Consumer and the signing_string is calculated as signing_string = HTTP Method + \n + HTTP URI + \n + canonical_query_string + \n + access_key + \n + Date + \n + signed_headers_string. The different terms in this calculation are explained below:

  • HTTP Method : HTTP request method in uppercase. For example, GET, PUT, POST etc.
  • HTTP URI : HTTP URI. Should start with “/” and “/” denotes an empty path.
  • Date : Date in the HTTP header in GMT format.
  • canonical_query_string : The result of encoding the query string in the URL (the string “key1 = value1 & key2 = value2” after the “?” in the URL).
  • signed_headers_string : Concatenation of the specified request headers.

TIP

If any of the terms are missing, they are replaced by an empty string.

Example #

The example below shows signature string splicing:

curl -i https://lk-api-v2.linksfield.net/mp-api/api/esim/queryOrderStatus?eid=89049032000001000000128255728753&resellerCode=SG00000010 \
-H "X-HMAC-SIGNED-HEADERS: Accept-Language;Content-Type" \
-H "Accept-Language: en-US" \
-H "Content-Type: application/json"

Explanation of signature generation formula process #

  1. The default HTTP Method for the above request is GET, which gives signing_string as
"GET"
  1. The requested URI is /mp-api/api/esim/queryOrderStatus, and the signing_string is obtained from the HTTP Method + \n + HTTP URI as
"GET
/mp-api/api/esim/queryOrderStatus"
  1. The query item in the URL is eid=89049032000001000000128255728753&resellerCode=SG00000010.
"GET
/mp-api/api/esim/queryOrderStatus
eid=89049032000001000000128255728753&resellerCode=SG00000010"
  1. The access_key is user-key, and the signing_string is obtained from HTTP Method + \n + HTTP URI + \n + canonical_query_string + \n + access_key as
"GET
/mp-api/api/esim/queryOrderStatus
eid=89049032000001000000128255728753&resellerCode=SG00000010
user-key"
  1. Date is in GMT format, as in Tue, 19 Jan 2021 11:33:20 GMT, and the signing_string is obtained from the HTTP Method + \n + HTTP URI + \n + canonical_query_string + \n + access_key + \n + Date as
"GET
/mp-api/api/esim/queryOrderStatus
eid=89049032000001000000128255728753&resellerCode=SG00000010
user-key
Tue, 19 Jan 2021 11:33:20 GMT"
  1. signed_headers_string specifies the header involved in the signature, fixed as Accept-Language: en-US and Content-Type: application/json.

And the signing_string is obtained from the HTTP Method + \n + HTTP URI + \n + canonical_query_string + \n + access_key + \n + Date + \n as

"GET
/mp-api/api/esim/queryOrderStatus
eid=89049032000001000000128255728753&resellerCode=SG00000010
user-key
Tue, 19 Jan 2021 11:33:20 GMT
Accept-Language:en-US
Content-Type:application/json
"

Tip

At present, the API gateway does not enable the restriction of time offset, so the request header Date field can not participate in the signature calculation, and the date position can be replaced by an empty string.

"GET
/mp-api/api/esim/queryOrderStatus
eid=89049032000001000000128255728753&resellerCode=SG00000010
user-key

Accept-Language:en-US
Content-Type:application/json
"

The Java code below shows how to generate the signature:

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.xml.bind.DatatypeConverter;

class Main {
  public static void main(String[] args) {
   try {
     String secret = "my-secret-key";
     //Date participation calculation
     String message = "GET\n" +
                      "/mp-api/api/esim/queryOrderStatus\n" +
                      "eid=89049032000001000000128255728753&resellerCode=SG00000010\n" +
                      "user-key\n" +
                      "Tue, 19 Jan 2021 11:33:20 GMT\n" +
                      "Accept-Language:en-US\n" +
                      "Content-Type:application/json\n";
//The date does not participate in the calculation
//   String message = "GET\n" +
//                    "/mp-api/api/esim/queryOrderStatus\n" +
//                    "eid=89049032000001000000128255728753&resellerCode=SG00000010\n" +
//                    "user-key\n" +
//                    "\n" +
//                    "Accept-Language:en-US\n" +
//                    "Content-Type:application/json\n";

     Mac hasher = Mac.getInstance("HmacSHA256");
     hasher.init(new SecretKeySpec(secret.getBytes(), "HmacSHA256"));

     byte[] hash = hasher.doFinal(message.getBytes());

     // to lowercase hexits
     DatatypeConverter.printHexBinary(hash);

     // to base64
     DatatypeConverter.printBase64Binary(hash);
   }
   catch (NoSuchAlgorithmException e) {}
   catch (InvalidKeyException e) {}
  }
}
Type Hash Note
SIGNATURE P0IuBBMV6fsf4UhdMsF3St9gaxqcidO7YwJ2eAzTRCM= Date participation calculation
SIGNATURE M8w5ai017BnWLoUFjbR2zaqapxj1gXK+Unll6twlDmg= The date does not participate in the calculation

Using the generated signature to make requests #

You can now use the generated signature to make requests as shown below:

curl -i "https://lk-api-v2.linksfield.net/mp-api/api/esim/queryOrderStatus?resellerCode=SG00000010&eid=89049032000001000000128255728753" \
-H "X-HMAC-SIGNATURE: P0IuBBMV6fsf4UhdMsF3St9gaxqcidO7YwJ2eAzTRCM=" \
-H "X-HMAC-ALGORITHM: hmac-sha256" \
-H "X-HMAC-ACCESS-KEY: user-key" \
-H "Date: Tue, 19 Jan 2021 11:33:20 GMT" \
-H "X-HMAC-SIGNED-HEADERS: Accept-Language;Content-Type" \
-H "Accept-Language: en-US" \
-H "Content-Type: application/json" \
curl -i "https://lk-api-v2.linksfield.net/mp-api/api/esim/queryOrderStatus?resellerCode=SG00000010&eid=89049032000001000000128255728753" \
-H "X-HMAC-SIGNATURE: M8w5ai017BnWLoUFjbR2zaqapxj1gXK+Unll6twlDmg=" \
-H "X-HMAC-ALGORITHM: hmac-sha256" \
-H "X-HMAC-ACCESS-KEY: user-key" \
-H "X-HMAC-SIGNED-HEADERS: Accept-Language;Content-Type" \
-H "Accept-Language: en-US" \
-H "Content-Type: application/json" \
{
    "code": 200,
    "msg": "Success",
    "data": {
        "eid": "89049032000001000000128255728753",
        "packageCode": "LP20230110005593",
        "status": "Enabled",
        "actualStartTime": "2023-01-10 10:37:18",
        "plannedEndTime": "2023-12-31 23:59:59"
    }
}