# Initialize Unity IAP

> Learn how to initialize the Unity IAP package, configure essential settings, and verify setup to start processing in‑app purchases across supported platforms.

Before you use Unity In-App Purchasing (IAP), [initialize the IAP package](#initialize-in-app-purchasing).

> **Important:**
>
> If you want to [integrate a Direct-to-Consumer (D2C) payment provider](./payment-providers/workflow.md), there are some differences so refer to [Initialize services to handle the startup sequence](./payment-providers/initialize-services.md) instead.

If you want to use [Unity Analytics](/analytics.md) or [Unity Authentication](/authentication.md) in your project, you need to initialize Unity Gaming Services (UGS) first before initializing IAP. Refer to the [Initialize Unity Gaming Services](#initialize-unity-gaming-services) section below for a how-to.

## Initialize Unity Gaming Services

Call `UnityServices.InitializeAsync()` to initialize all Unity Gaming Services. This method returns a `Task` that you can use to track initialization progress.

To learn more, refer to the [Initialization example](/services/services-core-api.md#initialization-example). For a fully functional sample, import the **06 Initialize Gaming Services** sample (**Package Manager** > **In-App Purchasing** > **Samples**).

For more information, refer to the [Services Core API](/services/services-core-api.md).

## Initialize In-App Purchasing

### Prerequisites

Choose one of the catalog setup methods in [Create an IAP catalog](./catalogs.md) to define the products you want to offer for purchase.

### Initialization steps

Initialization consists of the following steps:

1. Getting a `StoreController` for your app store.
2. Attaching event listeners to the `StoreController`.
3. Connecting to your app store.
4. Fetching products from your app store.
5. Fetching purchases from your app store.

```cs
using System.Collections.Generic;
using UnityEngine.Purchasing;

public class MyIAPManager
{
    private StoreController m_StoreController;
    public MyIAPManager()
    {
        // Define products
        var catalogProvider = new CatalogProvider();
        catalogProvider.AddProduct("100_gold_coins", ProductType.Consumable,
            new StoreSpecificIds()
            {
                {"100_gold_coins_google", GooglePlay.Name},
                {"100_gold_coins_mac", MacAppStore.Name}
            });

        // Get StoreController
        m_StoreController = UnityIAPServices.StoreController();

        // Add event listeners
        m_StoreController.OnStoreDisconnected += OnStoreDisconnected;

        m_StoreController.OnProductsFetched += OnProductsFetched;
        m_StoreController.OnProductsFetchFailed += OnProductsFetchFailed;

        m_StoreController.OnPurchasesFetched += OnPurchasesFetched;
        m_StoreController.OnPurchasesFetchFailed += OnPurchasesFetchFailed;

        // Connect to store
        m_StoreController.Connect().ContinueWith(_ =>
        {
            // Fetch products from store
            catalogProvider.FetchProducts(
                list => m_StoreController.FetchProducts(list)
                );
        });
    }

    /// <summary>
    /// Invoked when connection is lost to the current store, or on a Connect() failure.
    /// </summary>
    /// <param name="failure">Information regarding the failure.</param>
    private void OnStoreDisconnected(StoreConnectionFailureDescription failure)
    {
    }

    /// <summary>
    /// Invoked with products that are successfully fetched.
    /// </summary>
    /// <param name="products">Products successfully returned from the app store.</param>
    private void OnProductsFetched(List<Product> products)
    {
        // Fetch purchases for successfully retrieved products
        m_StoreController.FetchPurchases();
    }

    /// <summary>
    /// Invoked when an attempt to fetch products has failed or when a subset of products failed to be fetched.
    /// </summary>
    /// <param name="failure">Information regarding the failure.</param>
    private void OnProductsFetchFailed(ProductFetchFailed failure)
    {
    }

    /// <summary>
    /// Invoked when previous purchases are fetched.
    /// </summary>
    /// <param name="orders">All active pending, completed, and deferred orders for previously fetched products.</param>
    private void OnPurchasesFetched(Orders orders)
    {
    }

    /// <summary>
    /// Invoked when an attempt to fetch previous purchases has failed.
    /// </summary>
    /// <param name="failure">Information regarding the failure.</param>
    private void OnPurchasesFetchFailed(PurchasesFetchFailureDescription failure)
    {
    }

    /// <summary>
    /// Invoked when a purchase needs to be processed and fulfilled.
    /// </summary>
    /// <param name="order">The order awaiting fulfillment.</param>
    private void OnPurchasePending(PendingOrder order)
    {
    }
}
```

#### Get a StoreController

`StoreController` is the main interface for interacting with the In-App Purchasing functionality. You can get an instance of `StoreController` by calling [UnityIAPServices.StoreController](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.UnityIAPServices.html#UnityEngine_Purchasing_UnityIAPServices_StoreController_System_String_). It will return the default store controller or the specific store controller requested if a store name is provided.

#### Attach event handlers to the StoreController

For your store to function correctly, attach handlers to these events:

* [OnStoreDisconnected](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnStoreDisconnected)
* [OnProductsFetched](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnProductsFetched)
* [OnProductsFetchFailed](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnProductsFetchFailed)
* [OnPurchasesFetched](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnPurchasesFetched)
* [OnPurchasesFetchFailed](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnPurchasesFetchFailed)
* [OnPurchasePending](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_OnPurchasePending)

You may need to implement additional handlers as you integrate In-App Purchasing into your project. For a full list of events available through `StoreController`, refer to [Events](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#events).

#### Connect to your app store

Call [StoreController.Connect](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_Connect) to connect to the app store. The returned `Task` resolves when the connection either completes or fails. A connection failure will invoke the `OnStoreDisconnected` event. You must be connected to the store before using any IAP functionality.

#### Fetch products

> **Note:**
>
> Define your products in your catalog before fetching them. To choose a catalog setup method, refer to [Create an IAP catalog](/iap/catalogs.md).

To validate that your products are available for purchase, call [StoreController.FetchProducts](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_FetchProducts_System_Collections_Generic_List_UnityEngine_Purchasing_ProductDefinition__UnityEngine_Purchasing_IRetryPolicy_). Upon success, the `OnProductsFetched` event will be invoked with a list of successfully returned products. `OnProductsFetchFailed` will be invoked in the event of a failure.

Purchases can only be fetched or initiated for products which have been successfully returned. `FetchProducts` can be called multiple times during runtime, but you must wait for any previous requests to finish before calling `FetchProducts` again.

When using the Apple App Store, `OnPurchasePending` may be invoked for unprocessed orders after `FetchProducts` completes.

##### Fetch products from a catalog created in the Editor

The [initialization steps](#initialization-steps) example above defines products directly in code with `CatalogProvider`. If you instead defined your products using the [IAP Catalog window](./create-catalog-in-editor.md) in the Editor, follow these steps to fetch them:

1. Call [`ProductCatalog.LoadDefaultCatalog`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.ProductCatalog.html#UnityEngine_Purchasing_ProductCatalog_LoadDefaultCatalog) to load the catalog you created in the Editor.
2. Pass the catalog to [`CodelessCatalogProvider.PopulateCatalogProvider`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.CodelessCatalogProvider.html#UnityEngine_Purchasing_CodelessCatalogProvider_PopulateCatalogProvider_UnityEngine_Purchasing_ProductCatalog_) to get a `CatalogProvider` populated with your products.

The following example loads a catalog created in the Editor and populates a `CatalogProvider` with its products:

```cs
// Load the catalog created in the Editor
var catalog = ProductCatalog.LoadDefaultCatalog();
var catalogProvider = CodelessCatalogProvider.PopulateCatalogProvider(catalog);
```

Use this `catalogProvider` in place of the one built with `CatalogProvider.AddProduct` in the initialization steps example above, then continue with `catalogProvider.FetchProducts` as shown.

##### GetProducts

[`GetProducts`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_GetProducts) and `FetchProducts` are not interchangeable. Make sure to call `FetchProducts` during initialization. `FetchProducts` will append resulting products to the list returned by `GetProducts` each time it is called.

#### Fetch purchases

Call [`StoreController.FetchPurchases`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_FetchPurchases) to request your player's current active orders. Active orders include `PendingOrders`, `ConfirmedOrders` (active subscriptions and active non-consumables), and `DeferredOrders`. Refer to [Purchases](/iap/purchases.md) for more information.

Calls to `FetchPurchases` will trigger one of two event handlers: `OnPurchasesFetched`, which will be invoked with an `Orders` object containing all Pending, Confirmed, and Deferred orders returned from the store or `OnPurchasesFetchFailed`, which will be invoked in the event of a failure.
When using Google Play, this will invoke the `OnPurchasePending` event for any purchases which have not been processed.

This is not strictly required to begin using In-App Purchasing functionality. However, it is recommended that you fetch and handle existing purchases before initiating new purchases, as you may encounter unexpected behavior otherwise.

Note that if you fetch additional products during runtime, you will need to fetch purchases again.

##### Fetch purchases offline

Some platform libraries, such as Apple's StoreKit 2, cache entitlements on the device for offline access without caching product data. Although this approach isn't recommended, you can still call `FetchPurchases` after an `OnProductsFetchFailed` callback. In this case, `FetchPurchases` returns purchase information, but the linked products will have a `type` of [`ProductType.Unknown`](https://docs.unity3d.com/Packages/com.unity.purchasing@5.2/api/UnityEngine.Purchasing.ProductType.html). Also, both `ProductDefinition.id` and `ProductDefinition.storeSpecificId` are set to the store-specific identifier.

> **Note:**
>
> This doesn't apply to StoreKit 1. While StoreKit 1 caches the receipt on the device, the package requires fetched product data to parse receipt data. If product fetching fails, `FetchPurchases` doesn't return any purchase information.

##### GetPurchases

[`GetPurchases`](https://docs.unity3d.com/Packages/com.unity.purchasing@latest?subfolder=/api/UnityEngine.Purchasing.StoreController.html#UnityEngine_Purchasing_StoreController_GetPurchases) and `FetchPurchases` are not interchangeable. Make sure to call `FetchPurchases` during initialization. Unlike `GetProducts` and `FetchProducts`, `FetchPurchases` not only populates the list returned by `GetPurchases`, but also overwrites it. Otherwise the package will try to keep it as synchronized as possible with the stores, based on order data from events.

### Automatically initialize Codeless IAP

For instructions on how to set up Codeless IAP, refer to [Set Up Codeless IAP](/iap/codeless-iap.md#set-up-codeless-iap).

> **Note:**
>
> You should not enable auto-initialize if you also initialize manually in a script, as this may cause errors.

### Automatic Unity Game Services initialization for Codeless IAP

If you are using the Codeless IAP, enable Unity Gaming Services automatic initialization by checking the **Automatically initialize Unity Gaming Services** checkbox at the bottom of the **IAP Catalog** window.
This ensures that Unity Gaming Services initializes immediately when the application starts.

To use this feature, **Automatically initialize UnityIAPServices (recommended)** must be enabled. If you do not see these checkboxes inside the **IAP Catalog**, it may be because you have not yet added products in the catalog window.

This initializes Unity Gaming Services with the default initialization options. Some services require specific initialization options and might not work with the default configuration. If you need custom options, initialize Unity Gaming Services using the coded API described above.
