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_string
as
"GET"
- The requested URI is
/mp-api/api/esim/queryOrderStatus
, and thesigning_string
is 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_key
isuser-key
, and thesigning_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"
- Date is in GMT format, as in
Tue, 19 Jan 2021 11:33:20 GMT
, and thesigning_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"
signed_headers_string
specifies the header involved in the signature, fixed asAccept-Language: en-US
andContent-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"
}
}