# Step-by-step IAP integration guide for Unity

This guide provides a clear, step-by-step walkthrough for integrating in-game purchases (also known as in-app purchases or IAP) into your web game using the Playgama SDK. While this guide uses Unity as the example engine, the Playgama SDK is designed to work seamlessly with other engines and JavaScript frameworks. Once integrated, your IAP will function across any supported portal, including [Playgama.com](https://playgama.com/).&#x20;

#### Understanding In-App Purchases and Pricing

In-app purchases (IAP) allow players to buy digital items or features directly within your game. The way you set prices for your IAP can vary depending on the platform where your game is published.

* Some platforms may require you to set prices directly in **real-world currency** (e.g., USD).
* Other platforms utilize a **virtual currency system**. In this case, you'll set and display the price of your IAP in the platform's specific virtual currency (for example, **Gam\*** for Playgama.com, **Yan** for Yandex, **Stars** for Playdeck, etc.). Players first acquire the platform's currency and then spend it on items in your game.

<sub>(\* Note: The conversion rate between Gam and real-world currencies is managed by the platform Playgama.com. Basically, 1 Gam equals 0.1 USD, meaning an item priced at 3.99 USD would cost approximately 40 Gam. Precise rates can be confirmed with your Developer Success Manager.)</sub>

#### Prerequisites

Before you begin, ensure you have:

1. Downloaded and installed the latest **Playgama SDK** into your Unity project. [Here](https://wiki.playgama.com/playgama/sdk/getting-started) is more information.
2. Registered a developer account on the [**Developer portal**](https://developer.playgama.com/).

This guide references our [IAP Demo project](https://developer.playgama.com/qa-tool/cmfb6071i00e9pa0hzjj0fsdo), which showcases a basic integration using the Playgama Bridge SDK.

<figure><img src="https://1088849411-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5ukgSPDBOdbQp4FYtbz1%2Fuploads%2FgwdjPeAw0uVLZzOTFNY9%2FScreenshot%202025-09-08%20at%2017.51.20.png?alt=media&#x26;token=04b9cd56-d3e4-4f99-8121-0be068c6d356" alt=""><figcaption></figcaption></figure>

#### Step 1: Define Your IAP Types and Items

1\) First, decide which types of purchases your game will offer. We support two main types:

* **Consumable:** single-use items (e.g., coins, gems, boosters), they can be purchased repeatedly. Ideal for temporary boosts or resource refill.
* **Permanent:** items that remain with the player permanently (e.g., ad-free mode, skins, characters), they can only be purchased once.

Understanding this difference will help you design a clear, player-friendly IAP strategy.

2\) Next, create a list of your specific IAP items and assign a unique id to each. This id will be used consistently across platforms and in your code.

**💡 Important:** For id, it is allowed to use letters, numbers, and the underscore character (\_), but you can't use spaces or the hyphen character (-).

**Example IAPs for our Demo game:**

* `NO_Ads`: A non-consumable item to permanently remove advertisements (player buy once and then have it unlimited within the game).
* `100_Coins`: A consumable item granting 100 units of the demo's in-game currency (player can buy as much as they want and then spent within the game).

#### Step 2: Configure IAP in `playgama-bridge-config.json`

You need to declare your IAPs within the `playgama-bridge-config.json` file located in your Unity project. This file tells the SDK about your purchasable items on different platforms.

{% file src="<https://1088849411-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5ukgSPDBOdbQp4FYtbz1%2Fuploads%2FDQzmOWnHUPVHElWZqe8t%2Fplaygama-bridge-config.json?alt=media&token=3237fc3d-8a52-4ad2-988e-ea6e3720b3c4>" %}

Add your IAP definitions to the `payments` array in the JSON file. Here’s an example based on our Demo project:

```javascript
  "payments": [
        {
            "id": "NO_Ads",
            "playgama": {
                "amount": 1
            },
            "playdeck": {
                "amount": 1,
                "description": "Disable Interstitial advertisements from the game"
            }
        },
        {
            "id": "100_Coins",
            "playgama": {
                "amount": 1
            },
            "playdeck": {
                "amount": 1,
                "description": "Get 100 coins"
            }
        }
    ]
```

**Key Configuration Fields:**

* id: The primary identifier you'll use in your game's code to refer to this IAP. Make it descriptive (e.g., `REMOVE_ADS`, `PACK_100_GEMS`). Later we will use `id` to get purchase names and prices inside our game.
* `amount` : The price of the IAP in platform currency (**Gam\*\*** for playgama and qa\_tool, **Stars** for playdeck). Calculate this based on your desired USD price point using the platform's conversion rate.&#x20;

<sup>\*\* 1 Gam equals $0.1 USD.</sup>

* `description` : A user-friendly description of the IAP displayed on the specific platform.

Replace the example IAPs in the `payments` section with your own game's items.

#### Step 3: Implement IAP Logic in Unity

With the configuration complete, let's integrate the IAP functionality into your Unity project. We'll use the `PlaygamaIAP.cs` script provided in the demo project as a foundation. While this script covers the essential calls, you may want to refactor or build upon it for a production-ready implementation.

**Initialization and Catalog Fetching:**

The core logic typically starts by fetching the available product catalog from the Playgama Bridge SDK. This retrieves details like localized names and prices for the IAPs you defined in the JSON file.

```csharp
private void Start()
{
    // Initialize No-Ads text based on saved flag
    UpdateNoAdsAvailableText(isNoAdsBought);

    // Fetch the product catalog
    Bridge.payments.GetCatalog(OnGetCatalogCompleted);
}
```

Inside Start method, first we initialize `NoAdsAvailableText`, then load catalog by using `Bridge.payments.GetCatalog` method and `OnGetCatalogCompleted` callback.

Inside `OnGetCatalogCompleted` we are getting the information from Catalog and display it in our demo project.

#### Step 4: Trigger Purchases from UI Elements

You'll need UI elements (typically Buttons) in your game to allow players to initiate purchases. We call `InitiatePurchase` method with specific name to Initiate Purchase. Instead of name you can also use ID and match ID in your script, but for this case to keep things simple we will use name.

```csharp
public void InitiatePurchase(string id)
{
    // Show spinner & start the purchase flow
    iapLoading.SetActive(true);
    currentPurchaseId = id;
    Bridge.payments.Purchase(currentPurchaseId, OnPurchaseCompleted);
}
```

Here is full script for IAPButton class:

{% file src="<https://1088849411-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5ukgSPDBOdbQp4FYtbz1%2Fuploads%2FBBZym7f5ndg8ybBWdVn4%2FIAPButton.cs?alt=media&token=ccb45b54-2dbc-4180-9c8f-055e59cac9b9>" %}

You need to add **IAPButton.cs** script the the same gameobject which also has attached Button component. You can refer in screenshot below:

<figure><img src="https://1088849411-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5ukgSPDBOdbQp4FYtbz1%2Fuploads%2Fz3vvs8zfS06q1auq4LQV%2Fimage.png?alt=media&#x26;token=fcb4e9bf-98a4-4dbe-864b-fcd040bd1f71" alt=""><figcaption></figcaption></figure>

So basically, in our **IAPButton.cs** script, we have method for calling IAP purchase from **PlaygamaIAP.cs** script and a `RefreshButton()` method, which is reloading / assigning purchase.

```csharp
private void OnEnable()
{
    playgamaIAP.OnPurchasesLoaded.AddListener(RefreshButton);
}

private void OnDisable()
{
    playgamaIAP.OnPurchasesLoaded.RemoveListener(RefreshButton);
}


public void RefreshButton()
{
    purchaseName.text = playgamaIAP.GetPurchaseNameById(id);
    purchasePrice.text = playgamaIAP.GetPurchasePriceById(id);
}
```

In this example we subscribe / unsubscribe to `OnPurchaseLoaded` event and inside `RefreshButton` function we just refresh text on the button.

So, essentially, when the user clicks the button, in our Demo project the function with the parameter `"NO_Ads"` (or `"100_Coins"`) is called, and we initiate the purchase via the **PlaygamaIAP.cs** script.

#### Step 5: Handle Purchase Completion and Consumption

The final step is handling the outcome of the purchase attempt within your main IAP script. Let’s dive deeper into `InitiatePurchase(string id)` function that we are using inside **IAPButton.cs**.

```csharp
public void InitiatePurchase(string id)
{
    // Show spinner & start the purchase flow
    iapLoading.SetActive(true);
    Bridge.payments.Purchase(id, OnPurchaseCompleted);
}
```

As shown in Step 4, your UI button will call the `InitiatePurchase` method located in your **PlaygamaIAP.cs** script. The `iapName` parameter passed to this method is the `id` you defined in your **playgama-bridge-config.json** file (e.g., "NO\_Ads", "100\_Coins"). &#x20;

You need to fill it for each supported platform (but no worries, it can be same for each platform). <br>

<figure><img src="https://1088849411-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5ukgSPDBOdbQp4FYtbz1%2Fuploads%2FOTH1oFn4oN42iqWaUHEy%2FScreenshot%202025-05-29%20at%2018.32.38.png?alt=media&#x26;token=907234c3-02d1-4fce-8cb2-94c321940162" alt=""><figcaption></figcaption></figure>

The `id` is typically set in the Unity Editor for each IAPButton using \[SerializeField] section (screenshot below):<br>

<figure><img src="https://1088849411-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5ukgSPDBOdbQp4FYtbz1%2Fuploads%2FfPetnJNrni6HR7B97w0M%2FScreenshot%202025-09-08%20at%2017.12.46.png?alt=media&#x26;token=5441806b-68bc-4c53-b808-6838afab24ee" alt=""><figcaption></figcaption></figure>

Now we are getting to the most interesting part — that’s the `InitiatePurchase` function with `OnPurchaseCompleted` callback inside **PlaygamaIAP.cs** class. This function is responsible for starting the purchase process with the Playgama SDK.

```csharp
public void InitiatePurchase(string iapName)
{
    // Show spinner & start the purchase flow
    iapLoading.SetActive(true);
    Bridge.payments.Purchase(iapName, OnPurchaseCompleted);
}

private void OnPurchaseCompleted(bool success, Dictionary<string, string> purchase)
{
    // Hide spinner after a moment
    Invoke(nameof(InvokeDisable), 1f);

    if (!success) return;

    if (purchase != null && purchase.TryGetValue("id", out var id) && !string.IsNullOrEmpty(id))
    {
        Debug.Log($"OnPurchaseCompleted ({id}) successfully,");
        if (id == "NO_Ads")
        {
            // Non-consumable: NO ADS
            isNoAdsBought = true;
            UpdateNoAdsAvailableText(true);
            Debug.Log("NO_Ads purchased. Disabling ads.");
        }
        else
        {
            // Consumable: consume to grant items/currency
            Bridge.payments.ConsumePurchase(id, OnConsumePurchaseCompleted);
        }
    }
    else
    {
        Debug.LogWarning("Purchase payload missing 'id' or it is empty. Skipping.");
    }
}
    
private void OnConsumePurchaseCompleted(bool success, Dictionary<string, string> purchase)
{
  
    if (!success) return;

    if (purchase != null && purchase.TryGetValue("id", out var id))
    {
        Debug.Log($"OnConsumePurchaseCompleted ({id}), success: {success}");
        if (id == "100_Coins")
        {
            coinAmount += 100;
            coinAmountText.text = "Balance: " + coinAmount + " Coins";
        }
        else
        {
            Debug.Log($"Unhandled purchase id: {id}");
        }
    }
    else
    {
        Debug.LogWarning("No 'id' key found in purchase dictionary.");
    }

}
```

`OnPurchaseCompleted` callback function is executed once the platform processes the purchase request. It checks the `success` flag. If `false`, the purchase failed, and the function exits. If `success` is `true`:

* It checks if the `id` is "NO\_Ads". If so, it's a **non-consumable item**. The game state is updated by setting `isNoAdsBought` to `true`, and the UI is refreshed via `UpdateNoAdsAvailableText(true)`(remember to save this isNoAdsBought state persistently).
* If the `purchaseId` is not "NO\_Ads" (e.g., "100\_Coins"), it's treated as a **consumable item**. In this case, `Bridge.payments.ConsumePurchase()` is called. This is crucial for consumable items, as it informs the platform that the item has been delivered, allowing the player to purchase it again.&#x20;

**💡 Important:** Always call `ConsumePurchase`method for consumable items *after* a successful purchase callback like in example above. Failure to consume prevents the player from buying the item again and may indicate the item wasn't properly delivered.

#### Step 6: Testing Your Integration

Once you've implemented these steps and build your game, upload the build to the **QA Tool** available on the [Playgama Developer portal](https://developer.playgama.com/). Testing in the QA environment ensures your IAPs work as expected before releasing your game.

* **Test Purchases:** All purchases made through the QA Tool are "testing" transactions. You will not be charged any real money during this testing phase.
* **Non-Consumable Purchase Outcome:**
  * For non-consumable purchase you will get "Success" message for payment in the QA Tool logs
* **Consumable Purchase Outcome:**
  * For consumable purchase you will get "Success" message for payment, and right after you should see "Success" message for consume. (Remember, you need to call Consume method right after purchase, if it's consumable)
  * **Important Reminder:** For consumable items, it is crucial to call the `ConsumePurchase` method immediately after a successful purchase confirmation.

<figure><img src="https://1088849411-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F5ukgSPDBOdbQp4FYtbz1%2Fuploads%2FmAvgcQQ94xU1OczQDxKN%2FScreenshot%202025-09-08%20at%2017.51.20.png?alt=media&#x26;token=516b3c6b-d90f-4614-82bd-0377205b3c15" alt=""><figcaption></figcaption></figure>

Feel free to contact your Developer Success Manager if you need any help.

Let's boost your game experience and revenue together! 🚀
