Unity 集成指南
环境要求
- 支持 Unity 2019.4 及以上版本
准备
- 参照 准备工作 所述创建 app,配置 app 参数并且绑定 API 域名
- 参照 TapSDK 快速开始 配置包名和签名
获取 SDK
Unity 2020.3.15 之前的版本为了避免后面构建报错建议升级 Gradle 版本,可参考该 Gradle 升级步骤文档。
以下介绍了通过 Unity Package Manager 导入或者修改 Packages/manifest.json 配置文件引入两种方式,根据项目需要,任选其一即可:
1、通过 Package Manager 可视化界面引入
因为 TapTap IAP 依赖 EDM4U(External Dependency Manager for Unity) 来处理 Android 相关的依赖,因此引入依赖的步骤是先安装 EDM4U 库,然后安装 TapTap IAP。
安装 EDM4U
下面介绍了两种方式安装 EDM4U,分别是通过 OpenUPM 安装以及手动下载安装;
- 方法一:通过 OpenUPM 安装 EDM4U
EDM4U 可以通过 OpenUPM 进行下载,开发者可以通过 Edit > Project Settings > Package Manager 来注册使用 OpenUPM。
- 方法二:手动下载安装
开发者可以通过 Google APIs for Unity 下载 UPM 安装包. 并且通过从本地磁盘安装的方式进行安装。
安装 TapTap IAP
TapTap IAP 可以通过 NPMJS 进行安装, 开发者可以通过 Edit > Project Settings > Package Manager 来注册使用 NPMJS。
配置完成以后就可以在 Window > Package Manager > My Registries 中安装 TapTapSDK IAP 4.4.0。 如果安装目录中没有TapTap Payments Global V2
, 请尝试在 Edit > Project Settings > Package Manager 中重新注册 NPMJS。2、修改 Packages/manifest.json 文件
"dependencies": {
"com.taptap.sdk.iap": "4.4.0", //添加 TapTap IAP
"com.unity.purchasing": "3.1.0", //TapTap IAP 所须依赖
"com.google.external-dependency-manager": "1.2.179", //TapTap IAP 所须依赖
"com.taptap.sdk.core": "4.4.0",
...
...
},
// 添加 Registries
"scopedRegistries": [
{
"name": "taptap",
"url": "https://registry.npmjs.org",
"scopes": ["com.tapsdk", "com.taptap", "com.leancloud"]
},
{
"name": "openupm",
"url": "https://package.openupm.com",
"scopes": [
"com.google"
]
}
]
处理安卓依赖失败
EDM4U 会自动监控 TapTap IAP 引入的 Android 依赖,但是在某些特殊情况下自动依赖解析可能失败,开发者可以通过 Assets > External Dependency Manager > Android Resolver > Force Resolve 来强制依赖解析。在测试之前请确认对于 com.taptap.android.payment:unity
的依赖被加到了 mainTemplate.gradle 文件中,如果 EDM4U 没有自动添加这个依赖,开发者也可以通过手动添加的方式处理依赖。
SDK 指南
我们在 Unity IAP 的框架下实现了一个新的商店实现,通过这种方式降低已经有 Google Play 或者 App Store 内购的 app 的接入成本。如果开发者是第一次接触到内购的流程,我们会在接下来简要说明 Unity 的内购流程,开发者也可以在 Unity 的官方文档 中了解有关内购的详细内容。
初始化 Unity Gaming Services
调用 UnityServices.InitializeAsync()
来一次性初始化 Unity Gaming Services。 这个方法会返回一个 Task
对象,开发者可以通过这个对象来获取初始化的状态信息。
using System;
using Unity.Services.Core;
using Unity.Services.Core.Environments;
using UnityEngine;
public class InitializeUnityServices : MonoBehaviour
{
public string environment = "production";
async void Start()
{
try
{
var options = new InitializationOptions()
.SetEnvironmentName(environment);
await UnityServices.InitializeAsync(options);
}
catch (Exception exception)
{
// An error occurred during services initialization.
}
}
}
初始化 IAP
确保你在初始化 IAP 的时候添加 TapPurchasingModule
,并且设置正确的 clientId
和 clientToken
。
using UnityEngine;
using UnityEngine.Purchasing;
using UnityEngine.Purchasing.Extension;
using TapSDK.IAP;
public class MyIAPManager : IStoreListener {
private IStoreController controller;
private IExtensionProvider extensions;
public MyIAPManager () {
var builder = ConfigurationBuilder.Instance(TapPurchasingModule.Instance);
builder.Configure<ITapTapStoreConfiguration>().SetClientId("Your Client ID Here");
builder.Configure<ITapTapStoreConfiguration>().SetClientToken("Your Client Token Here");
builder.Configure<ITapTapStoreConfiguration>().SetRegionCode(1); // 0: CN, 1: GLOBAL
builder.AddProduct("100_gold_coins", ProductType.Consumable);
UnityPurchasing.Initialize (this, builder);
}
/// <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.
///
/// Note that this will not be called if Internet is unavailable; Unity IAP
/// will attempt initialization until it becomes available.
/// </summary>
public void OnInitializeFailed (InitializationFailureReason error)
{
}
public void OnInitializeFailed(InitializationFailureReason error, string str)
{
}
/// <summary>
/// Called when a purchase completes.
///
/// May be called at any time after OnInitialized().
/// </summary>
public PurchaseProcessingResult ProcessPurchase (PurchaseEventArgs e)
{
return PurchaseProcessingResult.Complete;
}
/// <summary>
/// Called when a purchase fails.
/// </summary>
public void OnPurchaseFailed (Product i, PurchaseFailureReason p)
{
}
}
发起内购流程
在 IAP 被成功初始化以后,你可以通过调用 IStoreController.InitiatePurchase
来发起内购流程。
// Example method called when the user taps a 'buy' button
// to start the purchase process.
public void OnPurchaseClicked(string productId) {
controller.InitiatePurchase(productId, "developerPayload, e.g. user_id or order_id");
}
处理购买结果
购买完成时会调用商店监听器的 ProcessPurchase 函数。无论用户购买任何物品,您的应用程序都应该履单;例如,解锁本地内容或将购买收据发送给服务器以更新服务器端游戏模型。
此过程会返回结果以指出应用程序是否已完成对购买的处理:
结果 | 描述 |
---|---|
PurchaseProcessingResult.Complete | 应用程序已完成对购买的处理,不应再次向应用程序通知此事。 |
PurchaseProcessingResult.Pending | 应用程序仍在处理购买,除非调用 IStoreController 的 ConfirmPendingPurchase 函数,否则将在下一次应用程序启动时再次调用 ProcessPurchase 。 |
请注意,在初始化成功后,随时可能调用 ProcessPurchase
。如果应用程序在 ProcessPurchase
处理程序执行过程中崩溃,那么在 Unity IAP 下次初始化时会再次调用它,因此您可能希望实现自己的额外重复数据删除功能。
可靠性
Unity IAP 要求明确确认购买以确保在网络中断或应用程序崩溃的情况下可靠地完成购买。在应用程序离线时完成的任何购买都将在下次初始化时发送给应用程序。
立即完成购买
返回 PurchaseProcessingResult.Complete
时,Unity IAP 立即完成交易(如下图所示)。
如果您正在销售可消耗商品并从服务器履行订单(例如,在网络游戏中提供游戏币),那么您不得返回 PurchaseProcessingResult.Complete
。
否则,如果在保存到云端之前卸载应用程序,则购买的消耗品将面临丢失的风险。
将购买保存到云端
如果要将消耗品购买交易保存到云端,您必须返回 PurchaseProcessingResult.Pending
,并且仅在成功保存购买时才调用 ConfirmPendingPurchase
。
返回 Pending
时,Unity IAP 会在底层商店中保持交易为未结 (open) 状态,直至确认为已处理为止,因此确保了即使在消耗品处于此待处理状态时用户重新安装您的应用程序,消耗品购买交易也不会丢失。
调试
我们当前只提供了 Android 的库实现, 请在 Android 环境下进行各功能调试(其他平台会逐步补充完善)。