Skip to content

Google Play Store Purchasing

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

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

Overview

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

Step 1: Initialize the IAP System

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

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)
// 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:

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:

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:

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:

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:

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

Complete Example Script

Complete implementation of the IAP manager
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);
}
}

Redeem Purchase For Class

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.

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

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.