This topic describes how to integrate the Google Play Billing Library into your app to start selling products. Before reading this topic, be sure you've set up your Google Play configuration beforehand by following the steps in Getting ready.
This topic includes code examples that are based on the official sample apps on GitHub. See additional resources for a complete list of sample apps and other resources that you can use while integrating.
Life of a purchase
Here's a typical purchase flow for a one-time purchase or a subscription.
- Show the user what they can buy.
- Launch the purchase flow for the user to accept the purchase.
- Verify the purchase on your server.
- Give content to the user, and acknowledge delivery of the content. Optionally, mark the item as consumed so that the user can buy the item again.
Subscriptions automatically renew until they are canceled. A subscription can go through the following states:
- Active: User is in good standing and has access to the subscription.
- Cancelled: User has cancelled but still has access until expiration.
- In grace period: User experienced a payment issue, but still has access while Google is retrying the payment method.
- On hold: User experienced a payment issue, and no longer has access while Google is retrying the payment method.
- Paused: User paused their access, and does not have access until they resume.
- Expired: User has cancelled and lost access to the subscription. The user is considered churned at expiration.
Purchase tokens and Order IDs
Google Play tracks products and transactions using purchase tokens and Order IDs.
- A purchase token is a string that represents a buyer's entitlement to a product on Google Play. It indicates that a Google user is entitled to a specific product that is represented by a SKU. You can use the purchase token with the Google Play Developer API.
- An Order ID is a string that represents a financial transaction on Google Play. This string is included in a receipt that is emailed to the buyer. You can use the Order ID to manage refunds in the used in sales and payout reports.
Order IDs are created every time a financial transaction occurs. Purchase tokens are generated only when a user completes a purchase flow.
- For one-time products, every purchase creates a new purchase token. Most purchases also generate a new Order ID. The exception to this is when the user is not charged any money, as described in Promo codes.
- For subscriptions, an initial purchase creates a purchase token and an Order ID. For each continuous billing period, the purchase token stays the same, and a new Order ID is issued. Upgrades, downgrades, replacements, and re-sign-ups all create new purchase tokens and Order IDs.
For subscriptions, note the following:
- Subscription upgrades, downgrades, and other subscription purchase
flows generate purchase tokens that must replace a previous
purchase token. You must invalidate the purchase tokens that appear in the
linkedPurchaseToken
field of the Google Play Developer API. For more information, see Implementing linkedPurchaseToken correctly to prevent duplicate subscriptions. - Order numbers for subscription renewals contain an
additional integer that represents a specific renewal instance. For
example, an initial subscription Order ID might be
GPA.1234-5678-9012-34567
with subsequent Order IDs beingGPA.1234-5678-9012-34567..0
(first renewal),GPA.1234-5678-9012-34567..1
(second renewal), and so on.
Error Handling
The Google Play Billing Library returns errors in the form of
BillingResult
.
A BillingResult
contains a
BillingResponseCode
,
which categorizes possible billing-related errors that your app can encounter.
For example, if you receive a SERVICE_DISCONNECTED
error code, your app should reinitialize the connection with Google Play.
Additionally, a BillingResult
contains a
debug message,
which is useful during development to diagnose errors.
Connect to Google Play
The first step to integrate with Google Play's billing system is to add the library to your app and initialize a connection.
Add the Google Play Billing Library dependency
Add the Google Play Billing Library dependency to your app's
build.gradle
file as shown:
dependencies { def billing_version = "3.0.0" implementation "com.android.billingclient:billing:$billing_version" }
If you're using Kotlin, the Play Billing Library KTX module contains
Kotlin extensions and coroutines support that enable you to write
idiomatic Kotlin when using the Google Play Billing Library. To include
these extensions in your project, add the following dependency to your
app's build.gradle
file as shown:
dependencies { def billing_version = "3.0.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Initialize a BillingClient
Once you've added a dependency on the Google Play Billing Library, you need to
initialize a BillingClient
instance. BillingClient
is the main interface for communication between the
Google Play Billing Library and the rest of your app. BillingClient
provides convenience methods, both synchronous and asynchronous, for
many common billing operations.
To create a BillingClient
, use
newBuilder()
.
To receive updates on purchases, you must also call
setListener()
,
passing a reference to a
PurchasesUpdatedListener
.
This listener receives updates for all purchases in your app.
Kotlin
private val purchasesUpdateListener = PurchasesUpdatedListener { billingResult, purchases -> // To be implemented in a later section. } private var billingClient = BillingClient.newBuilder(activity) .setListener(purchasesUpdatedListener) .enablePendingPurchases() .build()
Java
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() { @Override public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { // To be implemented in a later section. } }; private BillingClient billingClient = BillingClient.newBuilder(activity) .setListener(purchasesUpdatedListener) .enablePendingPurchases() .build();
Establish a connection to Google Play
After you have created a BillingClient
, you need to establish a connection
to Google Play.
To connect to Google Play, call
startConnection()
.
The connection process is asynchronous, and you must implement a
BillingClientStateListener
to receive a callback once the setup of the client is complete and it’s
ready to make further requests.
You must also implement retry logic to handle lost connections to
Google Play. To implement retry logic, override the
onBillingServiceDisconnected()
callback method, and make sure that the BillingClient
calls the
startConnection()
method to reconnect to Google Play before making further requests.
The following example demonstrates how to start a connection and test that it's ready to use:
Kotlin
billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } override fun onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } })
Java
billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } @Override public void onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } });
Show products available to buy
After you have established a connection to Google Play, you are
ready to query for your available products and display them to your users.
To query Google Play for in-app product details, call
querySkuDetailsAsync()
.
Querying for SKU details is an important step before displaying your products
to your users, as it returns localized product information. For
subscriptions, ensure your product display
follows all Play policies.
When calling querySkuDetailsAsync()
, pass an instance of
SkuDetailsParams
that specifies a list of product ID strings created in Google Play Console
along with a SkuType
. The SkuType
can be either SkuType.INAPP
for
one-time products or SkuType.SUBS
for subscriptions.
To handle the result of the asynchronous operation, you must also specify a
listener which implements the
SkuDetailsResponseListener
interface. You can then override
onSkuDetailsResponse()
,
which notifies the listener when the query finishes, as shown in the following
example:
Kotlin
fun querySkuDetails() { val skuList = ArrayList<String>() skuList.add("premium_upgrade") skuList.add("gas") val params = SkuDetailsParams.newBuilder() params.setSkusList(skuList).setType(SkuType.INAPP) withContext(Dispatchers.IO) { billingClient.querySkuDetailsAsync(params.build()) { billingResult, skuDetailsList -> // Process the result. } } }
Java
List<String> skuList = new ArrayList<> (); skuList.add("premium_upgrade"); skuList.add("gas"); SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder(); params.setSkusList(skuList).setType(SkuType.INAPP); billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() { @Override public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) { // Process the result. } });
The Google Play Billing Library stores the query results in a List
of
SkuDetails
objects.
You can then call a variety of methods on each SkuDetails
object in the
list to view relevant information about an in-app product, such as
its price or description. To view the available product detail information,
see the list of methods in the
SkuDetails
class.
Before offering an item for sale, check that the user does not already own the item. If the user has a consumable that is still in their item library, they must consume the item before they can buy it again.
Before offering a subscription, verify that the user is not already subscribed.
Launch the purchase flow
To start a purchase request from your app, call the
launchBillingFlow()
method from your app's main thread. This method takes a reference to a
BillingFlowParams
object that contains the relevant
SkuDetails
object
obtained from calling
querySkuDetailsAsync()
.
To create a BillingFlowParams object, use the
BillingFlowParams.Builder
class.
Kotlin
// An activity reference from which the billing flow will be launched. val activity : Activity = ...; // Retrieve a value for "skuDetails" by calling querySkuDetailsAsync(). val flowParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() val responseCode = billingClient.launchBillingFlow(activity, flowParams).responseCode
Java
// An activity reference from which the billing flow will be launched. Activity activity = ...; // Retrieve a value for "skuDetails" by calling querySkuDetailsAsync(). BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build(); int responseCode = billingClient.launchBillingFlow(activity, billingFlowParams).getResponseCode(); // Handle the result.
The launchBillingFlow()
method returns one of several response codes
listed in
BillingClient.BillingResponseCode
.
Be sure to check this result to ensure there were no errors launching the
purchase flow. A BillingResponseCode
of OK
indicates a successful launch.
On a successful call to launchBillingFlow()
, the system displays the
Google Play purchase screen. Figure 1 shows a purchase screen for a
subscription:

Google Play calls onPurchasesUpdated()
to deliver the result of
the purchase operation to a listener that implements the
PurchasesUpdatedListener
interface. The listener is specified using the
setListener()
method when you initialized your client.
You must implement onPurchasesUpdated()
to handle possible response codes.
The following example shows how to override onPurchasesUpdated()
:
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { handlePurchase(purchase) } } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
Java
@Override void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
A successful purchase generates a Google Play purchase success screen similar to figure 2.

A successful purchase also generates a purchase token, which is a unique identifier that represents the user and the product ID for the in-app product they purchased. Your apps can store the purchase token locally, though we recommend passing the token to your secure backend server where you can then verify the purchase and protect against fraud. This process is further described in the following section.
The user is also emailed a receipt of the transaction containing an Order ID or a unique ID of the transaction. Users receive an email with a unique Order ID for each one-time product purchase, and also for the initial subscription purchase and subsequent recurring automatic renewals. You can use the Order ID to manage refunds in the Google Play Console.
Processing purchases
Once a user completes a purchase, your app then needs to process that
purchase. In most cases, your app is notified of purchases through your
PurchasesUpdatedListener
.
but there are cases where your app is made aware of calling
BillingClient.queryPurchases()
as described in Fetching purchases.
Your app should process a purchase in the following way:
- Verify the purchase.
- Give content to the user, and acknowledge delivery of the content. Optionally, mark the item as consumed so that the user can buy the item again.
To verify a purchase, first check that the
purchase state
is PURCHASED
.
If the purchase is PENDING
, then you should process the purchase as described
in Handling pending transactions. For purchases received from
onPurchaseUpdated()
or queryPurchases,
you should further verify the purchase to ensure legitimacy before your
app grants entitlement. To learn how to properly verify a purchase, see
Verify purchases before granting entitlements.
Once you've verified the purchase, your app is ready to grant entitlement to the user. After granting entitlement, your app must then acknowledge the purchase. This acknowledgement communicates to Google Play that you have granted entitlement for the purchase.
The process to grant entitlement and acknowledge the purchase depends on whether the purchase is a non-consumable, a consumable, or a subscription.
For consumables, the
consumeAsync()
method fulfills the acknowledgement requirement and indicates that your app
has granted entitlement to the user. This method also enables your app to make
the one-time product available for purchase again.
To indicate that a one-time product has been consumed, call consumeAsync()
and include the purchase token that Google Play should make available for
repurchase. You must also pass an object that implements the
ConsumeResponseListener
interface. This object handles the result of the consumption operation.
You can override the
onConsumeResponse()
method, which the Google Play Billing Library calls when the operation
is complete.
The following example illustrates consuming a product using the associated purchase token:
Kotlin
fun handlePurchase(purchase: Purchase) { // Purchase retrieved from BillingClient#queryPurchases or your PurchasesUpdatedListener. val purchase : Purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() billingClient.consumeAsync(consumeParams, { billingResult, outToken -> if (billingResult.responseCode == BillingResponseCode.OK) { // Handle the success of the consume operation. } }) }
Java
void handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchases or your PurchasesUpdatedListener. Purchase purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); ConsumeResponseListener listener = new ConsumeResponseListener() { @Override public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Handle the success of the consume operation. } } }; billingClient.consumeAsync(consumeParams, listener); }
To acknowledge non-consumable purchases, use either
BillingClient.acknowledgePurchase()
from the Billing Library or
Product.Purchases.Acknowledge
from the Google Play Developer API. Before acknowledging a purchase, your
app should check whether it was already acknowledged by using the
isAcknowledged()
method in the Google Play Billing Library or the
acknowledgementState
field in the Google Developer API.
The following example shows how to acknowledge a purchase using the Google Play Billing Library:
Kotlin
val client: BillingClient = ... val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ... fun handlePurchase() { if (purchase.purchaseState === PurchaseState.PURCHASED) { if (!purchase.isAcknowledged) { val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) val ackPurchaseResult = withContext(Dispatchers.IO) { client.acknowledgePurchase(acknowledgePurchaseParams.build()) } } } }
Java
BillingClient client = ... AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ... void handlePurchase(Purchase purchase) { if (purchase.getPurchaseState() == PurchaseState.PURCHASED) { if (!purchase.isAcknowledged()) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
Subscriptions are handled similarly to non-consumables. You can
acknowledge a subscription Acknowledgement using either
BillingClient.acknowledgePurchase()
from the Google Play Billing Library or
Purchases.Subscriptions.Acknowledge
from the Google Play Developer API. All initial subscription purchases need
to be acknowledged. Subscription renewals do not need to be acknowledged.
For more information on when subscriptions need to be acknowledged, see the
Sell subscriptions topic.
Fetching purchases
Listening to purchase updates using a
PurchasesUpdatedListener
is not sufficient to ensure your app processes all purchases. It's possible
that your app might not be aware of all the purchases a user has made. Here
are some scenarios where your app could lose track or be unaware of purchases:
- Network Issues during the purchase: A user makes a successful
purchase and receives confirmation from Google, but their device loses
network connectivity before their device receives notification of
the purchase through the
PurchasesUpdatedListener
. - Multiple devices: A user buys an item on one device and then expects to see the item when they switch devices.
- Handling purchases made outside your app: Some purchases, such as promotion redemptions, can be made outside of your app.
To handle these situations, be sure that your app calls
BillingClient.queryPurchases()
in your onResume()
and onCreate()
methods to ensure that all purchases
are successfully processed as described in processing purchases.
Handling purchases made outside your app
Some purchases, such as promotion redemptions, can happen outside of your app. When a user makes a purchase outside of your app, they expect your app to show an in-app message, or use some kind of notification mechanism to let the user know that the app correctly received and processed the purchase. Some acceptable mechanisms are:
- Show an in-app popup.
- Deliver the message to an in-app message box, and clearly stating that there is a new message in the in-app message box.
- Use an OS notification message.
Keep in mind that it is possible for your app to be in any state when your app recognizes the purchase. It is even possible for your app to not even be installed when the purchase was made. Users expect to receive their purchase when they resume the app, regardless of the state in which the app is.
You must detect purchases regardless of the state in which the app is when the purchase was made. However, there are some exceptions where it may be acceptable to not immediately notify the user that the item was received. For example:
- During the action part of a game, where showing a message may distract the user. In this case, you must notify the user after the action part is over.
- During cutscenes, where showing a message may distract the user. In this case, you must notify the user after the cutscene is over.
- During the initial tutorial and user setup parts of the game. We recommend you notify new users of the reward immediately after they open the game or during initial user set up. However, it is acceptable to wait until the main game sequence is available to notify the user.
Always keep the user in mind when deciding when and how to notify your users of purchases made outside of your app. Any time a user doesn’t immediately receive a notification, they may get confused, and may stop using your app, contact user support, or complain about it on social media.
Handling pending transactions
Google Play supports pending transactions, or transactions that require one or more additional steps between when a user initiates a purchase and when the payment method for the purchase is processed. Your app should not grant entitlement to these types of purchases until Google notifies you that the user's payment method was successfully charged.
For example, a user can create a PENDING
purchase of an in-app item by
choosing cash as their form of payment. The user can then choose a physical
store where they will complete the transaction and receive a code through both
notification and email. When the user arrives at the physical store, they
can redeem the code with the cashier and pay with cash. Google then notifies
both you and the user that cash has been received. Your app can then grant
entitlement to the user.
To enable pending purchases, call
enablePendingPurchases()
as part of initializing your app.
When your app receives a new purchase, either through your
PurchasesUpdatedListener
or as a result of calling
queryPurchases()
,
use the getPurchaseState()
method to determine whether the purchase state is PURCHASED
or PENDING
.
Note that you should grant entitlement only when the state is PURCHASED
. If
your app is running when the user completes the purchase, your
PurchasesUpdatedListener
is called again, and the PurchaseState
is now PURCHASED
. At this point,
your app can process the purchase using the standard method for
processing one-time purchases. Your app should also call
queryPurchases()
in your app's onResume()
and onCreate()
methods to
handle purchases that have transitioned to the PURCHASED
state while your
app was not running.
Your app can also use
Real-time developer notifications
with pending purchases by listening for
OneTimeProductNotifications
. When the purchase transitions from PENDING
to PURCHASED
, your app receives a
ONE_TIME_PRODUCT_PURCHASED
notification. If the purchase is cancelled,
your app receives a ONE_TIME_PRODUCT_CANCELED
notification. This can
happen if your customer does not complete payment in the required timeframe.
When receiving these notifications, you can use the Google Play Developer
API, which includes a PENDING
state for
Purchases.products
.