在 Unity 项目中使用 Google Play 结算库

Google Play 结算服务插件扩展了 Unity 的应用内购买内置服务和资产(名为 Unity IAP),可以为您的游戏提供 Google Play 结算库的所有最新功能。本指南介绍了如何设置您的项目以使用此插件,以及如何在通过 Unity 开发的游戏中实现 Google Play 结算库功能。

设置 Google Play 结算服务插件

如需设置此插件,请完成以下每个链接部分中的步骤:

  1. 启用 Unity IAP 抽象层
  2. 下载并导入插件
  3. 配置插件的构建设置
  4. 启用插件

启用 Unity IAP 抽象层

Google Play 结算服务插件基于 Unity IAP 中自带的抽象层,因此您需要启用此抽象层后才能下载并导入该插件。如需启用 Unity IAP 抽象层,请执行以下操作:

  1. 完成以下 Unity 教程中的所有步骤:针对 Unity 服务设置项目
  2. 完成以下 Unity 教程中的所有步骤:启用 Unity IAP 服务

下载并导入插件

插件将作为 .unitypackage 格式的 Unity 软件包提供。如需下载并导入插件,请按以下步骤操作:

  1. 从代码库的 GitHub 版本页面中下载适用于 Unity 的最新版 Google Play 插件。
  2. 在 Unity 菜单栏中,依次点击 Assets > Import Package > Custom Package

  3. 找到 .unitypackage 文件的下载位置并选择该文件。

  4. Import Unity Package 对话框中,选择所有资产并点击 Import

软件包导入后,系统会在项目的资产中添加一个名为 GooglePlayPlugins 的新文件夹(位于 Assets 文件夹的根目录下)。此文件夹包含该插件的所有 Google Play 结算库资源。

配置构建设置

由于插件扩展了 Unity IAP,因此除非从 build 中移除 Unity IAP 中一些较旧的重叠依赖项,否则 Unity 会遇到冲突且无法构建 Android APK。插件提供了一种从项目中自动移除冲突库的方法。如需解决这些冲突,请按以下步骤操作:

  1. 从 Unity 菜单栏中依次选择 Google > Play Billing > Build Settings

  2. 在“Play Billing Build Settings”窗口中,点击 Fix。这样就可以解决冲突并将冲突的 Unity IAP 文件移至备份目录。点击 Fix 后,该按钮会变成 Restore,点击后可恢复原始的冲突文件。

启用插件

如需启用插件,请将 Google Play 的 Unity IAP 实现替换为 Google Play 结算服务插件。例如,使用 Unity IAP 购买者脚本时,您要更改传递到 IAP 构建器中的 StandardPurchaseModule 以使用 Google.Play.Billing.GooglePlayStoreModule

// Create a builder using the GooglePlayStoreModule.
var configurationBuilder =
    ConfigurationBuilder.Instance(Google.Play.Billing.GooglePlayStoreModule.Instance());

如果您的游戏将同一个购买者脚本用于多个平台,应添加一项平台检查,确保 Unity 针对其他平台继续使用自己的 IAP 解决方案:

ConfigurationBuilder builder;
if (Application.platform == RuntimePlatform.Android)
{
  builder = ConfigurationBuilder.Instance(
      Google.Play.Billing.GooglePlayStoreModule.Instance());
}
else
{
  builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
}

如果您在除 Google Play 商店以外的其他 Android 应用商店中发布游戏,则只有在选择 Google Play 商店时才应替换默认的 Unity IAP 实现:

ConfigurationBuilder builder;
if (Application.platform == RuntimePlatform.Android
       && SelectedAndoidAppStore == AppStore.GooglePlay)
{
  builder = ConfigurationBuilder.Instance(
      Google.Play.Billing.GooglePlayStoreModule.Instance());
}
else
{
  builder = ConfigurationBuilder.Instance(StandardPurchasingModule.Instance());
}

在游戏中实现 Google Play 结算库功能

Google Play 结算服务插件扩展了 Unity IAP 服务,因此您可以使用相同的 Unity API 管理通用的购买流程。请注意,由于 Google Play 结算库与其他应用商店的 Unity 标准 IAP 实现之间存在差异,因此 API 行为也发生了一些细微变化。如果您是 Unity IAP API 新手,请参阅 Unity IAP 教程中的“Making a Purchase Script”部分,通过示例了解如何实现基本购买流程。

Google Play 结算库还包含一些 Google Play 商店独有的功能。您可以通过扩展接口访问这些功能。本部分的其余内容介绍了如何在游戏中实现这些独有的 Google Play 结算库功能。

启用推迟购买功能

Google Play 支持推迟购买(也称为待处理的交易或待处理的购买交易),在这种情况下,用户可以创建购买交易并稍后在实体店中使用现金完成购买交易。

如需启用推迟购买功能,请在 IAP 构建器中调用 EnableDeferredPurchase() 方法修改模块配置:

// Create a builder using a GooglePlayStoreModule.
var configurationBuilder =
    ConfigurationBuilder.Instance(Google.Play.Billing.GooglePlayStoreModule.Instance());
// Enable deferred purchases
configurationBuilder.Configure<Google.Play.Billing.IGooglePlayConfiguration>()
    .EnableDeferredPurchase();

接下来,使用 Play 商店扩展程序实现推迟购买回调:

// Get the plugin extensions for the Google Play Store.
_playStoreExtensions =
    extensions.GetExtension<Google.Play.Billing.IGooglePlayStoreExtensions>();

// Set the deferred purchases callback.
_playStoreExtensions.SetDeferredPurchaseListener(
    delegate(Product product)
    {
        // Do not grant the item here. Instead, record the purchase and remind
        // the user to complete the transaction in the Play Store.
    });

向 Google Play 传递经过混淆处理的帐号 ID

您可以向 Google Play 传递经过混淆处理的用户帐号 ID 以方便检测滥用行为,例如检测是否有大量设备在短时间内使用同一帐号进行购买。

如需传递经过混淆处理的帐号 ID,请从扩展程序 API 调用 SetObfuscatedAccountId() 方法:

// Get the plugin extensions for the Google Play Store.
_playStoreExtensions =
    extensions.GetExtension<Google.Play.Billing.IGooglePlayStoreExtensions>();

// Pass an obfuscated account ID.
_playStoreExtensions.SetObfuscatedAccountId(obfuscatedAccountId);

向 Google Play 传递经过混淆处理的个人资料 ID

您可以向 Google Play 传递经过混淆处理的个人资料 ID 以方便检测欺诈行为,例如检测是否有大量设备在短时间内使用同一帐号进行购买。这与传递经过混淆处理的用户帐号 ID 类似。在这两种情况下,ID 都代表单个用户,但是个人资料 ID 可以帮助您从单个应用中的多份个人资料里唯一识别出单个用户。向 Google Play 传递经过混淆处理的个人资料 ID 后,您日后便可以在购买收据中检索此 ID。

如需传递经过混淆处理的个人资料 ID,请在 IAP 构建器中调用 SetObfuscatedProfileId() 方法修改模块配置:

// Get the plugin extensions for the Google Play Store.
_playStoreExtensions =
    extensions.GetExtension<Google.Play.Billing.IGooglePlayStoreExtensions>();

// Pass an obfuscated profile ID.
_playStoreExtensions.SetObfuscatedProfileId(obfuscatedProfileId);

确认订阅的价格变动

您可以通过 Google Play 更改有效订阅的价格。游戏的用户必须先确认任何价格变动,然后更改才能生效。如需提示用户确认其订阅的价格变动,请调用 ConfirmSubscriptionPriceChange() 方法:

// Get the plugin extensions for the Google Play Store.
_playStoreExtensions =
    extensions.GetExtension<Google.Play.Billing.IGooglePlayStoreExtensions>();

_playStoreExtensions.ConfirmSubscriptionPriceChange(productId,
    delegate (bool success)
    {
        // Returns whether the user has accepted the new price or not.
    });

Unity API 行为的变化

在您使用 Google Play 结算服务插件时,大多数 API 行为与其他应用商店的 Unity 标准 IAP 实现的行为相同。但在某些情况下,API 的行为会有所不同。本部分介绍了这些行为差异。

不支持开发者载荷

Google Play 已弃用开发者载荷,并用更有意义且更相关的替代方法代替它。因此,API 不支持开发者载荷。如需详细了解替代方法,请参阅开发者载荷 的相关页面。

您可以继续在其他应用商店中使用 Unity 标准 IAP 实现所定义的接口,包括 IStoreController。当您提示购买时,您仍可使用 IStoreController 并调用 InitiatePurchase() 方法:

public void InitiatePurchase(Purchasing.Product product, string payload);

但是,您传入的任何载荷都不会生效(不会出现在最终收据中)。

不支持 SubscriptionManager

Unity IAP 提供了管理订阅的 SubscriptionManager 类。由于此类的 Unity 标准 IAP 实现使用开发者载荷,因此不支持此类。您仍然可以创建此类,但是当您使用该类的任何 getter 方法时,您可能会收到不可靠的数据。

UpdateSubscription 出现细微的 API 变更

Google Play 结算服务插件不支持使用 SubscriptionManager.UpdateSubscription()SubscriptionManager.UpdateSubscriptionInGooglePlayStore() 方法升级和降级您的订阅。如果您的游戏调用了这些方法,系统会抛出 GooglePlayStoreUnsupportedException

Google Play 结算库提供了一个替代 API 来代替这些方法。如需升级或降级订阅,请调用使用按比例计费模式的 UpdateSubscription() 方法:

void UpdateSubscription(Product oldProduct, Product newProduct,
           GooglePlayStoreProrationMode prorationMode = GooglePlayStoreProrationMode.Unknown);

您可以用平台检查封装此方法调用,也可以在捕获 GooglePlayStoreUnsupportedException 时将其封装在 catch 块中。

如需了解按比例计费模式的详细使用方法和示例,请参阅设置按比例计费模式