Use this page with AI
Copy this into your coding assistant and add your request.
Read https://openiap.dev/docs/features/external-purchase and https://openiap.dev/llms.txt. Follow the reading instructions, detailed reference, and linked guides relevant to my task before making changes.
Inspect my existing project and reuse its framework and conventions. Ask me for missing product decisions. Implement the requested behavior and run the applicable checks.
Show the working result, the commands and actual test results, and any remaining limitations. Keep your explanation brief.
My request: [describe what customers should be able to do]External Purchase
Overview
External purchase allows you to redirect users to external payment systems instead of using platform-native billing (StoreKit on iOS, Google Play Billing on Android). This enables alternative payment methods and can reduce platform fees.
Platform Support
| Platform | Feature Name | Minimum OS Version | Native Framework |
|---|---|---|---|
| iOS | External Purchase URL | iOS 17.4+ (Notice Sheet) iOS 18.1+ (Custom Links) | StoreKit 2 |
| Android | Alternative Billing / Billing Programs | Android 6.0+ (API 23) | Google Play Billing 6.2+ (legacy), 8.2.0+ (External Content Links), 8.2.1+ (External Offers), 8.3.0+ (External Payments) |
Common Requirements#
Both platforms require the following infrastructure to support external purchases:
Backend Verification System
- Payment gateway integration
- Purchase verification endpoint
- Entitlement management system
- Transaction logging and auditing
Platform-Specific Implementation#
iOS - External Purchase
iOS supports external purchase through StoreKit's External Purchase API. The notice sheet presents within the app and returns results immediately - no browser redirect required.
Basic Usage
Check that the notice sheet can be shown, present it, then open your purchase link when the user continues:
import OpenIAP
@available(iOS 17.4, *)
func handleExternalPurchaseFlow() async {
let externalUrl = "https://your-payment-site.com/checkout"
do {
// Step 1: Check if notice sheet can be presented
let canPresent = try await OpenIapModule.shared
.canPresentExternalPurchaseNoticeIOS()
guard canPresent else {
print("External purchase notice sheet not available")
return
}
// Step 2: Present notice sheet (Apple's info sheet)
let noticeResult = try await OpenIapModule.shared
.presentExternalPurchaseNoticeSheetIOS()
if noticeResult.result == .continue {
// Step 3: Present external purchase link
let linkResult = try await OpenIapModule.shared
.presentExternalPurchaseLinkIOS(externalUrl)
if linkResult.success {
print("User acknowledged external purchase")
// User approved external purchase
// Call your backend API to initiate purchase
// await yourBackend.createPurchase(productId, userId)
} else {
print("External purchase link failed: \(linkResult.error ?? "")")
}
} else {
print("User dismissed notice sheet")
}
} catch {
print("External purchase error: \(error)")
}
}Requirements
- iOS 17.4+ - Required for
canPresentExternalPurchaseNoticeIOSandpresentExternalPurchaseNoticeSheetIOS - iOS 18.1+ - Required for the
ExternalPurchaseCustomLinkAPIs - StoreKit 2 - Uses StoreKit 2 framework
- Entitlement required -
com.apple.developer.storekit.external-purchaseentitlement must be configured in App Store Connect - Country code configuration - Must specify supported country codes in
SKExternalPurchasearray in Info.plist. Only available in EU countries and South Korea. See Apple Documentation - No deep linking required - Notice sheet presents within the app and returns results immediately
Configuration (iOS)
Add entitlement and country codes in Info.plist. Use lowercase ISO 3166-1 alpha-2 country codes:
1. SKExternalPurchase (Required)
Specify countries where your app supports external purchases:
<key>SKExternalPurchase</key>
<array>
<!-- South Korea -->
<string>kr</string>
<!-- Netherlands -->
<string>nl</string>
<!-- EU Countries (examples) -->
<string>de</string> <!-- Germany -->
<string>fr</string> <!-- France -->
<string>it</string> <!-- Italy -->
<string>es</string> <!-- Spain -->
<!-- Add other EU country codes as needed -->
</array>
<!-- Entitlement required -->
<!-- com.apple.developer.storekit.external-purchase: true -->2. SKExternalPurchaseLink (Optional - iOS 15.4+)
Provide destination URLs for each country. Required if using com.apple.developer.storekit.external-purchase-link entitlement:
<key>SKExternalPurchaseLink</key>
<dict>
<key>nl</key>
<string>https://your-site.com/checkout</string>
<key>de</key>
<string>https://your-site.com/de/checkout</string>
<key>kr</key>
<string>https://your-site.com/kr/checkout</string>
</dict>3. SKExternalPurchaseMultiLink (iOS 17.5+)
Provide multiple URLs (up to 5) for each country. Use this instead of SKExternalPurchaseLink for iOS 17.5+:
<key>SKExternalPurchaseMultiLink</key>
<dict>
<key>es</key>
<array>
<string>https://your-site.com/es1</string>
<string>https://your-site.com/new-user-es</string>
<string>https://your-site.com/seasonal-sale-es</string>
</array>
<key>fr</key>
<array>
<string>https://your-site.com/fr</string>
<string>https://your-site.com/global-sale</string>
</array>
<key>it</key>
<array>
<string>https://your-site.com/global-sale</string>
</array>
</dict>4. SKExternalPurchaseCustomLinkRegions (iOS 18.1+)
For custom links to communicate and promote offers. Required if using com.apple.developer.storekit.external-purchase-link entitlement and ExternalPurchaseCustomLink API:
<key>SKExternalPurchaseCustomLinkRegions</key>
<array>
<string>de</string> <!-- Germany -->
<string>fr</string> <!-- France -->
<string>nl</string> <!-- Netherlands -->
<!-- Add other EU country codes -->
</array>5. SKExternalPurchaseLinkStreamingRegions (iOS 18.2+)
For music streaming apps only. Required if using com.apple.developer.storekit.external-purchase-link-streaming entitlement:
<key>SKExternalPurchaseLinkStreamingRegions</key>
<array>
<string>at</string> <!-- Austria -->
<string>de</string> <!-- Germany -->
<string>fr</string> <!-- France -->
<string>nl</string> <!-- Netherlands -->
<string>is</string> <!-- Iceland -->
<string>no</string> <!-- Norway -->
<!-- Add other EU country codes -->
</array>Common Issues (iOS)
| Issue | Cause | Solution |
|---|---|---|
| Notice Sheet Not Showing | Missing entitlement or country code | Add com.apple.developer.storekit.external-purchase entitlement and configure SKExternalPurchase array |
| canPresent Returns False | Device region not supported | Check device is in supported country (EU, NL, KR) |
| FeatureNotSupported Error | iOS version too old | Requires iOS 17.4+ (notice sheet), iOS 18.1+ (custom links) |
Implementation Flow#
The complete external purchase flow involves coordination between your app, external website, and backend. The flow differs between iOS and Android:
iOS Flow (iOS 17.4+)
| Step | API / Action | Description |
|---|---|---|
| 1 | canPresentExternalPurchaseNoticeIOS() | Check if device supports external purchase notice sheet |
| 2 | presentExternalPurchaseNoticeSheetIOS() | Show Apple's notice sheet informing user about external purchase |
| 3 | User Action | User taps "Continue" or dismisses the notice sheet |
| 4 | presentExternalPurchaseLinkIOS(url) | If user continued, present external purchase link (user acknowledges external purchase) |
| 5 | Backend Payment Processing | App calls backend API to process payment with payment gateway (Stripe, PayPal, etc.) and grant entitlements |
| 6 | Unlock Content | App unlocks purchased content after backend confirmation |
Complete Examples#
For complete, production-ready examples with full UI implementation, please refer to the native example apps:
iOS (SwiftUI)
- AlternativeBillingScreen.swift - Complete implementation with notice sheet and external purchase link presentation
This example demonstrates:
- Complete UI implementation with state management
- Notice sheet presentation (iOS 17.4+)
- Deep link handling and verification flow
- Error handling and user feedback
- Production-ready code patterns
Related Documentation#
- External Purchase Types - Type definitions and parameters
- Onside Store Setup - alternative marketplace flow for
expo-iap - Alternative Billing Types - Type definitions and config
- Request Purchase API - API reference for requestPurchase
- Error Codes - Error handling reference
Native References#
- Apple · StoreKit External Purchase entitlement
- Apple · StoreKit ExternalPurchase — notice sheet and link APIs
- Google · User Choice Billing
- Google · Alternative billing in Play Billing Library
- Google · Play Billing 8.3.0 — External Payments (Japan)