This repository was archived by the owner on Apr 26, 2026. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 692
feat: sync with openiap v1.3.14 (billing library 8.0+ features) #3127
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
ad502c1
feat: sync with openiap v1.3.14 (billing library 8.0+ features)
hyochan f986692
fix(android): respect includeSuspended when type is specified
hyochan 2984378
fix(android): revert getAvailablePurchases change due to API limitation
hyochan 9d2a2d8
docs: update version 14.8.0 to 14.7.3 in blog and llms.txt
hyochan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
141 changes: 141 additions & 0 deletions
141
docs/blog/2026-01-19-release-14.7.3-billing-library-8.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| --- | ||
| slug: release-14.7.3-billing-library-8 | ||
| title: 14.7.3 - Google Play Billing Library 8.0+ Features | ||
| authors: [hyochan] | ||
| tags: [release, openiap, android, ios, billing-library-8] | ||
| description: React Native IAP 14.7.3 adds support for Google Play Billing Library 8.0+ features including product status codes, suspended subscription handling, and iOS WWDC 2025 promotional offer improvements. | ||
| date: 2026-01-19 | ||
| --- | ||
|
|
||
| # React Native IAP 14.7.3 | ||
|
|
||
| 14.7.3 syncs with [OpenIAP v1.3.14](https://www.openiap.dev/docs/updates/notes#1314) bringing Google Play Billing Library 8.0+ features and iOS WWDC 2025 enhancements. | ||
|
|
||
| <!-- truncate --> | ||
|
|
||
| ## New Features | ||
|
|
||
| ### Product Status (Android 8.0+) | ||
|
|
||
| Products now include a `productStatusAndroid` field indicating fetch results: | ||
|
|
||
| ```typescript | ||
| const products = await fetchProducts(['com.example.premium']); | ||
|
|
||
| products.forEach(product => { | ||
| switch (product.productStatusAndroid) { | ||
| case 'ok': | ||
| // Product fetched successfully | ||
| break; | ||
| case 'not-found': | ||
| // SKU doesn't exist in Play Console | ||
| break; | ||
| case 'no-offers-available': | ||
| // User not eligible for any offers | ||
| break; | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| Prior to Billing Library 8.0, products that couldn't be fetched were simply omitted. Now you can understand why a product wasn't available. | ||
|
|
||
| ### Suspended Subscriptions (Android 8.1+) | ||
|
|
||
| New `includeSuspended` option in `getAvailablePurchases`: | ||
|
|
||
| ```typescript | ||
| // Include suspended subscriptions in results | ||
| const purchases = await getAvailablePurchases({ | ||
| android: { | ||
| includeSuspended: true, | ||
| }, | ||
| }); | ||
|
|
||
| purchases.forEach(purchase => { | ||
| if (purchase.isSuspendedAndroid) { | ||
| // Subscription is suspended due to payment issues | ||
| // DO NOT grant entitlements | ||
| // Direct user to subscription management | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| Suspended subscriptions have `isSuspendedAndroid: true` and should NOT be granted entitlements. Users should be directed to the subscription center to resolve payment issues. | ||
|
|
||
| ### Win-Back Offers (iOS 18+) | ||
|
|
||
| New support for win-back offers to re-engage churned subscribers: | ||
|
|
||
| ```typescript | ||
| import { requestSubscription } from 'react-native-iap'; | ||
|
|
||
| await requestSubscription({ | ||
| ios: { | ||
| sku: 'com.example.premium_monthly', | ||
| winBackOffer: { | ||
| offerId: 'win_back_50_percent', | ||
| }, | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| ### JWS Promotional Offers (iOS 15+, WWDC 2025) | ||
|
|
||
| New simplified JWS format for promotional offers, back-deployed to iOS 15: | ||
|
|
||
| ```typescript | ||
| await requestSubscription({ | ||
| ios: { | ||
| sku: 'com.example.premium_monthly', | ||
| promotionalOfferJWS: { | ||
| jws: 'eyJ...your-server-signed-jws...', | ||
| offerId: 'promo_summer_2025', | ||
| }, | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| ### Introductory Offer Eligibility Override (iOS 15+) | ||
|
|
||
| Override system-determined eligibility for introductory offers: | ||
|
|
||
| ```typescript | ||
| await requestSubscription({ | ||
| ios: { | ||
| sku: 'com.example.premium_monthly', | ||
| introductoryOfferEligibility: true, // Force eligibility | ||
| }, | ||
| }); | ||
| ``` | ||
|
|
||
| ### Sub-Response Codes (Android 8.0+) | ||
|
|
||
| More granular error information via `SubResponseCodeAndroid`: | ||
|
|
||
| - `payment-declined-due-to-insufficient-funds` - Payment method has insufficient funds | ||
| - `user-ineligible` - User not eligible for the offer | ||
| - `no-applicable-sub-response-code` - No additional context available | ||
|
|
||
| ## Type Updates | ||
|
|
||
| - `SubscriptionOfferTypeIOS` now includes `'win-back'` variant | ||
| - `RequestPurchaseIosProps.withOffer` clarified: only applies to subscriptions | ||
| - `BillingResultAndroid` now includes optional `subResponseCode` | ||
|
|
||
| ## OpenIAP Versions | ||
|
|
||
| | Package | Version | | ||
| |---------|---------| | ||
| | openiap-gql | 1.3.14 | | ||
| | openiap-google | 1.3.25 | | ||
| | openiap-apple | 1.3.12 | | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| npm install react-native-iap react-native-nitro-modules | ||
| ``` | ||
|
|
||
| For detailed changes, see the [OpenIAP Release Notes](https://www.openiap.dev/docs/updates/notes#1314). | ||
|
|
||
| Questions or feedback? [GitHub issues](https://github.com/hyochan/react-native-iap/issues). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
includeSuspendedoption will be ignored when atypeis specified (e.g., 'subs' or 'inapp') becauseopenIap.getAvailableItems(typeEnum)is called, which doesn't seem to accept thepurchaseOptionsthat contain theincludeSuspendedflag. This will lead to inconsistent behavior where suspended purchases are only included when fetching all purchase types.To fix this, you should use
openIap.getAvailablePurchases(purchaseOptions)in both branches of the conditional and then filter the results by type if atypeis provided. This ensures theincludeSuspendedoption is always respected.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in
f986692.Changes:
openIap.getAvailablePurchases(purchaseOptions)to ensureincludeSuspendedis respectedThanks for catching this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: Reverted in
2984378.After investigation, the suggested fix doesn't work due to OpenIAP API limitations:
getAvailableItems(type)doesn't acceptPurchaseOptionsparameterPurchaseobjects don't have atypeproperty for filteringThe
includeSuspendedoption can only work when fetching all purchase types (without type filter). This is a limitation of the upstream OpenIAP library that would need to be addressed there.Added a comment in the code to clarify this limitation.