# Make IAP Purchases In-Game

In this guide, we will walk through how to implement the in-game purchase flow for Steam 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/)
* [Steam Store IAP configured for your game](/commerce/real-money-purchases/how-to/steam/configure-steam-iap-settings.md)
* A [Catalog Listing configured for Steam IAP](/commerce/real-money-purchases/how-to/steam/configure-catalog-listing-steam.md)
* [LootLocker SDK integrated](/the-basics/sdks.md) into your game

### Initiate Purchase In-Game

Trigger the Steam purchase flow using LootLocker’s Steam purchase redemption API.

This begins the transaction with Steam and returns an `entitlement_id`, which is used to track the purchase throughout the flow.

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

```csharp
CSteamID steamUser = SteamUser.GetSteamID();
string steamLanguage = SteamApps.GetCurrentGameLanguage();

LootLockerSDKManager.BeginSteamPurchaseRedemption(
    steamId: steamUser.ToString(),
    currency: "USD",
    language: steamLanguage,
    catalogItemId: "01HRCA5QQBV9P0A57RFK9J073T",
    onComplete: (response) =>
    {
        if (response.success)
        {
            Debug.Log("Steam purchase started. Entitlement ID: " + response.entitlement_id);
            entitlementId = response.entitlement_id;
            // Begin polling for purchase status
            StartCoroutine(PollSteamPurchaseStatus(entitlementId));
        }
        else
        {
            Debug.LogError("Failed to start purchase: " + response.errorData.message);
        }
    }
);
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="/files/gcaS9Fwjv4lncw0Eg3XB" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/q0svk_xn/">Blueprint example of Starting Redemption of purchase for Player</a></p></figcaption></figure>
{% endtab %}
{% endtabs %}

Use the `entitlement_id` to query the status of the purchase.

LootLocker will communicate with Steam to determine whether the user has approved, cancelled, or is still pending the transaction. Poll this endpoint until a final status is reached.

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

```csharp
IEnumerator PollSteamPurchaseStatus(string entitlementId)
{
    while (true)
    {
        LootLockerSDKManager.QuerySteamPurchaseRedemption(entitlementId, (response) =>
        {
            if (response.success)
            {
                if (response.status == LootLocker.LootLockerEnums.SteamPurchaseRedemptionStatus.Approved)
                {
                    Debug.Log("Purchase approved by user. Finalizing...");
                    FinalizeSteamPurchase(entitlementId);
                    purchasePollingComplete = true;
                }
                else if (response.status == LootLocker.LootLockerEnums.SteamPurchaseRedemptionStatus.Canceled)
                {
                    Debug.Log("Purchase was canceled by user");
                    purchasePollingComplete = true;
                }
                // If status is Pending, continue polling
            }
            else
            {
                Debug.LogError("Failed to query purchase status: " + response.errorData.message);
            }
        });
        
        yield return new WaitForSeconds(2f); // Poll every 2 seconds
        
        if (purchasePollingComplete)
            break;
    }
}
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="/files/DGJjHnkA1c8ahFpeN646" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/zj255w_8/">Blueprint example of querying the Purchase status</a></p></figcaption></figure>
{% endtab %}
{% endtabs %}

Once the purchase status is confirmed as approved, finalize the transaction using the `entitlement_id`.

LootLocker will then grant the configured rewards (Assets, Currency, Progressions) to the player.

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

```csharp
void FinalizeSteamPurchase(string entitlementId)
{
    LootLockerSDKManager.FinalizeSteamPurchaseRedemption(entitlementId, (response) =>
    {
        if (response.success)
        {
            Debug.Log("Purchase finalized! Rewards granted to player.");
            // Refresh player data to see the granted rewards
            LootLockerSDKManager.GetPlayerData((playerResponse) =>
            {
                if (playerResponse.success)
                {
                    Debug.Log("Player data updated with new rewards");
                }
            });
        }
        else
        {
            Debug.LogError("Failed to finalize purchase: " + response.errorData.message);
        }
    });
}
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="/files/4skG4AKfajTaboGPkAYx" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/yvuo2atg/">Blueprint example of Finalizing the purchase</a></p></figcaption></figure>
{% endtab %}
{% endtabs %}

If your game uses Classes, you can grant rewards directly to those instead of the player.

This is useful for character-specific purchases or unlocks.

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

```csharp
CSteamID steamUser = SteamUser.GetSteamID();
string steamLanguage = SteamApps.GetCurrentGameLanguage();

LootLockerSDKManager.BeginSteamPurchaseRedemptionForClass(
    steamId: steamUser.ToString(),
    currency: "USD",
    language: steamLanguage,
    catalogItemId: "01HRCA5QQBV9P0A57RFK9J073T",
    classId: playerClassId,
    onComplete: (response) =>
    {
        if (response.success)
        {
            Debug.Log("Steam purchase for class started. Entitlement ID: " + response.entitlement_id);
            entitlementId = response.entitlement_id;
            // Begin polling for purchase status
            StartCoroutine(PollSteamPurchaseStatus(entitlementId));
        }
        else
        {
            Debug.LogError("Failed to start purchase: " + response.errorData.message);
        }
    }
);
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="/files/jPVb8LET9ZS3ldXV4S4O" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/xynsg67z/">Blueprint example of beginning a Steam Purchase for Class</a></p></figcaption></figure>
{% endtab %}
{% endtabs %}

Make sure your implementation accounts for:

* Failed or cancelled purchases
* Pending transactions (user has not completed the Steam overlay flow)
* Polling for purchase completion (required for Steam flow)
* Duplicate finalization attempts (ensure idempotency when calling finalize)

LootLocker handles communication with Steam and validation, but your game is responsible for handling the polling flow and updating the user experience accordingly.

### Conclusion

You now have the full Steam purchase flow implemented: initiating a purchase, polling for its status, and finalizing it through LootLocker to grant rewards to the player.

With this setup, you can securely support Steam 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/steam/steam-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.
