本文演示如何使用 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 中引入了应用商店管理的易耗品。
要向用户提供消耗型附加组件,请遵循以下常规过程:
- 允许用户 从您的应用购买加载项。
- 当用户使用加载项(例如,他们在游戏中花费硬币)时,将加载项报告为已使用。
可以随时 为应用商店管理的易耗品获取剩余余额。
先决条件
这些示例具有以下先决条件:
- 适用于面向 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;
}
}