Skip to main content

8.2.3 - One-Time Purchase Discounts and Simplified Field Names

· 2 min read
Hyo
Maintainer of flutter_inapp_purchase & expo-iap

v8.2.3 syncs with OpenIAP v1.3.15 introducing one-time purchase discount support for Android 7.0+ and simplified input field naming conventions.

New Features

One-Time Purchase Discounts (Android 7.0+)

Apply discount offers to one-time (non-subscription) purchases using the new offerToken field:

// Fetch products and get available discount offers
final products = await iap.fetchProducts(
skus: ['premium_unlock'],
type: ProductQueryType.InApp,
);

final product = products.firstWhere((p) => p.id == 'premium_unlock');

// Check for available discount offers
if (product is ProductAndroid) {
final discountOffer = product.oneTimePurchaseOfferDetailsAndroid
?.discountOffers
?.firstOrNull;

if (discountOffer != null) {
// Purchase with discount applied
await iap.requestPurchase(
RequestPurchaseProps.inApp((
apple: RequestPurchaseIosProps(sku: 'premium_unlock'),
google: RequestPurchaseAndroidProps(
skus: ['premium_unlock'],
offerToken: discountOffer.offerToken, // Apply discount
),
useAlternativeBilling: null,
)),
);
}
}

Simplified Input Field Names

Input field names for Android-specific request props have been simplified by removing redundant Android suffixes. This follows the OpenIAP naming convention where input types inside platform-specific props don't need platform suffixes (they're already scoped to Android).

Migration Guide:

// Before (8.2.2 and earlier)
RequestPurchaseAndroidProps(
skus: ['sku'],
obfuscatedAccountIdAndroid: 'account-123',
obfuscatedProfileIdAndroid: 'profile-456',
);

RequestSubscriptionAndroidProps(
skus: ['sub'],
purchaseTokenAndroid: 'token',
replacementModeAndroid: 1,
obfuscatedAccountIdAndroid: 'account-123',
obfuscatedProfileIdAndroid: 'profile-456',
);

// After (8.2.3+)
RequestPurchaseAndroidProps(
skus: ['sku'],
obfuscatedAccountId: 'account-123',
obfuscatedProfileId: 'profile-456',
offerToken: 'discount-token', // NEW: for one-time purchase discounts
);

RequestSubscriptionAndroidProps(
skus: ['sub'],
purchaseToken: 'token',
replacementMode: 1,
obfuscatedAccountId: 'account-123',
obfuscatedProfileId: 'profile-456',
);

Builder Updates:

// Before
final builder = RequestPurchaseAndroidBuilder()
..skus = ['sku']
..obfuscatedAccountIdAndroid = 'account-123'
..obfuscatedProfileIdAndroid = 'profile-456';

// After
final builder = RequestPurchaseAndroidBuilder()
..skus = ['sku']
..obfuscatedAccountId = 'account-123'
..obfuscatedProfileId = 'profile-456'
..offerToken = 'discount-token';

Field Changes Summary

RequestPurchaseAndroidProps

Old NameNew Name
obfuscatedAccountIdAndroidobfuscatedAccountId
obfuscatedProfileIdAndroidobfuscatedProfileId
-offerToken (NEW)

RequestSubscriptionAndroidProps

Old NameNew Name
obfuscatedAccountIdAndroidobfuscatedAccountId
obfuscatedProfileIdAndroidobfuscatedProfileId
purchaseTokenAndroidpurchaseToken
replacementModeAndroidreplacementMode

Dependencies

PackagePreviousCurrent
openiap-gql1.3.141.3.15
openiap-google1.3.251.3.26
openiap-apple1.3.121.3.13

References