# StoreKit 在 App Review 或 TestFlight 里取不到产品:一份检查清单 > Product.products(for:) 在 Xcode 里能取到产品,到了 TestFlight 或审核员手里却是空的。按顺序检查付费 App 协议、Bundle ID 和产品 ID、产品元数据、StoreKit 配置文件,以及首个内购是否随版本提交。 - Canonical page: https://obelisk.club/blog/storekit-products-empty-app-review-testflight-zh - Author: Peter Zhang - Published: 2026-11-01 - Tags: app-review, app-store, storekit, in-app-purchase, testflight, guideline-2-1, checklist, indie, 中文 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 配置文件查看器](/tools/storekit-config-viewer) 打开它,把里面的产品 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 要求确认每个内购都设了价格并加了本地化信息。 可以用[内购设置检查工具](/tools/in-app-purchase-setup-checker)逐项核对这些设置。 - 在 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 限制速查](/tools/app-store-connect-limits)。 ## 审核员看不到产品会怎样 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 拒审指南](/blog/app-review-guideline-2-1-app-completeness-rejection-zh)。 提交前,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 日阅读。 - [Testing at all stages of development with Xcode and the sandbox](https://developer.apple.com/documentation/storekit/testing-at-all-stages-of-development-with-xcode-and-the-sandbox),Apple 开发者文档 - [Testing In-App Purchases with sandbox](https://developer.apple.com/documentation/storekit/testing-in-app-purchases-with-sandbox),Apple 开发者文档 - [Setting up StoreKit Testing in Xcode](https://developer.apple.com/documentation/xcode/setting-up-storekit-testing-in-xcode),Apple 开发者文档 - [products(for:)](https://developer.apple.com/documentation/storekit/product/products(for:)),Apple 开发者文档 - [TN3186: Troubleshooting In-App Purchases availability in the sandbox](https://developer.apple.com/documentation/technotes/tn3186-troubleshooting-in-app-purchases-availability-in-the-sandbox),Apple 开发者文档 - [Configure In-App Purchases for review in the sandbox](https://developer.apple.com/help/app-review/before-submitting-for-review/configure-in-app-purchases),App Review 帮助 - [Overview for configuring In-App Purchases](https://developer.apple.com/help/app-store-connect/configure-in-app-purchase-settings/overview-for-configuring-in-app-purchases),App Store Connect 帮助 - [Submit an In-App Purchase](https://developer.apple.com/help/app-store-connect/manage-submissions-to-app-review/submit-an-in-app-purchase),App Store Connect 帮助 - [In-App Purchase statuses](https://developer.apple.com/help/app-store-connect/reference/in-app-purchase-statuses),App Store Connect 帮助 - [Sign and update agreements](https://developer.apple.com/help/app-store-connect/manage-agreements/sign-and-update-agreements),App Store Connect 帮助 - [App Review Guidelines, 2.1 App Completeness](https://developer.apple.com/app-store/review/guidelines/#app-completeness),Apple Developer *Apple 的措辞和工具会变化,具体以上面这些页面的当前内容为准。*