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 #
- The default HTTP Method for the above request is GET, which gives
signing_stringas
"GET"
- The requested URI is
/mp-api/api/esim/queryOrderStatus, and thesigning_stringis obtained from the HTTP Method + \n + HTTP URI as
"GET
/mp-api/api/esim/queryOrderStatus"
- The query item in the URL is
eid=89049032000001000000128255728753&resellerCode=SG00000010.
"GET
/mp-api/api/esim/queryOrderStatus
eid=89049032000001000000128255728753&resellerCode=SG00000010"
- The
access_keyisuser-key, and thesigning_stringis 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"
- Date is in GMT format, as in
Tue, 19 Jan 2021 11:33:20 GMT, and thesigning_stringis 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"
signed_headers_stringspecifies the header involved in the signature, fixed asAccept-Language: en-USandContent-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"
}
}