Uses official StoreKit (iOS) or Play Billing Library (Android) for digital goods
Why it matters
Apple guideline 3.1.1 and Google Play Billing Policy both require that all digital goods sold within an app — subscriptions, consumables, non-consumables — are transacted exclusively through the platform's official billing API (StoreKit on iOS, Play Billing Library on Android). Routing a digital goods purchase through Stripe, Paddle, PayPal, or any other third-party processor via a webview or external link is not a gray area: it results in immediate rejection and, for repeat violations, developer account termination. Apple has removed apps and banned developer accounts for this specific violation. The business impact is severe: an app rejected during review has zero revenue until resubmitted, a process that takes days to weeks and requires removing the violating payment flow entirely.
Severity rationale
Critical because violation results in immediate App Store rejection and potential permanent developer account termination with no warning period.
Remediation
Remove any Stripe, Paddle, or other third-party payment flows used for digital goods and replace them with StoreKit (iOS) or Play Billing Library (Android). The fastest cross-platform path is RevenueCat, which wraps both platform SDKs and handles receipt validation server-side.
npm install react-native-purchases
npx pod-install
// React Native — purchase via RevenueCat
import Purchases from 'react-native-purchases';
const { customerInfo } = await Purchases.purchasePackage(pkg);
if (customerInfo.entitlements.active['premium']) {
unlockPremium();
}
For Expo projects: npx expo install expo-iap. For Flutter: add in_app_purchase: ^3.2.0 to pubspec.yaml. Physical goods and real-world services (delivery, rides, hotel bookings) are exempt — only digital goods require the platform store.
Detection
- ID:
storekit-billing - Severity:
critical - What to look for: Count all relevant instances and enumerate each. Verify that all digital goods purchases (subscriptions, consumables, non-consumables) flow through the platform's official billing API. For iOS: look for
import StoreKitin Swift files,StoreKit.Product.purchase()orSKPaymentQueuereferences, or an approved SDK wrapper (react-native-iap,expo-iap,react-native-purchasesfor RevenueCat,adapty,react-native-qonversion,in_app_purchaseFlutter plugin). For Android: look forBillingClientin Kotlin, or the same approved wrappers. In React Native, check files insrc/lib/iap/,src/services/iap.ts,src/hooks/useIAP.ts, or equivalent. In Flutter, checklib/services/iap_service.dartor similar. The critical failure pattern is a digital goods purchase flow routed through a third-party web payment processor (Stripe, Paddle, PayPal, LemonSqueezy, etc.) via an in-app webview orLinking.openURL()to a checkout page — this is one of the most severe guideline violations and results in immediate rejection and potential developer account termination. - Pass criteria: All digital goods available for purchase within the app are transacted exclusively through StoreKit (iOS) or Play Billing Library (Android), either directly or via an approved wrapper SDK. At least 1 implementation must be verified. A partial or placeholder implementation does not count as pass. Report the count even on pass.
- Fail criteria: Any digital good purchasable within the app uses a third-party payment processor, a web checkout page, or a custom payment form. Also fails if no IAP integration is detectable but the app clearly offers premium features or content for sale.
- Skip (N/A) when: App is entirely free with no purchasable features, content, or subscriptions.
- Detail on fail: Cite the specific pattern. Example:
"Stripe checkout URL opened via Linking.openURL() in src/screens/UpgradeScreen.tsx when user taps 'Go Premium' — Apple guideline 3.1.1 violation"or"No StoreKit or Play Billing integration found despite app displaying locked premium features" - Remediation: Apple and Google require all digital goods to be sold exclusively through their platforms. There is no exception for apps distributed through their stores.
- For React Native with RevenueCat (recommended for cross-platform):
npm install react-native-purchases npx pod-install// AppDelegate.swift (iOS) Purchases.configure(withAPIKey: "appl_xxxxx") // MainApplication.kt (Android) Purchases.configure(this, "goog_xxxxx") // React Native import Purchases from 'react-native-purchases'; const { customerInfo } = await Purchases.purchasePackage(package); - For Expo with
expo-iap:npx expo install expo-iap - For Flutter with
in_app_purchase:# pubspec.yaml dependencies: in_app_purchase: ^3.2.0 - Web checkout flows ARE permitted for physical goods and services consumed outside the app (e.g., Uber rides, food delivery, hotel bookings). Only digital goods require the platform store.
- For React Native with RevenueCat (recommended for cross-platform):
External references
- external · apple-guideline-3.1.1 — Apple App Store Review Guidelines § 3.1.1 — In-App Purchase
- external · google-play-billing-policy — Google Play Billing Policy — Use of Google Play's Billing System
Taxons
History
- 2026-04-18·v1.0.0·Initial import from app-store-iap-subscriptions·automated