8.2.3 - One-Time Purchase Discounts and Simplified Field Names
· 2 min read
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 Name | New Name |
|---|---|
obfuscatedAccountIdAndroid | obfuscatedAccountId |
obfuscatedProfileIdAndroid | obfuscatedProfileId |
| - | offerToken (NEW) |
RequestSubscriptionAndroidProps
| Old Name | New Name |
|---|---|
obfuscatedAccountIdAndroid | obfuscatedAccountId |
obfuscatedProfileIdAndroid | obfuscatedProfileId |
purchaseTokenAndroid | purchaseToken |
replacementModeAndroid | replacementMode |
Dependencies
| Package | Previous | Current |
|---|---|---|
| openiap-gql | 1.3.14 | 1.3.15 |
| openiap-google | 1.3.25 | 1.3.26 |
| openiap-apple | 1.3.12 | 1.3.13 |
