Skip to main content
Version: 6.8

๐Ÿ”ง FlutterInappPurchase API

The main class for handling in-app purchases across iOS and Android platforms.

๐Ÿ“ฆ Importโ€‹

import 'package:flutter_inapp_purchase/flutter_inapp_purchase.dart';

๐Ÿ—๏ธ Instance Accessโ€‹

// Access the singleton instance
final iap = FlutterInappPurchase.instance;

๐Ÿ”— Connection Managementโ€‹

initConnection()โ€‹

Initialize the connection to the platform billing service.

Future<void> initConnection()

Example:

try {
await FlutterInappPurchase.instance.initConnection();
print('Connection initialized successfully');
} catch (e) {
print('Failed to initialize connection: $e');
}

Platform Notes:

  • iOS: Calls canMakePayments and registers transaction observers
  • Android: Connects to Google Play Billing service

endConnection()โ€‹

End the connection to the platform billing service.

Future<void> endConnection()

Example:


void dispose() {
FlutterInappPurchase.instance.endConnection();
super.dispose();
}

Important: Always call this in your app's dispose method to prevent memory leaks.

๐Ÿ›๏ธ Product Managementโ€‹

fetchProducts()โ€‹

Load products or subscriptions using the OpenIAP request schema.

Future<FetchProductsResult> fetchProducts(ProductRequest request)

Example:

final inAppResult = await FlutterInappPurchase.instance.fetchProducts(
ProductRequest(
skus: ['premium_upgrade', 'extra_lives'],
type: ProductQueryType.InApp,
),
);
final products = inAppResult.inAppProducts();

final subsResult = await FlutterInappPurchase.instance.fetchProducts(
ProductRequest(
skus: ['monthly_premium'],
type: ProductQueryType.Subs,
),
);
final subscriptions = subsResult.subscriptionProducts();

๐Ÿ’ณ Purchase Managementโ€‹

requestPurchase()โ€‹

Request a purchase using the new unified API.

Future<void> requestPurchase({
required RequestPurchase request,
required PurchaseType type,
})

Parameters:

ParameterTypeDescription
requestRequestPurchasePlatform-specific purchase request
typePurchaseTypeType of purchase (inapp or subs)

Example:

await FlutterInappPurchase.instance.requestPurchase(
request: RequestPurchase(
ios: RequestPurchaseIosProps(sku: 'premium_upgrade'),
android: RequestPurchaseAndroidProps(skus: ['premium_upgrade']),
),
type: PurchaseType.inapp,
);

requestPurchaseSimple()โ€‹

Simplified purchase request for cross-platform products.

Future<void> requestPurchaseSimple({
required String productId,
required PurchaseType type,
String? applicationUsername,
String? obfuscatedAccountId,
String? obfuscatedProfileId,
})

Parameters:

ParameterTypeRequiredDescription
productIdStringโœ…Product ID to purchase
typePurchaseTypeโœ…Purchase type
applicationUsernameString?โŒiOS: Application username
obfuscatedAccountIdString?โŒAndroid: Obfuscated account ID
obfuscatedProfileIdString?โŒAndroid: Obfuscated profile ID

Example:

await FlutterInappPurchase.instance.requestPurchaseSimple(
productId: 'premium_upgrade',
type: PurchaseType.inapp,
);

๐Ÿ“‹ Purchase Historyโ€‹

getAvailablePurchases()โ€‹

Get all non-consumed purchases (restore purchases).

Future<List<Purchase>> getAvailablePurchases()

Returns: Future<List<Purchase>> - List of available purchases

Example:

final purchases = await FlutterInappPurchase.instance.getAvailablePurchases();
if (purchases != null) {
for (var purchase in purchases) {
print('Purchase: ${purchase.productId}');
}
}

getPurchaseHistory()โ€‹

Get purchase history (including consumed purchases on Android).

Future<List<Purchase>> getPurchaseHistory()

Returns: Future<List<Purchase>> - List of purchase history

โœ… Transaction Completionโ€‹

finishTransaction()โ€‹

Complete a transaction (cross-platform).

Future<void> finishTransaction(Purchase purchase, {bool isConsumable = false})

Parameters:

ParameterTypeRequiredDescription
purchasePurchaseโœ…Purchase to finish
isConsumableboolโŒWhether the purchase is consumable (Android)

Example:

// Listen for purchase updates
FlutterInappPurchase.purchaseUpdated.listen((purchase) async {
if (purchase != null) {
// Verify the purchase on your server first
await verifyPurchaseOnServer(purchase);

// Complete the transaction
await FlutterInappPurchase.instance.finishTransaction(
purchase,
isConsumable: true, // for consumable products
);
}
});

๐Ÿ“ฑ Platform-Specific Methodsโ€‹

iOS Methodsโ€‹

syncIOS()โ€‹

Sync pending iOS transactions.

Future<bool> syncIOS()

presentCodeRedemptionSheetIOS()โ€‹

Present the code redemption sheet (iOS 14+).

Future<void> presentCodeRedemptionSheetIOS()

showManageSubscriptionsIOS()โ€‹

Show the subscription management interface.

Future<void> showManageSubscriptionsIOS()

Android Methodsโ€‹

deepLinkToSubscriptionsAndroid()โ€‹

Deep link to subscription management.

Future<void> deepLinkToSubscriptionsAndroid({String? sku})

๐ŸŽง Event Streamsโ€‹

purchaseUpdatedโ€‹

Stream of purchase updates.

Stream<Purchase?> get purchaseUpdated

Example:

late StreamSubscription _purchaseSubscription;


void initState() {
super.initState();
_purchaseSubscription = FlutterInappPurchase.purchaseUpdated.listen(
(purchase) async {
if (purchase != null) {
// Handle successful purchase
await handlePurchase(purchase);
}
},
);
}


void dispose() {
_purchaseSubscription.cancel();
super.dispose();
}

purchaseErrorโ€‹

Stream of purchase errors.

Stream<PurchaseResult?> get purchaseError

Example:

FlutterInappPurchase.purchaseError.listen((error) {
if (error != null) {
print('Purchase error: ${error.message}');

// Handle specific error codes
if (error.code == ErrorCode.UserCancelled) {
// User cancelled - no action needed
} else if (error.code == ErrorCode.NetworkError) {
// Show retry option
showRetryDialog();
}
}
});

๐Ÿ” Error Handlingโ€‹

Common error codes you should handle:

Error CodeDescriptionAction
ErrorCode.UserCancelledUser cancelled purchaseNo action needed
ErrorCode.NetworkErrorNetwork errorOffer retry
ErrorCode.ItemUnavailableProduct not availableCheck product setup
ErrorCode.AlreadyOwnedUser already owns productRestore or acknowledge
ErrorCode.DeveloperErrorConfiguration errorCheck setup

Example Error Handling:

FlutterInappPurchase.purchaseError.listen((error) {
if (error == null) return;

switch (error.code) {
case ErrorCode.UserCancelled:
// User cancelled - no UI needed
break;
case ErrorCode.NetworkError:
showSnackBar('Network error. Please check your connection and try again.');
break;
case ErrorCode.ItemUnavailable:
showSnackBar('This item is currently unavailable.');
break;
case ErrorCode.AlreadyOwned:
showSnackBar('You already own this item.');
break;
default:
showSnackBar('Purchase failed: ${error.message}');
}
});

๐ŸŽฏ Best Practicesโ€‹

  1. Always initialize connection before making purchases
  2. Handle all error cases appropriately
  3. Verify purchases server-side before granting content
  4. Complete transactions after verification
  5. Clean up streams in dispose methods
  6. Test thoroughly on both platforms