在 Unity IAP v5 基础上接入 AppCoins
本指南介绍如何为已使用 Unity IAP v5(5.0 或更高版本)的 Unity 游戏接入 AppCoins Billing。如果您的工程使用的是更早的 Unity IAP 版本,请先参见在 Unity IAP v4 或更早版本基础上接入 AppCoins。您只需在现有的 Connect() 调用之前多加一行代码。您已编写的所有事件处理方法、商品定义和确认逻辑均保持不变——在通过 Aptoide 分发的构建中,AppCoins 会成为当前生效的商店。
配置
从 GitHub releases 页面 下载最新的 .unitypackage 并导入:
- 在 Unity 中依次选择 Assets → Import Package → Custom Package...
- 选择已下载的
.unitypackage文件。 - 在 Import Unity Package 对话框中确认所有项目均已选中,然后点击 Import。
插件文件将出现在 Assets/Plugins/iOS/AppCoinsSDKPlugin/ 下。
概览
AppCoins 以自定义商店提供方的形式与 Unity IAP v5 集成。配置完成后,您已在使用的 StoreController API 会在条件满足时自动将购买路由至 AppCoins Billing,其他情况下则回落到 Apple Billing。无需使用另一套购买 API。
唯一的改动
在任何使用 AppCoins API 的文件中只需添加两样东西:命名空间导入,以及 Connect() 之前的一次 await。
变更前:
_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();
变更后:
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();
controller.Connect() 之前调用并 await ConfigureStoreAsync。未先配置商店就调用 Connect() 会导致商店提供方错误或缺失。Automatic 模式的作用
AppCoinsStoreMode.Automatic 会在启动时查询 AppDistributor.current,并在 iOS 17.4 及以上、且安装来源不是 Apple App Store 或 TestFlight 时启用 AppCoins Billing。按安装来源的完整说明请参见运行时检测的原理。
无论当前生效的是哪个商店,您的 OnPurchasePending、OnProductsFetched、OnPurchaseConfirmed 和 OnPurchaseFailed 处理方法都会以完全相同的方式触发。在 ConfigureStoreAsync 返回后检查 AppCoinsIAP.SelectedStore,即可知道走的是哪条路径:
var selectedStore = await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic);
// selectedStore is either "AppCoinsAppStore" or "AppleAppStore"
Debug.Log("Active billing store: " + selectedStore);
收据的变化
如果您执行服务端购买验证,请注意:当 AppCoins Billing 生效时,order.Info.Receipt 中包含的是 AppCoins 的 JSON 负载,而非 Apple 收据。收据结构和服务端验证流程请参见购买验证。
变更前后的完整示例
下面的示例展示了完整的 Unity IAP v5 配置,并突出显示了接入 AppCoins 所需的唯一改动。
变更前 —— 仅 Apple 的标准 Unity IAP v5:
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}");
}
}
变更后 —— 接入 AppCoins 后的同一份代码(高亮行为新增):
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}");
}
}
AppCoins 专属的新增内容只有 using AppCoins.Unity; 指令和 await AppCoinsIAP.ConfigureStoreAsync(AppCoinsStoreMode.Automatic); 调用。其余部分——ProcessPendingOrdersOnPurchasesFetched(true)、FetchProducts(List<ProductDefinition>) 和 FetchPurchases()——都是标准的 Unity IAP v5 用法,在变更前和变更后的版本中都应存在。