Core Methods
Essential methods for implementing in-app purchases with flutter_inapp_purchase v6.0.0. All methods support both iOS and Android platforms with unified APIs.
⚠️ Platform Differences: While the API is unified, there are important differences between iOS and Android implementations. Each method documents platform-specific behavior.
Connection Management
initConnection()
Initializes the connection to the platform store.
Future<void> initConnection() async
Description: Establishes connection with the App Store (iOS) or Google Play Store (Android). Must be called before any other IAP operations.
Platform Differences:
- iOS: Connects to StoreKit 2 (iOS 15+) or StoreKit 1 (fallback)
- Android: Connects to Google Play Billing Client v8
Example:
try {
await FlutterInappPurchase.instance.initConnection();
print('IAP connection initialized successfully');
} catch (e) {
print('Failed to initialize IAP: $e');
}
Throws: PurchaseError
if connection fails or already initialized
See Also: endConnection(), Connection Lifecycle
endConnection()
Ends the connection to the platform store.
Future<void> endConnection() async
Description: Cleanly closes the store connection and frees resources. Should be called when IAP functionality is no longer needed.
Example:
try {
await FlutterInappPurchase.instance.endConnection();
print('IAP connection closed');
} catch (e) {
print('Failed to close IAP connection: $e');
}
Note: Connection can be re-established by calling initConnection()
again.
finalize()
Alternative name for endConnection()
for backward compatibility.
Future<void> finalize() async
Product Loading
requestProducts()
Loads product information from the store.
Future<List<BaseProduct>> requestProducts(RequestProductsParams params) async
Parameters:
params
- Request parameters containing SKUs and product type
Returns: List of products with pricing and metadata
Example:
final params = RequestProductsParams(
skus: ['product_1', 'product_2', 'premium_upgrade'],
type: PurchaseType.inapp,
);
try {
final products = await FlutterInappPurchase.instance.requestProducts(params);
for (final product in products) {
print('Product: ${product.id}');
print('Price: ${product.displayPrice}');
print('Title: ${product.title}');
}
} catch (e) {
print('Failed to load products: $e');
}
Platform Differences:
- iOS: Uses
SKProductsRequest
(StoreKit) - Android: Uses
querySkuDetails()
(Billing Client)
getProducts()
Legacy method for loading in-app products.
Future<List<IAPItem>> getProducts(List<String> skus) async
Parameters:
skus
- List of product identifiers
Returns: List of IAPItem
objects
Example:
final products = await FlutterInappPurchase.instance.getProducts([
'coins_100',
'coins_500',
'remove_ads'
]);
for (final product in products) {
print('${product.title}: ${product.localizedPrice}');
}
getSubscriptions()
Legacy method for loading subscription products.
Future<List<IAPItem>> getSubscriptions(List<String> skus) async
Parameters:
skus
- List of subscription identifiers
Returns: List of subscription IAPItem
objects with subscription-specific metadata
Example:
final subscriptions = await FlutterInappPurchase.instance.getSubscriptions([
'premium_monthly',
'premium_yearly'
]);
for (final sub in subscriptions) {
print('${sub.title}: ${sub.localizedPrice}');
print('Period: ${sub.subscriptionPeriodAndroid}'); // Android
print('Period: ${sub.subscriptionPeriodUnitIOS}'); // iOS
}
Purchase Processing
requestPurchase()
Initiates a purchase using platform-specific request objects.
Future<void> requestPurchase({
required RequestPurchase request,
required PurchaseType type,
}) async
Parameters:
request
- Platform-specific purchase requesttype
- Purchase type (PurchaseType.inapp
orPurchaseType.subs
)
Example:
// Create platform-specific request
final request = RequestPurchase(
ios: RequestPurchaseIOS(
sku: 'premium_upgrade',
quantity: 1,
),
android: RequestPurchaseAndroid(
skus: ['premium_upgrade'],
),
);
try {
await FlutterInappPurchase.instance.requestPurchase(
request: request,
type: PurchaseType.inapp,
);
// Listen to purchaseUpdated stream for result
} catch (e) {
print('Purchase request failed: $e');
}
Platform Differences:
- iOS: Single
sku
, supportsquantity
and promotional offers - Android: Array of
skus
, supports obfuscated user IDs
requestPurchaseAuto()
Simplified purchase method with automatic platform detection.
Future<void> requestPurchaseAuto({
required String sku,
required PurchaseType type,
// iOS-specific optional parameters
bool? andDangerouslyFinishTransactionAutomaticallyIOS,
String? appAccountToken,
int? quantity,
PaymentDiscount? withOffer,
// Android-specific optional parameters
String? obfuscatedAccountIdAndroid,
String? obfuscatedProfileIdAndroid,
bool? isOfferPersonalized,
String? purchaseToken,
int? offerTokenIndex,
int? prorationMode,
// Android subscription-specific
int? replacementModeAndroid,
List<SubscriptionOfferAndroid>? subscriptionOffers,
}) async
Parameters:
sku
- Product identifiertype
- Purchase type- Platform-specific optional parameters
Example:
try {
await FlutterInappPurchase.instance.requestPurchaseAuto(
sku: 'premium_upgrade',
type: PurchaseType.inapp,
quantity: 1, // iOS only
obfuscatedAccountIdAndroid: 'user_123', // Android only
);
} catch (e) {
print('Auto purchase failed: $e');
}
Transaction Management
finishTransaction()
Completes a transaction after successful purchase processing.
Future<void> finishTransaction(
PurchasedItem purchase, {
bool isConsumable = false,
}) async
Parameters:
purchase
- The purchased item to finishisConsumable
- Whether the product is consumable (Android only)
Example:
// In your purchase success handler
FlutterInappPurchase.purchaseUpdated.listen((purchase) async {
if (purchase != null) {
try {
// Deliver the product to user
await deliverProduct(purchase.productId);
// Finish the transaction
await FlutterInappPurchase.instance.finishTransaction(
purchase,
isConsumable: true, // For consumable products
);
print('Transaction completed successfully');
} catch (e) {
print('Failed to finish transaction: $e');
}
}
});
Platform Behavior:
- iOS: Calls
finishTransaction
on the transaction - Android: Calls
consumePurchase
(consumable) oracknowledgePurchase
(non-consumable)
consumePurchaseAndroid()
Android-specific method to consume a purchase.
Future<void> consumePurchaseAndroid({
required String purchaseToken,
}) async
Parameters:
purchaseToken
- The purchase token to consume
Example:
// Android-specific consumption
if (Platform.isAndroid) {
try {
await FlutterInappPurchase.instance.consumePurchaseAndroid(
purchaseToken: purchase.purchaseToken!,
);
print('Purchase consumed successfully');
} catch (e) {
print('Failed to consume purchase: $e');
}
}
Note: Only available on Android. Use finishTransaction()
for cross-platform compatibility.
Purchase History
getAvailablePurchases()
Gets all available (unconsumed) purchases.
Future<List<Purchase>> getAvailablePurchases() async
Returns: List of available purchases
Example:
try {
final purchases = await FlutterInappPurchase.instance.getAvailablePurchases();
print('Found ${purchases.length} available purchases');
for (final purchase in purchases) {
print('Product: ${purchase.productId}');
print('Date: ${purchase.transactionDate}');
}
} catch (e) {
print('Failed to get available purchases: $e');
}
getPurchaseHistories()
Gets purchase history including consumed items.
Future<List<Purchase>> getPurchaseHistories() async
Returns: List of historical purchases
Example:
try {
final history = await FlutterInappPurchase.instance.getPurchaseHistories();
print('Purchase history: ${history.length} items');
for (final purchase in history) {
print('${purchase.productId} - ${purchase.transactionDate}');
}
} catch (e) {
print('Failed to get purchase history: $e');
}
restorePurchases()
Restores previous purchases (primarily for iOS).
Future<void> restorePurchases() async
Example:
try {
await FlutterInappPurchase.instance.restorePurchases();
// Check available purchases after restoration
final restored = await FlutterInappPurchase.instance.getAvailablePurchases();
print('Restored ${restored.length} purchases');
} catch (e) {
print('Failed to restore purchases: $e');
}
Platform Behavior:
- iOS: Triggers App Store purchase restoration
- Android: Returns cached purchase data
Platform-Specific Methods
iOS-Specific Methods
presentCodeRedemptionSheetIOS()
Presents the App Store code redemption sheet.
Future<void> presentCodeRedemptionSheetIOS() async
Example:
if (Platform.isIOS) {
try {
await FlutterInappPurchase.instance.presentCodeRedemptionSheetIOS();
} catch (e) {
print('Failed to present redemption sheet: $e');
}
}
Requirements: iOS 14.0+
showManageSubscriptionsIOS()
Shows the subscription management interface.
Future<void> showManageSubscriptionsIOS() async
Example:
if (Platform.isIOS) {
try {
await FlutterInappPurchase.instance.showManageSubscriptionsIOS();
} catch (e) {
print('Failed to show subscription management: $e');
}
}
getAppStoreCountryIOS()
Gets the App Store country code.
Future<String?> getAppStoreCountryIOS() async
Returns: Country code or null
Example:
if (Platform.isIOS) {
final country = await FlutterInappPurchase.instance.getAppStoreCountryIOS();
print('App Store country: $country');
}
Android-Specific Methods
deepLinkToSubscriptionsAndroid()
Opens the Google Play subscription management page.
Future<void> deepLinkToSubscriptionsAndroid() async
Example:
if (Platform.isAndroid) {
try {
await FlutterInappPurchase.instance.deepLinkToSubscriptionsAndroid();
} catch (e) {
print('Failed to open subscription management: $e');
}
}
getConnectionStateAndroid()
Gets the current billing client connection state.
Future<int> getConnectionStateAndroid() async
Returns: Connection state code
Example:
if (Platform.isAndroid) {
final state = await FlutterInappPurchase.instance.getConnectionStateAndroid();
print('Billing client state: $state');
}
Error Handling
All core methods may throw PurchaseError
exceptions. Always wrap calls in try-catch blocks:
try {
await FlutterInappPurchase.instance.initConnection();
} on PurchaseError catch (e) {
switch (e.code) {
case ErrorCode.eAlreadyInitialized:
print('Already initialized');
break;
case ErrorCode.eNetworkError:
print('Network error - check connection');
break;
default:
print('Purchase error: ${e.message}');
}
} catch (e) {
print('Unexpected error: $e');
}
Best Practices
1. Connection Management
class IAPManager {
static bool _isInitialized = false;
static Future<void> initialize() async {
if (!_isInitialized) {
await FlutterInappPurchase.instance.initConnection();
_isInitialized = true;
}
}
static Future<void> dispose() async {
if (_isInitialized) {
await FlutterInappPurchase.instance.endConnection();
_isInitialized = false;
}
}
}
2. Product Loading with Caching
class ProductManager {
static List<BaseProduct>? _cachedProducts;
static DateTime? _lastFetch;
static const _cacheTimeout = Duration(hours: 1);
static Future<List<BaseProduct>> getProducts(List<String> skus) async {
if (_cachedProducts != null &&
_lastFetch != null &&
DateTime.now().difference(_lastFetch!) < _cacheTimeout) {
return _cachedProducts!;
}
final params = RequestProductsParams(skus: skus, type: PurchaseType.inapp);
_cachedProducts = await FlutterInappPurchase.instance.requestProducts(params);
_lastFetch = DateTime.now();
return _cachedProducts!;
}
}
3. Purchase Flow with Error Handling
Future<void> makePurchase(String sku) async {
try {
final request = RequestPurchase(
ios: RequestPurchaseIOS(sku: sku, quantity: 1),
android: RequestPurchaseAndroid(skus: [sku]),
);
await FlutterInappPurchase.instance.requestPurchase(
request: request,
type: PurchaseType.inapp,
);
// Success handling happens in purchaseUpdated listener
} on PurchaseError catch (e) {
if (e.code == ErrorCode.eUserCancelled) {
// User cancelled - don't show error
return;
}
// Show error to user
showErrorDialog(e.message);
}
}
Migration Notes
⚠️ Breaking Changes from v5.x:
- Method Names:
requestPurchase()
now requiresRequestPurchase
object - Parameters: Platform-specific parameters moved to request objects
- Error Handling:
PurchaseError
replaces simple string errors - Initialization: Must call
initConnection()
before other operations
See Also
- Types - Request and response object definitions
- Listeners - Event streams for purchase updates
- Error Codes - Comprehensive error handling
- Purchase Guide - Complete purchase implementation