承运商服务

承运商服务(也称为承运商计算服务或运输服务)向 SHOPLINE 提供实时运费费率。

商家安装承运商服务应用程序后,在 SHOPLINE 后台通过路径 设置 > 发货与配送 > 运费 > 添加运费 > 使用承运商或应用来计算费率 找到添加的承运商服务并选择运输服务,结账时为用户提供适用的运费。

**权限要求:**需要 shipping 访问范围


承运服务实施简介

向 Shopline 提供实时运费率计算,您可以参考以下步骤:

  1. 在应用市场搭建插件或为商家搭建私人应用。
  2. 商家将承运商服务添加到商店时,承运商服务应用程序调用创建承运商服务接口,为商家创建承运服务。
    1. 请求参数中您需要指定有效的 callback_url,在检索运输服务承运服务计算运费场景时, SHOPLINE 会通过 callback_url 向您的承运商服务应用程序发送请求。
    2. 您的承运商服务应用程序应处理此请求,根据提供的信息计算实时运费费率,以 Shopline API 指定的响应格式将计算的运费费率返回。
  3. SHOPLINE 后台配置运费方案在 **使用承运商或应用来计算费率 **中选择您的承运商服务时,SHOPLINE 会通过 callback_url 向您发送请求检索运输服务。
    1. 检索运输服务:SHOPLINE 通过 callback_url 向您发送请求,请求数据包含起始发地、目的地、商品、货币、语言环境、店铺 ID、店铺 Domain 和签名等参数。
      1. 当service_discovery = false,始发地、目的地为店铺默认地址。product_id、variant_id 为空,货币为店铺货币。
      2. 当 service_discovery = true,始发地为运费方案中发货地点,目的地为运费方案中收货国家地区(虚拟地址请求),排列组合触发多次请求。product_id、variant_id 为空,货币为店铺货币。

这种情况下会出现大量的接口请求,需要您关注接口的请求压力。为了减少非必要的请求,针对特殊场景做了一些特殊处理

1)当运费方案发货地组为默认分组时,店铺默认地点作为发货地,并跟收货区域的国家排列组合请求参数

2)当运费方案收货区域选择“其他国家地区”选项时,收货区域固定使用新加坡、英国、美国、澳大利亚、巴西、南非,并跟发货地排列组合请求参数

3)运费方案的发货地点,按照国家维度去重,按照地址优先级顺序选取

4)运费方案的收货区域,按照国家维度去重,使用虚拟的地址数据请求

  1. 用户结账使用承运服务计算运费时,SHOPLINE 会通过 callback_url 向您发送请求计算运费
    1. 承运服务计算运费:SHOPLINE 通过 callback_url 向您发送请求,请求数据包含起始发地、目的地、商品、货币、语言环境、店铺 ID、店铺 Domain和签名等参数。其中始发地为店铺默认地址,目的地为用户结账填写的收货地址。
    2. 请求的货币为订单结算货币。您返回的运费费率,当货币与入参不一致时,SHOPLINE 使用实时汇率转换后在参与运费计算。
  2. 在结账过程中,SHOPLINE 将向客户显示可用的运输选项及其相应的费率。

通过遵循这些步骤,您可以为您的 SHOPLINE 商店启用实时运费率计算。


API 对象

API对象 描述
创建承运商服务 创建一个新的承运商服务,为shopline提供实时运费计算。shopline通过请求承运商服务的callbackUrl获取承运商的服务和运费。
获取承运商列表 获取店铺所有承运商服务的列表。
获取指定承运商服务 通过指定承运商服务ID,获取承运商服务信息。
更新承运商服务 更新指定运营商服务。只有创建运营商服务的应用才可以更新它。
删除承运商服务 删除现有的承运商服务。只有创建它的应用才可以操作。

向 SHOPLINE 提供运费

将承运商服务添加到商店时,承运商服务应用程序调用创建承运商服务 API,为商家创建承运服务。在请求参数中您需要指定有效的 callback_url ,在检索运输服务和承运服务计算运费场景时 SHOPLINE 会通过 callback_url 向您的承运商服务应用程序发送请求。

请求示例:

SHOPLINE 请求 callback_url 参数

参数名 类型 是否必填 描述
X-Shopline-Hmac-Sha256 String Y 对请求参数数据体(json字符串,使用jackson转换)签名后的文本内容
X-Shopline-Shop-Id String Y 店铺id
X-Shopline-Shop-Domain String Y 店铺domain
origin object Y 始发地地址信息
destination object Y 目的地地址信息
items object Y 订单商品的数组
currency string Y 货币代码
locale string Y 语言简码
{
  "origin": {
    "country": "US",
    "postal_code": "02116",
    "province": "Massachusetts",
    "province_code": "MA",
    "city": "Boston",
    "name": "MAMAMAMAMA",
    "address1": "110 Huntington Avenue",
    "address2": "",
    "phone": "+16175952242",
  },
  "destination": {
    "country": "US",
    "postal_code": "02116",
    "province": "Massachusetts",
    "province_code": "MA",
    "city": "Boston",
    "name": "MAMAMAMAMA",
    "address1": "110 Huntington Avenue",
    "address2": "",
    "phone": "+16175952242",
  },
  "items": [
    {
      "name": "",
      "quantity": 1,
      "grams": 100,
      "price": 0,
      "requires_shipping": true,
      "taxable": true,
      "product_id": null,
      "variant_id": null
    }
  ],
  "currency": "HKD",
  "locale": "en"
}
{
  "origin": {
    "country": "US",
    "postal_code": "02116",
    "province": "Massachusetts",
    "province_code": "MA",
    "city": "Boston",
    "name": "MAMAMAMAMA",
    "address1": "110 Huntington Avenue",
    "address2": "",
    "phone": "+16175952242",
  },
  "destination": {
    "country": "US",
    "postal_code": "02116",
    "province": "Massachusetts",
    "province_code": "MA",
    "city": "Anytown",
    "name": "MAMAMAMAMA",
    "address1": "123 Main Street",
    "address2": "",
    "phone": "+18175938242",
  },
  "items": [
    {
      "name": "",
      "product_id": "16058052259566389880023534",
      "variant_id": "18058052259569577551123534",
      "quantity": 1,
      "grams": 1000,
      "price": 999,
      "requires_shipping": true,
      "taxable": false
    }
  ],
  "currency": "USD",
  "locale": "en"
}

承运商服务应用程序返回参数

参数名 是否必填 描述
service_name Y 在结账过程中显示给买家的运费名称。
description N 在结账过程中显示给买家的运费描述。
限制不超过300个字符,超出后截取。
service_code Y 运输服务代码。
currency Y 货币代码
total_price Y 运费金额,传入值必须乘以100。例如:5.00 加拿大元的表示为 "total_price": 500,1000 日元的表示为 "total_price": 100000
phone_required N 是否在结账时要求顾客提供电话号码。
当phone_required = true时,在所选的运输费率下方将显示一个电话输入字段。
min_delivery_date N 运输服务最早送达日期。
max_delivery_date N 运输服务最晚送达日期。
{
  "rates":[
    {
      "service_name":"canadapost-overnight",
      "service_code":"ON",
      "total_price":"1295",
      "description":"This is the fastest option by far",
      "currency":"CAD",
      "min_delivery_date":"2023-06-08T23:59:59+08:00",
      "max_delivery_date":"2023-06-09T23:59:59+08:00"
    },
    {
      "service_name":"fedex-2dayground",
      "service_code":"2D",
      "total_price":"2934",
      "currency":"USD",
      "min_delivery_date":"2023-06-08T23:59:59+08:00",
      "max_delivery_date":"2023-06-09T23:59:59+08:00"
    },
    {
      "service_name":"fedex-priorityovernight",
      "service_code":"1D",
      "total_price":"3587",
      "currency":"USD",
      "min_delivery_date":"2023-06-08T23:59:59+08:00",
      "max_delivery_date":"2023-06-09T23:59:59+08:00"
    }
  ]
}

签名及验签

基于数据的安全及业务的合法性来源校验的考虑,SHOPLINE 请求承运服务 callback_url 之前对请求进行签名,承运商服务应用程序可对请求进行签名验证。

采用 SHOPLINE Webhook 签名方式进行签名,使用 hmacSha256 签名算法

  • 签名算法:hmacSha256
  • 加签内容:请求body
  • 签名算法示例(java版本):
    /**
     * hmacSha256 
     * @param source signContent
     * @param secret appSecret
     * @return
     */
public static String hmacSha256(String source, String secret) {
    if (StringUtils.isEmpty(secret) || StringUtils.isEmpty(source)) {
        return null;
    }
    try {
        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
        SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
        sha256_HMAC.init(secret_key);
        byte[] bytes = sha256_HMAC.doFinal(source.getBytes(StandardCharsets.UTF_8));
        return new String(Hex.encodeHex(bytes));
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

响应超时

承运服务接口响应超过 1500ms,将触发响应超时。


服务器端缓存请求

SHOPLINE 提供服务器端缓存以减少其发出的请求数量。任何与以下字段完全相同的运费请求都将从 SHOPLINE 的初始响应缓存中检索:

  • 默认装运箱重量和尺寸
  • 币种
  • 承运商服务 code
  • 始发地
  • 目的地
  • 商品总重量
  • 签名

如果这些字段中的任何一个不同,或者如果自原始请求以来缓存已过期,则将请求新的运费。成功返回费率后,缓存将在 10 分钟后过期。