关于 salla-embedded-app
salla-embedded-app 是将自定义页面集成到 Salla Merchant Dashboard 的技能,涵盖页面注册、SDK 配置、后端安全令牌验证,以及导航和界面控件等仪表板模块的接入。
主要功能
- 01注册和管理嵌入式页面
- 02初始化 Salla 嵌入式 SDK
- 03通过后端会话流程验证令牌
- 04同步仪表板主题和语言
- 05接入导航、界面及结账模块
适用场景
- 01向 Salla 商家仪表板添加自定义页面
- 02使用后端验证的令牌认证嵌入式应用
- 03连接页面导航和仪表板控件
MCP 相关
它使用 Salla Partners MCP 服务,通过 `salla_embedded_pages` 工具注册和管理仪表板嵌入式页面。执行此步骤需要连接该 MCP 服务。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sallaapp/ salla-partners-agent-kit --skill salla-embedded-app安装后在 Claude Code 中输入/salla-embedded-app确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/auth-and-session.mddesign-guidelines.mdimplementation-guide.mdsdk-modules-guide.md详细介绍
Salla 内嵌应用流程
在 Salla 商家管理后台中集成自定义页面。第 1 步通过 Salla Partners MCP 执行页面注册;SDK 步骤是你要写入应用的代码。请按顺序完成每一步,并通过当前关卡后再继续。
Salla 官方采用 信任但验证 模型:Salla 会在 iframe URL 中传递一个短期有效的令牌;你的前端通过 embedded.auth.getToken() 捕获该令牌,并交给你的后端,后端通过 Salla 的 Introspection API 验证令牌,然后创建自己的会话。前端只是信使,不会做出授权决定。第 3 步是操作指南;references/auth-and-session.md 是权威来源。
安全规则(必须遵守)
- 通过后端验证每个页面。 后端验证 Salla 令牌(introspect),创建自己的会话,并根据该会话授权每个请求;前端只负责传递令牌。
- 通过后端 introspect 进行验证
(
POST https://api.salla.dev/exchange-authority/v1/introspect,请求头为S-Source: <YOUR_APP_ID>)。embedded.auth.introspect()(Client Introspect)仅用于开发/调试 — 文档指出,它“不应作为主要身份验证方法使用”。完整请求/响应 → 第 3 步 +auth-and-session.md。 - 身份信息只能来自 introspection。 将每条路由和每个查询限定为 introspection 返回的
merchant_id;只能通过 Salla 原生的内嵌应用支持访问管理后台(不要使用信任查询参数或 referer 的独立/dashboard?store_id=…URL)。
工具
| 工具 | 操作 | 功能 |
|---|---|---|
salla_embedded_pages | list / create / update / delete | 管理应用的内嵌(iframe)管理后台页面 |
**前置条件:**必须连接 Salla Partners MCP 服务,并且你需要应用的
app_id。如果工具返回 "Salla session expired",请重新运行登录流程。
第 0 步 — 了解需求
开始前先询问:
- 此页面的用途是什么?(设置界面、分析仪表板、插件购买等)
- 需要哪些 SDK 模块?
auth—getToken、refresh、introspect(仅用于开发),以及核心方法init/ready/destroypage—setTitle、navigate、redirect、navTonav— 操作按钮(setAction/onActionClick/clearAction)和子导航项ui— 提示消息、确认对话框、加载状态、面包屑checkout— 插件购买
- 页面是否需要销售插件?(启用 Checkout 模块)
第 1 步 — 注册页面
调用 salla_embedded_pages,并传入 action: "create"、app_id,以及以下参数来注册 iframe 页面:
route— 页面的 kebab 路径片段(≥ 3 个字符)。显示为https://s.salla.sa/embedded/app/{appId}/{route}。iframe_url— Salla 在 iframe 中加载的完整 URL(例如https://dashboard.myapp.net/salla/embedded)。Salla 会附加token、theme、lang。default— 可选;将此页面设为应用的默认落地页。
create 会返回新页面;Portal 的 update 不会返回响应正文,因此工具会回显你更改的字段({ page: { id, route, iframe_url, default, updated: true } })作为确认。调用 salla_embedded_pages action=list 获取权威的当前状态。使用 update/delete 更改或移除页面。
**手动备用方案:**Portal → App Details → Embedded Pages → Add page。
关卡:"salla_embedded_pages action=list 返回了页面 — 你能在商家管理后台的侧边栏中看到它吗?"
内嵌应用图片(发布时设置)
可嵌入应用包含两张应用商店图片,均在发布过程中设置,而非通过 SDK 设置。请在发布时设置(步骤 6 → salla-publication-consistency):
| 图片 | 设置位置 | 尺寸 / 限制 | 展示位置 |
|---|---|---|---|
内嵌应用横幅(embedded_image) | app_publish 的功能区 | 最小 710×260 px(建议 1420×520),最大 512 KB | 应用的内嵌 / iframe 展示 |
| Salla 宣传图片 | app_publish 的功能区(宣传 / 精选) | 生成前通过 app_publish readiness / salla-docs 确认尺寸 | Salla 的宣传 / 精选(构建)版块 |
Salla 宣传图片是第二张图片(除内嵌应用横幅外),用于 Salla 的宣传 / 精选版块——应用在该处展示时,请务必提供。
图片生成补充流程适用于两者:如果缺少任一图片(或这是首次发布),且有可用的图片生成工具 → 确认上述尺寸,生成图片,salla_upload,然后通过 app_publish 的功能区设置;否则请向商家索要真实素材。请勿重复这些步骤——标准流程(以及其他所有列表图片字段)见
salla-app-ui-builder。
手动备用流程:My Apps → App → App Details → Start publishing → App Features。
步骤 2 — 安装并初始化 SDK
安装 npm 包——不要依赖 CDN 全局变量。 从包中导入 embedded,以便 TypeScript 验证方法名称;CDN 版本的全局变量名称 / 结构可能不同,导致启动静默失败。
npm install @salla.sa/embedded-sdk
import { embedded } from "@salla.sa/embedded-sdk";
CDN 备用方案(仅适用于原生 / 未打包页面——请先确认全局变量):
<script src="https://unpkg.com/@salla.sa/embedded-sdk/dist/umd/index.js"></script>
<script>
const embedded = Salla.embedded; // or SallaEmbeddedSDK.embedded
</script>
每次页面加载时都要初始化——init() 会建立 postMessage 桥接,并解析为控制台 layout:
const { layout } = await embedded.init({ debug: false });
// layout carries theme ("light"|"dark"), locale ("ar"|"en"), dir ("rtl"|"ltr"), …
即使 SDK 调用正确,也有两件事会阻碍内嵌应用首次运行:
- 可嵌入性——宿主必须允许 Salla 对页面进行框架嵌入(设置
Content-Security-Policy: frame-ancestors https://s.salla.sa,移除X-Frame-Options),否则控制台会显示空白 /“拒绝”窗格。 - 开发循环——页面需要通过控制台握手获取令牌,因此无法在普通标签页中打开。将 localhost 隧道化,把
iframe_url指向该隧道,在演示商店中安装,然后点击 Run App。
响应头、开发循环、框架注意事项(React/Next、Vue)、完整示例及可直接复制粘贴的入门模板 → references/implementation-guide.md
模块指南 → references/sdk-modules-guide.md
第 3 步 — 验证会话(信任但验证)
流程顺序如下:
await embedded.init()— 建立桥接;读取layout。embedded.auth.getToken()— 从 iframe URL 获取短期令牌 (返回string | null;若返回null,表示在 Salla 外部打开)。- 将令牌发送到你自己的后端。 前端只是传递令牌的通道——不要在此处做授权决策。
- 后端通过以下接口验证:
POST https://api.salla.dev/exchange-authority/v1/introspect, 请求头S-Source: <YOUR_APP_ID>,请求体{ "token": "..." }→ 成功时,声明会嵌套在data下:读取data.merchant_id/data.user_id/data.exp(data.exp是 ISO-8601 日期时间字符串,不是 Unix 时间戳)。后端生成自己的会话 (JWT / 安全 Cookie)。 embedded.ready()— 仅在后端确认且数据已加载后调用。在此之前,控制面板会显示加载遮罩。- 失败时 — 调用
embedded.destroy()以正常退出,避免商家一直停留在加载界面。
// 1. Bridge + layout
const { layout } = await embedded.init({ debug: false });
try {
// 2. Capture the short-lived token from the URL
const token = embedded.auth.getToken();
if (!token) throw new Error("Opened outside Salla — no token");
// 3 + 4. Hand the token to YOUR backend; it introspects and mints a session.
const res = await fetch("/api/auth/session", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify({ token }),
});
if (!res.ok) throw new Error("Verification failed");
// 5. Backend confirmed + data loaded → reveal the iframe.
await loadDashboardData();
embedded.ready();
} catch (err) {
console.error("Auth failed", err);
embedded.destroy(); // exit gracefully instead of hanging on the loading overlay
}
embedded.auth.introspect() 仅用于开发/调试——这是前端辅助参考方法,用于演示文档明确指出“不应作为主要身份验证方式”的 introspection 流程。生产环境中的授权始终通过上述后端 introspect 完成。
当后端返回 401 / 令牌过期时 → 调用 embedded.auth.refresh();Salla 会使用新令牌重新加载 iframe,重新运行初始化流程,并从头开始。
完整的后端 introspect(包含 S-Source)、会话生成和 401→refresh 循环 →
references/auth-and-session.md
检查项:“你的后端是否会在调用 ready() 前,使用 S-Source 请求头 introspect 令牌并生成自己的会话?请使用演示商店测试。”
第 4 步 — 同步主题和语言区域设置
主题、语言区域设置和方向来自 embedded.init() 返回的 layout——不要手动读取查询参数:
if (layout) {
document.documentElement.setAttribute("data-theme", layout.theme);
document.documentElement.setAttribute("lang", layout.locale);
document.documentElement.setAttribute("dir", layout.dir); // "rtl" for ar, "ltr" for en
}
layout 是外观设置的事实来源;每当 SDK 重新初始化时(例如 embedded.auth.refresh() 重新加载 iframe 后),都要重新应用这些设置。控制面板也支持动态切换主题——在可用时,使用 embedded.onThemeChange() 监听变化。
设计令牌、品牌颜色、RTL 模式 → references/design-guidelines.md
第 5 步 — 接入 SDK 模块
要绘制可见的 UI? 请停在这里并加载 → salla-embedded-ui。 其中的检查项(原生令牌、No-Chrome、RTL、实时截图)必须遵守;仅在接入 SDK 时返回
salla-embedded-app,不要在此处处理样式。
根据第 0 步中的需求,实现相关模块:
Auth — 可恢复的过期情况使用 refresh;仅在无法恢复时 destroy:
// Backend reported the token expired (401): refresh — Salla re-renders the iframe with a fresh one.
embedded.auth.refresh();
// Only when auth is unrecoverable (a fresh token still can't verify, app suspended):
embedded.destroy(); // tears down the iframe so the dashboard doesn't hang
调用顺序很重要:临时过期时必须调用 refresh(),而不是 destroy()。
Page — 标题和控制面板导航:
embedded.page.setTitle("My App");
embedded.page.navigate("/orders"); // internal SPA route (React Router)
embedded.page.redirect("https://docs.my-app.com/help"); // external / full reload
embedded.page.navTo("/orders"); // auto-picks navigate vs redirect
Nav — 操作按钮和子导航项:
embedded.nav.setAction({
title: "Save",
value: "save",
icon: "hgi hgi-stroke hgi-tick-02",
}); // icon optional (Hugeicons class)
const off = embedded.nav.onActionClick((value) => {
if (value === "save") saveChanges();
});
embedded.nav.clearAction(); // when the merchant leaves this view
UI — 提示消息、加载状态、确认框、面包屑:
embedded.ui.toast.success("Saved!");
embedded.ui.toast.error("Something went wrong");
embedded.ui.loading.show();
embedded.ui.loading.hide();
const { confirmed } = await embedded.ui.confirm({
title: "Delete?",
message: "This cannot be undone.",
variant: "danger", // confirm() resolves to { confirmed }, not a bare boolean
});
embedded.ui.breadcrumbs.hide(); // or .show()
Checkout — 在应用内购买附加组件(如适用):
→ 按照 salla-addon-purchase-embedded 技能操作(嵌入式/应用内购买流程;
有关附加组件定价/权益机制,请参阅 salla-addon-purchase)
完整的方法签名 → references/sdk-modules-guide.md
检查项:“正式上线前,请在 SDK Playground 中测试你使用的每个模块。” → Playground / Test Kit
第 6 步 — 发布
发布父应用后,嵌入式页面即会上线。请遵循 salla-app-builder 发布步骤中的发布检查清单。
资源
各模块的页面位于
https://docs.salla.dev/embedded-sdk/modules/...(auth、page、nav、 ui、checkout)。打包的sdk-modules-guide.md中包含 相同的函数签名。