mcpField
S
salla-app-builder

salla-app-builder

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

关于 salla-app-builder

salla-app-builder 是指导 Agent 通过 Salla Partners MCP 从头创建并配置 Salla 应用的工作流。它按阶段推进创建、OAuth 与权限、Webhook 及发布,并要求核验变更结果和部署域名。

主要功能

  1. 01分阶段创建与配置应用
  2. 02查询类别、范围和事件
  3. 03设置 OAuth 与 Webhook
  4. 04写入后读取确认变更
  5. 05核对部署域名一致性

适用场景

  1. 01创建面向商家的 Salla 应用
  2. 02为应用配置最小必要权限
  3. 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.md
domain-consistency.md
onboarding-steps.md
private-apps.md

详细介绍

Salla App Builder — 从零创建应用

通过执行操作来构建完整的 Salla 应用,而不只是描述如何构建。 每个步骤都会调用一个 Salla Partners MCP 工具来完成工作。请按顺序执行各个步骤 — 完成当前关卡后,再继续下一步。

依据真实信息 — 读取真实值,确认真实结果。

  1. 在向 Salla 写入任何 URL 之前,先验证已部署的域名。 读取 Vercel 项目的实际域名 — 使用 vercel project ls、Vercel MCP 或 .vercel/project.json — 然后再设置 app_url、嵌入式 iframe_url 或代码片段 BASE。猜测一个无法解析的 *.vercel.app 域名,会导致安装、webhook 和 iframe 悄无声息地失效(写入时不会报错)。
  2. 每次修改后都要回读。 connect/update/subscribe 可能会返回精简或空的响应体 — 零字段响应无法与静默失败区分开来。将更改视为完成之前,先通过 get/list 确认;切勿只相信写入响应。
  3. 更改域名时,请同时更新所有使用该域名的位置 — 门户中的 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_appscreate / 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_scopesget 有效的权限范围标识(slug)(以及 disabled / selected)/ set 已选权限范围(扁平格式:slug → read | read_write | "")
salla_eventslist 可订阅的事件 / subscribe 将应用订阅到标识(slug)

**前提条件:**必须连接 Salla Partners MCP 服务(上述工具会显示在你的工具列表中)。如果未连接,请改用 Portal:https://portal.salla.partners,并参考内嵌的手动说明。如果工具返回“ Salla session expired — reconnect”,请运行 OAuth/登录流程。

步骤 0 — 了解需求

开始前先询问:

  1. 你的应用能做什么?(简要描述)
  2. **应用类型:**General / Communication / Shipping
  3. **可见性:**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 — 创建应用

  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。
  2. 上传 Logo。 使用公开图片的 source_url 调用 salla_upload。Logo 必须是正方形(1:1)图片,且尺寸 ≥ 250×250 px——上传前确保源图片满足 此要求。返回结果仅包含 {id, url}(不会返回尺寸),因此请使用返回的 id。如果创建时没有 Logo,且有可用的图像生成工具,请生成一个(1:1,≥ 250×250)并上传—— 完整的规范流程(以及其他每个上架/发布图片字段及其尺寸)→ salla-app-ui-builder。
  3. 创建应用。 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.authorize webhook 获取令牌,不使用 回调)是所有应用的推荐默认模式——除非有明确的技术原因导致它无法使用,否则请使用此模式。 自定义模式(OAuth /callback 代码交换)适用于开发期间的本地开发 / Postman;在自定义模式下发布应用, 如果没有真实且合理的使用场景,审核时可能会被拒绝。模式机制 → salla-app-auth。

在一次 salla_apps action=connect 调用中配置 OAuth 和 Webhook。首先检查 应用有效的权限范围 slug 和当前选择:

  1. 使用 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。
  2. 使用 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 — 订阅商店事件

  1. 调用 salla_events,设置 action: "list" 和 app_id,获取应用可以订阅的有效事件标识 (务必先调用此项——事件标识会经过验证)。
  2. 询问:“您的应用会对哪些领域作出响应?”仅订阅所需事件,调用 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 源码、上下文结构、Resp API 和超时。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 流程。”

  1. 在演示商店中测试。 使用 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}。

  2. 准备就绪后,将应用设为上线状态:salla_apps action=set_status,status: "live"。

  3. 验证并保存草稿。 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。
  4. 合作伙伴审核后,再发送发布请求。 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

评论

支持 Markdown