支持购买可消耗加载项

本文演示如何使用 Windows.Services.Store 命名空间中 StoreContext 类的方法来管理用户在 UWP 应用中的易耗型加载项的履行。 使用消耗型附加组件适用于可以购买、使用并且可以再次购买的物品。 这对于可以购买并用于购买特定道具的游戏内货币(如黄金、硬币等)特别有用。

注释

Windows.Services.Store 命名空间是在 Windows 10 版本 1607 中引入的,并且只能在面向 Windows 10 周年版(10.0; 版本 14393) 或更高版本的项目中使用,需在 Visual Studio 中构建。 如果你的应用面向早期版本的 Windows 10,则必须使用 Windows.ApplicationModel.Store 命名空间而不是 Windows.Services.Store 命名空间。 有关详细信息,请参阅 本文

易耗型加载项概述

应用可以提供两种类型的易耗型加载项,这些加载项在履行管理方式上有所不同:

  • 开发人员管理的易耗品。 对于这种类型的易耗品,你负责跟踪加载项表示的项目余额,并在用户使用所有商品后将加载项的购买报告给应用商店。 在应用将以前的加载项购买报告为已完成之前,用户无法再次购买加载项。

    例如,如果你的加载项在游戏中表示 100 个硬币,并且用户消耗了 10 个硬币,你的应用或服务必须为用户维护 90 个硬币的新剩余余额。 用户消耗所有 100 个硬币后,你的应用必须将加载项报告为已完成,然后用户可以再次购买 100 个硬币加载项。

  • 商店管理的消耗品。 对于这种类型的消耗品,商店会跟踪用户的附加组件所代表的项目余额。 当用户使用任何项目时,你负责将这些项目报告为“应用商店”,并且应用商店会更新用户的余额。 用户可以多次购买附加组件(无需先消耗物品)。 你的应用可以随时查询应用商店中用户的当前余额。

    例如,如果你的加载项表示游戏中的初始数量为 100 个硬币,并且用户消耗了 50 个硬币,你的应用会向应用商店报告加载项的 50 个单位已完成,并且应用商店会更新剩余余额。 如果用户随后重新购买您的附加组件以获取 100 个硬币,那么他们现在总共有 150 个硬币。

    注释

    Windows 10 版本 1607 中引入了应用商店管理的易耗品。

要向用户提供消耗型附加组件,请遵循以下常规过程:

  1. 允许用户 从您的应用购买加载项
  2. 当用户使用加载项(例如,他们在游戏中花费硬币)时,将加载项报告为已使用

可以随时 为应用商店管理的易耗品获取剩余余额

先决条件

这些示例具有以下先决条件:

  • 适用于面向 Windows 10 周年纪念版(10.0;版本 14393)或更高版本的通用 Windows 平台 (UWP) 应用的 Visual Studio 项目。
  • 在合作伙伴中心创建应用提交,此应用在应用商店中发布。 可以选择配置应用,以便在测试应用时无法在应用商店中发现它。 有关详细信息,请参阅我们的 测试指南
  • 你已 为合作伙伴中心中的应用 创建了易耗型加载项。

这些示例中的代码假定:

  • 代码在 Page 上下文中运行,其中包含名为 workingProgressRing,以及名为 textBlock。 这些对象分别用于指示异步操作的发生和显示输出消息。
  • 代码文件中有一个 ,该文件使用 语句用于 Windows.Services.Store 命名空间.
  • 该应用是一个单用户应用,仅在启动应用的用户的上下文中运行。 有关详细信息,请参阅 应用内购买和试用版

有关完整的示例应用程序,请参阅 Store 示例

注释

如果桌面应用程序使用 Desktop Bridge,则可能需要添加这些示例中未显示的其他代码来配置 StoreContext 对象。 有关详细信息,请参阅在使用桌面桥的桌面应用程序中使用的 StoreContext 类

将消耗品附加组件标记为已履行

用户 从应用程序购买加载项 并使用加载项后,您的应用程序必须通过调用 StoreContext 类的 ReportConsumableFulfillmentAsync 方法来报告加载项已被使用。 必须将以下信息传递给此方法:

  • 要标记为已完成的加载项的应用商店 ID 为
  • 要报告为已完成的加载项的单位。
    • 对于开发人员管理的易耗品,请为 数量 参数指定 1。 这会提醒应用商店已满足易耗品,然后客户可以再次购买易耗品。 在应用通知应用商店已完成之前,用户无法再次购买易耗品。
    • 对于应用商店管理的易耗品,请指定已使用的实际单位数。 应用商店将更新易耗品的剩余余额。
  • 履约的跟踪标识 这是开发人员提供的 GUID,用于标识与履行操作关联的特定事务,以便进行跟踪。 有关详细信息,请参阅 ReportConsumableFulfillmentAsync中的备注。

此示例演示如何将应用商店管理的易耗品报告为已完成。

private StoreContext context = null;

public async void ConsumeAddOn(string addOnStoreId)
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
        // If your app is a desktop app that uses the Desktop Bridge, you
        // may need additional code to configure the StoreContext object.
        // For more info, see https://aka.ms/storecontext-for-desktop.
    }

    // This is an example for a Store-managed consumable, where you specify the actual number
    // of units that you want to report as consumed so the Store can update the remaining
    // balance. For a developer-managed consumable where you maintain the balance, specify 1
    // to just report the add-on as fulfilled to the Store.
    uint quantity = 10;
    Guid trackingId = Guid.NewGuid();

    workingProgressRing.IsActive = true;
    StoreConsumableResult result = await context.ReportConsumableFulfillmentAsync(
        addOnStoreId, quantity, trackingId);
    workingProgressRing.IsActive = false;

    // Capture the error message for the operation, if any.
    string extendedError = string.Empty;
    if (result.ExtendedError != null)
    {
        extendedError = result.ExtendedError.Message;
    }

    switch (result.Status)
    {
        case StoreConsumableStatus.Succeeded:
            textBlock.Text = "The fulfillment was successful. " + 
                $"Remaining balance: {result.BalanceRemaining}";
            break;

        case StoreConsumableStatus.InsufficentQuantity:
            textBlock.Text = "The fulfillment was unsuccessful because the remaining " +
                $"balance is insufficient. Remaining balance: {result.BalanceRemaining}";
            break;

        case StoreConsumableStatus.NetworkError:
            textBlock.Text = "The fulfillment was unsuccessful due to a network error. " +
                "ExtendedError: " + extendedError;
            break;

        case StoreConsumableStatus.ServerError:
            textBlock.Text = "The fulfillment was unsuccessful due to a server error. " +
                "ExtendedError: " + extendedError;
            break;

        default:
            textBlock.Text = "The fulfillment was unsuccessful due to an unknown error. " +
                "ExtendedError: " + extendedError;
            break;
    }
}

获取应用商店管理的易耗品的剩余余额

此示例演示如何使用 StoreContext 类的 GetConsumableBalanceRemainingAsync 方法获取 Store 管理的易耗型加载项的剩余余额。

private StoreContext context = null;

public async void GetRemainingBalance(string addOnStoreId)
{
    if (context == null)
    {
        context = StoreContext.GetDefault();
        // If your app is a desktop app that uses the Desktop Bridge, you
        // may need additional code to configure the StoreContext object.
        // For more info, see https://aka.ms/storecontext-for-desktop.
    }

    workingProgressRing.IsActive = true;
    StoreConsumableResult result = await context.GetConsumableBalanceRemainingAsync(addOnStoreId);
    workingProgressRing.IsActive = false;

    // Capture the error message for the operation, if any.
    string extendedError = string.Empty;
    if (result.ExtendedError != null)
    {
        extendedError = result.ExtendedError.Message;
    }

    switch (result.Status)
    {
        case StoreConsumableStatus.Succeeded:
            textBlock.Text = "Remaining balance: " + result.BalanceRemaining;
            break;

        case StoreConsumableStatus.NetworkError:
            textBlock.Text = "Could not retrieve balance due to a network error. " +
                "ExtendedError: " + extendedError;
            break;

        case StoreConsumableStatus.ServerError:
            textBlock.Text = "Could not retrieve balance due to a server error. " +
                "ExtendedError: " + extendedError;
            break;

        default:
            textBlock.Text = "Could not retrieve balance due to an unknown error. " +
                "ExtendedError: " + extendedError;
            break;
    }
}