mcpField
S
salla-shipping-app

salla-shipping-app

github.com/sallaapp开发280 次安装5 天前更新
代码仓库

关于 salla-shipping-app

这是一套创建和配置 Salla 物流应用的引导流程,涵盖 Shipping Management/AWB 与 Order Fulfilment 两种模式。它通过 Salla Partners 工具依次处理应用设置、OAuth 与 Webhook、物流区域及函数测试。

主要功能

  1. 01选择 AWB 或履约模式
  2. 02创建并发布公开物流应用
  3. 03配置 OAuth 权限范围和 Webhook
  4. 04设置物流区域与选项
  5. 05实现并预览物流函数

适用场景

  1. 01使用 Salla AWB 构建承运商集成
  2. 02设置跨承运商订单履约
  3. 03配置商户配送范围和费率
  4. 04发布前测试物流函数

MCP 相关

需要连接 Salla Partners MCP 服务,并编排其工具来创建应用、配置 OAuth 和 Webhook、设置物流、订阅事件及管理 App Functions。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/sallaapp/salla-partners-agent-kit --skill salla-shipping-app

安装后在 Claude Code 中输入/salla-shipping-app确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
api-endpoints.md
fulfillment-cycle.md
shipment-cycle.md

详细介绍

Salla 配送应用流程

通过 使用 Salla Partners MCP 工具执行操作来构建配送应用。 请按顺序完成步骤 — 完成每个关卡后再继续。

配送应用必须为公开应用 — 此类别不支持私有应用 (https://docs.salla.dev/422995m0.md)。

两种应用模式 — 请先选择

Salla 有两种不同的配送应用模式(https://docs.salla.dev/422988m0.md)。它们 共用创建和 OAuth 流程,但在设置、生命周期和测试方面有所不同:

模式说明生命周期由何处管理
配送管理(承运商 / AWB)集成一家配送公司。现代化的 Salla AWB 模式 — 在 Salla Partners 内编写应用函数(无需构建或托管后端),调用承运商 API 生成 AWB 并将其返回给 Salla。references/shipment-cycle.md
订单履约跨多个承运商运行 — 接收订单、自动分配最合适的承运商 / 网点,然后驱动所分配的配送应用。references/fulfillment-cycle.md

Salla AWB 是首选的配送管理模式 — 你的配送服务会原生显示在商家的 AWB 创建界面(订单 → 创建配送标签)中, 无需维护服务器、部署或轮询。逻辑在 Salla 的应用函数运行时中执行,可直接访问 Salla Shipping API (https://docs.salla.dev/1792089m0.md)。

**显示在 AWB 承运商选项中 / Shipping Company ID:若要让配送管理(AWB)应用 显示在商家的 AWB 承运商选项中,请发送邮件至 [email protected] (https://docs.salla.dev/1792111m0.md)。**Shipping Company ID 仅由 Salla 分配 — 你无法自行设置。

工具

工具操作功能
salla_referencecategoriestype=shipping → 从 sub_categories 中选择 sub_category_id;发布所用的 main_category_id/categories 来自同一次调用的 main_categories/categories(App Theme,不限于 shipping)
salla_upload—上传徽标 → 文件 id
salla_appscreate / get / connect / set_status创建并配置 OAuth/webhooks;get 可读取应用状态,包括当前的 search_options 选择;shipping 应用是公开的,因此请使用 app_publish 发布
app_publishopen / set / validate公开应用:验证发布信息(保存为 DRAFT;合作伙伴在 Portal 中提交)
salla_eventslist / subscribe订阅异步发货事件
salla_functionslist_triggers / save / preview实现并测试同步发货 App Functions
salla_shippingget_zones / set_zones / set_policy_options / list_zone_countries / list_zone_cities / list_search_options配置配送费区域以及 policy-options / shipment-features 搜索选项——这是当前实时 Shipping Settings 页面管理的两项内容

**前提条件:**必须已连接 Salla Partners MCP 服务。请在每个步骤中传递 app_id。如果工具返回 "Salla session expired",请重新运行登录流程。


步骤 0 — 了解需求

开始前请询问:

  1. 要集成哪种模式?(这决定由哪个参考文档负责整个生命周期——见上表)
    • Shipping Management / AWB — 集成一家承运商;你需要编写生成 AWB 的 shipment.creating / shipment.cancelling App Functions
    • Order Fulfilment — 在多个 shipping 应用中自动分配最合适的承运商/网点
  2. 要集成哪家承运商或服务提供商?
  3. 是否支持货到付款(COD)?
  4. 承运商覆盖哪些地区/配送区域?

第 1 步 — 创建应用

  1. 查询类别:salla_reference action=categories type=shipping → sub_categories。 sub_category_id 必须从 sub_categories 中选择一个配送子类别,否则会被拒绝。(目前,Fulfillment / Other / Drop-shipping 对应的 ID 为 45 / 46 / 54;这些 ID 仅作示例 — 请始终读取实时值,不要硬编码。)不要将同一次调用返回的 main_categories/categories 用作发布时的 main_category_id/categories — 那是与类型无关的独立「应用主题」/「应用影响」列表,并非配送专用列表 → step-basic-information.md。
  2. 上传徽标:salla_upload(正方形 1:1,≥ 250×250 像素)→ 文件 id。
  3. 创建应用:调用 salla_apps action=create,设置 type = shipping、sub_category_id、name、short_description(50–200)、app_url、email、logo。将应用设为公开(此类别仅支持此模式)。

结果会返回 app_id。(如需在 AWB 快递选项中显示,请发送邮件至 [email protected] — 参见上文的模型部分。)

手动备用方案: Portal → My Apps → Create App(Public,类别为 Shipping App)。 完整操作指南:https://docs.salla.dev/422995m0.md

关卡:「应用已创建 — 请确认 app_id(salla_apps action=get)。」


第 2 步 — OAuth、权限范围与 Webhook 连接

通过一次 salla_apps action=connect 调用配置 OAuth + Webhook(从 salla_apps action=get 读取有效的权限范围 slug — 没有权限范围目录参考端点):

  • scopes — 配送 + 订单访问权限(slug → "read" | "read_write")。仅申请应用所需的最低限度权限范围;除非确实需要写入权限,否则选择 read 而非 read_write,不要申请不会使用的宽泛权限。
  • redirect_urls、webhook_url、webhook_security_strategy: "signature"

签名 Webhook 的密钥不会由 connect 生成 — 请在 Partner Portal (https://portal.salla.partners/apps/{app_id})中创建或轮换密钥,并在部署前通过 salla_apps action=get(webhook_secret 字段)读取当前值;妥善保存该密钥以供 HMAC 验证使用。

OAuth、令牌存储/刷新以及针对每个商家的刷新锁 → salla-app-auth。 Webhook 签名验证(根据原始请求体验证 X-Salla-Signature,拒绝无效签名,绝不记录密钥)和幂等性 → salla-webhooks。将这些事项交由对应模块处理 — 不要在此处重新实现。

关卡:「连接已应用,且没有 _partial。Webhook URL 是否已上线并返回 200?」


第 3 步 — 配置配送区域与设置

**配送应用没有商家设置表单。**不要调用 salla_settings define_form — 该表单适用于公开/私有/通信应用,而 Portal 会拒绝配送应用的 POST /settings。配送配置是下方的 salla_shipping 区域和搜索选项;承运商凭据通过 Shipping Settings URL 设置。设置表单这一概念本身 → salla-app-settings。

此步骤仅涵盖当前实时 Shipping Settings 页面管理的内容 — 不多不少。 后端功能标志下还有一种更新、更丰富的配送设置模型(包含按国家划分的公司类型、启用的服务类型和结构化时长),但该功能尚未发布,也没有面向商家的页面 — 不要基于它进行开发,也不要因为 salla_shipping 没有相关操作而感到意外。如果该功能标志将来发布,此步骤会增加一个子步骤;在此之前,区域 + 搜索选项就是全部可用内容。

salla_shipping 管理两项彼此独立的内容,分别通过不同的调用保存 — 区域,以及由两个选项组组成的组合。请将它们作为两个独立的子流程处理。

3a — 费率区域(必需)

某个区域是适用于一个国家及一组城市的费率规则。没有按区域创建/更新/删除的接口——set_zones 每次调用都会替换_整个_区域列表。要添加区域,请重新发送所有现有区域及新增区域。要编辑区域,请重新发送所有区域,并修改目标区域。要删除区域,请重新发送除目标区域外的所有区域。

  1. 获取当前状态:salla_shipping action=get_zones、app_id。**注意:**新建的配送应用已预置默认区域(所有国家 → 所有城市,固定费用)——响应非空不代表你已经配置过该区域。

  2. **写入区域前,先查找真实的国家/城市 ID。**这些不是 salla_reference ID——区域使用独立的 ID 空间:

    • salla_shipping action=list_zone_countries、app_id → 真实的国家 ID。
    • salla_shipping action=list_zone_cities、app_id、country_id(可选的 keyword 用于搜索)→ 该国家的真实城市 ID。
    • 两个列表都不会返回 id: -1“所有国家”/“所有城市”哨兵值——已通过实时验证:API 只会返回真实 ID。-1 是实时配送设置页面为展示而在客户端添加的约定值;如果商家指的是“所有地区”,请直接在区域的 country/city 中使用该值,不要在列表响应中搜索它。
    • 在此处使用 salla_reference/通用国家 ID 不会报错——Portal 会静默接受写入但不执行任何操作,看起来就像出了 Bug。务必从 list_zone_countries/list_zone_cities 获取 country/city(或使用 -1 哨兵值),切勿猜测。
  3. **就每个区域的所有字段询问商家/合作伙伴——不要擅自做业务决策。**费率、覆盖范围、配送时长和是否支持货到付款(COD)都是只有他们才知道的信息;无法从应用或其类别推断。

    • 如果 get_zones(第 1 步)只显示预置的默认区域,这就是首次设置——请进行下方的完整询问。如果已有真实区域,请总结这些区域,并具体询问有哪些变更(添加国家、修改费率、删除区域),而不是从头重新询问所有内容。
    • 首次询问时,每次只询问一个国家:先询问要添加哪个国家/地区,再解析其 ID(第 2 步),然后询问该区域的费率类型(固定或按重量浮动)、金额、配送时长文本,以及是否支持货到付款(如果支持,询问其费用)。向商家确认该区域后,再询问“还要添加其他国家吗?”,并重复此过程,直到他们表示完成——不要因为对方只回答了一个国家,就认定询问已经结束。
    • 在商家表示已完成添加国家之后(而不是在添加第一个国家后——只有完整了解其实际覆盖范围,才能做出下面的决定),明确询问是否保留或移除预置的“所有国家/所有城市”兜底区域——不要默默替他们做决定。保留它意味着未列出的国家仍会使用默认费率(很可能不合适);移除它意味着未列出的国家将没有费率。
    • 切勿替商家填写看似合理的费率、时长或货到付款默认值。如果他们还没告诉你,就询问;不要提交猜测。
  4. 提交:salla_shipping action=set_zones、app_id、shipping(区域对象数组)。每个区域:

    字段是否必填说明
    id新建区域时省略或设为 0要原地更新的现有区域 ID。
    country✅ 始终必填来自 list_zone_countries(或设为 -1 表示全部)。
    city(数组)✅ 始终必填来自 list_zone_cities(或设为 [-1] 表示全部)。
    cities_excluded(数组)可选在已包含的国家/城市选择范围内排除的城市。仅当 country/city 不是“全部”哨兵值时才有意义。
    fees.type✅ 始终必填"fixed" | "rate" | "automatic"。
    fees.amount✅ 当 type: "fixed" 时必填固定费用。必须为 1–9999 — set_zones 会在请求到达 Portal 之前进行校验(见下文)。
    fees.amount_per_unit、fees.up_to_weight、fees.per_unit✅ 当 type: "rate" 时必填可变费率定价:超过阈值后按单位重量计费。三项必须同时提供;amount_per_unit/per_unit > 0,up_to_weight 为 1–9999,且所有值上限均为 9999。
    duration✅ 始终必填自由文本,例如 "2-3 business days" — 不是结构化值。
    cash_on_delivery.status✅ 始终必填(布尔值)—
    cash_on_delivery.fees✅ 当 cash_on_delivery.status: true 时必填必须 > 0,上限为 9999。

    此调用会替换完整的区域列表 — 请包含要保留的所有区域。

业务规则,严格执行 — 区域的 country/city 一经创建便会锁定。 创建现有区域后,无法更改其国家或城市,只能修改费率/时长/COD。set_zones 会拒绝任何 id 与现有区域匹配、但 country/city 不同的已提交区域 — 请创建新区域,而不是尝试“移动”现有区域。 Portal 不会拒绝无效的费用数据,而是会静默地将其破坏。 实测已确认:缺少 amount_per_unit/up_to_weight/per_unit 的 "rate" 类型区域仍会被创建,且这三个字段都会默认为 0(结果是一个永久免运费区域,而不是报错);负数 fees.amount 会被静默截断为 0;超出范围的费用(例如 999999)会导致 Portal 静默丢弃整个提交批次,而不只是有问题的区域,同时仍报告成功。现在,set_zones 会在发起任何网络调用前,根据上表中的范围验证每个费用字段,并且在每次写入后重新读取区域列表,确认其确实反映了提交内容——如果某次“成功”的写入未能完整持久化,调用就会失败并给出明确提示,而不会再静默地谎报成功。如果你看到 set_zones 因“post-write zone count doesn't match”消息而失败,切勿盲目重新提交同一批次——请逐个检查其中的区域。

检查关卡:“salla_shipping action=get_zones 反映了你的区域(国家/城市/费率/货到付款均正确),现有 id 的任何区域都没有更改其 country/city,并且 set_zones 返回成功——而不是 post-write mismatch 错误。”

3b — 政策选项与货运功能(必需)

这是两个语义不同的选项组,共用一个目录和一次保存调用——不要为它们构建独立流程:

  • 政策选项——运单/货运详情字段(包装类型、产品类型、尺寸等),用于“帮助识别货运详情,让配送体验更轻松”。这些描述的是_货运本身_。
  • 货运功能——应用商店的发现/筛选元数据(“帮助用户按类型和覆盖范围搜索货运应用”)。这些信息帮助商家在应用市场中_找到_你的应用——它们不是货运数据。
  1. 获取目录: salla_shipping action=list_search_options、app_id → 每个可用选项,格式为 {id, slug, type, is_filter, is_shipping_policy, categories, name: {ar, en}, values: [{id, slug, name: {ar, en}}]}, 响应 meta 中还包含一个 shipping_category id。自行拆分:

    • 政策选项 = is_shipping_policy === true 的选项。
    • 货运功能 = 满足 is_filter === true、is_shipping_policy === false 且 categories 包含响应中 shipping_category id 的选项。 (这与实时「货运设置」页面筛选同一目录的方式完全一致——不要另行推导不同的筛选条件。)已知缺口: 实测发现,在某些环境中,meta 可能为空(没有 shipping_category id)。如果发生这种情况,不要猜测类别 id——检查每个选项的 categories 数组是否都包含同一个 id(实际情况确实如此;该共享 id 就是货运类别),并将结果有歧义视为需要上报的阻塞问题,而不是悄悄变通。你会看到不符合任一规则的目录条目(实测确认:类似 included_destination_cities、destination_countries 的地理覆盖范围型 slug,以及其他类似条目——is_filter: false 且 is_shipping_policy: false)。这些属于较新的、尚未发布的货运设置流程(由 shipping_settings_page 后端功能标志控制,不在本技能范围内——参见本步骤顶部的说明)。实时「货运设置」页面也采用同样的拆分规则忽略这些条目——不要向商家询问它们;这是有意为之,并非拆分逻辑有缺陷。

    已确认的实时目录(仅供参考——始终读取实际响应;Salla 可能会添加/移除选项;不要将这些 slug 硬编码为完整清单):

    分组slug阿拉伯语标签含义
    政策选项shipment_content_type运输类型货件内的产品/内容类型(例如,电子产品)。
    政策选项packaging_type包装类型货件的包装方式。
    政策选项support_dimensions货件尺寸商家是否必须提供包裹尺寸。
    政策选项support_number_of_box箱子数量商家是否必须提供箱子数量。
    货件功能delivery_service_type取件和配送方式承运商提供的取件/配送方式。
    货件功能shipping_cover_type配送覆盖范围地理覆盖范围(例如,国内/国际)。
    货件功能company_type公司类型承运商公司的类型/分类。
    货件功能services服务承运商提供的服务。
    货件功能support_change_name公司显示名称不是发现元数据——这是一个实际面向商家的开关:商家能否在店面结账时覆盖所显示的承运商名称。即使它位于「货件功能」组中,也应像对待任何其他运营设置一样谨慎对待。
  2. 构建选择前,先了解每个选项的 type:

    • "multi_select" / "select" — 按 id 从该选项的 values[] 中选择一个或多个条目。
    • "boolean" — 不是直接填写 true/false:请选择 slug 为 "true" 或 "false" 的单个值对象(每个布尔选项的 values[] 中都实际包含这两个值)。两者都不选表示“未回答”。
    • is_required 仅适用于政策选项——在线的配送设置页面只会为政策选项显示每个选项对应的“必填”复选框;配送功能在 UI 中没有此控件。API 理论上允许为任何选项设置 is_required,但为配送功能设置此项,在商家实际使用中没有对应效果——除非有特殊原因,否则不要为其设置此项。
  3. 使用真实目录采访商家/合作伙伴——不要猜测哪些值适用于他们的承运商。 每个选项的正确值都是只有他们才知道的业务事实(他们的包装、配送范围、公司类型);目录只会告诉你_可以_回答什么,而不是答案本身。

    • 先检查 salla_apps action=get 的 search_options 字段。字段为空或不存在表示是首次设置——请进行下方的完整采访。如果已有选择,请先概述这些选择,并具体询问哪些内容有变化,而不是重新询问所有内容。
    • 首次采访,按分组批量提问:在一条消息中列出全部 4 个政策选项,使用每个选项真实的 name.ar/name.en 标签,以及第 1 步中该选项真实的 values[] 选项(绝不可编造选项)——询问每个选项的取值,并明确询问该选项是否应设为必填。然后在第二条消息中列出全部 5 个配送功能,采用相同的真实标签/真实取值方式,不询问是否必填(参见上述差异)。如果在线目录中某个分组没有任何选项,则完全跳过该分组的消息。
    • 对 support_change_name(配送功能),应以通俗语言提问,而不是使用术语——它的实际含义是“商家能否在店铺结账页面更改承运商的显示名称?”;请这样提问,不要直接念出 slug。
  4. 一次调用提交两个分组: 调用 salla_shipping action=set_policy_options,传入 app_id 和 search_options(由 {id, is_required?, values} 组成的数组——id 是搜索选项 ID,values 是第 3 步收集的所选 values[].id,is_required 是可选的逐选项开关)。在同一个数组中混合政策选项和配送功能条目——这种分组仅用于说明,并非结构上的区分。此调用会替换当前选择——请包含你要保留的所有选项(来自两个分组)。

  5. 验证实际保存的内容。 salla_shipping 没有读取应用_当前_选择项的操作——action=list_search_options 始终只返回静态目录(所有可能的选项/取值),不受已保存内容影响。要确认实际选中了哪些选项,请调用 salla_apps action=get 并读取其 search_options 字段(当前应用的一组 {id, values})——这是当前选择项的唯一真实来源。不要在不同轮次中自行跟踪;请重新读取。

检查点:“salla_shipping action=set_policy_options 调用成功,并且 salla_apps action=get 的 search_options 字段显示了所有你打算保留的选项——没有任何选项因遗漏而丢失。”

红旗——区域与政策选项
看似诱人的想法错在哪里
“我会用一个看起来合理的费率/时长,这样就不用问了。”商家的费率由商家自行决定,无法推断出来——看似合理但实际错误的数字,会导致真实客户遇到实际定价错误(3a)。
“他们提到了一个国家——这大概就是他们覆盖的全部范围。”商家通常不会主动列出完整名单——结束区域访谈前,务必明确询问是否还有其他国家/地区(3a)。
“我会跳过‘必填’问题,设为可选。”必填还是可选,会实实在在影响商家的结账流程,而不是走个形式——务必针对每个政策选项明确询问(3b)。
“slug 名称一看就懂——没必要向商家解释。”support_change_name 等名称,光看 slug 并不能看出其实际含义(例如,它指的是覆盖结账时显示的名称)——要用通俗语言提问,不要使用行话(3b)。

你仍需在 Portal 中设置 Shipping Settings URL——这是 Salla 在商家后台加载的页面,用于收集承运商凭据(API key、账号)。这与上文的区域/搜索选项是不同的概念——该 URL 页面收集的是商家每个店铺的承运商凭据,而不是你应用自身的配置。显示或保存任何凭据之前,先验证商家/会话身份,并对凭据加密存储,绝不要记录它们。(嵌入式页面会话身份验证 → salla-embedded-app。)

设置指南:https://docs.salla.dev/422996m0.md


第 4 步——核心应用功能(Shipping Management / AWB)

Shipping Management(AWB)应用会实现 两个同步 App Functions (salla_functions action=list_triggers 类别 merchant_actions),并可订阅 三个异步事件(merchant_events)。App Functions 在 Salla 运行时中执行, 通过其返回值塑造操作,并通过 App Function MCP 预览进行测试——而不是通过 webhook 端点。

触发器类别(MCP 已确认)返回类型触发时机处理程序的操作
shipment.creatingmerchant_actions(同步)Promise<Shipment>创建货件或退货时(订单 → completed,或创建发货标签/创建退货标签)调用承运商 API → 生成 AWB;返回一个 Shipment(运单号 + PDF 标签 + 状态)
shipment.cancellingmerchant_actions(同步)Promise<Resp>取消货件/退货之前调用承运商 API 作废/取消;返回 Resp.success()(或返回错误以拒绝)
shipment.createdmerchant_events(异步)—创建货件之后同步下游状态(后台处理)
shipment.cancelledmerchant_events(异步)—取消货件之后对账/通知(后台处理)
shipment.updatedmerchant_events(异步)—货件详情变更之后同步跟踪/状态(后台处理)

要用于 save 的名称: 同步取消函数是 shipment.cancelling (merchant_actions,返回 Resp),尽管 AWB 文档将其页面标为“货件已取消” (https://docs.salla.dev/1797616m0.md)。`shipment.cancelled` 是单独的 异步事件。使用 salla_functions action=list_triggers 核对名称(详情 → references/shipment-cycle.md)。

shipment.creating 同时处理新货件和退货——使用一个函数,根据载荷的 type 字段("shipment" 与 "return")进行分支处理(https://docs.salla.dev/1792119m0.md)。

这些同步触发器是 App Functions,而不是 Webhook。 使用 salla_functions action=save 实现每个触发器(每个触发器一个函数),并使用 salla_functions action=get 获取锁定的封装模板。处理程序签名(每个签名的首行均已锁定):

// shipment.creating — generate the AWB and return a Shipment
export default async (context: Shipments): Promise<Shipment> => {
  const { payload, settings, merchant } = context;
  const { data: shipment } = payload; // type: "shipment" | "return"

  const result = await callCarrierAwbApi(shipment); // your third-party API

  // setShipmentNumber() is REQUIRED; setPdfLabel/setStatus shape the AWB.
  // Return Shipment.error("…") on carrier failure.
  return Shipment.success()
    .setShipmentNumber(result.awb_number)
    .setPdfLabel(result.label_url)
    .setStatus(ShipmentStatusEnum.IN_TRANSIT);
};
// shipment.cancelling — void with the carrier, return Resp (NOT a Shipment)
export default async (context: Shipments): Promise<Resp> => {
  await voidWithCarrier(context.payload.data.shipping_number);
  return Resp.success().setData({});
};

App Function 的机制归 salla-app-functions 系列文档介绍——包括 V8 沙箱 限制、锁定模板/首行规则、保存/验证、5 秒同步预算 (每次内部异步调用 < 2 秒)、预先通过身份验证的 Admin API(无需 Authorization 标头), 以及 Resp/Shipment 构建器运行时:设计 → salla-app-functions-design, 处理程序正文 → salla-app-functions-handler,保存/验证 → salla-app-functions-validate,测试/预览 → salla-app-functions-test。 发货相关的具体内容——完整的 Shipment 构建器方法列表、ShipmentStatusEnum、 Shipments 上下文载荷,以及三种 AWB 处理流程——见 references/shipment-cycle.md。 保存之前:请先根据获取到的类型确认载荷字段名称。 在获取模板(salla_functions action=get)与 salla_functions action=save 之间,将处理程序主体交给 salla-app-functions-handler 编写——它负责写入主体,包括以下规则:获取 action=get 返回的 types 数组中的每个 URL,并根据这些 .d.ts 定义,从 context.payload.data 中读取 shipment.creating / shipment.cancelling 的确切载荷字段名称(地址、包裹、重量、type: "shipment" | "return")。不要猜测 sender_address / receiver_address / weight 这类载运商 API 风格的名称。

关卡:“处理程序主体已通过 salla-app-functions-handler 编写,且每个 context.payload.data 字段都已根据触发器获取的 types .d.ts 确认——没有猜测任何字段——之后才执行 salla_functions action=save?”

通过 App Function MCP 预览进行测试(由 salla-app-functions-test 负责):保存函数,轮询 salla_functions action=deploy_status,直到状态为 COMPLETED,然后使用 app_id、trigger、演示用 store_id 以及触发器的表单字段(例如真实的 shipment_id)运行 salla_functions action=preview。

异步事件(shipment.created / shipment.cancelled / shipment.updated)是普通的店铺事件——使用 salla_events action=subscribe 订阅(它会替换完整列表,因此请包含所有要启用的事件)。使用 salla_events action=list 验证。传输(签名、快速返回 200、幂等性)→ salla-webhooks。

App Function 会同步返回 AWB。对于承运商确认后的带外更新(实际运费、跟踪信息、状态变更),请使用由合作伙伴发起的 Update Shipment Details REST 调用(PUT /shipments/{id},存储商家的 access_token——令牌存储/刷新 → salla-app-auth;端点结构、必填字段和状态枚举 → references/api-endpoints.md)。请根据端点的 docs.salla.dev/<id>.md 页面中记录的 OpenAPI 架构验证 PUT /shipments/{id} 请求体(通过 salla-docs 查找该页面),并在依赖它之前修正问题;使用 salla-api-core 中的读取架构 → 构建 → 验证 → 修正 → 重试循环。

关卡:“在演示店铺上,salla_functions action=preview 对 shipment.creating(type: shipment 和 type: return 两种情况)均返回有效的 Shipment,对 shipment.cancelling 返回 Resp.success(),且订单上显示了 AWB 编号 / 跟踪信息。”


步骤 5 — 订单履约(如果这是你的模式)

如果你在步骤 0 中选择的模式是订单履约(https://docs.salla.dev/423000m0.md),流程会有所不同:你无需编写 shipment.creating App Function——而是响应 order.created,选择承运商/网点,并分配货件,这会触发已分配的 Shipping App 的 shipment.creating 函数。请根据 https://docs.salla.dev/423002m0.md 配置权限范围(Basic Info、Orders、Webhooks、Shipping)和事件(order.created、shipment.created)。

完整的分配 + 退货/取消流程 → references/fulfillment-cycle.md。


第 6 步 — 测试与发布

**测试:**通过 App Testing 连接演示商店,并模拟:新订单 → 费率请求 → 标签 → 物流跟踪 → 取消 → 退货。端到端演示商店验证由 salla-live-testing 负责。使用演示数据/非敏感数据:不要将生产承运商凭据、OAuth/Bearer 令牌、Webhook 签名密钥和真实客户个人身份信息(PII)提供给任何第三方捕获/检查工具;完成后恢复真实配置。

**发布:**物流应用是公开应用(见顶部说明)→ 分步执行 app_publish(open → 对每个部分执行 set → validate 保存为 DRAFT;合作伙伴随后在 Portal 的 /publish 页面中一键提交 — 由 salla-publication-consistency 负责)。针对特定商家构建的承运商应用属于 type: "private" 应用 → 请改用 salla-app-builder → 私有应用:无需 sub_category_id,且 shippings 作用域保持禁用状态(适用于常规合作伙伴,除非 Salla 将该应用加入允许列表)或不可用(适用于商家合作伙伴)。type: "shipping" 应用有两个阻碍:

获批后,你的应用将列在 https://apps.salla.sa/en 的 Shipping 类别下。

测试指南:https://docs.salla.dev/422998m0.md · 发布指南:https://docs.salla.dev/422990m0.md

门槛:“已发布 — salla_apps action=get 显示预期状态。”


资源

主题链接
配送概览(两种模式)https://docs.salla.dev/422988m0.md
配送 API 列表https://docs.salla.dev/api-5578809
Salla AWB — 入门指南https://docs.salla.dev/1792089m0.md
AWB — 创建应用https://docs.salla.dev/1792111m0.md
AWB — 设置应用https://docs.salla.dev/1792112m0.md
AWB 功能 — 创建货件https://docs.salla.dev/1792119m0.md
AWB 功能 — 取消货件https://docs.salla.dev/1797616m0.md
配送管理 — 创建https://docs.salla.dev/422995m0.md
配送管理 — 设置https://docs.salla.dev/422996m0.md
配送管理 — 应用周期https://docs.salla.dev/422994m0.md
配送管理 — 测试https://docs.salla.dev/422998m0.md
订单履行 — 创建https://docs.salla.dev/423001m0.md
订单履行 — 设置https://docs.salla.dev/423002m0.md
订单履行 — 应用周期https://docs.salla.dev/423000m0.md
订单履行 — 测试https://docs.salla.dev/423003m0.md
Postman 集合https://www.postman.com/salla-app/workspace/salla-e-commerce-platform/collection/17687195-d700cd60-adf3-4b20-82ee-94851e88bd44
开发者社区https://t.me/salladev

评论

支持 Markdown