How to handle API signatures
For many APIs that require signature verification, the typical workflow involves first manually accessing the signature endpoint, then attaching the obtained signature to other requests. This process can be quite cumbersome.
To streamline this flow, here provides a automatic method to retrieve the latest signature when making requests to other endpoints.
How to handle API signatures
- Create a public script that implements the signature logic, read the API request parameters, and then use a built-in library (for example, crypto-js) to generate the signature.
- There are two ways to add the generated signature as a parameter.
- Method 1: Add a signature parameter and modify request information directly via scripts (no need to use environment variables).
- Method 2: Write the generated signature to an environment variable, and references the variable in the API parameters.
- Reference the public script created above in the preprocessor script for the API.
- If the signature algorithm is written in another language, you can use the
dog.execute
method to call a program written in another language.
Example
Signature generation rule
Step 1: Let’s set the parameters as set M. We arrange the non-empty parameter in set M based on ASCII code by ascending order, and use URL key value pair format (i.e. key1=value1&key2=value2...) to concat the non-empty parameter into stringA.
TIP
- Order the parameter name based on ASCII code by ascending order (dictionary order).
- Empty parameter value will not be included in the signature.
- Parameter names are case-sensitive.
- The sign parameter will also not be included in the signature.
Step 2: Concat the key at the end of the stringA to get stringSignTemp, use MD5 algorithm on stringSignTemp, convert the resulting string to uppercase to get the signValue.
Public script implementation
// Get the key from the environment variable APPKEY
let key = pm.environment.get("APPKEY");
// Store all parameters needed for signature
let param = {};
// Add query parameters
let queryParams = pm.request.url.query;
queryParams.each(item => {
if (item.value !== '') { // Only non-empty value will be included.
param[item.key] = item.value;
}
});
// Add body parameter
if (pm.request.body) {
let formData;
switch (pm.request.body.mode) {
case 'formdata':
formData = pm.request.body.formdata;
break;
case 'urlencoded':
formData = pm.request.body.urlencoded;
break;
case 'raw':
// If there is no JSON-formatted request body, or if the JSON-formatted body is not included in the signature, remove the code block.
let contentType = pm.request.headers.get('content-type');
if (
contentType
&& pm.request.body.raw
&& contentType.toLowerCase().indexOf('application/json') !== -1
) {
try {
let jsonData = JSON.parse(pm.request.body.raw);
/*
* If the API parameter extracted from the script includes variables, the variables will not automatically be replaced by its value. In order to get its value, use `pm.variables.replaceIn`.
* let body = pm.variables.replaceIn(pm.request.body.raw);
* let jsonData = JSON.parse(body);
*/
for (let key in jsonData) {
let value = `${jsonData[key]}`; // Note that if the actual value is not string type, you will need to modify the code block accordingly.
if (value !== '') { // Only non-empty parameter values will be included.
param[key] = value;
}
}
} catch (e) {
console.log('request body is not in JSON format')
}
}
break;
default:
break;
}
if (formData) {
formData.each(item => {
if (item.value !== '') { // Only non-empty parameter values will be included.
param[item.key] = item.value;
}
});
}
}
// Get the key.
let keys = [];
for (let key in param) {
// Note that we need to remove the sign parameter.
if (key !== 'sign') {
keys.push(key);
}
}
// Sort the parameter name based on ASCII code by ascending order (dictionary order).
keys.sort();
// Convert to key-value pairs.
let paramPair = [];
for (let i = 0, len = keys.length; i < len; i++) {
let k = keys[i];
paramPair.push(k + '=' + encodeURIComponent(param[k])) // urlencode coding
}
// Add key.
paramPair.push("key=" + key);
// Concatenation.
let stringSignTemp = paramPair.join('&');
// console.log(stringSignTemp);
let sign = CryptoJS.MD5(stringSignTemp).toString().toUpperCase();
// console.log(sign);
// Method 1: Add a signature parameter and modify request information directly via scripts (no need to use environment variables).
// View more in documentation. [https://apidog.com/help/app/scripts/examples/request-handle/](https://apidog.com/help/app/scripts/examples/request-handle/)
queryParams.upsert({
key: 'sign',
value: sign,
});
// Method 2: Write it into an environment variable. You will need to reference the environment variables in API parameters.
// pm.environment.set("SIGN", sign);
Translation API Signature Example
Signature Generation Rule
Step 1: Concat the appid, test to be translated q (UTF-8 encoding), random number salt, and the platform assigned key (available in the management console) into string 1 based on the order of appid + q + salt + key.
Step 2: Use md5 algorithm on string 1 to get the 32-bit lowercase sign.
TIP
- Text to be translated (q) needs to be in UTF-8 encoding.
- When concating appid+q+salt+key into signature, do not apply URL encode on q. When the signature is generated, apply URL encode on q before sending out the HTTP request.
Example - Translate apple from English to Japanese
Request parameters:
q=apple
from=en
to=ja
appid=2015063000000001
salt=1435660288
Platform assigned key: 12345678
Generate sign:
>Concat string 1.
Concat appid=2015063000000001+q=apple+salt=1435660288+key=12345678
into string 1 =2015063000000001apple143566028812345678
> Generate the signature sign. Use the md5 algorithm on string 1 to get the 32-bit lowercase sign. Before using the md5 algorithm, string 1 needs to be in UTF-8 encoding.
sign=md5(2015063000000001apple143566028812345678)
sign=f89f9594663708c1605f3d736d01d2d4
The complete request is going to be:
http://xxx/api/trans/vip/translate?q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4
Public Script Implementation
// Get query params
var queryParams = pm.request.url.query;
// Get q from query params.
var q = queryParams.get("q");
// Get the value of environment variables APPID and SECRET_KEY
var appid = pm.environment.get("APPID");
var secretKey = pm.environment.get("SECRET_KEY");
// Generate a random number between 32768 and 65536.
var salt = parseInt(Math.random() * 32769 + 32768, 10);
// Convert the random number into a string.
salt = salt.toString();
console.log(salt);
// Concat a string using appid+q+salt=secretKey
var str = appid + q + salt + secretKey;
console.log(str);
// Use md5 algorithm on the string to generate sign
var sign = CryptoJS.MD5(str).toString();
// Method 1: Add salt and sign in the query parameters for the API (no need to use environment variables).
// View documentation here: https://apidog.com/help/app/scripts/examples/request-handle/
queryParams.upsert({
key: "salt",
value: salt,
});
queryParams.upsert({
key: "sign",
value: sign,
});
// Method 2: Write salt and sign in global variables. You will need to reference the global variables in API parameters.
// pm.environment.set("SALT", salt);
// pm.environment.set("SIGN", strmd5);