Finally we reach the most important process in this extension, making a purchase.
Making a purchase requires making a request to initiate the purchase and then "finishing the purchase" to finalise the purchase and remove it from any internal queues.
Firstly create a
PurchaseRequest object and set the
quantity you wish to purchase.
Then pass this object to the
This will initiate the purchase flow, most likely leaving your application and taking the user to the store interface.
As the state of the purchase transaction changes you will be notified through the
Note: We have deprecated all of the old
PurchaseEvent's such as
PURCHASE_SUCCESSin favour of a processing queue through the
If you use any of the old events they will still work in the near future however we suggest you migrate to the
PURCHASES_UPDATEDevent to better handle purchase transaction states.
It is also important that you listen for the
PURCHASE_FAILED event. This will be dispatched
in situations where the purchase could not be attempted due to various reasons. You should
refer to the error code and message in the event to determine if it can be resolved.
One of the most common situations that this will occur on is when the product is already owned
by the user on Android. This case you should check for the
ITEM_ALREADY_OWNED error code and
then load the purchases to retrieve the purchase.
See the section on Get Purchases for more information on this process of retrieving purchases.
As a rule it is important that you call
finishPurchase() when you have completed the purchase
and either handled the error or deployed the product to the user's inventory.
If you don't call
finishPurchase() then the next time the user opens the application and
setup() you will get notified again of the purchase as the system believes it to
still be pending. In some circumstances, failing to finish a purchase may result in the purchase
being cancelled and the user refunded.
Once complete the extension will dispatch the
FINISH_SUCCESS event or if an error occurred then the
FINISH_FAILED event will be dispatched:
You must call
finishPurchaseand confirm by receiving the
FINISH_SUCCESSevent before attempting any other operation such as consuming the purchase.
The purchase is still in a pending state and not considered delivered to the user until you do.
Apple In-App Purchases
With Apple's In-App Purchases
finishPurchase() will remove the purchase from the transaction queue,
and inform Apple that you have delivered (and potentially verified) the purchase.
On iOS you most often use this process to verify the transaction with your server, to verify whether you should deliver the product before calling
finishPurchase() and the purchase information is removed from the queue.
Google Play Billing
With Google Play Billing the call to
finishPurchase() performs the acknowledgement of the purchase.
Purchases that aren't acknowledged will be returned by the
getPendingPurchases() method and may be refunded if you do not acknowledge them.
Google Play supports purchasing products from inside of your app (in-app) or outside of your app (out-of-app). In order for Google Play to ensure a consistent purchase experience regardless of where the user purchases your product, you must acknowledge all purchases received through the Google Play Billing Library as soon as possible after granting entitlement to the user. If you do not acknowledge a purchase within three days, the user automatically receives a refund, and Google Play revokes the purchase.
Note: Previously you may have attached a developer payload at this point. This is no longer supported and has been removed by Google in the Play Billing library v3.0. Instead consider using an obfuscated
applicationUsername on your purchase request which will now get returned with a
Purchase through Google Play Billing.
The simplest way to do this is to simply call this in the event handler, however you may wish to do this at a later time, for example, if you wish to validate the purchase using the transaction receipt with your application server.
Handling User Cancellations
When a user cancels a purchase there are two avenues that you'll need to handle, due to the different ways that Android and iOS handle these cases.
On iOS there will be a
Purchase initiated immediately so when the user cancels the purchase you will receive a
PurchaseEvent.PURCHASES_UPDATED and the purchases transaction state will be set to
You will need to handle this case in your purchases updated handler and finish the purchase to remove it from the pending purchases queue.
On Android the purchase is not initiated so there is no
Purchase to return, hence you will not receive a purchases updated event but instead a
PurchaseEvent.PURCHASE_FAILED event will be dispatched. The error code on the failed event will be set to
ErrorCodes.RESPONSE_CANCELLED so you can use this code to process the user cancellation. As this purchase was not initiated it does not need to be finished and will not appear in the pending purchases queue.
You should ensure you handle both these cases in your application if you wish to handle user cancellations.
Of special note are deferred purchases. Deferred purchases are purchases that are in progress and require further user action external to your application, such as a parental approval or payment in cash at a physical store.
With Apple's In-App Purhcases:
The transaction is in the queue, but its final status is pending external action such as Ask to Buy. Update your UI to show the deferred state, and wait for another callback that indicates the final status.
With Google Play Billing the deferred state is equivalent to the "PENDING" purchase state where additional action is required before granting entitlement.
For example, a user might choose to purchase your in-app product at a physical store using cash. This means that the transaction is completed outside of your app. In this scenario, you should grant entitlement only after the user has completed the transaction.
In order to correctly handle deferred purchases you should not finish the purchase, but leave it in the queue until the user completes the external action.
Once the user completes the action you will receive a purchases updated event and should process the purchase at that point. It is important however if you display some "purchase in progress" UI during the making a purchase process that you close that once you receive this event. You may wish to display a message appropriate to your application indicating that they need to take action outside the app.