3.1.9 - Alternative Billing Support
Expo IAP 3.1.9 introduces Alternative Billing support for both iOS and Android platforms, enabling developers to offer external payment options in compliance with App Store and Google Play requirements.
This release integrates StoreKit External Purchase APIs (iOS 16.0+) and Google Play Alternative Billing APIs, providing a unified interface for alternative payment flows across platforms.
๐ Highlightsโ
iOS Alternative Billing (StoreKit External Purchase)โ
Three new APIs for managing external purchases on iOS:
canPresentExternalPurchaseNoticeIOS()
- Check if the notice sheet is available (iOS 18.2+)presentExternalPurchaseNoticeSheetIOS()
- Present a notice before redirecting to external purchase (iOS 18.2+)presentExternalPurchaseLinkIOS(url)
- Open external purchase link in Safari (iOS 16.0+)
Expo Config Plugin Support: The new iosAlternativeBilling
configuration automatically sets up required Info.plist keys and entitlements:
// app.config.ts
export default {
plugins: [
[
'expo-iap',
{
iosAlternativeBilling: {
countries: ['kr', 'nl'], // ISO 3166-1 alpha-2
links: {
kr: 'https://your-site.com/kr',
nl: 'https://your-site.com/nl',
},
enableExternalPurchaseLink: true,
},
},
],
],
};
The plugin handles:
SKExternalPurchase
- Country codes where external purchases are supportedSKExternalPurchaseLink
- External purchase URLs per country (iOS 15.4+)SKExternalPurchaseMultiLink
- Multiple URLs per country (iOS 17.5+)SKExternalPurchaseCustomLinkRegions
- Custom link regions (iOS 18.1+)SKExternalPurchaseLinkStreamingRegions
- Streaming regions for music apps (iOS 18.2+)- StoreKit entitlements:
com.apple.developer.storekit.external-purchase*
Android Alternative Billingโ
Three new APIs for Google Play Alternative Billing flow:
checkAlternativeBillingAvailabilityAndroid()
- Check if alternative billing is available for the usershowAlternativeBillingDialogAndroid()
- Show Google's required information dialogcreateAlternativeBillingTokenAndroid(sku)
- Generate reporting token after successful payment
Configuration Support: initConnection()
now accepts an optional config parameter:
import {initConnection} from 'expo-iap';
// Initialize with alternative billing mode
await initConnection({
alternativeBillingModeAndroid: 'user-choice', // or 'alternative-only'
});
Two Billing Modes:
user-choice
- Users choose between Google Play billing (30% fee) or your payment system (lower fee)alternative-only
- Only your payment system is available (Google Play billing disabled)
๐ Usage Examplesโ
iOS External Purchaseโ
import {presentExternalPurchaseLinkIOS} from 'expo-iap';
// Redirect user to external purchase website
const result = await presentExternalPurchaseLinkIOS(
'https://your-site.com/checkout',
);
if (result.success) {
console.log('User redirected to external website');
}
Android Alternative Billingโ
User Choice Mode - When using user-choice
mode, listen for user selection with userChoiceBillingListenerAndroid()
:
import {initConnection, userChoiceBillingListenerAndroid} from 'expo-iap';
// Initialize with user-choice mode
await initConnection({
alternativeBillingModeAndroid: 'user-choice',
});
// Listen for when user selects alternative billing
const subscription = userChoiceBillingListenerAndroid((details) => {
console.log('User selected alternative billing');
console.log('Token:', details.externalTransactionToken);
console.log('Products:', details.products);
// Process payment in your system, then report token to Google
await processPaymentAndReportToken(details);
});
// Clean up when done
subscription.remove();
Alternative Only Mode - Manual 3-step flow:
import {
checkAlternativeBillingAvailabilityAndroid,
showAlternativeBillingDialogAndroid,
createAlternativeBillingTokenAndroid,
} from 'expo-iap';
// Step 1: Check availability
const isAvailable = await checkAlternativeBillingAvailabilityAndroid();
// Step 2: Show Google's information dialog
const userAccepted = await showAlternativeBillingDialogAndroid();
if (userAccepted) {
// Step 3: Process payment in your system, then create token
const token = await createAlternativeBillingTokenAndroid(productId);
// Step 4: Report token to Google Play backend within 24 hours
await reportTokenToGooglePlay(token);
}
๐จ Example Appโ
A complete alternative billing demo screen has been added to the example app:
- Platform-specific flows - Demonstrates iOS and Android alternative billing patterns
- Billing mode toggle (Android) - Switch between
alternative-only
anduser-choice
with auto-reconnect - External URL input (iOS) - Configure and test external purchase links
- Real-time results - View purchase flow status and responses
- Step-by-step guidance - Visual flow diagrams for both platforms
Navigate to example/app/alternative-billing.tsx
to explore the implementation.
๐ง OpenIAP Upgradesโ
- openiap-apple upgraded to 1.2.10 with StoreKit external purchase support
- openiap-google upgraded to 1.2.12 with alternative billing APIs
- openiap-gql upgraded to 1.0.12 with updated type definitions
๐งช Testingโ
Added 30+ comprehensive tests for the iOS config plugin:
- Info.plist configuration validation
- Entitlements setup verification
- URL validation and country code checks
- Edge case handling
All existing tests continue to pass with 98%+ coverage.
โ ๏ธ Platform Requirementsโ
iOSโ
- Minimum Version: iOS 16.0+ for external purchase links, iOS 18.2+ for notice sheet
- App Store Connect: Must request and receive approval for external purchase entitlements
- Provisioning Profile: Must include StoreKit external purchase entitlements
- See StoreKit External Purchase documentation
Androidโ
- Google Play Console: Must be approved for alternative billing program
- Token Reporting: Must report tokens to Google within 24 hours
- Backend Integration: Server-side validation and reporting required
- See Google Play Alternative Billing documentation
๐ฆ Installationโ
bun add expo-iap@3.1.9
# or
npm install expo-iap@3.1.9
# or
yarn add expo-iap@3.1.9
After installation, run prebuild to apply iOS config plugin changes:
npx expo prebuild --clean
๐จ Important Notesโ
For iOS Developersโ
Alternative billing on iOS requires explicit approval from Apple. During development:
- Keep
iosAlternativeBilling
commented out in your config - Test regular IAP flows without entitlements
- When ready for production, uncomment the config and follow Apple's approval process
For Android Developersโ
Alternative billing on Android requires:
- Approval from Google Play Console
- Backend integration to report tokens within 24 hours
- Proper error handling for users not eligible for alternative billing
No Breaking Changes: All changes are additive. Existing apps will continue to work without modifications.
๐ Referencesโ
- OpenIAP Documentation
- StoreKit External Purchase
- Google Play Alternative Billing
- Example Implementation
Questions or issues? Let us know via GitHub issues.