关于 salla-app-builder
salla-app-builder 是指导 Agent 通过 Salla Partners MCP 从头创建并配置 Salla 应用的工作流。它按阶段推进创建、OAuth 与权限、Webhook 及发布,并要求核验变更结果和部署域名。
主要功能
- 01分阶段创建与配置应用
- 02查询类别、范围和事件
- 03设置 OAuth 与 Webhook
- 04写入后读取确认变更
- 05核对部署域名一致性
适用场景
- 01创建面向商家的 Salla 应用
- 02为应用配置最小必要权限
- 03准备应用审核与发布
MCP 相关
该技能使用 Salla Partners MCP 工具操作应用、范围和事件,并在服务不可用时提供 Portal 手动流程。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sallaapp/ salla-partners-agent-kit --skill salla-app-builder安装后在 Claude Code 中输入/salla-app-builder确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/demo-store-testing.mddomain-consistency.mdonboarding-steps.mdprivate-apps.md详细介绍
Salla App Builder — 从零创建应用
通过执行操作来构建完整的 Salla 应用,而不只是描述如何构建。 每个步骤都会调用一个 Salla Partners MCP 工具来完成工作。请按顺序执行各个步骤 — 完成当前关卡后,再继续下一步。
依据真实信息 — 读取真实值,确认真实结果。
- 在向 Salla 写入任何 URL 之前,先验证已部署的域名。 读取 Vercel 项目的实际域名 — 使用
vercel project ls、Vercel MCP 或.vercel/project.json— 然后再设置app_url、嵌入式iframe_url或代码片段 BASE。猜测一个无法解析的*.vercel.app域名,会导致安装、webhook 和 iframe 悄无声息地失效(写入时不会报错)。- 每次修改后都要回读。
connect/update/subscribe可能会返回精简或空的响应体 — 零字段响应无法与静默失败区分开来。将更改视为完成之前,先通过get/list确认;切勿只相信写入响应。- 更改域名时,请同时更新所有使用该域名的位置 — 门户中的
app_url、嵌入式iframe_url、代码片段 BASE,以及每个环境变量。检查清单: references/domain-consistency.md。
流程: 创建 → 配置 → 发布。 创建应用只是第一道关卡 — 应用创建后并未发布;它仍需要配置权限范围、webhook/事件、任何 UI,并通过审核后才能面向商家 (docs.salla.dev/421410m0.md)。所有操作都通过 Salla Partners 账户(已验证) → portal.salla.partners → 我的应用 (docs.salla.dev/421412m0.md) 完成。下方的 MCP 工具会操作同一个门户,因此连接后优先使用这些工具。
工具
以下步骤将调用 Salla Partners MCP 工具。每项工具都有一个 action:
| 工具 | 功能 |
|---|---|
salla_reference | 查询 categories、countries、cities |
salla_upload | 上传徽标/文件 → 返回文件 id |
salla_apps | create / update / get / list / connect(OAuth+webhooks)/ set_status / demo_stores(测试)。公开应用发布使用单独的 app_publish 工具;私有应用使用 salla_private_apps。 |
salla_private_apps | 私有应用:status(不带 app_id = 账户类型)/ publish(需确认)/ withdraw / 商店请求(list_requests get_request create_request update_request delete_request)→ references/private-apps.md |
salla_scopes | get 有效的权限范围标识(slug)(以及 disabled / selected)/ set 已选权限范围(扁平格式:slug → read | read_write | "") |
salla_events | list 可订阅的事件 / subscribe 将应用订阅到标识(slug) |
**前提条件:**必须连接 Salla Partners MCP 服务(上述工具会显示在你的工具列表中)。如果未连接,请改用 Portal:https://portal.salla.partners,并参考内嵌的手动说明。如果工具返回“ Salla session expired — reconnect”,请运行 OAuth/登录流程。
步骤 0 — 了解需求
开始前先询问:
- 你的应用能做什么?(简要描述)
- **应用类型:**General / Communication / Shipping
- **可见性:**Public(App Store)还是 Private(仅限邀请)?
这是两个独立的选项(docs.salla.dev/421410m0.md):
Public 应用会显示在 Salla App Store,供任何商家浏览、下载或购买;Private 应用是为特定商家构建的,不会出现在商店的列表或搜索结果中。Category(General 与 Shipping)是另一个维度——应用的 type 只有一个值(app / private / shipping / communication),因此 Shipping 应用始终是 Public,而 Communication 应用通常也是 Public。可见性由 Portal 按类型强制执行,因此应让 create/publish 验证组合,而不要自行假定。
根据回答调整步骤 1、4–7。
步骤 1 — 创建应用
- 确定类别。 使用
action: "categories"调用salla_reference,并提供type("app"或"shipping")以获取sub_categories——从中选择 create 的sub_category_id(不匹配的子类别会被拒绝)。私有应用在此处使用type: "app"——"private"不是有效的salla_reference类别类型。对于app/shipping,创建时必须提供sub_category_id(对于app,可选项为 POS、OMS、Subscription、Cross-sell/Upsell、Manage Store、AI、Others)。同一次调用还会 返回main_categories/categories——暂时不要使用它们;它们是与类型无关的 “App Theme”/“App Impact”列表,用于发布时的main_category_id/categories,而不是此步骤 → salla-publication-consistency。 - 上传 Logo。 使用公开图片的
source_url调用salla_upload。Logo 必须是正方形(1:1)图片,且尺寸 ≥ 250×250 px——上传前确保源图片满足 此要求。返回结果仅包含{id, url}(不会返回尺寸),因此请使用返回的id。如果创建时没有 Logo,且有可用的图像生成工具,请生成一个(1:1,≥ 250×250)并上传—— 完整的规范流程(以及其他每个上架/发布图片字段及其尺寸)→ salla-app-ui-builder。 - 创建应用。 Salla 创建应用时要求的基本信息包括图标、名称、类别、
描述、应用网站和支持邮箱
(docs.salla.dev/421410m0.md);通过 MCP,这些信息
对应下方的字段。使用
action: "create"调用salla_apps,并提供: | 字段 | 要求 | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |name+name_ar| Salla 要求应用名称使用阿拉伯语,以不带变音符号/元音符号的普通字母书写(例如 هريفاي,而不是 هرّفاي),且在 Salla 应用中保持唯一。请将这些要求视为由 Portal 强制执行——让create进行验证:先提交,再根据错误采取行动(如果名称已被占用或无效,则重命名并重新提交),不要在客户端预先检查。如有疑问,请从create响应中确认具体限制。 | |type| 来自步骤 1(private或某个公开类别) | |short_description(+_ar) | 每项 50–200 个字符——与name一样使用双语 | |app_url| 应用的线上 URL——从已部署的 Vercel 项目中读取(Grounding 规则 1),不要猜测*.vercel.app。这是源域名;如果之后发生变化,也要在此处更新(步骤 1 门槛/域名一致性检查清单)。 | |email| 支持邮箱 | |logo| 来自salla_upload的文件id| |sub_category_id| 当type为app/shipping时必填 | |is_paid| 私有应用必填——传入步骤 3a 中的private_app_is_paid。 | **3a. 仅限私有应用:**在调用create前,不带app_id调用salla_private_apps action=status,并将其private_app_is_paid作为is_paid传入(商家合作伙伴传入"0";普通合作伙伴传入"1",除非 Salla 已授予免费私有应用)。规则 → references/private-apps.md。
结果会返回新的 app_id——在后续每一步中都使用它。在合作伙伴门户中打开应用以查看、配置和测试:
https://portal.salla.partners/apps/{app_id}(替换为返回的 id)。每次创建后,都向用户提供此链接。应用详情页面是后续步骤所配置内容的中心,包括应用密钥(客户端 ID/密钥、OAuth 模式)、Scope、Webhooks、受信任的 IP、应用函数、设置、引导流程、嵌入式页面、代码片段、自定义套餐、测试和发布(docs.salla.dev/421410m0.md)。
**关于
salla_apps action=update的注意事项:**门户不会返回正文,因此工具会回显你更改的字段({ app: { id, …changed, updated: true } })作为确认——这反映的是你的输入,而不是服务器存储的状态。对于影响重大的更改,仍应使用salla_apps action=get读回,以确认值确实已保存。
**手动备用方案:**门户 → 我的应用 → 创建应用。
确认关卡:“应用已创建——确认返回的 app_id(salla_apps action=get);如果是 type: private,确认 is_paid 来自 salla_private_apps action=status。”应用创建后尚未发布(docs.salla.dev/421410m0.md);继续完成配置 → 发布。
危险信号 — 创建
| 看似合理的想法 | 错误原因 |
|---|---|
"create 被拒绝了——提示“不能创建超过 N 个私有应用”;一定是该功能已关闭。" | 该账户没有剩余的免费私有应用(普通合作伙伴默认没有免费名额)。将其创建为付费应用:在 salla_apps action=create 中设置 is_paid: "1"。 |
步骤 2 — OAuth、权限范围与 Webhook 连接
默认使用简易模式。 简易模式(通过
app.store.authorizewebhook 获取令牌,不使用 回调)是所有应用的推荐默认模式——除非有明确的技术原因导致它无法使用,否则请使用此模式。 自定义模式(OAuth/callback代码交换)适用于开发期间的本地开发 / Postman;在自定义模式下发布应用, 如果没有真实且合理的使用场景,审核时可能会被拒绝。模式机制 → salla-app-auth。
在一次 salla_apps action=connect 调用中配置 OAuth 和 Webhook。首先检查
应用有效的权限范围 slug 和当前选择:
- 使用
action: "get"和app_id调用salla_scopes,读取有效的权限范围 slug、 当前选择,以及任何按应用设置的disabled标记。(没有权限范围目录 参考端点——salla_scopes会从应用读取这些信息。)最小权限原则: 仅请求应用所需的最少 slug;除非应用确实需要写入,否则优先选择read而非read_write——权限范围过多可能导致审核延迟或被拒绝。disabled选项不会保存,因此请遵循get返回的标记。在商户合作伙伴的私有应用中,shippings、settlements、subscriptions和customer_wallets均为隐藏状态(不允许通过允许列表例外启用);在普通合作伙伴的私有应用中,除非 Salla 将应用加入允许列表,否则shippings会被禁用。受限权限范围不会保存,并且salla_scopes action=set会在dropped下列出它们 → references/private-apps.md。 - 使用
action: "connect"、app_id以及以下任意参数调用salla_apps:scopes—slug → "read" | "read_write"映射(例如{"orders": "read", "products": "read"})。此处仅传入资源映射——offline_access应放在 OAuth 授权 URL 中,而不是scopes映射中。 (也可以单独使用salla_scopes action=set调整选择。)redirect_urls— OAuth 重定向 URL。仅限 HTTPS;请严格限制允许列表 (仅注册实际使用的确切回调 URL)。webhook_url— Webhook 接收端(仅限 HTTPS,必须通过以下签名 / 令牌策略验证传入请求)webhook_security_strategy—"signature"(推荐)或"token"trusted_ips、webhook_headers
部分失败会在 _partial 下返回——仅重新应用失败的部分。
connect 不会生成或轮换 Webhook 签名密钥。请在 Partner Portal
(https://portal.salla.partners/apps/{app_id})中创建或轮换密钥;在那里轮换会使旧值失效。使用 salla_apps action=get 读取当前密钥(webhook_secret 字段),
并将其存储在密钥管理器中(绝不要存入源代码 / 仓库);每个 Webhook 都要用它验证 HMAC-SHA256 签名。部署前请实时读取密钥——绝不要重复使用跨会话沿用的密钥。签名验证 + 幂等性 → salla-webhooks 技能。令牌处理
(简易模式与自定义模式、存储、刷新)→ salla-app-auth 技能。(在此处指引,不要
重新实现。)
检查关卡:“权限范围 + 重定向 + Webhook 均已应用(没有 _partial),并且回读
(salla_scopes action=get / salla_apps action=get)确认权限范围、重定向和
Webhook URL 均已正确保存(依据原则 2)。Webhook URL 是已部署的线上域名
(依据原则 1),返回 200,且密钥已存储?”
步骤 3 — 订阅商店事件
- 调用
salla_events,设置action: "list"和app_id,获取应用可以订阅的有效事件标识 (务必先调用此项——事件标识会经过验证)。 - 询问:“您的应用会对哪些领域作出响应?”仅订阅所需事件,调用
salla_events并设置action: "subscribe"、app_id和events: [...slugs]。
Hookable 规则——优先使用 App Functions。在为 STORE 事件(订单 / 商品 / 购物车 / 客户……)订阅 webhook 之前,请检查 App Function 触发器目录 (
salla-app-functions),并优先使用 App Function:它在 Salla 内部运行,读取context.settings,并调用 Salla API,无需自行处理令牌 / 刷新逻辑或进行签名验证。仅当没有触发器时,才对生命周期 / 授权事件使用 webhook——app.store.authorize(会传送 Easy-Mode 令牌)、安装 / 卸载、试用 / 订阅。 清晰的职责划分:生命周期 / 授权 → webhook · 商店自动化 → App Function · 店面 UI → snippet · 商家配置 → 嵌入式仪表板。
按领域划分的常见事件标识:
| 领域 | 关键事件 |
|---|---|
| 生命周期(始终) | app.store.authorize、app.installed、app.uninstalled、app.updated、app.subscription.started |
| 订单 | order.created、order.updated、order.status.updated |
| 商品 | product.created、product.updated、product.deleted |
| 客户 | customer.created、customer.updated |
| 发货 | shipment.created、shipment.cancelled、shipment.updated(异步 webhook)——shipment.creating/shipment.cancelling 是同步 App Functions(参见 salla-shipping-app) |
事件开始传送前,必须先设置
webhook_url(步骤 2)。未知事件标识会被拒绝,并返回有效列表——请从中选择(salla_events action=list是权威来源)。
检查点:“已订阅。请从演示商店触发一个事件,并确认 webhook 已收到该事件。”
步骤 4 — 店面片段
询问:“您的应用是否需要向商家的店面注入 HTML/JS?”
- 是 → 按照
salla-snippets技能操作(使用salla_snippets创建片段)。 - 否 → 跳至步骤 5。
步骤 5 — 嵌入式应用页面
询问:“您的应用是否需要在 Salla 商家仪表板中提供自定义 UI?”
- 是 → 按照
salla-embedded-app技能操作(使用salla_embedded_pages注册 iframe 页面,并设置 SDK、身份验证和主题同步)。 - 否 → 跳至步骤 5a。
步骤 5a — 安装后引导步骤(可选)
询问:“您的应用是否需要在安装后立即向商家显示引导设置步骤?” 引导流程可选,如果存在,则每位商家仅在首次安装时运行一次。常见用途:在应用激活前收集凭据(例如邮箱和密码)、收集店铺资料,或配置之后无法更改的设置。
- 是 → 每个步骤都由两个必需部分按顺序构成:先创建步骤(表单,且
fields不能为空),再创建其 App Function 处理程序。使用salla_onboarding_steps action=create创建步骤(icon、title、slug均为必填项——title是单语言纯字符串,不是{ar,en};步骤没有url;fields必填,架构与公开应用设置相同;sort、required为可选项),使用action=sort重新排序(更改显示顺序),使用action=list/delete管理。然后——确认步骤已通过action=list创建后 (触发器根据已保存的步骤解析,因此先保存处理程序会返回“Unknown trigger”)——使用salla_functions action=save添加处理程序(触发器app.onboarding.step.creating.{slug}, 上下文Onboarding):商家的输入会作为context.payload.data.fields传入,以供验证或执行自定义逻辑;返回Resp.success()(继续)或Resp.error().setFields(...)(停止并显示反馈)。处理程序必须支持重复调用——每次提交时都会触发(商家可以在激活前编辑并重新保存),因此每次运行都要执行 upsert 并重新验证。在服务提供方一侧验证凭据,仅存储加密或哈希后的内容。 完整工具参数、硬性规则、update重新验证规则、处理程序及完成负载格式:请加载 references/onboarding-steps.md。 - 否 → 跳至步骤 6。
步骤 6 — App Functions
询问:“您的应用是否需要由 Salla 事件触发的无服务器处理程序?”
- 是 → 遵循
salla-app-functions技能,了解 App Function 源码、上下文结构、RespAPI 和超时。App Functions 用于处理店铺事件自动化(存在相应触发器时);生命周期和身份验证事件仍通过 Webhook 处理(步骤 3,由salla-app-lifecycle/salla-app-auth负责)。
使用 salla_functions action=save 保存函数(app_id、trigger、content、
name)——这是 upsert(创建或更新)。 保存的函数会立即在应用的演示店铺中生效;只有应用发布后(步骤 8)才会在真实店铺中生效。使用 salla_functions action=get 读取,使用 action=delete 移除。(salla_functions 受运营者权限限制:如果 MCP 部署未启用 App Builder 服务,它会明确报错。)详情 → salla-app-functions。
检查条件:“函数是否已保存并在演示店铺中正常运行?”(发布到生产环境将在之后专门的发布步骤中进行——不是现在。)
步骤 7 — 特定应用类型的设置
根据步骤 0 中的应用类型分支:
通用应用
需要按商家分别配置(API 密钥、开关、URL)?→ 遵循
salla-app-settings 技能(使用 salla_settings action=define_form)。
通信应用
代表商家发送消息(WhatsApp、SMS、电子邮件):
- 创建时将
type设为通信类别——通信应用不使用sub_category_id。 - **发布阻断条件:**发布前必须通过
salla_settings action=set_features声明支持的功能(sms_local、sms_international、email_all、whatsapp)——未提交这些功能将返回 403。 - 完整流程(渠道、负载、发送状态)→
salla-communication-app技能。
物流应用
集成承运商或履约服务提供商:
- 通常为 Public;如果要设为 Private,请让
create/发布操作验证是否允许,而不要假定可以。 - 遵循
salla-shipping-app技能(它使用salla_shipping管理区域/设置,并使用salla_apps管理完整生命周期)。
步骤 8 — 测试、验证草稿并移交给合作伙伴
Public 应用与 Private 应用 — 各自的发布方式
发布前,先根据应用类型确定流程——两者的流程并不通用:
- 如果
type是private(只能由特定商家通过商店请求安装)→salla_private_apps:status→publish(confirm: true,仅在合作伙伴确认后执行——商家合作伙伴的应用通常会立即上线)→ 每个商店执行一次create_request。无需入驻流程、无需公开上架,也没有就绪度分区——完全跳过下方的app_publish流程。完整流程 → references/private-apps.md。 - 否则(公开应用——上架至 App Store,任何商家都能发现/安装)→ 使用下方子步骤 1–4 中逐步进行的
app_publish入驻流程:open→ 按分区引导执行set→app_publish action=validate(验证并保存为草稿)→ 引导合作伙伴在 Portal 中一键提交。这需要完整的公开上架信息(类别、定价、截图、权益、联系信息等)。具体操作 → 遵循 salla-publication-consistency。
关卡:“type 是 private 吗?→ salla_private_apps action=status app_id → 合作伙伴明确确认 → 使用 confirm: true 执行 publish → 发布状态变为 approved 后(普通合作伙伴的应用会先进入 Salla 审核),对每个商店执行一次 create_request(references/private-apps.md),然后停止——不执行 app_publish,不进行入驻。否则,继续下方的公开应用 app_publish 流程。”
-
在演示商店中测试。 使用
salla_apps action=demo_stores、app_id列出公司的演示商店。每个商店会返回:connected—true表示应用已安装在该商店中。install_url— 在浏览器中打开,以便在该商店中安装应用。dashboard_url— 自动登录该商店的管理后台(用于打开嵌入式控制面板、更改设置等)。url— 店面预览(用于验证商品页上的代码片段/紧迫性提示)。
选择一个商店,打开其
install_url进行安装,然后打开dashboard_url进行管理,并触发每个已订阅事件,以验证端到端行为。将这些链接提供给用户。你也可以在 Portal 中打开应用本身:https://portal.salla.partners/apps/{app_id}。 -
准备就绪后,将应用设为上线状态:
salla_apps action=set_status,status: "live"。 -
验证并保存草稿。 Agent 的终端发布操作是验证,而非提交——它会验证每个分区,保存为草稿,然后停止。请按引导流程操作:
- 主要流程 — 分步引导式
app_publish:open→(设置<section>→readiness)* →validate。open会创建草稿(并解锁用于刊登页面的app_page_builder);然后针对 5 个版块(basic_information、features、pricing、contact_information、service_trial)逐一调用set,重新检查readiness,并根据返回的missing列表一次修复一个版块,直到每个版块都显示为complete;然后运行app_publish action=validate来验证并保存草稿。首次发布是引导式入驻流程,而不是盲目填写: 这些版块涉及合作伙伴的业务决策(刊登文案、类别、定价、联系方式)——逐个版块询问合作伙伴,提供基于 Salla 的选项,并根据他们的回答填写;切勿自行编造。版块字段、引导式入驻规则、刊登图片规则和 Portal 交接 → salla-publication-consistency(请遵循其中的操作流程)。 如果尚未准备就绪,同一个服务端关卡(app_publish action=validate)也会运行,并返回 422 以及仍缺少的版块。刊登内容 (名称/描述/徽标/截图/权益)通过app_page_builder编写 → salla-app-ui-builder;套餐/附加组件定价 → salla-app-billing。
- 主要流程 — 分步引导式
-
合作伙伴审核后,再发送发布请求。
validate只会保存为 DRAFT。验证通过后,向合作伙伴提供实际的/publish链接,并替换为应用的真实 ID (绝不能使用占位符):https://portal.salla.partners/apps/{app_id}/publish(例如:.../apps/1234567/publish),请他们在那里审核草稿。只有在他们于 Portal 中一键提交,或他们明确确认后你调用app_publish action=send_publish_request(confirm: true),才会提交给 Salla 审核——必须先审核并确认,之后才能提交。提交并获批后,应用就会在 https://apps.salla.sa/en 上线。操作流程 → salla-publication-consistency。
测试指南:references/demo-store-testing.md
关卡:“版块已验证并保存为草稿,合作伙伴已审核真实的 /publish
链接,且发布请求仅在他们一键提交或明确确认后发送?”
发布 — 危险信号
| 容易产生的想法 | 错误原因 |
|---|---|
“这是一个私有应用,我会运行公开的 app_publish 引导流程来发布它。” | 私有应用不使用分步上架流程。使用 salla_private_apps action=publish 发布(合作伙伴确认后设置 confirm: true)——不需要分区、引导流程或上架。 |
“我要运行 app_publish action=submit,或让私有应用通过就绪检查关卡。” | 私有应用没有公开上架信息可供验证,因此不适用公开的 validate 检查关卡。使用 salla_private_apps,然后通过 create_request 将其提交到应用商店。 |
“app_publish action=validate 已通过——公开应用现在已提交审核。” | validate 仅进行验证并保存为草稿;不会提交。将真实的 /publish 链接(.../apps/{app_id}/publish)提供给合作伙伴;只有合作伙伴单击提交,或在明确确认后调用 send_publish_request(confirm:true),审核请求才会到达 Salla。 |
资源
| 主题 | 链接 |
|---|---|
| 开始使用 | https://docs.salla.dev/421412m0.md |
| 创建你的第一个应用 | https://docs.salla.dev/421410m0.md |
| 合作伙伴门户 | https://portal.salla.partners/ |
| 应用市场 | https://apps.salla.sa/en |
| Webhook 指南和事件列表 | https://docs.salla.dev/421119m0.md |
| 应用事件(生命周期) | https://docs.salla.dev/421413m0.md |
| Salla 管理 API 参考 | https://docs.salla.dev/421117m0.md |
| 开发者社区(Telegram) | https://t.me/salladev |