Mind Elixir 是一款基于 Tauri 框架的跨平台思维导图应用,支持 iOS、macOS、Linux、Windows、Android。免费用户最多创建 24 个思维导图,付费用户(订阅/终身许可)可解锁无限数量。付费功能通过官网购买,应用内登录账号解锁。
第一次把 Tauri 应用提交到 App Store,iOS 被驳回了 3 次,macOS 跟 Apple 来回沟通了 12 轮才通过。这篇文章记录整个过程中踩过的坑,希望能帮到同样在做跨平台付费应用的开发者。
iOS:3 次驳回,10 天通过
Round 1:登录体验 + 商业模式审查
4月15日收到驳回,涉及两个条款:
Guideline 4 --- Design:应用把用户跳转到外部浏览器登录注册,Apple 认为体验不好。
当时我的登录逻辑是直接调起系统默认浏览器走 OAuth 流程。Apple 的要求是要么在应用内实现登录,要么用 ASWebAuthenticationSession 在应用内嵌浏览器完成。
Guideline 2.1(b) --- Information Needed:Apple 看到应用有付费功能,但不确定商业模式,要求回答四个问题:
- 用户在哪里购买订阅?
- 用户能访问哪些已购内容?
- 有哪些付费内容不走 IAP?
- 用户如何注册账号?
我回复解释了跨平台架构------订阅通过官网购买,登录后解锁"无限思维导图"。
Round 2:IAP 产品没提交
4月17日再次驳回,条款 Guideline 2.1(b) --- App Completeness。
这是个低级错误。我的应用里引用了 Annual Pass、Lifetime Pass 这些订阅产品,但我在 App Store Connect 里没有把这些 IAP 产品一起提交审核。Apple 直接说"我们没法继续审核,因为找不到这些 IAP"。
教训:提交应用审核的同时,必须把关联的 IAP 产品也一起提交,并且要提供审核截图。
Round 3:订阅信息不完整
4月20日第三次驳回,涉及两个条款:
Guideline 3.1.2(c) --- Subscriptions:应用内缺少自动续期订阅的必要信息展示。Apple 要求必须展示:
- 订阅服务标题
- 订阅时长
- 价格
- Terms of Use 链接
- Privacy Policy 链接
Apple 还建议使用 SubscriptionStoreView,可以一站式搞定这些信息展示。
Guideline 2.1(b) --- Information Needed:还是找不到 IAP 产品。这次 Apple 明确说了,要在 sandbox 环境测试通过,并且确保 Paid Apps Agreement 已签署。
最终通过
4月21日第四次提交,4月23日通过。
macOS:12 轮拉锯战
macOS 的审核比 iOS 复杂得多。一方面是 macOS 的审核规则和 iOS 有差异,另一方面我用了 Tauri 框架打包,引入了一些 iOS 不存在的问题。
第一轮:三个条款同时命中
4月15日 / 16日收到驳回,一次性命中三个条款:
Guideline 2.4.5(vii) --- Performance:应用包含了可能用于在 Mac App Store 之外更新应用的框架或 API。
这个是我用 Tauri 打包时带进来的。Tauri 默认会集成一些自动更新的依赖,即使我没有在代码里使用,打包后的二进制文件里仍然包含了这些框架。Mac App Store 要求所有更新必须通过 App Store 进行,不能有额外的更新检查机制。
Guideline 3.1.1 --- In-App Purchase:Premium 会员可以通过官网购买,但应用内没有提供 IAP 购买选项。
Apple 的规则很明确:跨平台应用可以让用户访问在其他平台购买的内容,但前提是该内容也必须可以通过 IAP 购买(参考 Guideline 3.1.3(b))。不能只允许通过网站购买。
Guideline 4 --- Design:和 iOS 一样的登录体验问题。
这个条款后来拉扯了好几轮,说起来挺搞笑的。我在 macOS 版已经用了 ASWebAuthenticationSession,但问题是 macOS 上的 ASWebAuthenticationSession 表现出来就是打开默认浏览器 ------这是 Apple 自己文档里写的行为,不是我的实现问题。但审核员看到"打开了浏览器",就直接判我没用 ASWebAuthenticationSession,反复驳回。
我后来把 Apple 官方文档里关于 macOS ASWebAuthenticationSession 行为的说明贴了回去,审核员才承认我确实用了,然后换了个理由继续驳回。笑死。
后续拉锯
这之后经历了多轮驳回和重新提交:
| 日期 | 动作 | 主要问题 |
|---|---|---|
| 4/21 | Apple 驳回 | 继续追问细节 |
| 4/24 | Apple 驳回 | 新问题出现 |
| 4/24 | 我回复 x2 | 提供更多信息 |
| 4/27 | Apple 驳回 | IAP 功能 bug |
| 4/27 | 我回复 | 说明修复进展 |
| 4/29 | Apple 驳回 | 订阅链接问题 |
| 4/30 | 我回复 | 补充元数据 |
| 5/2 | Apple 驳回 | 最后几个问题 |
| 5/2 | 我最终回复 | 一次性解决所有问题 |
最终回复中解决的问题
- Guideline 2.1(b):修复了一个 bug------"升级"按钮在某些情况下会变灰无法点击
- Guideline 3.1.2(c) :在 App Store 元数据的 app description 里添加了 Terms of Use 链接(
https://desktop.mind-elixir.com/eula) - Guideline 4 :详细解释了 Tauri 框架下使用
ASWebAuthenticationSession的技术方案,说明这是 Tauri 应用做 OAuth 的标准做法 - Guideline 5.1.1(v):Apple 其实不推荐让用户必须登录后才能购买 IAP,他们认为这会增加购买摩擦。但我解释了跨平台场景下的实际需求------用户登录后购买,可以关联到账号,这样在其他平台(Linux、Windows、Web)也能直接使用,避免重复购买。Apple 最终接受了这个解释。
5月2日最终通过。
踩坑总结
IAP 相关
- IAP 产品必须和应用一起提交。不要想着先提交应用再补 IAP,这会导致 Round 2 那种情况
- 订阅页面必须展示完整信息 。用
SubscriptionStoreView可以省很多事 - 跨平台应用必须同时提供 IAP 购买选项。即使你的主要销售渠道是官网,App Store 里也必须有 IAP
登录相关
- 不要跳转外部浏览器登录 。用
ASWebAuthenticationSession在应用内完成 - 支持注册的应用必须支持账号删除(Guideline 5.1.1(v))
- Apple 不推荐"先登录再购买"。默认情况下,用户应该能直接购买 IAP,不需要先注册或登录。但如果你有合理的跨平台需求(比如购买需要关联账号以同步到其他平台),可以在回复中详细说明理由,Apple 会酌情考虑
macOS 专项
- 检查打包依赖中是否包含更新框架。Tauri、Electron 等框架可能默认带入自动更新模块,需要在打包时排除
- Mac App Store 禁止任何应用外更新机制
审核策略
- 首次提交会收到更详细的反馈。Apple 会恭喜你加入开发者计划,同时可能一次性指出多个问题
- 回复 Apple 消息时要详细、有条理。我最后一轮回复是一次性解决了四个条款的问题,之后就通过了
- 准备好被驳回的心态。尤其是跨平台 + 付费模式的组合,审核会更严格
- 每次回复都要把之前的问题重新说一遍 。这是我踩的一个大坑------macOS 审核过程中,Apple 多次提出相同的问题,比如登录体验、IAP 覆盖等,明明我在之前的回复里已经解释过了,下一轮又会重新问。我不确定是每次 review 的审核员不同、上下文没延续,还是他们就希望你每次都确认。总之,不要假设审核员看过你之前的回复,每次提交补充信息时,把之前已回答的问题也一并带上,避免来回拉锯
审核时间线
iOS:
04/13 提交
04/15 ❌ 驳回(登录体验 + 商业模式)
04/17 ❌ 驳回(IAP 未提交)
04/20 ❌ 驳回(订阅信息不完整)
04/21 第四次提交
04/23 ✅ 通过
macOS:
04/15 提交
04/16 ❌ 驳回(更新机制 + IAP + 登录)
04/17 ~ 05/02 12 轮消息往来
05/02 ✅ 通过
整个过程最大的体会:跨平台应用上架 App Store,技术上要处理框架带来的隐式依赖(比如 Tauri 的更新模块),产品上要适配 Apple 的 IAP 生态(即使你的主力销售在官网),体验上要符合 Apple 的设计规范(登录流程不能跳外部浏览器)。三个维度缺一不可。