Google Play Billing 8.3 Features
Plugin v13.13.0 upgraded to Google Play Billing Library 8.3.0. This brings several new behaviors and capabilities for Android in-app purchases.
Requirement: minSdkVersion 23 or higher (Android 6.0+).
One-Time Product Offers
Google Play now supports multiple offers for one-time (INAPP) products, similar to how subscriptions have base plans and offers. This is called the "v12.0 format" in Google's documentation.
When a one-time product has multiple offers, each offer has its own pricing and offer token:
const product = store.get('premium_upgrade');
// The product may have multiple offers
if (product) {
product.offers.forEach(offer => {
console.log('Offer: ' + offer.id);
offer.pricingPhases.forEach(phase => {
console.log(' Price: ' + phase.price + ' (' + phase.currency + ')');
});
});
}
To purchase a specific offer:
// Get a specific offer by ID, or the default one
const offer = product.getOffer('special-offer-id') || product.getOffer();
if (offer) {
await store.order(offer);
}
Note: If you previously relied on a single price for one-time products, your code continues to work unchanged. The plugin resolves the first available offer with pricing data when using product.getOffer() without an argument.
Suspended Subscriptions
Previously, Google Play did not return suspended subscriptions (paused or payment on hold) in the purchases list. Starting with Billing Library 8.3, suspended subscriptions are now included, aligning Google Play's behavior with Apple's App Store.
How it works
- Suspended subscriptions appear in the purchases list with an
expirationDatein the past product.ownedcorrectly returnsfalsefor expired/suspended subscriptions- No code changes are needed — the existing expiration date check handles this automatically
What this means for your app
store.when().verified(receipt => {
receipt.collection.forEach(purchase => {
if (purchase.id === 'premium_sub') {
if (purchase.expiryDate && purchase.expiryDate < Date.now()) {
// Subscription is expired or suspended
lockPremiumContent();
} else {
// Subscription is active
unlockPremiumContent();
}
}
});
receipt.finish();
});
If you already handle expiration dates correctly, suspended subscriptions are handled automatically.
Pending Purchases
Billing Library 8.3 enables pending purchases for both one-time products and prepaid subscription plans. A pending purchase occurs when the user chooses a delayed payment method (e.g., cash payment at a convenience store in certain markets).
Handling pending transactions
Pending purchases go through the INITIATED state before reaching APPROVED:
store.when()
.initiated(transaction => {
// Payment is pending — inform the user
showStatus('Your purchase is pending. You will get access once payment completes.');
})
.approved(transaction => {
// Payment completed — proceed with validation
transaction.verify();
})
.verified(receipt => {
receipt.finish();
});
Important notes
- Do not grant access to content while a purchase is in the
INITIATED/pending state - The purchase transitions to
APPROVEDonce the payment is confirmed by Google - Pending purchases can also be cancelled by the user or expire
Auto Service Reconnection
The plugin now enables automatic reconnection of the Google Play Billing client. If the connection to Google Play Services drops (e.g., due to a service update or network interruption), the client automatically reconnects without requiring manual intervention.
This is handled internally and requires no code changes.
Migration Notes
If you are upgrading from a plugin version prior to v13.13.0:
- Ensure your
minSdkVersionis 23 or higher in yourconfig.xmlorbuild.gradle - Test with Google Play's test tracks to verify suspended subscription handling
- If you use one-time products, test that pricing and offers resolve correctly
- No API changes are required — the upgrade is backward compatible at the JavaScript level