In-App Purchases with Flutter: A Comprehensive Guide
Published on by Flutter News Hub
In-app purchases (IAPs) allow mobile app users to purchase digital goods or services within an app. The Flutter In-App Purchase plugin provides a unified, cross-platform interface for implementing IAPs in Flutter apps. This guide will walk you through the process of setting up and using the plugin to integrate IAPs into your app.
Prerequisites
- Flutter SDK 2.2+
- iOS 12.0+ (for App Store)
- Android SDK 16+ (for Google Play)
- Completed IAP setup in App Store and Google Play
Getting Started
-
Install the plugin:
dependencies: in_app_purchase: ^3.0.0
-
Import the plugin:
import 'package:in_app_purchase/in_app_purchase.dart';
-
Connect to the store:
InAppPurchase.instance.isAvailable(); // Check if the store is available
-
Load product details:
final Set ids = {'product1', 'product2'}; final ProductDetailsResponse response = await InAppPurchase.instance.queryProductDetails(ids); final List products = response.productDetails;
-
Start a purchase:
final ProductDetails productDetails = ...; if (productDetails.isConsumable) { InAppPurchase.instance.buyConsumable(purchaseParam: PurchaseParam(productDetails: productDetails)); } else { InAppPurchase.instance.buyNonConsumable(purchaseParam: PurchaseParam(productDetails: productDetails)); }
Handling Purchase Updates
Listen for purchase updates on the InAppPurchase.instance.purchaseStream
:
_subscription = InAppPurchase.instance.purchaseStream.listen((purchaseDetailsList) {
_listenToPurchaseUpdated(purchaseDetailsList);
}, onDone: () {
_subscription.cancel();
}, onError: (error) {
// Handle error
});
In the _listenToPurchaseUpdated
method:
void _listenToPurchaseUpdated(List purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) async {
if (purchaseDetails.status == PurchaseStatus.purchased || purchaseDetails.status == PurchaseStatus.restored) {
bool valid = await _verifyPurchase(purchaseDetails);
if (valid) {
_deliverProduct(purchaseDetails);
} else {
_handleInvalidPurchase(purchaseDetails);
}
}
if (purchaseDetails.pendingCompletePurchase) {
await InAppPurchase.instance.completePurchase(purchaseDetails);
}
});
}
Restoring Previous Purchases
InAppPurchase.instance.restorePurchases();
Platform-Specific Considerations
The plugin provides both cross-platform and platform-specific APIs:
-
Generic Flutter API (
in_app_purchase
): Use for most IAP use cases. -
Platform-specific Dart APIs (
store_kit_wrappers
,billing_client_wrappers
): Allow for finer control and access to platform-specific features (but require different purchase handling logic for different platforms).
Code Examples
Load and Purchase a Product:
// Get a specific product
final ProductDetails product = products.firstWhere((product) => product.id == 'my_product');
// Start the purchase
if (product.isConsumable) {
InAppPurchase.instance.buyConsumable(productDetails: product);
} else {
InAppPurchase.instance.buyNonConsumable(productDetails: product);
}
// Complete the purchase
_listenToPurchaseUpdated((purchaseDetailsList) {
purchaseDetailsList.forEach((PurchaseDetails purchaseDetails) {
if (purchaseDetails.id == productId && purchaseDetails.status == PurchaseStatus.purchased) {
InAppPurchase.instance.completePurchase(purchaseDetails);
}
});
});
Handle Purchase Verification:
Future _verifyPurchase(PurchaseDetails purchaseDetails) async {
// Validate receipt on server-side
final bool isValid = await server.validateReceipt(purchaseDetails.verificationData);
return isValid;
}
Access Platform-Specific Properties:
Android (Google Play):
if (purchaseDetails is GooglePlayPurchaseDetails) {
final BillingClientPurchase billingClientPurchase = purchaseDetails.billingClientPurchase;
// Access platform-specific properties, such as `originalJson`
}
iOS (App Store):
if (purchaseDetails is AppStorePurchaseDetails) {
final SKPaymentTransactionWrapper transaction = purchaseDetails.skPaymentTransaction;
// Access platform-specific properties, such as `transactionState`
}
Redeem Offer Codes (iOS 14+):
final InAppPurchaseStoreKitPlatformAddition platformAddition = InAppPurchase.getPlatformAddition();
platformAddition.presentCodeRedemptionSheet();
Conclusion
The Flutter In-App Purchase plugin simplifies the integration of IAPs into your Flutter apps. By following the steps and examples outlined in this guide, you can provide users with a seamless purchasing experience on both iOS and Android platforms.