Purchases
Complete guide to implementing in-app purchases with flutter_inapp_purchase v7.0.
Purchase Flow
- Initialize Connection - Connect to the store
- Setup Listeners - Handle purchase updates and errors
- Load Products - Fetch available products
- Request Purchase - Initiate purchase
- Deliver Content - Provide purchased content
- Finish Transaction - Complete the transaction
Initialize Connection
final iap = FlutterInappPurchase.instance;
await iap.initConnection();
Setup Purchase Listeners
StreamSubscription<Purchase>? _purchaseUpdatedSubscription;
StreamSubscription<PurchaseError>? _purchaseErrorSubscription;
void setupListeners() {
_purchaseUpdatedSubscription = iap.purchaseUpdatedListener.listen(
(purchase) {
debugPrint('Purchase received: ${purchase.productId}');
_handlePurchase(purchase);
},
);
_purchaseErrorSubscription = iap.purchaseErrorListener.listen(
(error) {
debugPrint('Purchase error: ${error.message}');
_handleError(error);
},
);
}
void dispose() {
_purchaseUpdatedSubscription?.cancel();
_purchaseErrorSubscription?.cancel();
super.dispose();
}
Load Products
final products = await iap.fetchProducts(
skus: ['product_id_1', 'product_id_2'],
type: ProductQueryType.inApp,
);
for (final product in products) {
print('${product.title}: ${product.displayPrice}');
}
Request Purchase
await iap.requestPurchase(
sku: 'product_id',
obfuscatedAccountIdAndroid: userId,
obfuscatedProfileIdAndroid: profileId,
);
Handle Purchase
Future<void> _handlePurchase(Purchase purchase) async {
// 1. Validate purchase on your server (required for production)
final isValid = await verifyPurchaseOnServer(purchase);
if (!isValid) return;
// 2. Deliver content to user
await deliverContent(purchase.productId);
// 3. Finish transaction
await iap.finishTransaction(
purchase: purchase,
isConsumable: true, // or false for non-consumables/subscriptions
);
}
Product Types
Consumable Products
Products that can be purchased multiple times (coins, gems):
await iap.finishTransaction(
purchase: purchase,
isConsumable: true, // Consumes on Android, finishes on iOS
);
Non-Consumable Products
One-time purchases (premium features, ad removal):
await iap.finishTransaction(
purchase: purchase,
isConsumable: false, // Acknowledges on Android, finishes on iOS
);
Subscriptions
Recurring purchases - see Subscription Offers
Restore Purchases
// Restore previous purchases
await iap.restorePurchases();
// Get available purchases
final purchases = await iap.getAvailablePurchases();
for (final purchase in purchases) {
await deliverContent(purchase.productId);
}
Best Practices
- Always set up listeners first before making purchase requests
- Validate purchases server-side for security
- Use correct
isConsumable
flag - it handles consume/acknowledge automatically - Handle errors gracefully - see Error Handling
- Test thoroughly in sandbox environments
Complete Example
See working implementations in Examples.
Next Steps
- Purchase Lifecycle - Understand the full lifecycle
- Subscription Offers - Handle subscriptions
- Error Handling - Handle purchase errors