Skip to main content

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 request
  • type - Purchase type (PurchaseType.inapp or PurchaseType.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, supports quantity 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 identifier
  • type - 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 finish
  • isConsumable - 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) or acknowledgePurchase (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:

  1. Method Names: requestPurchase() now requires RequestPurchase object
  2. Parameters: Platform-specific parameters moved to request objects
  3. Error Handling: PurchaseError replaces simple string errors
  4. Initialization: Must call initConnection() before other operations

See Also