Documentation

Support

In-App Purchasing

In-App Purchasing

Upgrade from IAP version 4 to version 5

Follow this guide to migrate from Unity In-App Purchasing version 4 to version 5.
Read time 5 minutesLast updated a day ago

In-App Purchasing (IAP) version 5 (v5) introduces significant architectural improvements that give you better control over each step of your connection and purchase flow. While migration requires that you make significant updates to your existing IAP implementation, this guide provides step-by-step instructions and code samples to help you transition.

Overview of changes

The following table summarizes the changes in IAP v5 and what you need to update in your implementation. For more information on the benefits of upgrading, refer to the Why you should upgrade to Unity In-App Purchasing (IAP) v5.x support article.

Change

Required update

Initialization is split into separate async calls for store connection, product fetching, and purchase fetching.Replace UnityPurchasing.Initialize()
ConfigurationBuilder
is removed. Products are now defined via a
CatalogProvider
or a list of
ProductDefinitions
.
Replace ConfigurationBuilder
Store Extensions are replaced with Store Extended Services.Replace ConfigurationBuilder
IDetailedStoreListener
and
IStoreListener
are replaced with optional event handlers on
StoreController
and the individual store services.
Replace IDetailedStoreListener and IStoreListener
IStoreController
is replaced with
StoreController
, which can be fetched at any time via
UnityIAPServices.StoreController()
.
Replace IStoreController
The
ProcessPurchase
callback is replaced with
OnPurchasePending
for new purchases and
OnPurchasesFetched
for restored purchases.
Replace purchase flow
RestoreTransactions
has moved from Store Extensions to
StoreController
and
PurchaseService
.
Restore transactions
Entitlement checks are now event-based, using
FetchPurchases
or
CheckEntitlement
.
Replace entitlement checks
Apple App Store receipt validation is deprecated. Google Play receipt validation now uses
Order.Info.Receipt
.
Update receipt validation
CodelessIAPStoreListener.initializationComplete
is replaced with
CodelessIAPStoreListener.IsInitialized()
.
Update Codeless IAP

Replace UnityPurchasing.Initialize()

As of IAP v5, you can initialize the Unity IAP package with greater flexibility. You can connect to the store, fetch products, and handle purchases independently and asynchronously. This approach can help you identify and resolve issues that might block a successful initialization.
Note
In versions 4 and earlier, the Unity IAP package connects to the store, fetches products, and fetches purchases synchronously at package initialization. The package reports a successful initialization only after completing all these steps.
Follow these steps to replace the behavior of
UnityPurchasing.Initialize()
:
  1. Call and await
    StoreController.Connect()
    :
    • When this call completes, IAP has connected to your current app store.
  2. Call
    FetchProducts()
    :
    • You can add products to an instance of
      CatalogProvider
      , similar to adding products to the
      ConfigurationBuilder
      . You can also pass a list of
      ProductDefinitions
      to
      ProductService.FetchProducts()
      or
      StoreController.FetchProducts()
      . For more information, refer to Code sample of new initialization process.
    • Your
      OnProductsFetched
      event handler is called when the request has successfully completed. If no specified products could be fetched,
      OnProductsFetchFailed
      is invoked.
  3. Call
    FetchPurchases()
    after your products have been successfully fetched:
    • Your
      OnPurchasesFetched
      event handler is called when the request has successfully completed. The
      Orders
      object contains a filterable collection of all deferred, pending, and completed orders returned by the app store. On failure,
      OnPurchasesFetchFailed
      is invoked.
Note
By default, calling
FetchPurchases
invokes
OnPurchasePending
for any pending purchases which have not yet been handled in the session. You can disable this behaviour with
StoreController.ProcessPendingOrdersOnPurchasesFetched(false)
.

Code sample of new initialization process using StoreController

The following example shows how to initialize IAP v5:
StoreController m_StoreController; async void InitializeIAP() { m_StoreController = UnityIAPServices.StoreController(); m_StoreController.OnPurchasePending += OnPurchasePending; await m_StoreController.Connect(); m_StoreController.OnProductsFetched += OnProductsFetched; m_StoreController.OnPurchasesFetched += OnPurchasesFetched; var initialProductsToFetch = new List<ProductDefinition> { new(goldProductId, ProductType.Consumable), new(diamondProductId, ProductType.Consumable) }; m_StoreController.FetchProducts(initialProductsToFetch); }void OnProductsFetched(List<Product> products) { // Handle fetched products m_StoreController.FetchPurchases(); } void OnPurchasesFetched(Orders orders) { // Process purchases, for example, check for entitlements from completed orders }

Replace IDetailedStoreListener and IStoreListener

IAP v5 no longer requires an implementation of
IDetailedStoreListener
or
IStoreListener
for handling purchases or initialization. Replace functionality previously handled by
IDetailedStoreListener
by attaching event handlers to
StoreController
, or to the individual
ProductService
,
PurchaseService
, and
StoreService
services.
For an example of adding event handlers to
StoreController
, refer to Code sample of new initialization process.
Note
You can add or remove event handlers at any time, however certain event handlers are recommended before calling certain methods. Unity IAP displays a warning when you call a function before the recommended event handlers have been attached.
To migrate, replace each
IDetailedStoreListener
function with the following:

IDetailedStoreListener
functions

IAP v5 replacement

OnPurchaseFailed(Product, PurchaseFailureDescription)
Add an event handler to
StoreController.OnPurchaseFailed(FailedOrder)
or
PurchaseService.OnPurchaseFailed(FailedOrder)
OnInitialized(IStoreController controller, IExtensionProvider extensions)
Continue execution after
StoreController.Connect()
or
StoreService.Connect()
completes.
OnInitializeFailed(InitializationFailureReason error)
Add event handlers to
StoreService.OnStoreDisconnected(StoreConnectionFailureDescription)
,
ProductService.OnProductsFetchFailed(ProductFetchFailed)
, and
PurchaseService.OnPurchasesFetchFailed(PurchasesFetchFailureDescription)
. You can also add these event handlers via
StoreController
.
OnInitializeFailed(InitializationFailureReason error, string message = null)
Add an event handler to
StoreController.OnStoreDisconnected(StoreConnectionFailureDescription)
or
StoreService.OnStoreDisconnected(StoreConnectionFailureDescription)
PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
Add an event handler to
StoreController.OnPurchasePending(PendingOrder)
or
PurchaseService.OnPurchasePending(PendingOrder)

Replace ConfigurationBuilder

Replace the following
ConfigurationBuilder
functions with the following behaviours:

ConfigurationBuilder
functions

IAP v5 replacement

ConfigurationBuilder.AddProduct()
Rather than calling
ConfigurationBuilder.AddProduct()
, you can add products to an instance of a
CatalogProvider
via
CatalogProvider.AddProduct()
or
CatalogProvider.AddProducts()
. To fetch products, you can call
CatalogProvider.FetchProducts
and pass a callback, such as
UnityIAPServices.DefaultProduct().FetchProductsWithNoRetries
. For more information on products and
CatalogProvider
, refer to Define your products. You can also create
ProductDefinitions
and pass them directly to a
FetchProducts()
call on
StoreController
or
ProductService
.
IAppleConfiguration
and
IGoogleConfiguration
You can find functionality in
IAppleConfiguration
and
IGoogleConfiguration
in the Extended Store Services, such as
AppleStoreExtendedService
.
Note
If you fetch a Store Extended Service on an unsupported platform (for example, fetching
AppleStoreExtendedService
in the Editor or on Android), the service will be null. Always check that the service isn't null before adding event handlers or changing settings.

Replace IStoreController

Replace
IStoreController
with
StoreController
.
StoreController
exposes IAP functionality similar to
IStoreListener
, but you can fetch
StoreController
by calling
UnityIAPServices.StoreController()
at any time.
Replace these methods from
IStoreController
with the following methods from
StoreController
:

IStoreController

StoreController

Notes

products
GetProducts
GetProducts
returns a list of products.
InitiatePurchase
Purchase
or
PurchaseProduct
Purchase
functions no longer have a
payload
argument. Support for developer payloads was removed in Google Billing v3.
FetchAdditionalProducts
FetchProducts
FetchProducts
is also used to fetch initial products.
ConfirmPendingPurchase
ConfirmPurchase
ConfirmPurchase
requires a
PendingOrder
.

Replace purchase flow

To initiate a purchase, call
Purchase()
or
PurchaseProduct()
on
StoreController
or
PurchaseService
. To confirm a pending purchase, call
StoreController.ConfirmPurchase(PendingOrder)
or
PurchaseService.ConfirmPurchase(PendingOrder)
with the
PendingOrder
you want to confirm. For more information about the purchase flow, refer to Purchases.
In IAP v4 and earlier, the
ProcessPurchase
method automatically handled all purchase events. In IAP v5, purchase handling uses the following callbacks:
  • OnPurchasePending
    : Called for new purchases.
  • OnPurchasesFetched
    : Called for restored purchases.
Use your existing
ProcessPurchase
logic within both of these new callbacks.

Restore transactions

RestoreTransactions
has moved from Store Extensions to
StoreController
and
PurchaseService
.
Confirmed purchases are automatically restored when you call
FetchPurchases()
or through calling
CheckEntitlement()
.

Replace entitlement checks

To check a user's entitlement to a product, IAP relies on events. You can check the entitlements for all your fetched products by calling
FetchPurchases
and handling the
OnPurchasesFetched
event. To check the entitlement for a single product, call
CheckEntitlement
and handle the
OnCheckEntitlement
event.

Fetch additional products

Call
FetchProducts
on either
StoreController
or
ProductService
with a list of additional products to trigger your
OnPurchasesFetched
event handler. Alternatively, you can call
FetchProducts
on a
CatalogProvider
instance. For an example of fetching products via
ProductService
, refer to Code sample of new initialization process. For an example of calling
FetchProducts
on
CatalogProvider
, refer to Define your products.

Receipt validation

Receipt validation for Apple App Store receipts has been deprecated. Receipt validation is supported only for Google Play Store. To fetch receipts, use
Order.Info.Receipt
from
Order
instead of
Product.Receipt
.
Note
Move from StoreKit 1 receipts to StoreKit 2 jwsRepresentation as soon as possible to improve reliability, security, performance, and ultimately deliver a better experience for your users.
Note
Use OrderInfo.Apple.jwsRepresentation for server-side validation.

Codeless IAP specifics

Replace the following
CodelessIAPStoreListener
function with the following:

CodelessIAPStoreListener
function

IAP v5 replacement

CodelessIAPStoreListener.initializationComplete
CodelessIAPStoreListener.IsInitialized()