メインコンテンツまでスキップ

在 Unity IAP v4 或更早版本基础上接入 AppCoins

本指南介绍如何为使用 Unity IAP v4 或更早版本的 Unity 游戏接入 AppCoins Billing。AppCoins 插件需要 Unity IAP v5,因此您需要先升级。Unity IAP 从 v4 升级到 v5 会改变购买完成的处理方式,这会在接入 AppCoins 之前先影响到您的现有代码。

如果您的工程已经使用 Unity IAP v5 或更高版本,请改为参见在 Unity IAP v5 基础上接入 AppCoins


步骤 1:将 Unity IAP 升级到 v5

打开 Window → Package Manager,找到 In App Purchasing,升级到 5.0 或更高版本

⚠️
升级之后,在您应用下文的 v5 API 变更之前,工程会出现编译错误。这是预期行为。

步骤 2:应用 Unity IAP v5 的 API 变更

Unity IAP v5 以 IStoreController 上的事件订阅取代了 IStoreListener 回调接口。变化最大的是购买完成模式——ProcessPurchase 已被移除。

购买完成

变更前(v4):

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
GiveItemToUser(args.purchasedProduct.definition.id);
return PurchaseProcessingResult.Complete;
}

变更后(v5):

// Subscribe in your initialization code
_controller.OnPurchasePending += OnPurchasePending;

private void OnPurchasePending(PendingOrder order)
{
var product = order.CartOrdered.Items().FirstOrDefault()?.Product;
if (product != null) GiveItemToUser(product.definition.id);
_controller.ConfirmPurchase(order); // replaces returning PurchaseProcessingResult.Complete
}

商店初始化

变更前(v4):

public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
_controller = controller;
foreach (var product in controller.products.all)
Debug.Log(product.definition.id);
}

变更后(v5):

// Subscribe before Connect()
_controller.OnProductsFetched += OnProductsFetched;

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

初始化失败

变更前(v4):

public void OnInitializeFailed(InitializationFailureReason error) { }
public void OnInitializeFailed(InitializationFailureReason error, string message) { }

变更后(v5):

_controller.OnStoreDisconnected += failure =>
Debug.LogError($"Store connection failed: {failure.Message}");

购买失败

变更前(v4):

public void OnPurchaseFailed(Product product, PurchaseFailureReason reason) { }

变更后(v5):

_controller.OnPurchaseFailed += OnPurchaseFailed;

private void OnPurchaseFailed(FailedOrder order)
{
Debug.LogError($"Purchase failed: {order.FailureReason}");
}

不再需要 IStoreListener

迁移到事件订阅模式之后,您的类无需再实现 IStoreListener。请移除该接口声明以及所有残留的空实现方法。

初始化商店

变更前(v4):

var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.AddProduct("gas", ProductType.Consumable);
UnityPurchasing.Initialize(this, builder); // synchronous, IStoreListener callback

变更后(v5):

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

await _controller.Connect();

// Replaces builder.AddProduct — define product definitions and fetch after Connect
_controller.FetchProducts(new List<ProductDefinition>
{
new ProductDefinition("gas", ProductType.Consumable)
});

步骤 3:添加 AppCoins 插件

GitHub releases 页面 下载最新的 .unitypackage 并导入:

  1. 在 Unity 中依次选择 Assets → Import Package → Custom Package...
  2. 选择已下载的 .unitypackage 文件。
  3. Import Unity Package 对话框中确认所有项目均已选中,然后点击 Import

插件文件将出现在 Assets/Plugins/iOS/AppCoinsSDKPlugin/ 下。


步骤 4:接入 AppCoins

当工程在 Unity IAP v5 下可以顺利编译后,接入 AppCoins 只需一行代码。请在 Connect() 调用之前添加:

using AppCoins.Unity;

// Add this before Connect()
await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);

await _controller.Connect();

AppCoinsStoreMode.Automatic 会在符合条件的安装场景下启用 AppCoins Billing,其他情况下回落到 Apple Billing——参见运行时检测的原理。无需其他代码改动。


变更前后的完整示例

变更前 —— Unity IAP v4:

using UnityEngine;
using UnityEngine.Purchasing;

public class IAPManager : MonoBehaviour, IStoreListener
{
private IStoreController _controller;

void Start()
{
var builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
builder.AddProduct("gas", ProductType.Consumable);
UnityPurchasing.Initialize(this, builder);
}

public void OnInitialized(IStoreController controller, IExtensionProvider extensions)
{
_controller = controller;
}

public void OnInitializeFailed(InitializationFailureReason error) { }

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

public PurchaseProcessingResult ProcessPurchase(PurchaseEventArgs args)
{
GiveItemToUser(args.purchasedProduct.definition.id);
return PurchaseProcessingResult.Complete;
}

public void OnPurchaseFailed(Product product, PurchaseFailureReason reason)
{
Debug.LogError($"Purchase failed: {reason}");
}

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

变更后 —— 接入 AppCoins 的 Unity IAP v5:

using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Purchasing;
using AppCoins.Unity;

public class IAPManager : MonoBehaviour
{
private StoreController _controller;

private readonly List<ProductDefinition> _products = new List<ProductDefinition>
{
new ProductDefinition("gas", ProductType.Consumable)
};

private async void Start()
{
// AppCoins: configure before Connect
await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);

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

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

await _controller.Connect();

// Fetch product metadata (replaces builder.AddProduct + UnityPurchasing.Initialize)
_controller.FetchProducts(_products);

// 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.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 OnPurchaseFailed(FailedOrder order)
{
Debug.LogError($"Purchase failed: {order.FailureReason}");
}

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

从 v4 到最终结果的关键变化:

  1. 移除 IStoreListener——不再需要实现任何接口
  2. UnityPurchasing.Initialize(this, builder)await _controller.Connect() + _controller.FetchProducts(products)
  3. ProcessPurchaseOnPurchasePending + controller.ConfirmPurchase(order)
  4. OnInitialized → 订阅 OnProductsFetched 事件
  5. Connect() 之前新增 await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic)