One-time purchase lifecycle

One-time purchase products have a simpler lifecycle than subscription products, but there are still several states and transition events that your backend needs to be able to handle properly.

Figure 1 Lifecycle states and transition events for one-time purchases.

New one-time product purchases

After the user completes the billing flow, your app can see information about the new purchase in one of two ways:

After receiving the new purchase, use the getPurchaseState method to determine the payment state of the new purchase.

Pending transactions

One-time product purchases only generates RTDNs when they are pending. The format of the data field for this type of RTDN is OneTimeProductNotification. To update your backend purchase state, use the purchase token provided in the OneTimeProductNotification object to call the purchases.products.get method. This method provides the latest purchase and consumption status given a purchase token.

You should handle transaction-related RTDNs in your secure backend.

Handle completed transactions

When a user completes a pending one-time product purchase, Google Play send a OneTimeProductNotification message with the type ONE_TIME_PRODUCT_PURCHASED. When you receive this RTDN, process the purchase as described in Process one-time product purchases in your backend.

Handle canceled transactions

When a pending one-time product purchase is canceled, Google Play sends a OneTimeProductNotification message with the type ONE_TIME_PRODUCT_CANCELED. For example, this can occur if the user doesn't complete payment within the required timeframe. When your backend server receives this notification, call the purchases.products.get method to get the latest purchase state, then update your backend accordingly, including user entitlements.

Only one-time product purchases in Pending state can be canceled. If a one-time product purchase in Purchased state gets refunded, you will be made aware via the Voided Purchases API.

Process one-time product purchases in your backend

Whether you have detected a new purchase via a ONE_TIME_PRODUCT_PURCHASED RTDN or you have been made aware in-app through PurchasesUpdatedListener or manually fetching purchases in your app's onResume() method, you must process the new purchase. We recommend that you handle purchase processing in your backend for better security.

Follow these steps to process a new one-time purchase:

  1. Query the purchases.products.get endpoint to obtain the latest one-time product purchase status. To call this method for a purchase, you need the corresponding purchaseToken either from your app or from the ONE_TIME_PRODUCT_PURCHASED RTDN.
  2. Call getPurchaseState() and make sure that the purchase state is PURCHASED.
  3. Verify the purchase.
  4. Give the user access to the content. The user account associated with the purchase can be identified with the obfuscatedExternalAccountId field from purchases.products.get, if one was set using setObfuscatedAccountId() when the purchase was made.
    1. For non-consumable product purchases, acknowledge delivery of the content by calling the purchases.products.acknowledge method. Make sure that the purchase hasn't been previously acknowledged by checking the acknowledgementState field.
    2. If the product is consumable, mark the item as consumed by calling the purchases.products.consume method so that the user can buy the item again after they have consumed it. This method also acknowledges the purchase.

There are also purchase acknowledgement and consume methods available in the Play Billing Library that allow you to process purchases from you app, but we recommend that you handle processing in your backend if you have one for a more secure implementation.