调用 API 接口


URL 中的参数 Query Params

参数 说明 类型 必填 默认值
id Api Id String  
timestamp 时间戳 (秒) (服务器可识别的时间格式 例如:1612876331 该时间戳与服务器时间前后相差不能超过 60 秒,合计 2 分钟) Integer  
signature Base64 字符串 (查看签名算法) String  
limit 返回结果中 rows 的最大数量。 意义等同于 pageSize Integer  
skip 忽略查询结果中的前 n 个值 Integer  
sort 查询结构排列方式.例: sort[]=regionCode:desc&sort[]=countryCode:asc    
keywords 关键字查询以逗号区分 例如在区域查询中 keywords=america,canada String  

URL 中的参数用法

POST /some_service?id={id}&timestamp={timestamp}&signature={signature}

**POST 请求中 Body 参数 **

请参照具体接口说明以JSON数据类型提供

签名算法

  1. 将调用接口时 Url 中的 Query 参数(去除 siagnature 参数) 与 Body 参数合并 (GET 方法时, 请忽略 body)

  2. 将合并后的对象中的参数 第一个字母按升序排列

  3. 将每个参数值 urlencode

  4. 将所有参数用“&”号连接,如:orderNumber=XXXXXX&keywords=YYYYYY

  5. 将连接好的参数加上密钥(App Secret),用 HMAC SHA256 加密

  6. 将加密的字符串用 base64 编码,得到签名

JS Example

const id = "1234567";
const secret = "secret";
const timestamp = parseInt(new Date().getTime() / 1000, 10);
/* query 参数 */
const queryParams = {
  skip: 0,
  limit: 100,
  sort: ["regionCode:desc", "coutryCode:asc"],
  id,
  timestamp,
};

/* body 参数 */
const body = {
  initiation: {
    regionCode: "CA",
  },
  destination: {
    regionCode: "cn",
  },
  shipmentType: "parcel",
};

/* 合并query & body参数 */
const params = { ...queryPrams, ...body };

/* 格式化参数函数 */
function params2string(params) {
  let strArray = [];
  const keys = Object.keys(params);
  const sortedKeys = keys.sort();
  sortedKeys.forEach((key) => {
    let str = "";
    str += typeof key === "string" ? key.toLowerCase() : key;
    str += "=";
    str +=
      typeof params[key] === "string"
        ? encodeURIComponent(params[key]).replace("%7E", "~")
        : JSON.stringify(params[key]);
    strArray.push(str);
  });
  return strArray.join("&");
}
/* 格式化参数 */
const urlEncodedString = params2string(params);

const { createHmac } = require("crypto");
const signature = createHmac("sha256", secret)
  .update(urlEncodedString)
  .digest("base64");

请求实例

GET /service?id=7f16f1b0-61bf-11eb-ae75-75abac9d9f41&skip=0&signature=O5XHLnECvcdoMKe6WdvN1AbBUqBa3ZOyneQxSwl1zsw%3D&limit=20&timestamp=1612885847

返回结果

请求成功 HTTP Status 200

参数 说明 类型 默认值
success 当请求正常结束时返回真值 true Boolean  
elapsed 请求消耗时间    
timestamp 时间戳 (服务器可识别的时间格式 例如:1612876331 该时间戳与服务器时间前后相差不能超过 60 秒,合计 2 分钟) Integer  
query 提交的请求参数 (id, timestamp, signature, api, livemode) Object  
result 请求结果 Object  
result/rows 查询结果 Array  
result/count 查询结果的 total number Integer  
result/limit 返回结果中 rows 的最大数量。 意义等同于 pageSize Integer  
result/skip 忽略查询结果中的前 n 个值 Integer  
result/message 消息 String  
result/*** 其他 Object  

请求失败 HTTP Status 2XX / 4XX / 5XX

参数 说明 类型 默认值
error 当请求发生错误时会返回错误类别 例: badRequest, carrierError, usageError, orderError 等 String  
code 错误代码 E_XXX_YYY_ZZZ 例: E_ACCOUNT_BALANCE_NOT_INSUFFICIENT String  
message 错误消息 例: options: [OPTION-B, OPTION-A] are not supported with current service String  
Problems 当遇到多个问题是返回字符串数组 例: [‘pak length show grater than 10cm’, ‘pak width show grater than 30cm’] Array  

POSTMAN 设置 Pre-request Script

在使用 Postman 进行测试时,可以通过设置 Pre-request Script 来自动生成带时间戳的签名

Example

// 在环境变量中添加id,
// 在环境变量中添加timestamp
// 在环境变量中添加signature
// {X} 大括号中为postman环境变量
Request Url : ///some_service?id={id}&signature={signature}&limit=20&timestamp={timestamp}

const apiKey = '1234567';
const id = 'secret';
const timestamp = parseInt(new Date().getTime()/1000,10);
const queryParams = pm.request.url.query.toObject(); // 获取URL中的query参数
queryParams.id = id;
queryParams.timestamp = timestamp;

pm.environment.set('id', id );
pm.environment.set('timestamp',timestamp);

	/* 当在url中使用数组Array 参数时, 如sort[] */
  for (const i in queryParams) {
    if (Object.hasOwnProperty.call(queryParams, i)) {
      const item = queryParams[i];
      if (Array.isArray(item)) {
          newKey = i.replace('[]', '');
        queryParams[newKey] = item;
        delete queryParams[i];
      }
    }
  }

/* 去除query参数中的signature */
delete queryParams.signature;
/* Post 方法时,获取body参数 */
let body = pm.request.body;
body = body && body.raw? JSON.parse(body.raw): {};

/* 合并query & body参数 */
const params = {...queryParams, body}
/* 格式化参数函数 */
function params2string (params) {
    let strArray = [];
    const keys = Object.keys(params);
    const sortedKeys = keys.sort();
    sortedKeys.forEach(key => {
      let str = '';
      str += typeof key === 'string' ? key.toLowerCase() : key;
      str += '=';
      str += typeof params[key] === 'string' ? encodeURIComponent(params[key]).replace('%7E', '~') : JSON.stringify(params[key])
      strArray.push(str);
    });
    return strArray.join('&');
  }

/* 格式化参数 */
const urlEncodedString = params2string(params);
/* 生成签名 */
const hash = CryptoJS.HmacSHA256(urlEncodedString, secret);
const signature = CryptoJS.enc.Base64.stringify(hash);
/* 将签名urlEncode后在环境变量中更新 */
pm.environment.set("signature", encodeURIComponent(signature));