racoonbytes logoracoonbytes label

Unity IAP Guide (2025): How to Implement In-App Purchases After the Big API Change

10. September 2025

ArticleGames

On August 31, 2025, Google Play enforced a critical policy change: all apps must now use Google Play Billing Library v7.0.0 or newer, or their updates will be rejected.

If you’ve tried reading Unity’s docs on this… you’ve probably noticed they’re not super clear. This post is your practical guide to setting up Unity IAP with the latest API, handling purchases, and making sure your app passes Google’s new compliance checks.

Important: The August 31, 2025 Deadline

  • Starting August 31, 2025, Google requires Billing Library ≥ 7.0.0.
  • Unity addressed this with Unity IAP version 5.0.0, released on August 7, 2025, which ships with Billing Library 8.0.0.
  • If you’re still on Unity IAP 4.x or earlier, your builds will likely get rejected.

Step 1: Setting Up Unity IAP

Before writing any code, let’s get Unity IAP configured correctly. Install Unity IAP

  • Open Unity Package Manager → search for In-App Purchasing.
  • Install or update to version 5.0.0+ (this is required for Google Play Billing v6).

Enable IAP Services

  • Go to Services → In-App Purchasing in the Unity dashboard.
  • Enable it for your project.

Create a Product Catalog

  • Open Services → In-App Purchasing → IAP Catalog in the Unity editor.
  • Add all your products here:
    • Consumables → e.g. coins, gems.
    • Non-consumables → e.g. “Remove Ads”.
    • Subscriptions → if your game offers recurring content.

Uncheck Auto Initialization

  • In the IAP Catalog settings, disable “Automatically initialize UnityIAPServices”.
  • Why? Because we’ll initialize IAP manually in our IAPManager to have full control over the purchase flow and event handling.

Step 2: Central IAP Manager

To keep things clean, we’ll use an IAPManager singleton to initialize Unity IAP, fetch product metadata, and handle purchases. The IAPManager will be the central hub for all in-app purchases. Instead of sprinkling purchase logic throughout your game, we keep everything in one place. This makes it easier to debug, test, and expand later.

2.1 Create a Singleton Manager

We want only one IAPManager in the scene. Let’s set that up:

public class IAPManager : MonoBehaviour
{
    public static IAPManager Instance;

    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

Now any script can call IAPManager.Instance to trigger purchases or fetch product info.

2.2 Define Your Products

Hardcoding product IDs everywhere is messy. Instead, we put them in one place:

public static class ProductIDs
{
    public const string NO_ADS = "com.mygame.no_ads";
    public const string COINS_SMALL = "com.mygame.coins_0099";
    public const string COINS_LARGE = "com.mygame.coins_0999";
}

public enum ProductKeys
{
    no_ads,
    coins_small,
    coins_large
}
  • The constants (ProductIDs) match the IDs you created in Google Play Console / App Store Connect.
  • The enum (ProductKeys) makes it safer to reference products in code without typos.

2.3 Initialize Unity IAP

Now we connect to Unity’s new IAP system and fetch products. This step prepares the store so you can later trigger purchases.

private StoreController storeController;

private async void Start()
{
    storeController = UnityIAPServices.StoreController();

    // Listen to store events
    storeController.OnPurchasePending += OnPurchasePending;
    storeController.OnPurchaseConfirmed += OnPurchaseConfirmed;
    storeController.OnPurchaseFailed += OnPurchaseFailed;

    await storeController.Connect();

    // Fetch your products
    FetchProducts();
}

private void FetchProducts()
{
    var products = new List<ProductDefinition>
    {
        new(ProductIDs.NO_ADS, ProductType.NonConsumable),
        new(ProductIDs.COINS_SMALL, ProductType.Consumable),
        new(ProductIDs.COINS_LARGE, ProductType.Consumable)
    };

    storeController.FetchProducts(products);
}
  • Connect() makes sure the game can talk to the App Store / Google Play.
  • FetchProducts() retrieves product details (title, price, description) which you’ll display in your shop UI.

At this point, we have:

  • A singleton manager
  • Product IDs and enums
  • Unity IAP connected & fetching products

Next, we’ll handle purchases and rewards.

2.4 Handling Purchases

Once products are fetched, we need to handle what happens when a player taps Buy. Purchases go through three main states:

  • Pending → the purchase is started but not yet confirmed.
  • Confirmed → the store verifies the payment.
  • Failed → something went wrong (canceled, declined, network issues).

Let’s add handlers inside IAPManager:

private void OnPurchasePending(PendingOrder order)
{
    var product = order.CartOrdered.Items().First()?.Product;
    Debug.Log($"Pending purchase: {product.definition.id}");

    // Grant reward now if you want immediate effect
    // But for consumables, best practice is to wait until confirmed

    // Confirm purchase so the transaction is completed
    storeController.ConfirmPurchase(order);
}

private void OnPurchaseConfirmed(Order order)
{
    var product = order.CartOrdered.Items().First()?.Product;
    Debug.Log($"Confirmed purchase: {product.definition.id}");

    GrantReward(product.definition.id);
}

private void OnPurchaseFailed(FailedOrder order)
{
    var product = order.CartOrdered.Items().First()?.Product;
    Debug.Log($"Purchase failed for {product?.definition.id}, reason: {order.FailureReason}");
}

2.5 Granting Rewards

Now let’s define what happens when a product is bought. This is where you remove ads, give coins, unlock skins, etc.

private void GrantReward(string productId)
{
    switch (productId)
    {
        case ProductIDs.NO_ADS:
            GameManager.Instance.PlayerProfile.RemoveAds();
            break;

        case ProductIDs.COINS_SMALL:
            GameManager.Instance.PlayerProfile.AddCoins(1000);
            break;

        case ProductIDs.COINS_LARGE:
            GameManager.Instance.PlayerProfile.AddCoins(5000);
            break;

        default:
            Debug.LogWarning("Unknown product: " + productId);
            break;
    }
}

We map product IDs → game rewards in one place. This avoids duplicating logic across the project.

2.6 Triggering Purchases

Finally, we need a way to start a purchase when the user clicks a buy button.

public void BuyProduct(ProductKeys key)
{
    string productId = key switch
    {
        ProductKeys.no_ads => ProductIDs.NO_ADS,
        ProductKeys.coins_small => ProductIDs.COINS_SMALL,
        ProductKeys.coins_large => ProductIDs.COINS_LARGE,
        _ => null
    };

    if (!string.IsNullOrEmpty(productId))
    {
        storeController.PurchaseProduct(productId);
    }
    else
    {
        Debug.LogWarning("Invalid product key: " + key);
    }
}

At this stage, our IAPManager can:

  • Initialize Unity IAP
  • Fetch products from the store
  • Handle purchase events
  • Grant rewards
  • Expose a clean BuyProduct(ProductKeys key) method

This gives us a complete backend for IAP.

Step 3: Hooking IAP into the UI

At this point, our IAPManager can talk to the store and handle purchases. Now we need a way for players to see items in the shop and buy them. We’ll create a BuyItem component that you can attach to shop buttons or cards.

3.1 Basic Setup

We’ll start with the structure:

using UnityEngine;
using UnityEngine.UI;

public class BuyItem : MonoBehaviour
{
    [SerializeField] private TMPro.TextMeshProUGUI productName;
    [SerializeField] private TMPro.TextMeshProUGUI productDescription;
    [SerializeField] private TMPro.TextMeshProUGUI price;
    [SerializeField] private Image productImage;
    [SerializeField] private Button buyButton;

    private IAPManager.ProductKeys product;

    public void SetProduct(IAPManager.ProductKeys key, Sprite icon)
    {
        product = key;
        productImage.sprite = icon;
        UpdateUI();
    }

    private void UpdateUI()
    {
        var meta = IAPManager.Instance.GetProductMetaData(product);
        productName.text = meta.localizedTitle;
        productDescription.text = meta.localizedDescription;
        price.text = meta.localizedPriceString;
    }
}
  • SetProduct assigns which IAP item this UI element represents.
  • UpdateUI pulls real data (title, description, price) directly from the store instead of hardcoding.
  • This means prices will always match Google Play / App Store automatically.

3.2 Hooking the Buy Button

Now let’s make the button trigger a purchase:

private void Awake()
{
    buyButton.onClick.AddListener(OnBuyClicked);
}

private void OnBuyClicked()
{
    IAPManager.Instance.BuyProduct(product);
}

The button stays simple → it just calls the IAPManager. No store logic is hidden in the UI.

3.3 Showing Success Feedback

We’ll add a little success popup when a transaction completes.

[SerializeField] private GameObject successUI;

private void OnEnable()
{
    IAPManager.Instance.OnSuccessfullTransaction += OnSuccess;
}

private void OnDisable()
{
    IAPManager.Instance.OnSuccessfullTransaction -= OnSuccess;
}

private void OnSuccess()
{
    successUI.SetActive(true);
}

Why subscribe/unsubscribe? To avoid memory leaks or duplicate events if this UI gets enabled/disabled often.

3.4 Putting It Together in Unity

  • Create a prefab for your shop item card.
  • Add the BuyItem script.
  • Drag your TextMeshProUGUI fields, Image, Button, and Success UI into the inspector.
  • Call SetProduct when populating your shop screen:
buyItem.SetProduct(IAPManager.ProductKeys.no_ads, noAdsSprite);

Now your shop item will:

  • Display the real price and description from the store.
  • Trigger purchases when tapped.
  • Show success UI on completion.

With this, your UI is fully connected to the IAP system.

Step 4: Testing and Deployment

By now, you have:

  • Installed the latest Unity IAP.
  • Built an IAPManager to handle all store logic.
  • Connected your UI to real product metadata and purchase flow.

The last step is making sure everything works in the real store environments before launch.

4.1 Local Testing (Editor Play Mode)

Unity IAP 5+ comes with a fake store that lets you simulate purchases without uploading to Google or Apple.

  • In Editor Play Mode, purchases don’t contact the real store.
  • You’ll see test popups (like “Purchase succeeded” or “Purchase failed”).
  • Great for testing your UI logic and event handling.

Note: Prices, receipts, and purchase flow won’t be identical to real Google/Apple behavior. Always move to sandbox testing next.

4.2 Sandbox Testing on Google Play

  • Upload your build to the Google Play Console → Internal Testing Track.
  • Add license testers under Play Console → Settings → License Testing (usually your own Gmail).
  • Make sure your products are set up in Monetization → Products → In-app products with the same IDs you used in IAPManager.
  • Install the test version via Play Store internal testing link.
  • Try buying your product:
  • The price shows as real, but the transaction completes with a special sandbox account popup.
  • You won’t actually be charged.

4.3 Sandbox Testing on iOS

  • In App Store Connect, go to Users and Access → Sandbox Testers.
  • Create a test Apple ID.
  • In App Store Connect → Features → In-App Purchases, create the products with matching IDs.
  • Build your game for iOS and install via TestFlight or Xcode.
  • Sign into the test device with your sandbox Apple ID when prompted.

4.4 Restoring Purchases (iOS-only Requirement)

On iOS, Apple requires that you provide a Restore Purchases button for non-consumables (like “No Ads” or bundles).

In IAPManager, you can hook it up like this:

public void RestorePurchases()
{
    storeController.RestorePurchases();
}

Add a button in your shop UI that calls RestorePurchases(). Google Play doesn’t require this, purchases are auto-restored when reinstalling.

4.5 Deployment Checklist

Before you hit Publish, double-check:

  • All products exist in both the store console and your ProductIDs class.
  • Product types match (Consumable vs NonConsumable).
  • Testing works on at least one sandbox account.
  • A Restore Purchases button exists for iOS.
  • Your UI reacts gracefully to failures (like no internet).

You’re Ready to Launch!

With Unity IAP v5.0+:

  • You’re future-proof against Google’s Billing v6 requirement.
  • Your IAP flow is centralized in one clean IAPManager.
  • Your UI auto-updates prices and descriptions from the store.
  • Testing is streamlined with editor, sandbox, and restore purchase flows. Now you can safely publish your game with real monetization.

Related Articles for Further Reading