关于 salla-publication-consistency
这是用于准备 Salla 公开应用并提交 App Store 审核的引导技能,说明草稿、就绪检查、验证及合作伙伴确认流程,并将各发布步骤指向相应的 Salla 技能。
主要功能
- 01读取并恢复发布草稿
- 02跟踪各部分就绪状态和缺失字段
- 03验证内容并保存草稿
- 04要求合作伙伴审核并确认
- 05将步骤路由至对应 Salla 技能
适用场景
- 01准备公开应用以提交 App Store 审核
- 02恢复或检查现有发布草稿
- 03提交前修复未完成的部分
MCP 相关
该技能描述了使用 `app_publish` 等 Salla 工具的流程,但未说明 MCP 服务或协议实现。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ sallaapp/ salla-partners-agent-kit --skill salla-publication-consistency安装后在 Claude Code 中输入/salla-publication-consistency确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/step-app-config.mdstep-basic-information.mdstep-contact.mdstep-features.mdstep-pricing.mdstep-service-trial.md详细介绍
Salla 发布一致性
适用范围:公开应用(应用商店列表)。 私有应用不使用此分步流程 —
它们通过 salla_private_apps action=publish 发布 →
salla-app-builder → 私有应用。
发布前 — 先决条件
请先检查以下各项;无论涉及哪些部分,它们都是整个流程的门槛:
这三项都可以从应用详情中读取 — app_publish action=get(或 salla_apps action=get)
会返回 can_publish、requires_citc 和 can_have_free_plan。填写前请先检查:
- 应用必须可以发布。
can_publish必须为true。如果为false,则无法提交应用。 - 合作伙伴的账户必须已验证。 发布前,合作伙伴需在 https://portal.salla.partners/account 验证其账户。未验证的账户会阻止提交
(validate/submit 会返回
id_verification错误)。 - CITC 认证(短信通信应用)。 当
requires_citc为true时,合作伙伴必须在发布前通过账户验证表单上传 CITC 认证(沙特监管要求)→ salla-communication-app。
通过 app_publish(基础路径 /app/{id}/publication)准备 Salla 应用以供审核:这是一个由就绪状态驱动的循环,而不是一次性批量调用。逐个填写各部分;由服务端决定草稿何时就绪。
open → get(读取当前草稿)→(set <section> → 就绪状态)* → validate → 合作伙伴查看 /publish 链接 → send_publish_request
app_publish action=validate 会验证所有部分是否完整、正确,并保存草稿,返回有效的发布内容 — 但不会提交。将应用送审受严格限制:通过 validate 且无错误后,展示合作伙伴实际的 /publish 链接(已替换 id),并请他们审核草稿。只有此后应用才会进入审核流程 — 合作伙伴可以在 Portal 中一键提交,或者在他们明确确认后,由 Agent 调用 app_publish action=send_publish_request 并设置 confirm: true。在 validate 成功、合作伙伴审核链接并确认之前,绝不要发送请求。
根据 open 和每个 set 返回的就绪状态检查清单推进:它会标记每个部分为 complete,或者列出未完成部分的确切 missing 字段。修复其指出的部分,重新检查并重复操作。validate 会运行相同的服务端检查;如果有任何部分未完成,则返回 422 + 缺失部分;所有部分都完成后,则保存草稿。
发布流程(app_publish,基础路径为 /app/{id}/publication)
| 操作 | 方法 | 请求体 | 说明 |
|---|---|---|---|
open | POST | — | 创建草稿并返回各部分的就绪情况清单;打开后也会开放 app_page_builder,以便列出内容。 |
get | GET | — | 只读:获取当前草稿的完整内容(publication_last_save — 每个已保存的值)以及权限范围和 webhook_config。用于恢复/审查:就绪情况显示缺少什么,get 显示已有内容。 |
readiness | GET | — | 重新获取清单:哪些部分已 complete,以及确切的 missing 字段。纯读取操作。 |
set | PUT | { section, ...data } | 写入一个部分;只修改你传入的字段;返回更新后的就绪情况。 |
validate | PUT | — | 验证所有部分并保存草稿;返回有效的发布内容。不完整时 → 422 + 缺少的部分。不会提交。 |
send_publish_request | PUT | confirm:true | 将应用提交给 Salla 审核——严格门控:仅在执行 validate、合作伙伴审阅 /publish 链接并确认后才能提交。不提供 confirm:true 时不会提交(会返回链接)。 |
withdraw | PUT | — | 撤回正在审核中的发布(已提交/审核中)——例如,其 webhook 配置比开发环境中的配置旧时。然后再次执行 validate 并提交。仅限合作伙伴同意时操作。 |
列表内容(名称、描述、徽标、屏幕截图、优势)通过
app_page_builder → salla-app-ui-builder 编写。
先读取当前草稿(恢复/审查)
在填写或修正任何内容之前——尤其是在恢复草稿或被要求审查草稿时——
使用 app_publish action=get 读取草稿。它会返回 publication_last_save(每个已保存部分的
值),以及应用的 scopes 和 webhook_config(开发环境、最新发布和已批准的
webhook 配置,并附带一条需要转达的 note)。readiness 会告诉你缺少什么;get 会告诉你已有
什么——不要再次向合作伙伴询问草稿中已有的值,也不要盲目覆盖尚未读取的部分。应根据 webhook_config 判断 webhook,绝不要依据 publication_last_save.webhook_*——
这是草稿自身的副本,仅在执行 validate/提交时刷新。webhook_config.approved 是线上
商店在下一次审批前使用的配置(参见 step-app-config.md → 了解
各状态的含义,以及每个步骤应告知合作伙伴的内容)。
验证应逐步进行
分为三个层次,按顺序执行——不要把所有检查都留到最后一次性完成:
set按章节验证格式(服务端的PublicationSectionRequest:例如,short_description为 50–200,video_url/URL 格式正确,计划符合数值规则)。如果set返回 422,这是当前章节的验证错误——工具会显示字段错误消息;修正后再次执行set,再继续下一步。readiness报告完整性——哪些章节为complete,以及确切的missing(空白) 字段。完整性 ≠ 正确性:字段可能已填写但无效(由set捕获),也可能已填写但为空白 (由readiness捕获)。validate是针对整个草稿的最终跨字段和必填项检查——检查通过后会保存 草稿,否则返回 422,并列出仍缺少的章节。
循环流程:set <section> → 如果返回 422,修正当前章节 → readiness → 下一章节。编写
每个章节时就处理其错误,不要等到流程结束后再通过一次 validate 才发现。
步骤映射——此技能是主路由器
每个发布步骤都会路由到负责其建模的技能,并且每个步骤都有一份参考文档 (数据获取 → 提交架构 → 提交方式):
| 步骤(发布章节) | 负责技能 | 参考文档 |
|---|---|---|
| 基本信息 | 此技能 | step-basic-information.md |
应用配置(scopes/webhooks——不是 set 章节) | salla-app-auth + salla-webhooks | step-app-config.md |
| 功能(横幅 / 嵌入式图片;截图/优势) | salla-app-ui-builder | step-features.md |
| 定价 | salla-app-billing | step-pricing.md |
| 联系信息 | 此技能 | step-contact.md |
| 服务试用 / 审核 | 此技能 + salla-app-billing | step-service-trial.md |
app_page_builder是应用商店列表/资料页构建器——用于构建公开的应用资料页 (评分、计划、安装按钮)。它与发布流程关联:会从草稿中提取图片/文本/计划,可针对 草稿发布内容进行编辑,并且其图片和内容会覆盖发布内容中的对应项。它不是安装后 的嵌入式仪表板 UI(→ salla-embedded-app / salla-embedded-ui)。
一览 5 个部分
传入 section 和仅包含你要填写的字段(本地化字段使用 { ar, en };图片字段使用 salla_upload 中的整数 ID;多值字段使用数组)。每个步骤的参考文档中都包含各字段的架构、服务器规则和完整的 set 示例(见上方步骤索引)——填写前请先阅读。
| 部分 | 设置项(摘要) | 参考文档 |
|---|---|---|
basic_information | short_description、main_category_id(App Theme/Impact)、categories、video_url(必填)、demo_url、search_terms、supported_countries | step-basic-information.md |
features | banner、embedded_image(截图/优势 → app_page_builder) | step-features.md |
pricing | plan_type + 该类型对应的 plan/addon/once 字段 | step-pricing.md → salla-app-billing |
contact_information | contact_method、通知/提交/支持联系人、website_url、policy_url、faq_url | step-contact.md |
service_trial | service_link、trial_username、trial_password、trial_description、update_note(仅限更新) | step-service-trial.md |
转到其他工具中处理 — 不通过 app_publish 设置
这些内容位于发布部分之外。请分别在各自的工具中完成设置,然后重新检查 就绪状态:
| 内容 | 位置 |
|---|---|
上架内容:name、description、logo、screenshots、benefits | app_page_builder → salla-app-ui-builder |
| OAuth 作用域(仅申请所需的最小范围) | salla_scopes → salla-app-auth |
| Webhook URL/签名密钥/标头 | salla_apps action=connect → salla-webhooks |
商店事件订阅(order.*、product.*、…) | salla_events action=subscribe → salla-webhooks |
| 商家设置表单 | salla_settings → salla-app-settings |
安全审查检查由相应技能负责:OAuth 作用域最小化 → salla-app-auth;Webhook 签名验证 + 已验证的接口 → salla-webhooks;密钥处理 → 仅使用测试凭据、进行脱敏,绝不以明文形式保存。
草稿是 validate 时生成的快照,并非实时镜像。设置会在草稿保存时生成快照,并与实时状态进行比对,因此请先完成外部设置,然后再执行 validate,并最后设置商家设置:
- 在
validate之前完成设置表单(salla_settings)——草稿保存时生效的设置,就是合作伙伴提交的设置。 - 通信应用必须在
validate之前声明支持的功能 (salla_settings action=set_features),否则检查关卡会阻止操作。 - Webhook URL、策略、密钥、订阅事件和标头会在
validate和提交时复制到草稿中,并且只有获批后才会应用到商家的线上商店——请从webhook_config中读取;非空的approved.differs_from_development表示线上商店仍在使用旧配置,而正在审核中的latest_publication若存在差异,则表示其携带的是更早的配置。 - 更改任何外部设置(作用域、Webhook、事件、设置、构建器内容)后,请重新运行
readiness(必要时重新执行open),然后再次执行validate,再移交。
首次发布 — 引导式入驻,而不是盲目填写
发布部分涉及合作伙伴的业务决策 — 列表文案、分类、定价/套餐/试用、联系方式、支持的国家/地区、截图/权益。对于首次发布,应引导合作伙伴逐一填写各个部分;每项内容都必须根据他们的回答填写,绝不自行编造或自动填充。对于每个部分:
- 提出该部分的恰当问题,例如:
basic_information→ 价值主张/简短描述、主要分类 + 子分类、支持的国家/地区、演示/视频 URL?(video_url为必填项 — 如果他们没有视频,请引导他们查看教育视频指南:https://salla.dev/tutorial/educational-video-guidelines-apps-ar/)pricing→ 免费还是付费?一次性付款、订阅套餐,还是附加项?是否提供试用?contact_information→ 支持邮箱/电话、政策 + 常见问题 URL?- App Information(
app_page_builder)→ 名称、描述、徽标、≥3 张截图、权益?
- 提供基于 Salla 的有效选项建议,让合作伙伴从真实选项中选择,而不是猜测:来自
salla_reference action=categories的实际分类;Salla 账单支持的定价模式(免费/一次性付款/订阅套餐 + 附加项 + 试用 → salla-app-billing);来自salla_reference action=countries的支持国家/地区选项。 - 根据回答填写,然后运行
app_publish action=readiness查看还有哪些内容缺失,并继续下一个部分。
建议使用发布窗口期间的变现功能。 首次发布正是设置这些功能的时机 — 将其作为有依据的自愿选择提供(绝不自动添加),每项都应引导至 salla-app-billing / salla-addon-purchase:
- 附加项 — 在任意套餐基础上购买应用内额外项目。
- 试用 — 免费的
plan_trial(天数)和/或审核员服务试用。 - 促销 — 限时套餐折扣(
promotions[])。 - 对比矩阵 — 使用
plan_features[]并排比较套餐。 - 推荐/重点展示的套餐 —
recommended、is_compare_included。 - 划线价 —
one_time_old_price(一次性付款)或套餐的old_price。 - 可调整的数量 —
plan_additional_features(一次性付款)/每个套餐的additional_features。 - 挽留流失用户 —
unsubscribe_reward、unsubscribe_email_reward。
说明哪些功能仅限发布窗口期间设置;按商家定制的套餐可在之后通过 App details → Custom Plans 设置。任何付费选项都会触发账单周期门槛(见下文)。
这与下方的图片素材规则相辅相成(先索要图片;如跳过,则使用明确标注的占位图 + 告知合作伙伴替换)。
门槛:“每个部分 — 列表文案、分类、定价、联系方式 — 都是根据合作伙伴的回答填写,而非自动编造的吗?”
列表图片 — 先索要图片,仅在提前说明的情况下使用占位图
列表需要真实图片:logo + ≥3 张截图(App Information)、banner + embedded_image(App Features)。这些由 salla-app-ui-builder 负责 — 请阅读相关说明,了解字段、尺寸以及先生成后上传的流程。此处的原则是:
- 如果你没有图片,请向用户索要所有必需图片。 不要编造看似真实的图片,也不要默默跳过 — 应核实,而非编造。
- 如果用户跳过或拒绝提供,请使用明确标注的默认占位图继续操作,确保草稿仍可通过验证 — 然后明确告知合作伙伴,在一键提交前,必须在 Portal 中替换占位图。绝不要将占位图当作最终图片。
门槛:“每张列表图片都是真实的合作伙伴素材 — 或是已明确告知合作伙伴提交前必须替换的占位图吗?”
发布前流程(按顺序)
- 打开草稿(
action=open);阅读初始就绪检查清单。 - 为每个未完成部分使用
set设置其data,每次设置后重新检查readiness——一次只处理一个部分,根据返回的missing列表逐项进行。 - 通过
app_page_builder→ salla-app-ui-builder 编写构建器内容(截图、优势、上架名称/描述/Logo),使features完成——对于任何缺失的图片,遵循上文的图片资源规则。 - 完成设置表单(
salla_settings);对于通信类应用,运行salla_settings action=set_features。 - 再次运行
readiness——确认全部 5 个部分都显示为complete。 - 验证并保存草稿(
action=validate)。如果返回 422,使用set补齐缺失部分,然后再次运行validate,直到返回有效的发布内容。 6b. 计费周期关卡——仅适用于付费定价,且必须在提交前完成。 如果草稿定价中包含周期性方案或任何附加项,应用必须处理订阅生命周期,才能进入审核。生命周期通过应用事件(app.subscription.*/app.trial.*)运行,应用默认已订阅这些事件——Salla 会自动将其发送到webhook_url。因此,无需检查订阅调用。自动检查:salla_apps action=get显示已设置webhook_url,且合作伙伴的处理程序覆盖完整的app.subscription.*/app.trial.*事件系列(→ salla-app-billing 第 2 步)。这只能证明接收端已在平台层面接通,不能证明处理程序代码已部署并正常运行。因此,还要**验证一次真实的往返流程:**在演示商店触发一条测试订阅事件,并确认应用能正确开通/撤销权限(→ salla-live-testing)。 然后向用户确认:请合作伙伴确认,整个生命周期的处理程序都已部署并测试——在started时开通权限,在renewed时重新设置权限,在expired/canceled时撤销权限(核实item_type:方案还是附加项);对于external_recurring附加项,还要确认续订 API 已接通(→ salla-app-billing)。 如果流程不完整,切勿提交——保留已保存的草稿,将任务交给 salla-app-billing / salla-addon-purchase 实施计费周期,然后重新检查并再次通过关卡。只有计费周期完整一致,才能通过此关卡。 - 请合作伙伴审核,然后发送发布请求。向他们提供真实的 Portal 链接——替换为应用的实际 ID,绝不能使用占位符:
https://portal.salla.partners/apps/{app_id}/publish(例如:https://portal.salla.partners/apps/1234567/publish)。请他们在那里审核草稿。要进入审核,可以由合作伙伴在 Portal 中一键点击提交,也可以——但必须先获得他们的明确确认——由你调用app_publish action=send_publish_request,并设置confirm: true。**硬性规定:**只有在成功完成validate、向合作伙伴提供链接并获得其确认后,才能发送请求。
关卡:“所有部分均已验证并保存为草稿;对于付费定价(周期性方案或任何附加项),计费周期已接通并得到确认(否则,保持草稿状态,直到完成为止);已向合作伙伴提供真实的 /publish 链接并请其审核——并且只有在他们确认后才调用 send_publish_request(或者由他们自行一键提交)?”
对于 Agent 而言,完成意味着 validate 返回有效的发布内容,且合作伙伴已审核真实的 /publish 链接——应用只有在他们一键提交或明确确认后(随后调用 send_publish_request confirm=true)才会进入审核,绝不能提前。
危险信号
| 看似合理的想法 | 错在哪里 |
|---|---|
| “验证成功了,所以我会发送发布请求来完成任务。” | send_publish_request 有严格门槛——只有在合作伙伴通过 /publish 链接审核草稿并明确确认后,才允许发送(步骤 7)。仅凭验证通过不能发送。 |
“我直接把 …/apps/{app_id}/publish 模板发给他们,他们自己填写就行。” | 请替换为真实的 app id(步骤 7)。占位链接无法将合作伙伴带到正确页面,他们也无法提交。 |
| “没有提供图片——我就跳过,或放个占位图继续。” | 先询问用户;如果他们拒绝提供,请使用清楚标明的占位图,并且告知他们提交前要在 Portal 中替换。 |
| “我来写描述、选类别、设价格,让应用达到就绪状态。” | 这些都是合作伙伴的业务决策。请询问他们,提供基于 Salla 的选项,并根据他们的回答填写——切勿捏造信息或盲目填写某个部分来通过门槛。 |
| “验证通过了,而且这个应用销售订阅/附加项——我就提交。” | 付费定价要求先接通并确认计费周期(步骤 6b)。如果尚未完成,请保留已保存的草稿,并在提交前实现计费周期(salla-app-billing / salla-addon-purchase)。 |
“已经设置了 webhook_url,可以送审了。” | 接收 ≠ 处理。app.subscription.* / app.trial.* 事件会自动发送到 webhook_url(应用事件——无需调用订阅接口),因此自动检查只能证明接收端在平台层面已接通,并不能证明处理程序已部署且正常工作。提交前,应用必须在 started 时开通服务、在 renewed 时重新指向、在 expired/canceled 时撤销(检查 item_type),针对 external_recurring 调用续订 API,并通过真实测试事件验证(salla-live-testing)(步骤 6b)。 |
| “我需要先让应用订阅其订阅/试用事件。” | 不需要——这些是应用事件,由于应用默认已订阅自身的应用事件,因此会自动发送到 webhook_url。无需检查订阅步骤;salla_events action=subscribe 用于商店事件(order.*、product.*)。计费门槛是设置 webhook_url,且处理程序涵盖完整事件系列(步骤 6b → salla-app-billing 步骤 2)。 |
| “所有部分都已完成,所以我会提交。”(应用不可发布/未验证) | 请先检查前置条件:can_publish 必须为 true,且合作伙伴的账户必须已在 portal.salla.partners/account 完成验证(未验证的账户提交时会因 id_verification 失败);短信通信应用还需在验证表单中提供 CITC 认证(salla-communication-app)。 |
“我会把 sub_category_id 调用返回的 type 结果也用于 main_category_id。” | main_category_id 不按类型区分——它始终来自同一次 salla_reference action=categories 调用返回的 main_categories(类别类型为 app_impact,所有应用类型共用一份“应用主题”/“应用影响”列表)。categories 数组是第三份独立列表(类别类型为 app)。两者都不是创建应用时 sub_category_id 所用的 sub_categories 树(step-basic-information.md)。 |