# Make IAP Purchases In-Game

In this guide, we will walk through how to implement the in-game purchase flow for Google Play Store using LootLocker, from initiating a purchase to validating and granting rewards to the player.

### Prerequisites

* [A LootLocker account](https://lootlocker.com/sign-up)
* At least one created game in the [LootLocker Web Console](https://console.lootlocker.com/)
* [Google Play Store IAP configured for your game](/commerce/real-money-purchases/how-to/google-play-store/configure-google-play-store-iap-settings.md)
* A [Catalog Listing configured for Google Play Store IAP](/commerce/real-money-purchases/how-to/google-play-store/configure-catalog-listing-google-play-store.md)
* [LootLocker SDK integrated](/the-basics/sdks.md) into your game

{% hint style="warning" %}
It is presumed that you have at least made an Application in Google Play Console!
{% endhint %}

To implement in-app purchases in your game, you need to:

1. **Initialize** Unity's IAP system
2. **Register** your Google Play products in the IAP system
3. **Handle** the purchase flow when users buy items
4. **Redeem** purchases with LootLocker

{% tabs %}
{% tab title="Unity" %}

#### Overview

Unity's IAP system handles the communication with Google Play Store. To use it, you must:

* Inherit from `IDetailedStoreListener` to receive purchase callbacks
* Import the [Unity In-App Purchasing package](https://docs.unity3d.com/Packages/com.unity.purchasing@4.1/manual/UnityIAPGoogleConfiguration.html)

#### Step 1: Initialize the IAP System

In your `Awake()` method, initialize Unity Services and create an IAP configuration builder:

```csharp
public async void Awake()
{
    try
    {
        var options = new InitializationOptions()
            .SetEnvironmentName("production");
        await UnityServices.InitializeAsync(options);
    }
    catch (Exception exception)
    {
        Debug.Log(exception);
    }

    // Create a configuration builder specifically for Google Play Store
    var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance(AppStore.GooglePlay));
}
```

#### Step 2: Register Your Products

For each product you created in Google Play Console, you must register it with the IAP system using `AddProduct()`. This tells Unity which products are available for purchase.

The `AddProduct()` method takes two parameters:

* **Product ID**: The ID you created in Google Play Console (e.g., "com.company.game.coins100")
* **Product Type**: The type of product - `Consumable` (can be purchased multiple times) or `NonConsumable` (one-time purchase)

```csharp
// Register a consumable product (can be repurchased)
builder.AddProduct("com.company.game.coins100", ProductType.Consumable);
builder.AddProduct("com.company.game.coins500", ProductType.Consumable);

// Register a non-consumable product (one-time purchase)
builder.AddProduct("com.company.game.premium_pass", ProductType.NonConsumable);
```

Replace `com.company.game.coins100` with your actual product IDs from Google Play Console.

#### Step 3: Initialize the Purchasing System

After configuring all your products, initialize the IAP system:

```csharp
UnityPurchasing.Initialize(this, builder);
```

This call registers your `IDetailedStoreListener` (typically your class implementing the interface) to receive purchase notifications.

#### Step 4: Handle Purchase Initialization Callback

When the IAP system is ready, `OnInitialized()` is called. Store the controller for later use:

```csharp
public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
    this.controller = controller;
    this.extensions = extensions;
}
```

#### Step 5: Trigger a Purchase

When a user clicks a "Buy" button, call `InitiatePurchase()` with the product ID. First, verify the product exists and is available:

```csharp
public void Purchase(string productId)
{
    var product = controller.products.WithID(productId);

    // Check if the product exists and can be purchased
    if (product is { availableToPurchase: true })
    {
        controller.InitiatePurchase(product);
    }
    else
    {
        Debug.Log("Product not available for purchase");
    }
}
```

#### Step 6: Handle Purchase Success

When a purchase completes successfully, `ProcessPurchase()` is called. In this method, send the purchase data to LootLocker for validation and redemption:

```csharp
public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
{
    // Extract purchase details
    string productID = e.purchasedProduct.definition.id;
    string purchaseToken = e.purchasedProduct.transactionID;

    // Send to LootLocker for validation and redemption
    LootLockerSDKManager.RedeemGooglePlayStorePurchaseForPlayer(productID, purchaseToken, (result) =>
    {
        if (!result.success)
        {
            Debug.Log("Redeem Purchase unsuccessful!");
            return;
        }
        Debug.Log("Purchase successfully redeemed with LootLocker");
    });

    return PurchaseProcessingResult.Complete;
}
```

#### Step 7: Handle Purchase Failures

If a purchase fails, `OnPurchaseFailed()` is called:

```csharp
public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription)
{
    Debug.Log($"Purchase failed for product {product.definition.id}: {failureDescription.reason}");
}
```

#### Complete Example Script

<details>

<summary>Complete implementation of the IAP manager</summary>

```csharp
using Unity.Services.Core;
using Unity.Services.Core.Environments;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Extension;

public class IAPManager : MonoBehaviour, IDetailedStoreListener
{
    public IStoreController controller;
    private IExtensionProvider extensions;

    public async void Awake()
    {
        try
        {
            var options = new InitializationOptions()
                .SetEnvironmentName("production");

            await UnityServices.InitializeAsync(options);
        }
        catch (Exception exception)
        {
            Debug.Log(exception);
        }

        // Create IAP configuration for Google Play Store
        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance(AppStore.GooglePlay));

        // Register your products (replace with your actual product IDs from Google Play Console)
        builder.AddProduct("com.company.game.coins100", ProductType.Consumable);
        builder.AddProduct("com.company.game.coins500", ProductType.Consumable);

        // Initialize the purchasing system
        UnityPurchasing.Initialize(this, builder);
    }

    /// <summary>
    /// Called when a user clicks the purchase button
    /// </summary>
    public void OnPurchaseClicked(string productId)
    {
        Purchase(productId);
    }

    /// <summary>
    /// Initiates a purchase for the given product ID
    /// </summary>
    public void Purchase(string productId)
    {
        var product = controller.products.WithID(productId);

        if (product is { availableToPurchase: true })
        {
            controller.InitiatePurchase(product);
        }
        else
        {
            Debug.Log($"Product {productId} is not available for purchase");
        }
    }

    /// <summary>
    /// Called when Unity IAP is ready to make purchases
    /// </summary>
    public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
    {
        this.controller = controller;
        this.extensions = extensions;
    }

    /// <summary>
    /// Called when Unity IAP encounters an unrecoverable initialization error
    /// </summary>
    public void OnInitializeFailed(InitializationFailureReason error)
    {
        Debug.Log($"IAP initialization failed: {error}");
    }

    /// <summary>
    /// Called when a purchase completes successfully
    /// </summary>
    public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs e)
    {
        string productID = e.purchasedProduct.definition.id;
        string purchaseToken = e.purchasedProduct.transactionID;

        LootLockerSDKManager.RedeemGooglePlayStorePurchaseForPlayer(productID, purchaseToken, (result) =>
        {
            if (!result.success)
            {
                Debug.Log("Redeem Purchase unsuccessful!");
                return;
            }
        });

        return PurchaseProcessingResult.Complete;
    }

    /// <summary>
    /// Called when a purchase fails
    /// </summary>
    public void OnPurchaseFailed(Product product, PurchaseFailureDescription failureDescription)
    {
        Debug.Log($"Purchase failed: {failureDescription.reason}");
    }

    public void OnInitializeFailed(InitializationFailureReason error, string message)
    {
        Debug.Log("IAP Error: " + message);
    }
}
```

</details>
{% endtab %}

{% tab title="Unreal" %}

#### Coming soon

{% endtab %}
{% endtabs %}

### Redeem Purchase For Class

{% tabs %}
{% tab title="Unity" %}
`Product` is from using UnityEngine.Purchasing;

It is possible to redeem a purchase for a class instead of a player, the flow is the same just that you use the function called `RedeemGooglePlayStorePurchaseForClass` instead.

```csharp
public void RedeemPurchase(Product product)
{
    string productID = product.definition.id;
    string purchaseToken = product.transactionID;
    int classID = 123;
    LootLockerSDKManager.RedeemGooglePlayStorePurchaseForClass(productID, purchaseToken, classID, (result) =>
    {
        if (!result.success)
        {
            Debug.Log("Redeem Purchase unsuccessful!");
            return;
        }

    });
}
```

{% endtab %}

{% tab title="Unreal" %}
It is possible to redeem a purchase for a class instead of a player, the flow is the same just that you use the function called `RedeemGooglePlayStorePurchaseForClass` instead.

<figure><img src="/files/IrTNFE9DdqBY6JnPc15m" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/pl549sul/">Blueprint example of redeeming purchase for class</a></p></figcaption></figure>
{% endtab %}

{% tab title="REST" %}

```bash
curl --location --request POST 'https://api.lootlocker.io/game/redeem/store/google' \
--header 'x-session-token: {{session_token}}' \
--header 'User-Agent: Apidog/1.0.0 (https://apidog.com)' \
--header 'Content-Type: application/json' \
--data-raw '{
    "sandboxed": true,
    "transaction_id": "2000000316432499",
    "character_id": 123
}'
```

On a successful Purchase, a 204 will be returned with no body.
{% endtab %}
{% endtabs %}

### Conclusion

You now have the full Google Play Store purchase flow implemented: initiating a purchase using Google Play Billing, validating it through LootLocker, and granting rewards to the player.

With this setup, you can securely support Google Play in-app purchases while keeping your game logic centralized through LootLocker.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.lootlocker.com/commerce/real-money-purchases/how-to/google-play-store/google-play-store-purchasing.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
