承运商服务运费计算

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

安装承运商服务应用后,商家可以前往 SHOPLINE 商家后台,依次点击 设置 > 发货与配送。在 运费 区域,设置 通用运费自定义运费,并在相应页面的 收货地址 处点击 添加运费。在弹出的对话框中选择 使用承运商或应用来计算费率,然后找到已添加的承运商服务并选择相应的运费方案。客户结账时,将根据该方案实时计算运费。


实现原理和步骤

为 SHOPLINE 提供实时运费计算功能,可按以下步骤操作:

Carrierservice125.png

1. 应用开发部署

开发公共应用并发布至应用市场,或为商家开发私有化应用,详情可参考 应用开发

2. 商家服务配置

当商家在店铺中添加承运商服务时,承运商服务应用需调用 创建承运商服务 接口完成服务的创建。
必须在请求参数中配置有效的 callback_url 回调地址。SHOPLINE 将通过该地址向你的承运商服务应用发起请求,主要用于以下场景:获取运输服务、计算运费费率。
你的承运商服务应用需要:

  • 接收并处理 SHOPLINE 的请求
  • 根据提供的订单信息实时计算运费
  • 按照 SHOPLINE API 规定的响应格式返回计算结果

3. 在 SHOPLINE 商家后台配置运费方案

当商家在 SHOPLINE 商家后台配置运费方案,并选择 使用承运商或应用来计算费率 下的你的服务时,系统将通过 callback_url 向你发起请求,以获取可用的运输服务。详情如下:

参数

SHOPLINE 将通过 callback_url 发送请求,请求数据包含以下参数:

  • origin:始发地
  • destination:目的地
  • items:商品信息
  • currency:货币类型
  • locale:语言环境
  • X-Shopline-Shop-Id:店铺 ID
  • X-Shopline-Shop-Domain:店铺域名
  • X-Shopline-Hmac-Sha256:数字签名

参数处理规则

系统会根据不同的 service_discovery 模式采用不同的参数处理规则:

模式始发地与目的地商品参数货币类型
service_discovery: false始发地和目的地均默认使用店铺预设地址。product_idvariant_id 均为空值。店铺货币
service_discovery: true始发地为运费方案中设置的发货地址;
目的地为运费方案中设置的收货国家或地区(系统会使用虚拟地址触发多次请求)。
product_idvariant_id 均为空值。店铺货币

请求优化逻辑

在结账场景下,系统将会产生大量接口请求,因此需要特别注意接口的请求压力。为了减少不必要的请求,我们针对特定情况做了以下优化处理:

  • 发货地处理规则
    当运费方案的“发货地分组”为默认分组时,系统将自动采用店铺默认地址作为发货地,并与收货地参数 destination 组合生成请求。
  • 收货地处理规则
    当运费方案选择“其他国家和地区”选项时,收货地将固定采用以下 6 个国家:新加坡、英国、美国、澳大利亚、巴西、南非。这些预设国家会与发货地参数 origin 组合生成请求。
  • 去重机制
    • 发货地:按国家维度进行去重,并根据地址优先级顺序筛选。
    • 收货地:同样按国家维度去重,并采用虚拟地址数据发起请求。

4. 客户结账时获取承运商运费方案

当客户使用承运商服务结算运费时,SHOPLINE 将通过 callback_url 向你发送运费计算请求。详情如下:

参数

核心参数包含:

  • origin:始发地(默认取用店铺预设地址)
  • destination:目的地(用户结算时填写的收货地址)
  • items:商品信息
  • currency:货币类型
  • locale:语言环境
  • X-Shopline-Shop-Id:店铺 ID
  • X-Shopline-Shop-Domain:店铺域名
  • X-Shopline-Hmac-Sha256:数字签名
  • customer:客户信息

货币处理规则

以下规则说明了 SHOPLINE 处理货币数据及汇率转换的方式。

  • 请求货币:采用订单结算货币。
  • 汇率转换:当返回的运费币种与输入的币种参数 currency 不一致时,SHOPLINE 将按实时汇率转换后再参与运费计算。

在客户结账环节,SHOPLINE 结账页将向客户展示所有可用的运费方案和对应的实时运费(前提是需要在 SHOPLINE 商家后台配置好可用的承运商运费方案)。


API 接口参考

承运商服务 API

API说明
创建承运商服务创建一个新的承运商服务,为 SHOPLINE 提供实时运费计算。SHOPLINE 通过请求承运商服务的 callback_url 来获取承运商的服务及运费信息。
获取承运商服务列表检索商店的所有承运商服务列表。
获取指定承运商服务通过指定承运商服务 ID 来检索承运商服务信息。
更新承运商服务更新指定的承运商服务。只有创建该承运商服务的应用才能更新它。
删除承运商服务删除指定的承运商服务。只有创建该承运商服务的应用才能删除它。

调用 创建承运商服务更新承运商服务 接口时,可通过 metafield 参数预配置 CustomerProductVariant 资源的元字段,在结账页请求 callback_url 获取实时费率时将自动透传。

参数类型是否必传描述
metafieldobject[]元字段信息。
metafield.resourcestring元字段资源,当前只支持 CustomerProductVariant
metafield.identifiersobject[]元字段定义信息。
metafield.identifiers.keystring元字段定义 Key。
metafield.identifiers.namespacestring元字段定义命名空间。
注意

入参最多支持 50 个 Key,超出限制将被拦截并报错。

请求 callback_url 时的参数说明

请求头

字段类型是否必传描述
X-Shopline-Hmac-Sha256string签名的请求参数数据体的文本内容(使用 Jackson 转换的 JSON 字符串)。
X-Shopline-Shop-Idstring店铺 ID。
X-Shopline-Shop-Domainstring店铺域名。

请求体

字段类型是否必传描述
originobject发货地对象。
destinationobject收货地对象。
itemsobject[]商品列表,其中金额是分摊商品折扣和订单折扣后的金额。
currencystring币种。格式:ISO 4217
示例:USD
localestring语言环境。
is_express_checkoutboolean是否为快捷支付。
  • true:表示快捷支付(不区分渠道)。
  • false:表示普通支付流程。
customerobject客户信息。其中,metafield 里一个 key 可能有多个 value。只在结账页请求时传递该参数。
提示

origindestinationitemscustomer 参数均为对象类型,包含若干子字段。传入时需要填写相应子字段的值,具体结构见下方的示例代码。

请求 callback_url 时的参数示例:

{
"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":"phone",
"quantity":1,
"grams":100,
"price":0,
"requires_shipping":true,
"taxable":true,
"product_id":"1607337290976137******0910",
"variant_id":"1807337290976254******0910",
"sku":"abc-123",
"activity_type":"1",
"benefit_type":"2",
"properties": [
{
"name":"color",
"value":"red",
"show":"true",
"type":"text",
"urls":"https://img-va.myshopline.com/image/store/168076****839/fgsdfgs.jpg?w=588&h=386"
}
],
"selling_price": {
"presentment_money": {
"amount":"10.00",
"currency":"USD"
},
"shop_money": {
"amount":"10.00",
"currency":"USD"
}
},
"variant_metafield": [
{
"key":"sku_long",
"value":"21"
},
{
"key":"sku_width",
"value":"22"
},
{
"key":"sku_height",
"value":"23"
}
]
}
],
"currency":"HKD",
"locale":"en",
"customer": {
"id":"460****098",
"email":"test@gmail.com",
"phone":"1321****678",
"metafield": [
{
"key":"member_level",
"value":"1"
}
]
}
}

返回参数

字段是否必需描述
service_name结账时向客户显示的运费方案名称。
description结账时向客户显示的运费方案描述。
限制为 300 个字符。如果超出此限制,则会被截断。
service_code运费方案代码。
currency币种。格式:ISO 4217
示例:USD
total_price运费值,除以 100 后为实际金额。例如,运费金额为 5 美元,total_price 取值为 500;运费金额为 1000 美元,total_price 取值为 100000
phone_required指示客户是否必须在结账时提供电话号码。
当值为 true 时,结账时所选运费下方将显示一个电话号码输入字段。
min_delivery_date显示运费方案的最早发货时间。格式:ISO 8601
max_delivery_date显示运费方案的最晚发货时间。格式:ISO 8601
shipping_discount运费折扣信息,包含 typevaluedescription 子字段。其中,description 会展示在结账页对应运费方案处(目前最多支持 100 个字符);type 的枚举值为 percentagefixed
  • typepercentage 时,折扣后运费金额为:total_price × (1 - value%) + 手续费。
  • typefixed 时,折扣后运费金额为:total_price - value + 手续费。

image.png

承运商服务返回实时运费示例:

{
"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",
"shipping_discount": {
"type": "fixed",
"value": "10",
"description": "This is a shipping discount"
}
},
{
"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",
"shipping_discount": {
"type": "fixed",
"value": "10",
"description": "This is a shipping discount"
}
},
{
"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",
"shipping_discount": {
"type": "fixed",
"value": "10",
"description": "This is a shipping discount"
}
}
]
}

注意事项

签名验证机制

为了保障数据安全,并确保业务来源的合法性,SHOPLINE 在将请求发送到承运商服务的 callback_url 之前会进行签名。承运商服务应用必须对请求进行签名验证。

签名采用 SHOPLINE Webhook 签名方法,并结合 HMAC-SHA256 签名算法生成。待签名内容为原始请求体。

签名算法示例(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;
}
}

响应超时

如果承运商服务接口响应超过 1500 毫秒,则会触发响应超时。

服务端缓存请求

SHOPLINE 采用服务端缓存机制来优化请求效率,具体缓存规则如下:

  • 缓存触发条件
    当运费计算请求的以下属性完全匹配时,系统将命中缓存并直接返回缓存结果:
    • 默认运输箱重量及尺寸
    • 货币类型
    • 承运商服务 ID
    • 始发地地址
    • 目的地地址
    • 商品重量数据
    • 数字签名
    • 客户信息
  • 缓存失效机制
    出现以下任一情况时将发起新请求:
    • 上述任一属性发生变动
    • 缓存已超过有效期(自成功返回运费信息后 10 分钟自动失效)
这篇文章对你有帮助吗?