# Make IAP Purchases In-Game

Set up in-app purchases through Apple App Store and redeem them with LootLocker to grant rewards to players.

## Prerequisites

* [A LootLocker account and a created game](https://lootlocker.com/sign-up)
* An Apple Developer account with access to [App Store Connect](https://appstoreconnect.apple.com/)
* [An active Game Session](/players/authentication.md)
* Unity with the [In-App Purchasing package](https://docs.unity3d.com/Packages/com.unity.purchasing@4.1/manual/UnityIAPGoogleConfiguration.html) installed
* [A Catalog Listing configured for Apple App Store IAP](/commerce/real-money-purchases/how-to/apple-app-store/configure-catalog-listing-apple-app-store.md)

## Implementing In-App Purchases

To implement purchases in your game, you need to:

1. **Initialize** Unity's IAP system for Apple App Store
2. **Register** your products with the Product IDs from App Store Connect
3. **Handle** the purchase flow when users buy items
4. **Redeem** purchases with LootLocker to grant rewards

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

#### Setting Up the IAP Manager

Create an `IAPManager` script that inherits from `IDetailedStoreListener` to handle all purchase callbacks.

<details>

<summary>IAPManager Script</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 Apple App Store
        var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance(AppStore.AppleAppStore));

        // Register your products from App Store Connect
        builder.AddProduct("com.company.game.coins100", ProductType.Consumable);
        builder.AddProduct("com.company.game.coins500", ProductType.Consumable);
        builder.AddProduct("com.company.game.premium_pass", ProductType.NonConsumable);

        // 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 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 purchaseToken = e.purchasedProduct.transactionID;

        // Redeem with LootLocker (see section below for details)
        RedeemPurchaseForPlayer(purchaseToken);

        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);
    }

    private void RedeemPurchaseForPlayer(string purchaseToken)
    {
        LootLockerSDKManager.RedeemAppleAppStorePurchaseForPlayer(purchaseToken, (result) =>
        {
            if (!result.success)
            {
                Debug.Log("Redeem Purchase unsuccessful!");
                return;
            }
        });
    }
}
```

</details>
{% endtab %}

{% tab title="Unreal" %}
Coming soon
{% endtab %}

{% tab title="REST" %}
To initiate a purchase, use the Apple App Store's StoreKit. After a successful purchase, extract the transaction ID and send it to LootLocker for validation.

```bash
# After getting a transaction ID from a successful purchase, redeem it:
curl -X POST 'https://api.lootlocker.io/game/store/apple/redeem' \
    -H 'x-session-token: your_session_token' \
    -H 'Content-Type: application/json' \
    -d '{
        "sandboxed": true,
        "transaction_id": "2000000316432479"
    }'
```

{% endtab %}
{% endtabs %}

## Redeeming Purchases for the Player

After a purchase completes, you need to redeem it with LootLocker to validate the purchase and grant rewards to the player.

When redeeming, provide the **transaction ID** from the completed purchase. LootLocker will validate it with Apple's servers and grant the configured rewards.

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

```csharp
private void RedeemPurchaseForPlayer(string purchaseToken)
{
    LootLockerSDKManager.RedeemAppleAppStorePurchaseForPlayer(purchaseToken, (result) =>
    {
        if (!result.success)
        {
            Debug.Log("Redeem Purchase unsuccessful!");
            return;
        }

        Debug.Log("Purchase successfully redeemed with LootLocker!");
    });
}
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="/files/QkAMnSypMoNQReAYkTkh" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/8yuhry6z/">Blueprint example of Redeeming purchase for Player</a></p></figcaption></figure>

Extract the transaction ID from a successful purchase and pass it to the redeem function.
{% endtab %}

{% tab title="REST" %}

```bash
curl -X POST 'https://api.lootlocker.io/game/store/apple/redeem' \
    -H 'x-session-token: your_session_token' \
    -H 'Content-Type: application/json' \
    -d '{
        "sandboxed": true,
        "transaction_id": "2000000316432479"
    }'
```

On successful redemption, a `204 No Content` response is returned.
{% endtab %}
{% endtabs %}

## Redeeming Purchases for a Class

You can also redeem purchases to reward a specific class that the player owns. This is useful for class-specific cosmetics or items.

When redeeming for a class, provide both the **transaction ID** and the **class ID** of the target class.

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

```csharp
public void RedeemPurchaseForClass(string purchaseToken, int classID)
{
    LootLockerSDKManager.RedeemAppleAppStorePurchaseForClass(purchaseToken, classID, (result) =>
    {
        if (!result.success)
        {
            Debug.Log("Redeem Purchase unsuccessful!");
            return;
        }

        Debug.Log($"Purchase successfully redeemed for class {classID}!");
    });
}
```

{% endtab %}

{% tab title="Unreal" %}

<figure><img src="/files/A2zF5L96IBA1oTiGNXtl" alt=""><figcaption><p><a href="https://blueprintue.com/blueprint/vatf8o79/">Blueprint example of redeeming purchase for class</a></p></figcaption></figure>

Extract the transaction ID and provide the class ID to the redeem function.
{% endtab %}

{% tab title="REST" %}

```bash
curl -X POST 'https://api.lootlocker.io/game/redeem/store/apple' \
    -H 'x-session-token: your_session_token' \
    -H 'Content-Type: application/json' \
    -d '{
        "sandboxed": true,
        "transaction_id": "2000000316432499",
        "character_id": 123
    }'
```

On successful redemption, a `204 No Content` response is returned.
{% endtab %}
{% endtabs %}

## Conclusion

You now have a complete Apple in-app purchase flow: setting up products in App Store Connect, implementing the IAP system in Unity, handling purchases, and redeeming them through LootLocker to grant rewards.

With this setup, your game can securely support Apple in-app purchases while maintaining centralized reward logic 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/apple-app-store/apple-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.
