逃离 Mac App Store:如何从零构建独立应用的分发与售卖体系

这是 Zipic 独立开发复盘系列的第二篇文章。在 上一篇 中,开发者 十里 分享了 Zipic 从痛点到产品的诞生过程。

本文中,将聚焦于独立开发者最头疼的“基建”问题——当决定离开 Mac App Store 的舒适区后,如何独自解决打包、公证、自动更新以及全球收款等一系列棘手难题。

嗨,大家好,我是十里👋!

在这一篇中,我想深入探讨一个更现实、也更“劝退”的话题:独立分发

AppStore vs 独立分发

很多 macOS 开发者即使完成了产品,也会被挡在“如何卖出去”的门槛外。离开 App Store 意味着失去现成的支付和更新系统,一切都要亲力亲为。但这又是 Zipic 必须走的一步路,为了更自由的权限和更直接的用户关系,我不得不啃下这块硬骨头。

Zipic Origin Story

Zipic 最初是在 Mac App Store 上架的。App Store 分发的好处明显:不用操心更新机制,也不用自己搭建支付系统。但随着迭代深入,我逐渐意识到一些难以逾越的问题:

  • 沙盒限制太多:Mac App Store 要求应用必须开启沙盒(Sandbox)。对于图片压缩工具来说,最明显的是文件读写权限——用户压缩完图片想保存并覆盖原位置,却发现没有权限。虽然可以通过 Security-Scoped Bookmark 持久化来解决目录授权,但管理复杂,用户体验也变繁琐。
  • 审核周期不可控:提交更新至少要等 1~2 天才能上线,遇到节假日甚至超过一周。用户反馈的 bug 修复本来很快,却因为审核拖得很长。
  • 分成比例偏低:默认 70%,申请小型企业计划最高 85%。

我想做的是体验流畅的工具,但 App Store 的限制让很多想法无法实现。加上后续希望上架其它平台(比如数码荔枝),总要搭建独立授权系统,权衡之后决定切换到独立分发。

如果不是万不得已,真心建议别折腾独立分发,你会变得非常不幸 😂 不如直接上架 App Store + 申请小型企业计划。

选择独立分发意味着要自己搞定打包、更新、授权、支付等整套体系。做好心理准备,这会占用很多精力,不符合快速 MVP 的原则。当然,这也是一劳永逸的工作,准备好了其他产品可以轻松复用。

DMG Canvas 打包流程

DMG Canvas Package

应用开发完成后要打包成 DMG 格式分发。用 Disk Utility 简单创建 DMG 效果比较粗糙,专业的应用 DMG 通常有漂亮的背景图、精心设计的布局、自动设置的窗口大小。手动制作很繁琐,更重要的是 macOS 的公证(Notarize)流程比较复杂,配置不对用户下载后会提示“文件已损坏”。

我用的是 DMG Canvas,所见即所得的编辑界面,可以自定义背景、图标位置、窗口样式。配置好模板后,每次打包只需选择新版本的 app 包重新 build 就行。公证流程它也做了集成,配置好 App-Specific Password 和 Team ID,勾选“Notarize”选项,打包完成后会自动上传到 Apple 服务器公证,整个流程自动化。

具体操作参考:使用 DMG Canvas 打包 macOS app 为 DMG

使用 Sparkle 实现自动更新

Sparkle

做独立应用还要解决更新机制。用户下载安装后如何及时获取新版本?手动下载覆盖安装体验很差,还要考虑安全性、确保更新包没被篡改。

Sparkle 是 macOS 平台上最常用的自动更新框架,很多知名应用都在用。支持签名验证、增量更新、发布说明展示,基本该有的功能都有了。集成过程不算复杂,主要是配置 Appcast(更新信息文件)和签名密钥,添加少量代码就能实现自动更新。Appcast 是个 XML 文件,记录最新版本号、下载地址、更新说明等信息,Sparkle 定期检查这个文件,发现新版本就提示用户更新。

具体使用步骤写在这篇文章:macOS 开发 - 使用 Sparkle 轻松实现 App 更新管理

踩坑经验:文件托管我最终用了 CloudFlare R2。相比 GitHub Releases 或自建服务器,R2 的优势很明显——全球都能访问(包括国内),存储有限额但流量无限制,还可以自定义域名,既保证分发稳定性又控制成本。

另外,Sparkle 会自动生成 delta 包(增量更新文件),可以显著减少用户下载量。但要记得把这些 delta 文件一起上传到托管服务,不然增量更新会失效,目录结构要和 appcast.xml 中的路径一致。

授权系统

Keygen

Zipic 用的是密钥验证激活方式,有免费版和 Pro 版,需要一个系统来管理许可证、验证用户购买状态。需求比较特殊:要支持多个销售平台(数码荔枝、官网商城等),每个平台的订单都要能自动生成授权码。

我选择了 Keygen.sh 的 CE(社区版)进行自部署。Keygen 本身是商业授权管理服务,但提供了开源的社区版本。功能基本够用,支持许可证生成、验证、使用统计等。自部署的好处是完全掌控数据,而且可以按需定制。用 Docker 部署在自己服务器上,配置好数据库和 Redis,系统就跑起来了。通过自实现 Webhook 服务对接各个电商平台,订单完成后自动生成授权码发给用户。

详细部署过程可以看这篇:软件授权用 Keygen.sh - 自部署服务

踩坑经验:Docker 网络配置是个坑。Keygen 需要连接数据库和 Redis,一开始用默认网络,服务启动后连不上数据库,后来建了自定义网络才解决。另外,如果直接用 Keygen 与第三方对接的话,可以通过产品 token 提供生成 License 的权限,尽量减少第三方的权限范围。

支付系统集成

Payment Stripe

独立分发还要解决一个关键问题:用户怎么付款购买?这块我踩过不少坑。

Fatbobman 注:作为一个来自中国的开发者,十里在实现全球分发,全球收款时遇到的困难会明显高于很多地区的开发者。

最开始使用的是 LemonSqueezy,功能很全——支付、密钥管理、联盟推广、邮件营销一站式搞定。但 2024 年被 Stripe 收购后,国人新账户提交申请基本不予理睬,这条路基本不推荐了。

网上有人提议用个人身份注册香港 Stripe 账号,技术上可行,但没有真实香港身份始终有合规风险,提现还需要香港银行卡,也不是长久之计。

最终我走了注册美国公司使用 Stripe 的路。过程一波三折:注册公司还算顺利,是通过 Stripe Atlas 完成的,然后开银行公户。很多人推荐水星银行,但我申请了几十次都失败,证明材料都是完整且准确的,但还是失败了,推测是姓名和某些敏感人物重名,最后注册申请空中云汇账户才办好了银行公户。注册企业 Stripe 还需要美国电话号码,我用的是 Ultra Mobile PayGo,月租仅 3 美元。

  1. 注册美国公司还有一种方式,在怀俄明州自助注册公司(约 $150),再申请 EIN 联邦税号(代理约 $39)
  2. 如果有条件的话,最好是办一些香港银行卡,推荐香港汇丰、中银香港、众安银行,港卡可以用于 Stripe 个人账号的提现、Paypal 提现(服务费很低)、Stripe 绑定的银行公户收益回流等

据我了解,不同身份适合不同方案:

  • 个人主体出海:推荐 Creem,其次是 Paddle
  • 国内企业主体:可以考虑 Paddle
  • 国外实体(美国/英国公司):建议用 Stripe
  • 只面向国内:蓝兔或 Zpay

如果对 Paddle 感兴趣,可以参考:两天内完成 Paddle 账户的注册和验证

还有一种思路:不自建支付,直接对接销售平台。比如数码荔枝,只需实现密钥分发接口就行。国外也有类似平台,如 Setapp(目前只接受 AI 应用)和 AppSquad,感兴趣可以了解。

打通支付与密钥分发

License Distribution Stripe

有了 Stripe 处理支付、Keygen 管理授权,但问题是这两个系统是独立的。用户付完款,还得手动去 Keygen 生成许可证再发邮件——这流程显然不能接受,必须打通自动化。

我的方案是搭一个 Webhook 服务作为中间层(用 n8n 搭建应该也行😉)。核心思路是建立 Stripe 产品与 Keygen 授权策略的映射关系。比如“Zipic Personal - 1 Device”在 Stripe 是一个价格 ID,在 Keygen 对应一个特定的 Policy,服务里配置好这个对应关系。然后在 Stripe 后台注册 Webhook 地址,订阅 checkout.session.completed 等支付完成事件。

用户完成购买后,Stripe 立即向服务发送通知,服务收到后自动完成:

  1. 在 Keygen 中查找或创建用户(基于邮箱)
  2. 根据购买的产品,调用 Keygen API 生成对应的许可证
  3. 通过 Resend 发送邮件,包含许可证密钥和激活说明

整个过程对用户无感,付款成功后几秒钟邮箱就收到许可证了。

踩坑经验:Webhook 幂等性很重要。Stripe 为保证消息送达,同一事件可能发送多次,不做处理用户可能收到多封邮件甚至生成多个许可证。解决方案是记录已处理的事件 ID,重复请求直接跳过。邮件发送也要考虑失败重试,我加了重试队列,同时所有发送记录入库方便排查和手动补发。

接下来

至此,Zipic 终于拥有了一套属于自己的完整分发体系:从代码提交到自动打包公证,从全球支付收款到许可证自动下发,再到用户端的无感增量更新。虽然前期搭建过程非常繁琐,涉及很多并未写在代码里的“坑”,但一旦跑通,它就是一套可以复用于未来任何产品的自动化资产。

搞定了销售的渠道,接下来终于可以回归代码本身了。

在下一篇 技术细节复盘 中,我将分享开发 Zipic 过程中遇到的纯技术挑战:SwiftUI 在 macOS 上的水土不服、如何利用 ImageIO 将内存占用降低千倍、以及 Core Graphics 处理 PDF 的黑科技。

我们下一篇见!

About Author

十里ZipicOrchardHiPixelTimeGo Clock 等应用的作者,喜欢做「小而美」的产品——功能不贪多,但每个细节都想抠到位。 如果你也在折腾独立产品,欢迎来聊!

订阅 Fatbobman 周报

每周精选 Swift 与 SwiftUI 开发技巧,加入众多开发者的行列。

立即订阅