TestFlight中In-App Purchase无法使用导致应用被苹果审核驳回的问题排查求助
Hey Joseph, let's walk through the most common issues that could be blocking your In-App Purchase from working in TestFlight—since it worked in Xcode local testing, the problem is almost certainly tied to how TestFlight interacts with App Store Connect and your app's production-ready configuration.
1. Double-Check App Store Connect IAP Setup
Even though your IAP shows "Ready to Submit," a few easy-to-miss details could break things:
- Confirm your code's
[my IAP identifier]matches the exact Product ID in App Store Connect (case-sensitive, no extra spaces or typos). - In your app's App Store Connect page, go to App Information and make sure the "Use In-App Purchase" checkbox is enabled. This is a common oversight!
- Verify your IAP's Availability settings: it should be set to your test region (or "All Territories")—TestFlight respects geographic restrictions for IAPs.
- Ensure your TestFlight build is linked to the IAP: if you added the IAP after uploading your build, reupload a new build to sync the association.
2. Fix StoreKit Configuration for TestFlight
This is likely the biggest culprit:
- When testing real IAPs in TestFlight, you must set StoreKit Configuration to "None" in Xcode's build settings. The
Configuration.storekitfile is only for local Xcode testing—it forces the app to use mock data instead of connecting to Apple's real Sandbox servers. - After changing this setting, recompile and upload a fresh build to TestFlight—old builds will retain the incorrect configuration.
3. Correct Payment Queue Observer Setup
Your code adds the observer only when initiating a purchase, which can cause missed callbacks:
- Add the payment queue observer as soon as your scene loads, not just when the user taps "buy." Add this to your
Menuscene:override func didMove(to view: SKView) { super.didMove(to: view) SKPaymentQueue.default().add(self) } - Also, clean up the observer when the scene is destroyed to avoid memory leaks:
override func willMove(from view: SKView) { super.willMove(from: view) SKPaymentQueue.default().remove(self) }
This ensures you catch all transaction states, even if there are pending transactions from previous test attempts.
4. Use a Sandbox Tester Account
TestFlight IAPs require a dedicated Sandbox test account—you can't use your personal Apple ID:
- Create a Sandbox tester in App Store Connect under Users and Access > Sandbox Testers.
- On your test device, sign out of the App Store (Settings > [Your Name] > Media & Purchases > Sign Out), then launch the TestFlight app and sign in with the Sandbox tester credentials when prompted to make a purchase.
5. Log Detailed Error Messages
Your current code only prints "Failed" without context—add error logging to pinpoint issues:
case .failed: SKPaymentQueue.default().finishTransaction(transaction) if let error = transaction.error as? SKError { print("Purchase failed: \(error.localizedDescription) | Code: \(error.code.rawValue)") } else { print("Purchase failed with unknown error") }
Common error codes like SKError.productNotFound (mismatched Product ID) or SKError.paymentNotAllowed (Sandbox account issue) will immediately tell you what's wrong.
6. Reupload a Fresh Build
After fixing any configuration or code issues, upload a new build to TestFlight. Old builds sometimes don't sync changes to Capabilities or IAP associations, so a fresh upload ensures all settings are applied correctly.
Start with the StoreKit Configuration fix and Sandbox account check—those are the most frequent causes of TestFlight IAP failures. Once you add the error logging, you'll have concrete details if you hit any remaining snags.
内容的提问来源于stack exchange,提问作者Joseph

