Skip to main content

Adding AppCoins alongside Unity IAP v5

This guide covers adding AppCoins Billing to a Unity game that already uses Unity IAP v5 (5.0 or later). If your project uses an older Unity IAP version, see Adding AppCoins alongside Unity IAP v4 or earlier first. One additional line of code is required before your existing Connect() call. Every event handler, product definition, and confirm logic you have written stays unchanged — AppCoins becomes the active store on Aptoide-distributed builds.

Setup

Download the latest .unitypackage from the GitHub releases page and import it:

  1. In Unity, go to Assets → Import Package → Custom Package...
  2. Select the downloaded .unitypackage file.
  3. In the Import Unity Package dialog, ensure all items are selected and click Import.

The plugin files will appear under Assets/Plugins/iOS/AppCoinsSDKPlugin/.

Overview

AppCoins integrates with Unity IAP v5 as a custom store provider. Once configured, the StoreController API you already use routes purchases through AppCoins Billing automatically when the conditions are met, and falls back to Apple Billing everywhere else. No separate purchase API is required.

The One Change

Two things to add to any file that uses AppCoins APIs: the namespace import, and a single await before Connect().

Before:

_controller = UnityIAPServices.StoreController();
_controller.OnProductsFetched += OnProductsFetched;
_controller.OnPurchasePending += OnPurchasePending;
_controller.ProcessPendingOrdersOnPurchasesFetched(true);
await _controller.Connect();
_controller.FetchProducts(new List<ProductDefinition> { new ProductDefinition("your_product_id", ProductType.Consumable) });
_controller.FetchPurchases();

After:

using AppCoins.Unity; // Add this using directive

// ↓ This is the only new line required
await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);

_controller = UnityIAPServices.StoreController();
_controller.OnProductsFetched += OnProductsFetched;
_controller.OnPurchasePending += OnPurchasePending;
_controller.ProcessPendingOrdersOnPurchasesFetched(true);
await _controller.Connect();
_controller.FetchProducts(new List<ProductDefinition> { new ProductDefinition("your_product_id", ProductType.Consumable) });
_controller.FetchPurchases();
⚠️
Warning: Call and await ConfigureStoreAsync before controller.Connect(). Calling Connect() without configuring the store first will result in an incorrect or missing store provider.

What Automatic Mode Does

AppCoinsStoreMode.Automatic queries AppDistributor.current at launch and activates AppCoins Billing on iOS 17.4+ installs that are not from the Apple App Store or TestFlight. For the full breakdown by install source, see How Runtime Detection Works.

Your OnPurchasePending, OnProductsFetched, OnPurchaseConfirmed, and OnPurchaseFailed handlers fire identically regardless of which store is active. Inspect AppCoinsIAP.SelectedStore after ConfigureStoreAsync returns to see which path was taken:

var selectedStore = await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);
// selectedStore is either "AppCoinsAppStore" or "AppleAppStore"
Debug.Log("Active billing store: " + selectedStore);

Receipt Changes

If you perform server-side purchase validation, note that order.Info.Receipt contains an AppCoins JSON payload instead of an Apple receipt when AppCoins Billing is active. See Purchase Validation for the receipt structure and server-side validation flow.

Before / After Full Example

The example below shows a complete Unity IAP v5 setup and highlights the single change needed to add AppCoins.

Before — standard Unity IAP v5 with Apple only:

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Extension;

public class IAPManager : MonoBehaviour
{
private StoreController _controller;

private async void Start()
{
_controller = UnityIAPServices.StoreController();
_controller.OnProductsFetched += OnProductsFetched;
_controller.OnPurchasePending += OnPurchasePending;

_controller.ProcessPendingOrdersOnPurchasesFetched(true);

await _controller.Connect();

_controller.FetchProducts(new List<ProductDefinition> { new ProductDefinition("your_product_id", ProductType.Consumable) });
_controller.FetchPurchases();
}

private void OnProductsFetched(List<Product> products)
{
foreach (var product in products)
{
Debug.Log($"Product: {product.definition.id}{product.metadata.localizedPriceString}");
}
}

public void BuyProduct(string productId)
{
_controller.PurchaseProduct(productId);
}

private void OnPurchasePending(PendingOrder order)
{
var product = order.CartOrdered.Items().FirstOrDefault()?.Product;
if (product == null) return;

GiveItemToUser(product.definition.id);
_controller.ConfirmPurchase(order);
}

private void GiveItemToUser(string productId)
{
Debug.Log($"Delivering item: {productId}");
}
}

After — same code with AppCoins added (highlighted lines are new):

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Extension;
using AppCoins.Unity; // Add this using directive

public class IAPManager : MonoBehaviour
{
private StoreController _controller;

private async void Start()
{
// ↓ This is the only new line required
await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);

_controller = UnityIAPServices.StoreController();
_controller.OnProductsFetched += OnProductsFetched;
_controller.OnPurchasePending += OnPurchasePending;

// Re-fire OnPurchasePending for any unfinished purchases found by FetchPurchases()
_controller.ProcessPendingOrdersOnPurchasesFetched(true);

await _controller.Connect();

_controller.FetchProducts(new List<ProductDefinition> { new ProductDefinition("your_product_id", ProductType.Consumable) });

// Trigger recovery of unfinished purchases — results arrive via OnPurchasePending
_controller.FetchPurchases();
}

private void OnProductsFetched(List<Product> products)
{
foreach (var product in products)
{
Debug.Log($"Product: {product.definition.id}{product.metadata.localizedPriceString}");
}
}

public void BuyProduct(string productId)
{
_controller.PurchaseProduct(productId);
}

private void OnPurchasePending(PendingOrder order)
{
var product = order.CartOrdered.Items().FirstOrDefault()?.Product;
if (product == null) return;

GiveItemToUser(product.definition.id);
_controller.ConfirmPurchase(order);
}

private void GiveItemToUser(string productId)
{
Debug.Log($"Delivering item: {productId}");
}
}

The only AppCoins-specific addition is the using AppCoins.Unity; directive and the await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic); call. Everything else — ProcessPendingOrdersOnPurchasesFetched(true), FetchProducts(List<ProductDefinition>), and FetchPurchases() — is standard Unity IAP v5 and belongs in both the Before and After versions.