If you work with in-app purchases on Android, sooner or later you'll have to deal with the Google Play Billing Library v7It's not just another update: it comes with API changes, new subscription features, console requirements, and very clear deadlines from Google. Ignoring it is no longer an option if you want to continue publishing or updating your app on Google Play without any surprises.
Throughout this article you will see how Update and implement the Google Play Billing Library v7 Step by step: from what's different from PBL 5 and 6, to how to integrate subscriptions, one-time purchases, RTDN, testing with Play Billing Lab, and how to survive in ecosystems like .NET MAUI where official support lags behind. The idea is that, when you finish reading, you can prepare your migration with confidence and without spending a penny.
Overview of Google Play Billing Library v7
The Google Play Billing Library 7 introduces significant improvements in how bills are managed Payments, subscriptions, and special plansHowever, it's designed to make the migration relatively smooth. The good news is that many of the new APIs are optional: you can update the dependency, tweak a few references, and your basic integration will still work.
This version focuses on three key areas: new subscription options (such as virtual quotas), better support for pending purchases on prepaid plansand API changes that clean up what was already obsolete in previous versions (PBL 5 and 6). Additionally, Google adjusts some error handling and how you should handle pending transactions to avoid inconsistencies.
To begin, in your app module you need to update the dependency in your file build.gradle:
dependencies {
def billingVersion = "7.0.0"
implementation "com.android.billingclient:billing:$billingVersion"
}
Once this is done, it's time to review the code that uses legacy APIs. Many calls related to subscription proration and alternative billing They have been renamed or removed, so it's a good idea to take a good look at all references to BillingClient and BillingFlowParams before compiling and uploading anything to the Play Console.
Monetization strategies with one-time purchases and subscriptions
When you sell digital products within your app, simply pasting the purchase dialog and calling it a day isn't enough: designing a seamless user experience throughout the entire purchase cycleThis applies to both single products (consumable or non-consumable) and subscriptions. The more natural and frictionless the process, the higher the conversions and the lower the cancellation rate.
A typical purchase flow with Play Billing, whether for a subscription or a single item, usually follows these well-defined stages that your backend should also be aware of:
- The user explores the available products and selects one.
- The app initiates the Google Play billing process to complete the payment.
- The purchase is completed and your app receives the result.
- Your server validates the purchase against the Google Play Developer API.
- The corresponding content or right is granted to the user in your system.
- Google is informed that the purchase has been processed (consumed or acknowledged).
In the case of consumable products, it is vital that consume the token at the right time to allow seamless repurchases and help Block accidental purchases on Google PlayIn subscriptions, you must control renewals, grace periods, suspensions, and cancellations so that the user receives exactly what they have paid for and not a day less.
Integration into the app is only half the job: your server must maintain a reliable record of rights and purchase statusesThis is especially important if you offer cross-platform access or need detailed statistics on revenue, retention, and churn. This is where real-time developer notifications (RTDNs) come in, acting as the "black box" of the purchase lifecycle.
With RTDN you can react in near real-time to critical events: a new purchase, a renewal failure, a subscription entering its grace period, or a canceled purchase. This allows you to develop strategies for subscriber recovery and fraud prevention, such as automatic email sending when a payment fails or rights adjustments if the customer does not receive the message due to network problems.
Real-time developer notifications (RTDN) and Google Cloud Pub/Sub
RTDNs use Google Cloud Pub / Sub as a real-time messaging system between Google Play and your backend. Google Play publishes events about a Pub/Sub topic, and you subscribe to that topic to receive messages whenever the status of a purchase or subscription changes.
The basic flow is simple: Google Play sends a base64-encoded message to the Pub/Sub topic, your subscriber extracts it, decodes it, and processes the notification. Within the field data Within the message you will find a JSON object DeveloperNotificationwhich includes information such as message version, package name, event time, and specific data on one-time purchases, subscriptions, canceled purchases, or trials.
{
"version": string,
"packageName": string,
"eventTimeMillis": long,
"oneTimeProductNotification": OneTimeProductNotification,
"subscriptionNotification": SubscriptionNotification,
"voidedPurchaseNotification": VoidedPurchaseNotification,
"testNotification": TestNotification
}
Thanks to these messages you can Keep your backend synchronized even if the user's device failsImagine a user successfully makes a purchase, Google Play confirms it, but the mobile device loses connection before your app receives the callback from the Billing Library. Without RTDN, you might never know. With Pub/Sub, your server receives a separate notification and can grant the entitlement independently of the client.
Cloud Pub/Sub configuration for RTDN
Before activating RTDN in the Google Play console, you need to prepare a project in Google Cloud Platform (GCP) and configure Pub/Sub there. The process is relatively straightforward, but it's best to follow it carefully to avoid any surprises with permissions or resource names.
Creating the topic
First you must create a Pub/Sub topic which will act as your Google Play publishing point. From the Google Cloud console, select your project, go to the Pub/Sub section, and create a new topic following the official "create topic" guide. The result will have a name in the following format:
projects/{project_id}/topics/{topic_name}
That full name is the one you'll have to paste into the Play Console when you activate notifications.
Subscription creation
To read the messages in this thread, you need a Pub/Sub subscriptionYou can configure it as push or as pullIn the reference codelab, we work with pull subscription, where your backend initiates the requests to retrieve messages.
You should review the options in the Cloud Pub/Sub subscriber guide to decide whether push or pull is a better fit for your architecture. Once you've decided, follow the "add subscription" documentation and link it to the topic you created earlier. From that point on, any messages that Google Play publishes in the topic will be accessible to your subscriber.
Permissions for Google Play to publish to your theme
Pub/Sub will not allow Google Play to publish anything unless you give it explicit permission. service accountIn the Google Cloud console, you need to go to the topic permissions settings and add the main one:
google-play-developer-notifications@system.gserviceaccount.com
Grant this account the role of Pub/Sub publisher (Publisher). Save the changes and from that moment on, Google Play will be able to send RTDNs to your theme without authorization problems.
Activate RTDN in Google Play Console

Once Pub/Sub is configured, you need to tell Play Console where to send notifications. Within your app in Google Play Console, go to Monetize with Play > Monetization Settings and locate the real-time developer notifications section.
There you will need to:
- Check the box to enable real-time notifications.
- Enter the full Pub/Sub topic name in the corresponding field, respecting the format
projects/{project_id}/topics/{topic_name}. - Send a test message using the test button.
The test message is essential to verify that the The integration is well implemented.If you have a pull subscription, you can go to the Cloud console, select the subscription, click "View messages," and extract the test message. Don't forget to do ack of any message you read to avoid repeated receptions.
For push subscriptions, verify that your endpoint receives the message and responds with a valid HTTP code. If something goes wrong, the console will display an error when publishing the test, usually related to the topic name or service account permissions.
Finally, you can configure which types of notifications you want to receive: only subscriptions and canceled purchases, or all notifications including one-time purchases (events such as ONE_TIME_PRODUCT_PURCHASED and ONE_TIME_PRODUCT_CANCELED). If you also use unique products, it's common practice to activate the entire set to maintain visibility on everything.
Build a Pub/Sub subscriber in your backend
With the theme and subscription ready, it's time to implement a subscriber who reads and processes RTDNsGoogle provides examples in several languages; a typical case in Java uses the Cloud Pub/Sub client libraries to start a Subscriber who listens to messages and calls a MessageReceiver.
The general pattern is always the same: you retrieve the message, you decode the field data You convert base64 to text, parse the JSON, and extract the relevant fields (such as packageName, oneTimeProductNotification o subscriptionNotification) and decide what to do in your system. After successfully processing the notification, you must Confirm the message with an ack so that Pub/Sub doesn't send it again.
The example code shows how the receiver prints the version and package name, but in a real implementation you would go further: You would validate the purchase, granting the right to the correct userYou would update your database and, if necessary, call the Play Developer API to consume or recognize the purchase.
Link notifications to the user: using obfuscatedAccountId
A common problem when managing purchases from the server is knowing which user a specific RTDN notification belongs to. For this, the Billing Client API allows you to attach a obfuscated account identifier when you launch the purchase flow: obfuscatedAccountId.
The idea is that you use a stable identifier from your system (for example, the user's internal ID) but obfuscated for privacy and security reasonsThis value is associated with the purchase and then appears in the information returned from the Google Play Developer API, so that when you receive the RTDN and verify the token, you will know unequivocally which account in your database you should grant the right to.
On the customer side, when preparing the BillingFlowParamsYou just need to build the list of ProductDetailsParams and call setObfuscatedAccountId(obfuscatedAccountId) before launching the flow. That doesn't change the visible user experience, but it greatly simplifies the process. backend purchase allocation logic and helps Google detect fraud.
Verify purchases using the Google Play Developer API
Before granting any rights on your server, it is mandatory to verify that the purchase is legitimate by calling the Google Play Developer APIIt's not enough to rely on what the client or even the RTDN says: you must validate the purchaseToken directly against the official endpoints, and if necessary manage refunds.
In the case of unique products, you will use the endpoint purchases.products:getFor subscriptions, the path leads through purchases.subscriptionsv2:getThe recommended flow is:
- Extract the
purchaseTokenfrom the Pub/Sub message. - Check your database to see if you've already processed it; each token is globally uniqueSo it's perfect as a primary key to avoid duplicates.
- If it's new, call the Google Play Developer API with the package, SKU, and the
purchaseToken. - Verify that the response indicates a purchase status PURCHASED (not PENDING or cancelled).
- If everything matches up, register the token and grant the corresponding right to the associated user.
To communicate with the Play Developer API from Java you can use AndroidPublisher, initialized with service account credentials in JSON format. You configure the scope AndroidPublisherScopes.ANDROIDPUBLISHERYou build the client and call the method purchases().products().get(...)If the call fails due to a temporary network or service problem, it is recommended implement retries with exponential backoff so as not to miss the event.
Confirm or complete the purchase from the server
Once you've verified the purchase and granted the authorization in your system, the next step is to notify Google that the transaction has been processed successfully. For single-item products, you have two options: consume the purchase or simply recognize her.
Consumable products (e.g., virtual currency, lives, etc.) must pass through the endpoint purchases.products:consumeThis marks the token as used and allows the user to repurchase the same item without conflict. For non-consumable products (such as unlocking the premium version for life), you must call purchases.products:acknowledge, which informs Google that the user already has the associated right.
Subscriptions are used purchases.subscriptions:acknowledgeindicating that the subscription has been successfully processed and assigned to the user. If you don't acknowledge a purchase within a reasonable timeframe, Google may assume there's a problem and reverse the transaction, so it's important that you back is done right after granting the right.
In your AndroidPublisher helper you can add methods like executeProductPurchasesConsume y executeProductPurchasesAcknowledge that call the corresponding endpoints. Again, it's advisable to implement retries in case of occasional failures, to ensure that no token remains in a dangerous intermediate state.
Advanced testing with Play Billing Lab
One aspect that many developers underestimate is the testing phase. To launch with any degree of confidence, you need to be able to simulate network errors, non-standard responses, and edge casesThat's where Play Billing Lab comes in, a free app on Google Play designed specifically for testing Play Billing Library integrations.
Play Billing Lab includes a answer simulator which allows for forcing different BillingResponseCode in your app's calls to the Billing Library. This way, you can recreate scenarios where, for example, the customer is unable to complete the purchase due to a network issue, but your backend correctly processes the RTDN and ultimately grants the entitlement without user intervention.
In order for your app to communicate with the simulator, you need to enable "billing overrides" testing using metadata in the AndroidManifest.xml:
<manifest ... >
<application ... >
...
<meta-data
android:name="com.google.android.play.largest_release_audience.NONPRODUCTION"
android:value="" />
<meta-data
android:name="com.google.android.play.billingclient.enableBillingOverridesTesting"
android:value="true" />
</application>
</manifest>
The label enableBillingOverridesTesting Activate the simulated response tests in the Billing Library. The NONPRODUCTION tag is a kind of reminder that this build shouldn't go into production with the overrides active. When preparing the final version for users, make sure to Remove this metadata or use a separate manifest.
Once configured, from the Play Billing Lab app, log in with a license tester account, activate the "Simulate Play Billing Library response" option, and select which error codes you want to return for each API (for example, a specific error in consumeAsyncThen you simply open your app and run the flow you want to test: the simulator will return the configured responses and you can verify that your retry logic, error handling and RTDN behave as expected.
Key API changes when migrating to Play Billing Library 7
Beyond RTDN and testing, migrating to PBL 7 involves addressing some specific API points. For those coming from PBL 5 or 6, it's worth reviewing the most relevant changes to ensure the project compiles smoothly and the business logic remains consistent.
First, the APIs related to ProrationMode The subscription change options have been removed. Now, the following is used: ReplacementMode to manage plan changes (upgrades, downgrades, etc.). If you're still using methods like setReplaceProrationMode o setReplaceSkusProrationModeYou will have to migrate them to the new variants of setSubscriptionReplacementMode and adjust the logic according to the updated documentation.
The API has also been removed launchPriceConfirmationFlowwhich was already marked as obsolete. To handle subscription price changes, you should refer to the new workflows and recommendations in the pricing change guide, which details how to properly inform the user and how to manage consent.
Another important point is the Alternative billing APIsThe methods BillingClient.Builder.enableAlternativeBilling, AlternativeBillingListener y AlternativeChoiceDetails have disappeared in favor of a more aligned nomenclature: now you must use BillingClient.Builder.enableUserChoiceBilling() along with UserChoiceBillingListener y UserChoiceDetailsAccording to Google itself, it is basically a name change with no changes in behavior, in a context marked by agreements such as Google and Epic Games agree to open Android.
Finally, a new error code is entered. NETWORK_ERROR en BillingResultand the meanings and conditions of SERVICE_TIMEOUT and SERVICE_UNAVAILABLEIf you have custom error handling logic (for example, deciding when to show a message to the user, when to silently retry, etc.), it's advisable to review it to take these new nuances into account.
Pending transactions and absence of orderId until PURCHASED
A subtle change in PBL 7 is that the library no longer generates a Order ID for pending purchasesIn these cases, the orderId It will only be available once the purchase reaches the PURCHASED state. This especially affects workflows where you used the order ID as the primary reference from the start.
Google's recommendation is that you rely on the purchaseToken for your records and reconciliationsat least while the transaction is pending. If you find a purchase that has disappeared from Play, check What to do if the purchase disappears.
If you haven't worked with outstanding balances yet, review the Billing Library integration guide and documentation on procurement lifecycle managementThere you will find the different states, how to react to each one, and how RTDNs fit into this puzzle.
New optional capabilities in PBL 7: virtual installments and prepayments
Among the "nice" new features of PBL 7 are the virtual fee subscriptions (virtual installment subscriptions) and extended support for pending purchases for prepaid subscriptions. These features are not mandatory, but they can give you more flexibility when adapting your business model to different markets.
Virtual installments allow a user to pay for a longer-term subscription in small periodic paymentsInstead of a single large payment, Google explains that for developer billing purposes, you continue to receive monthly payments under an annual plan with monthly installments. If a user misses a payment, neither you nor Google should attempt to recover past installments. This makes its practical use quite similar to a standard monthly subscription, at least initially.
For now, these subscription fees are only available in Brazil, France, Italy and SpainGoogle recommends keeping an eye on the Play Console for newly supported countries. Configuration is done via ProductDetails.InstallmentPlanDetails and following the specific guide to integrate them into your app.
In parallel, support is being expanded pending purchases for prepaid subscriptionsNow you can offer models where the user starts the purchase in the app and completes the payment later through other means, and the Billing Library knows how to handle that flow correctly. Activation is done by calling enablePendingPurchases() when initializing BillingClient and, specifically for prepaid plans, using PendingPurchasesParams.Builder.enablePrepaidPlans().
Depreciation periods for Play Billing Library 5 and 6
With PBL 7 on the scene, Google has set clear dates for the withdrawal of support for versions 5 and 6If you are still in any of them, you must mark the calendar in red:
- Google Play Billing Library 5 will be officially deprecated on August 31, 2024, for new apps and updates. It's possible to request an extension until November 1, 2024, but this isn't something you should rely on long-term.
- Google Play Billing Library 6 can be used to publish new apps until August 1, 2025, and to update existing apps until November 1, 2025.
After that date, if you haven't migrated to at least version 6 or ideally to version 7, you will need to update to the latest version. version 7You will have updates blocked in the Play Console. Although your app will continue to function on users' devices, you will be frozen, unable to fix bugs or add new features that depend on publishing in the store.
The case of .NET MAUI and current limitations
If you're working with .NET MAUI and subscriptions on Android, you've probably already read or experienced that it's not so simple. Many projects used Plugin.InAppBilling by James Montemagno, but the plugin is archived and unmaintained, so it won't be updated to support Billing Library 7. At the same time, the official package Xamarin.Android.Google.BillingClient It has remained anchored to the Xamarin.Android ecosystem and is not directly compatible with .NET MAUI.
The practical consequence is that the Play Console warns Your app doesn't use Billing Library 7.0.0 or higher, which blocks updates if you continue using older libraries. Some developers have opted for drastic solutions, such as temporarily disabling subscriptions to be able to upload a version, but obviously that's not sustainable if your business model depends on that monetization.
In this context, many teams are considering alternatives such as Third-party SDKs These services already support PBL 7 underneath and expose a more stable, cross-platform API (for example, subscription backend solutions with SDKs for Android, iOS, and other platforms). These services typically handle Billing Library version migrations and expose a stable wrapper, significantly reducing stress with each new Google deprecation.
Until Microsoft and the MAUI team offer a Official package updated and fully compatible With Billing Library 7, the options include: implementing your own binding to the native Billing Library, using a third-party service, or rethinking how you integrate purchases within your MAUI project. In any case, it's best not to leave the decision until the last minute, because Play's deadlines are fixed.
Overall, the update to Google Play Billing Library v7 involves reviewing dependencies, cleaning up obsolete APIs, strengthening backend logic with purchase verification and RTDN, and leveraging testing tools like Play Billing Lab to uncover all bugs before going live. Those who take the time to fine-tune this migration will be better able to handle prepaid plans, virtual fees, network errors, and subscription lifecycle changes, and will have a much better chance of maintaining stable revenue and a polished user experience on Google Play. Share the information so that more users can learn about the topic.