跳到正文
返回博客
·约 3 分钟读完

StoreKit 在 App Review 或 TestFlight 里取不到产品:一份检查清单

Product.products(for:) 在 Xcode 里能取到产品,到了 TestFlight 或审核员手里却是空的。按顺序检查付费 App 协议、Bundle ID 和产品 ID、产品元数据、StoreKit 配置文件,以及首个内购是否随版本提交。

StoreKit 在 TestFlight 或 App Review 里取不到产品,意思是 App Store 在沙盒里找不到你请求的产品 ID,于是把它们从结果里去掉了。Apple 的文档写明:Product.products(for:) 会排除无效的、或 App Store 找不到的标识符,并且不会因此抛错。TestFlight 和 App Review 用的都是沙盒,读的是 App Store Connect 里配置的产品,而不是你 Xcode 里的 StoreKit 配置文件。所以按顺序查:付费 App 协议(Paid Apps Agreement)已生效且银行和税务信息齐全,Bundle ID 和 App Store Connect 里的应用一致,产品 ID 完全一致,每个产品都有价格和本地化信息,用沙盒测试时已关掉 StoreKit Testing。

如果从 Xcode 运行时产品都在,换个地方就全没了,第一个怀疑对象就是 StoreKit 配置文件:它的数据从来不会离开你的 Mac。

为什么 Xcode 里正常,TestFlight 里不行

Apple 描述了三个测试环境:

  • Xcode 中的 StoreKit Testing:从 StoreKit 配置文件读产品。Apple 说它「without requiring a connection to App Store servers」(不需要连 App Store 服务器),并且文件里的名称、ID、价格「don't upload to App Store Connect, and don't appear in App Store-signed apps」(不会上传到 App Store Connect,也不会出现在 App Store 签名的应用里)。
  • 沙盒(Sandbox):使用你在 App Store Connect 里配置的内购数据。
  • TestFlight:构建「always run in the sandbox environment」(始终运行在沙盒环境)。

App Review 同样用沙盒。Apple 的 App Review 帮助说,App Review「evaluates your In-App Purchases in the same sandbox environment you use for testing」(在你测试所用的同一个沙盒环境里评估内购)。所以只存在于 StoreKit 配置文件里、或在 App Store Connect 里没配完整的产品,测试员和审核员都看不到。

想看配置文件里到底有什么,可以用 StoreKit 配置文件查看器 打开它,把里面的产品 ID 和 App Store Connect 对一遍。

检查清单

按顺序过。前几项会让所有产品一起消失,后几项影响的是单个产品。

1. 付费 App 协议已生效,银行和税务信息齐全

  • Account Holder 必须在 App Store Connect 的 Business 区域接受 Paid Apps Agreement,并提供银行和税务信息。
  • Apple 原话:「The agreement must be Active to test In-App Purchases in the sandbox environment.」(协议必须处于生效状态才能在沙盒里测试内购。)App Review 帮助还说,协议生效前付费内购「won't function in review」(在审核中无法使用)。
  • Apple 的沙盒排查技术说明 TN3186 还列了这些情况:协议没签、有新版协议待接受、协议过期、银行或税务信息不全或过时、开发者会员过期或未激活、有新版 Apple Developer Program License Agreement 没接受。续费会员后,要确认协议和财务信息是否需要重新接受或更新。

2. Bundle ID 和签名

TN3186 列出的会导致产品不可用的情况:

  • 应用的 Bundle ID 和 App Store Connect 里任何一个应用都对不上;
  • 这个 Bundle ID 在 Certificates, Identifiers & Profiles 里关掉了 In-App Purchase 能力;
  • 应用用的是通配符 App ID(沙盒里不能用含通配符 App ID 的描述文件测试内购);
  • 应用用无效的证书或描述文件签名。

3. 产品 ID 完全一致

Apple 原话:「Make sure the bundle identifier and product identifiers in Xcode match those configured for your app and In-App Purchases in App Store Connect.」TN3186 要求逐个核对:列表里每个标识符都要和该应用在 App Store Connect 里建的内购 Product ID 一致。内购不能在不同应用之间共用。因为对不上的 ID 只是被从结果里去掉,拼错一个字母表现为「少了一个产品」,不会报错。把请求的 ID 集合和返回的 ID 做差集,并把差集打到日志里。

4. 每个产品的元数据齐全

  • 沙盒测试的最低要求是参考名称、产品 ID、本地化名称和价格。TN3186 要求确认每个内购都设了价格并加了本地化信息。
  • 在 App Store Connect 里,处于 Prepare for Submission 且缺必填元数据的产品,要先补完才能加入审核。
  • 刚建好或刚改过的产品要等一等:Apple 说改动「can take up to one hour」(最多可能要一小时)才会出现在沙盒里。
  • 在沙盒里测试不需要先过审。Apple 还说内购「do not need prior approval from App Review to function in review」(不需要事先获批,审核时就能用)。

5. 用沙盒测试时关掉 StoreKit Testing

TN3186:如果项目里有 StoreKit 配置文件,确认你测的是想测的环境;要测沙盒,就在 scheme 里关掉 Xcode 的 StoreKit Testing。Apple 说关掉后应用「starts using the data from App Store Connect」(开始使用 App Store Connect 的数据)。上传前,用沙盒 Apple 账户从 Xcode 这样跑一次。

6. 沙盒账户和店面

  • 沙盒 Apple 账户在 App Store Connect 里创建,只能用于同一个开发者账号下的应用。
  • 测 TestFlight 构建时,在设置的开发者(Developer)选项里登录沙盒 Apple 账户,才有沙盒控制项。
  • 除非你限制,产品在所有地区都可售。在 App Store Connect 里改了沙盒账户地区后,要在设备上退出沙盒 Apple 账户再重新登录。
  • 如果你按店面或设备限制了内购,Apple 要求在 App Review Information 的 Notes 里说明。

7. 首个内购要随版本一起提交

Apple 原话:「The first consumable, non-consumable, auto-renewable subscription, and non-renewing subscription In-App Purchase of each type must be submitted with a new app version.」(每种类型的第一个内购都必须和新的应用版本一起提交。)新订阅要和它的订阅群组一起提交;应用版本、订阅群组和要一起审的每个产品,都要在点 Submit for Review 之前放进同一个草稿提交。某类型的第一个产品获批后,同类型后续产品可以不带新版本提交,前提是应用至少有一个已获批的版本。产品 ID、显示名称和描述的长度上限见 App Store Connect 限制速查。

审核员看不到产品会怎样

Guideline 2.1(b) 原文:「If you offer in-app purchases in your app, make sure they are complete, up-to-date, visible to the reviewer and functional. If any configured in-app purchase items cannot be found or reviewed in your app, explain the reason in your review notes.」(应用提供内购的,要确保内购完整、最新、审核员可见且能用。如果配置的某个内购在应用里找不到或无法审核,要在审核备注里说明原因。)空白的付费墙、点了没反应的购买按钮都过不了这一条。怎样按审核员的冷启动方式复现,见 2.1 拒审指南。

提交前,Apple 的 App Review 帮助要求:在应用里展示内购之前先用 StoreKit 拉取产品信息,确保展示的内容和 App Store Connect 一致;并在沙盒里测试。如果某个产品显示不出来,按 TN3186 排查。

对于「自己用 TestFlight 能取到,审核员取不到」,Apple 没有单独写原因。它的页面说两者都用沙盒;如果结果不同,第 6 步里的店面和设备限制是文档里写到的、可以先排除的差异。

常见问题

Product.products(for:) 为什么返回空数组?

Apple 文档写明,无效的或 App Store 找不到的标识符会被排除在结果之外,所以空数组表示请求的 ID 一个都没找到。只有系统相关的故障才会抛错。去查协议、Bundle ID、产品 ID 和产品元数据。

TestFlight 会用我的 StoreKit 配置文件吗?

不会。TestFlight 构建始终运行在沙盒,读的是你在 App Store Connect 里配置的产品。Apple 说 StoreKit 配置文件里的数据不会上传到 App Store Connect,也不会出现在 App Store 签名的应用里。

内购要先过审,App Review 才能看到吗?

不用。Apple 说内购不需要事先获批就能在审核中使用,沙盒测试也不需要提交内购。但每种类型的第一个内购必须和新的应用版本一起提交。

产品刚建好还是取不到,要等多久?

Apple 说内购信息的改动最多可能要一小时才出现在沙盒里。超过一小时还没有,就回到协议和 ID 那几项去查。

取不到产品会被 App Review 拒吗?

Guideline 2.1(b) 要求内购完整、最新、审核员可见且能用。如果某个已配置的产品在应用里找不到或无法审核,要在审核备注里说明原因。

参考资料

均于 2026 年 11 月 1 日阅读。

Apple 的措辞和工具会变化,具体以上面这些页面的当前内容为准。

作者

独立开发者,在 Obelisk Club 做本地优先的 Mac 与 iOS 效率应用。 关于作者 →