承运商服务(也称为承运商计算服务或运输服务)向 SHOPLINE 提供实时运费费率。
商家安装承运商服务应用程序后,在 SHOPLINE 后台通过路径 设置 > 发货与配送 > 运费 > 添加运费 > 使用承运商或应用来计算费率 找到添加的承运商服务并选择运输服务,结账时为用户提供适用的运费。
**权限要求:**需要 shipping 访问范围
承运服务实施简介
向 Shopline 提供实时运费率计算,您可以参考以下步骤:
- 在应用市场搭建插件或为商家搭建私人应用。
- 商家将承运商服务添加到商店时,承运商服务应用程序调用创建承运商服务接口,为商家创建承运服务。
- 请求参数中您需要指定有效的 callback_url,在检索运输服务和承运服务计算运费场景时, SHOPLINE 会通过 callback_url 向您的承运商服务应用程序发送请求。
- 您的承运商服务应用程序应处理此请求,根据提供的信息计算实时运费费率,以 Shopline API 指定的响应格式将计算的运费费率返回。
- SHOPLINE 后台配置运费方案在 **使用承运商或应用来计算费率 **中选择您的承运商服务时,SHOPLINE 会通过 callback_url 向您发送请求检索运输服务。
- 检索运输服务:SHOPLINE 通过 callback_url 向您发送请求,请求数据包含起始发地、目的地、商品、货币、语言环境、店铺 ID、店铺 Domain 和签名等参数。
- 当service_discovery = false,始发地、目的地为店铺默认地址。product_id、variant_id 为空,货币为店铺货币。
- 当 service_discovery = true,始发地为运费方案中发货地点,目的地为运费方案中收货国家地区(虚拟地址请求),排列组合触发多次请求。product_id、variant_id 为空,货币为店铺货币。
- 检索运输服务:SHOPLINE 通过 callback_url 向您发送请求,请求数据包含起始发地、目的地、商品、货币、语言环境、店铺 ID、店铺 Domain 和签名等参数。
这种情况下会出现大量的接口请求,需要您关注接口的请求压力。为了减少非必要的请求,针对特殊场景做了一些特殊处理
1)当运费方案发货地组为默认分组时,店铺默认地点作为发货地,并跟收货区域的国家排列组合请求参数
2)当运费方案收货区域选择“其他国家地区”选项时,收货区域固定使用新加坡、英国、美国、澳大利亚、巴西、南非,并跟发货地排列组合请求参数
3)运费方案的发货地点,按照国家维度去重,按照地址优先级顺序选取
4)运费方案的收货区域,按照国家维度去重,使用虚拟的地址数据请求
- 用户结账使用承运服务计算运费时,SHOPLINE 会通过 callback_url 向您发送请求计算运费
- 承运服务计算运费:SHOPLINE 通过 callback_url 向您发送请求,请求数据包含起始发地、目的地、商品、货币、语言环境、店铺 ID、店铺 Domain和签名等参数。其中始发地为店铺默认地址,目的地为用户结账填写的收货地址。
- 请求的货币为订单结算货币。您返回的运费费率,当货币与入参不一致时,SHOPLINE 使用实时汇率转换后在参与运费计算。
- 在结账过程中,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 分钟后过期。