Skip to main content
Version: 8.0

Migration from v7

IapKit - Fraud-proof your in-app purchases

This guide helps you migrate from flutter_inapp_purchase v7.x to v8.0.

Breaking Changes

oneTimePurchaseOfferDetailsAndroid is now an array

The most significant breaking change is that oneTimePurchaseOfferDetailsAndroid changed from a single object to an array. This was necessary to support multiple discount offers per product (Google Play Billing 7.0+).

Before (v7.x):

final price = product.oneTimePurchaseOfferDetailsAndroid?.formattedPrice;

After (v8.x):

final offers = product.oneTimePurchaseOfferDetailsAndroid;
final price = offers?.isNotEmpty == true ? offers![0].formattedPrice : null;

// Or iterate through all offers
for (final offer in offers ?? []) {
print('Offer: ${offer.offerId ?? "default"}');
print('Price: ${offer.formattedPrice}');

// Check for discount info
if (offer.discountDisplayInfo != null) {
print('Discount: ${offer.discountDisplayInfo!.percentageDiscount}% off');
}
}

verifyPurchase API changed

The verification APIs now use platform-specific options objects instead of the deprecated sku and androidOptions parameters.

Before (v7.x):

// iOS
final result = await iap.verifyPurchase(sku: 'product_id');

// Android
final result = await iap.verifyPurchase(
sku: 'product_id',
androidOptions: VerifyPurchaseAndroidOptions(
accessToken: 'token',
packageName: 'com.your.app',
productToken: 'purchase_token',
),
);

After (v8.x):

// iOS - use apple options
final result = await iap.verifyPurchase(
apple: VerifyPurchaseAppleOptions(sku: 'product_id'),
);

// Android - use google options
final result = await iap.verifyPurchase(
google: VerifyPurchaseGoogleOptions(
sku: 'product_id',
accessToken: 'your-oauth-token', // From your backend
packageName: 'com.your.app',
purchaseToken: purchase.purchaseToken,
),
);

// Meta Horizon (Quest) - use horizon options
final result = await iap.verifyPurchase(
horizon: VerifyPurchaseHorizonOptions(
sku: 'product_id',
accessToken: 'your-meta-token',
userId: 'user_id',
),
);

Note: The same change applies to validateReceipt and validateReceiptIOS.

Deprecated APIs

Alternative Billing APIs

The Alternative Billing APIs are deprecated in favor of the new Billing Programs API:

DeprecatedReplacement
checkAlternativeBillingAvailabilityAndroid()isBillingProgramAvailableAndroid(BillingProgramAndroid.ExternalOffer)
showAlternativeBillingDialogAndroid()launchExternalLinkAndroid()
createAlternativeBillingTokenAndroid()createBillingProgramReportingDetailsAndroid(BillingProgramAndroid.ExternalOffer)

Before (v7.x):

final available = await iap.checkAlternativeBillingAvailabilityAndroid();
if (available) {
await iap.showAlternativeBillingDialogAndroid();
final token = await iap.createAlternativeBillingTokenAndroid();
}

After (v8.x):

final result = await iap.isBillingProgramAvailableAndroid(
BillingProgramAndroid.ExternalOffer,
);

if (result.isAvailable) {
await iap.launchExternalLinkAndroid(
LaunchExternalLinkParamsAndroid(
billingProgram: BillingProgramAndroid.ExternalOffer,
launchMode: ExternalLinkLaunchModeAndroid.LaunchInExternalBrowserOrApp,
linkType: ExternalLinkTypeAndroid.LinkToDigitalContentOffer,
linkUri: 'https://your-payment-site.com/purchase',
),
);

final details = await iap.createBillingProgramReportingDetailsAndroid(
BillingProgramAndroid.ExternalOffer,
);
// Use details.externalTransactionToken
}

New Features

Billing Programs API

The new Billing Programs API provides three methods:

  • isBillingProgramAvailableAndroid(program) - Check if a billing program is available
  • launchExternalLinkAndroid(params) - Launch external link for billing programs
  • createBillingProgramReportingDetailsAndroid(program) - Get external transaction token

See Billing Programs Guide for detailed usage.

One-Time Product Discount Fields

New fields are available in ProductAndroidOneTimePurchaseOfferDetail:

  • offerId - Unique offer identifier
  • fullPriceMicros - Full (non-discounted) price
  • discountDisplayInfo - Contains percentageDiscount and discountAmount
  • limitedQuantityInfo - Maximum and remaining quantity
  • validTimeWindow - Offer start and end times
  • offerTags - List of tags for the offer
  • offerToken - Token for purchase requests
  • preorderDetailsAndroid - Pre-order release dates (Android 8.0+)
  • rentalDetailsAndroid - Rental period info (Android 8.0+)

Purchase Suspension Status

Check if a subscription is suspended due to payment issues:

final purchases = await iap.getAvailablePurchases();

for (final purchase in purchases) {
if (purchase is PurchaseAndroid && purchase.isSuspendedAndroid == true) {
// Do NOT grant entitlements for suspended subscriptions
// Direct user to fix payment method
}
}

Dependencies Update

Update your pubspec.yaml:

dependencies:
flutter_inapp_purchase: ^8.0.0

The plugin automatically uses:

  • openiap-apple: 1.3.2
  • openiap-google: 1.3.14
  • openiap-gql: 1.3.4