v3.4.3 - Win-Back Offers & Advanced Billing Features
This release syncs with OpenIAP v1.3.14, introducing iOS 18+ win-back offers, JWS promotional offers, Android 8.0+ product status codes, and important type cleanup.
New Features
Win-Back Offers (iOS 18+)
Win-back offers allow you to re-engage churned subscribers with special discounts or free trials.
import {requestPurchase} from 'expo-iap';
// Apply a win-back offer during subscription purchase
await requestPurchase({
request: {
apple: {
sku: 'premium_monthly',
winBackOffer: {
offerId: 'winback_50_off', // iOS 18+
},
},
},
type: 'subs',
});
Win-back offers are automatically presented via StoreKit Message when eligible, or can be applied programmatically.
JWS Promotional Offers (iOS 15+)
A new simplified format for promotional offers using compact JWS strings, back-deployed to iOS 15.
await requestPurchase({
request: {
apple: {
sku: 'premium_yearly',
promotionalOfferJWS: {
offerId: 'promo_20_off',
jws: 'eyJhbGciOiJFUzI1NiI...', // Server-signed JWS
},
},
},
type: 'subs',
});
Introductory Offer Eligibility Override (iOS 15+)
Override system-determined introductory offer eligibility.
await requestPurchase({
request: {
apple: {
sku: 'premium_monthly',
introductoryOfferEligibility: true, // Force eligible
},
},
type: 'subs',
});
Product Status Codes (Android 8.0+)
Get detailed feedback on why products couldn't be fetched.
import {fetchProducts} from 'expo-iap';
import type {ProductAndroid} from 'expo-iap';
const result = await fetchProducts({
skus: ['product_1', 'product_2'],
type: 'in-app',
});
result.forEach((product) => {
const androidProduct = product as ProductAndroid;
if (androidProduct.productStatusAndroid) {
switch (androidProduct.productStatusAndroid) {
case 'ok':
// Product available
break;
case 'not-found':
// SKU doesn't exist in Play Console
break;
case 'no-offers-available':
// User not eligible for any offers
break;
}
}
});
Suspended Subscriptions Support (Android 8.1+)
Include suspended subscriptions when fetching available purchases. This feature required native code updates to pass the option through to the OpenIAP SDK.
import {getAvailablePurchases} from 'expo-iap';
const purchases = await getAvailablePurchases({
includeSuspendedAndroid: true, // Include suspended subs
});
// Check if subscription is suspended
purchases.forEach((purchase) => {
if (purchase.isSuspendedAndroid) {
// Direct user to resolve payment issues
// Do NOT grant entitlements for suspended subscriptions
}
});
Important: Suspended subscriptions should NOT be granted entitlements. Users should be directed to the Play Store subscription center to resolve payment issues.
Sub-Response Codes (Android 8.0+)
More granular error information for purchase failures.
// SubResponseCodeAndroid provides additional context:
// - 'no-applicable-sub-response-code'
// - 'payment-declined-due-to-insufficient-funds'
// - 'user-ineligible'
Type Cleanup
Subscription-Only Fields Removed from RequestPurchaseIosProps
The following fields have been removed from RequestPurchaseIosProps because they only apply to subscription purchases:
winBackOffer- Win-back offers are subscription-only (iOS 18+)promotionalOfferJWS- JWS promotional offers are subscription-onlyintroductoryOfferEligibility- Introductory eligibility is subscription-only
These fields remain available in RequestSubscriptionIosProps where they belong.
Migration: If you were incorrectly using these fields with one-time purchases, move them to subscription purchases with type: 'subs'.
New Types
| Type | Platform | Description |
|---|---|---|
WinBackOfferInputIOS | iOS 18+ | Win-back offer configuration |
PromotionalOfferJwsInputIOS | iOS 15+ | JWS promotional offer input |
ProductStatusAndroid | Android 8.0+ | Product fetch status codes |
SubResponseCodeAndroid | Android 8.0+ | Granular purchase error codes |
BillingResultAndroid | Android 8.0+ | Extended billing result with sub-response |
Updated Types
SubscriptionOfferTypeIOSnow includes'win-back'typeRequestSubscriptionIosPropsnow supports:winBackOfferpromotionalOfferJWSintroductoryOfferEligibilitywithOffer(promotional offer)
PurchaseOptionsnow supportsincludeSuspendedAndroidProductAndroidandProductSubscriptionAndroidnow includeproductStatusAndroid
OpenIAP Versions
| Package | Version |
|---|---|
| openiap-gql | 1.3.14 |
| openiap-google | 1.3.25 |
| openiap-apple | 1.3.13 |
For detailed changes, see the OpenIAP Release Notes.
