启用可消费应用内产品购买Enable consumable in-app product purchases

通过应用商店商业平台提供可消费应用内产品(这些项目可以进行购买、使用和再次购买),以便为客户提供强大可靠的购买体验。Offer consumable in-app products—items that can be purchased, used, and purchased again—through the Store commerce platform to provide your customers with a purchase experience that is both robust and reliable. 这对游戏内货币(金子、硬币等)等来说尤为有用,可以购买此类货币,然后将其用于购买特定道具。This is especially useful for things like in-game currency (gold, coins, etc.) that can be purchased and then used to purchase specific power-ups.

重要

本文介绍如何使用 Windows.ApplicationModel.Store 命名空间的成员来支持易耗型应用内产品购买。This article demonstrates how to use members of the Windows.ApplicationModel.Store namespace to enable consumable in-app product purchases. 此命名空间不再更新新功能,我们建议你使用 Windows.Services.Store 命名空间。This namespace is no longer being updated with new features, and we recommend that you use the Windows.Services.Store namespace instead. Windows.Services.Store 命名空间支持最新的加载项类型(如应用商店管理的易耗型加载项和订阅),并且设计为与 Windows 开发人员中心和应用商店将来支持的产品和功能类型兼容。The Windows.Services.Store namespace supports the latest add-on types, such as Store-managed consumable add-ons and subscriptions, and is designed to be compatible with future types of products and features supported by Windows Dev Center and the Store. Windows.Services.Store 命名空间在 Windows 10 版本 1607 中引入,它仅可用于面向 Windows 10 周年纪念版(10.0;版本 14393)或 Visual Studio 更高版本的项目中。The Windows.Services.Store namespace was introduced in Windows 10, version 1607, and it can only be used in projects that target Windows 10 Anniversary Edition (10.0; Build 14393) or a later release in Visual Studio. 有关使用 Windows.Services.Store 命名空间支持易耗型应用内产品购买的更多信息,请参阅本文For more information about enabling consumable in-app product purchases using the Windows.Services.Store namespace, see this article.

先决条件Prerequisites

  • 本主题介绍可消费应用内产品的购买和实施报告。This topic covers the purchase and fulfillment reporting of consumable in-app products. 如果你不熟悉应用内产品,请查看启用应用内产品购买,了解许可证相关信息以及如何在应用商店中恰当地列出应用内产品。If you are unfamiliar with in-app products, please review Enable in-app product purchases to learn about license information, and how to properly list in-app products in the Store.
  • 首次编码和测试新的应用内产品时,必须使用 CurrentAppSimulator 对象而不是 CurrentApp 对象。When you code and test new in-app products for the first time, you must use the CurrentAppSimulator object instead of the CurrentApp object. 这样,你可以使用对许可证服务器的模拟调用验证许可证逻辑,而不是调用实时服务器。This way you can verify your license logic using simulated calls to the license server instead of calling the live server. 若要实现此目的,需要在 %userprofile%\AppData\local\packages\<程序包名称>\LocalState\Microsoft\Windows Store\ApiData 中自定义名为“WindowsStoreProxy.xml”的文件。To do this, you need to customize the file named WindowsStoreProxy.xml in %userprofile%\AppData\local\packages\<package name>\LocalState\Microsoft\Windows Store\ApiData. Microsoft Visual Studio 仿真器会在你首次运行应用时创建此文件,你也可以在运行时加载一个自定义文件。The Microsoft Visual Studio simulator creates this file when you run your app for the first time—or you can also load a custom one at runtime. 有关详细信息,请参阅将 WindowsStoreProxy.xml 文件与 CurrentAppSimulator 一起使用For more info, see Using the WindowsStoreProxy.xml file with CurrentAppSimulator.
  • 本主题还参考了应用商店示例中提供的代码示例。This topic also references code examples provided in the Store sample. 若要获得为通用 Windows 平台 (UWP) 应用提供的不同货币化选项的实际体验,此示例是一个不错的选择。This sample is a great way to get hands-on experience with the different monetization options provided for Universal Windows Platform (UWP) apps.

步骤 1:提出购买请求Step 1: Making the purchase request

初始购买请求是通过 RequestProductPurchaseAsync 提出的,其方式与通过应用商店提出的任何其他购买相似。The initial purchase request is made with RequestProductPurchaseAsync like any other purchase made through the Store. 易耗型应用内产品的不同之处在于在成功购买后,客户无法再次购买同一个产品,直到应用通知应用商店之前的购买已成功实施。The difference for consumable in-app products is that after a successful purchase, a customer cannot purchase the same product again until the app has notified the Store that the previous purchase was successfully fulfilled. 应用负责实施购买的消费品,并通知应用商店该项实施。It's your app's responsibility to fulfill purchased consumables and notify the Store of the fulfillment.

下面的示例显示了一个可消费应用内产品的购买请求。The following example shows a consumable in-app product purchase request. 你会注意到代码注释,指明应用何时应该为下面两种不同情况的易耗型应用内产品执行本地实施:已成功提出请求的情况和请求因同一产品未实施购买而失败的情况。You'll notice code comments indicating when your app should conduct its local fulfillment of the consumable in-app product for two different scenarios—when the request is successful, and when the request is not successful because of an unfulfilled purchase of that same product.

PurchaseResults purchaseResults = await CurrentAppSimulator.RequestProductPurchaseAsync("product1");
switch (purchaseResults.Status)
{
    case ProductPurchaseStatus.Succeeded:
        product1TempTransactionId = purchaseResults.TransactionId;

        // Grant the user their purchase here, and then pass the product ID and transaction ID to
        // CurrentAppSimulator.ReportConsumableFulfillment to indicate local fulfillment to the
        // Windows Store.
        break;

    case ProductPurchaseStatus.NotFulfilled:
        product1TempTransactionId = purchaseResults.TransactionId;

        // First check for unfulfilled purchases and grant any unfulfilled purchases from an
        // earlier transaction. Once products are fulfilled pass the product ID and transaction ID
        // to CurrentAppSimulator.ReportConsumableFulfillment to indicate local fulfillment to the
        // Windows Store.
        break;
}

步骤 2:跟踪易耗型应用内产品的本地实施Step 2: Tracking local fulfillment of the consumable

当授权客户访问易耗型应用内产品时,持续跟踪实施的产品 (productId) 以及跟踪与实施相关联的交易 (transactionId) 非常重要。When granting your customer access to the consumable in-app product, it's important to keep track of which product is fulfilled (productId), and which transaction that fulfillment is associated with (transactionId).

重要

应用负责向应用商店准确报告实施情况。Your app is responsible for the accurately reporting fulfillment to the Store. 对于维护客户公平、可靠的购买体验来说,此步骤非常重要。This step is essential to maintaining a fair and reliable purchase experience for your customers.

以下示例说明了使用上一步骤中 RequestProductPurchaseAsync 调用的 PurchaseResults 属性,标识要实施的已购买产品。The following example demonstrates use of the PurchaseResults properties from the RequestProductPurchaseAsync call in the previous step to identify the purchased product for fulfillment. 使用一个集合将产品信息存储在可供稍后引用的位置中,以便确认成功完成本地的实施。A collection is used to store the product information in a location that can later be referenced to confirm that local fulfillment was successful.

private void GrantFeatureLocally(string productId, Guid transactionId)
{
    if (!grantedConsumableTransactionIds.ContainsKey(productId))
    {
        grantedConsumableTransactionIds.Add(productId, new List<Guid>());
    }
    grantedConsumableTransactionIds[productId].Add(transactionId);

    // Grant the user their content. You will likely increase some kind of gold/coins/some other asset count.
}

下一个示例显示了如何使用上一个示例的数组来访问产品 ID/交易 ID 对,稍后将使用它们向应用商店报告实施情况。This next example shows how to use the array from the previous example to access product ID/transaction ID pairs that are later used when reporting fulfillment to the Store.

重要

无论应用使用何种方法来跟踪和确认实施,应用都必须恪尽职守,确保客户不会为没有收到的项目付费。Whatever methodology your app uses to track and confirm fulfillment, your app must demonstrate due diligence to ensure that your customers are not charged for items they haven't received.

private Boolean IsLocallyFulfilled(string productId, Guid transactionId)
{
    return grantedConsumableTransactionIds.ContainsKey(productId) &&
        grantedConsumableTransactionIds[productId].Contains(transactionId);
}

步骤 3:向 Microsoft Store 报告产品实施情况Step 3: Reporting product fulfillment to the Store

完成本地实施后,应用必须调用 ReportConsumableFulfillmentAsync,其中包含 productId 和包括产品购买在内的交易。After local fulfillment is completed, your app must make a ReportConsumableFulfillmentAsync call that includes the productId and the transaction the product purchase is included in.

重要

如果无法向应用商店报告已实施的易耗型应用内产品,则会导致在上次购买的实施情况得到报告之前,用户无法再次购买该产品。Failure to report fulfilled consumable in-app products to the Store will result in the user being unable to purchase that product again until fulfillment for the previous purchase is reported.

FulfillmentResult result = await CurrentAppSimulator.ReportConsumableFulfillmentAsync(
    "product2", product2TempTransactionId);

步骤 4:标识未实施的购买Step 4: Identifying unfulfilled purchases

你的应用可以随时使用 GetUnfulfilledConsumablesAsync 方法来检查是否存在尚未实施的易耗型应用内产品。Your app can use the GetUnfulfilledConsumablesAsync method to check for unfulfilled consumable in-app products at any time. 你应该定期调用此方法,以便检查是否存在由未参与的应用事件(如网络连接中断或应用终止)所导致的未实施的易耗品。This method should be called on a regular basis to check for unfulfilled consumables that exist due to unanticipated app events like an interruption in network connectivity or app termination.

以下示例说明了如何使用 GetUnfulfilledConsumablesAsync 枚举未实施的易耗品,以及应用如何通过此列表进行迭代以便完成本地实施。The following example demonstrates how GetUnfulfilledConsumablesAsync can be used to enumerate unfulfilled consumables, and how your app can iterate through this list to complete local fulfillment.

private async void GetUnfulfilledConsumables()
{
    products = await CurrentApp.GetUnfulfilledConsumablesAsync();

    foreach (UnfulfilledConsumable product in products)
    {
        logMessage += "\nProduct Id: " + product.ProductId + " Transaction Id: " + product.TransactionId;
        // This is where you would pass the product ID and transaction ID to
        // currentAppSimulator.reportConsumableFulfillment to indicate local fulfillment to the Windows Store.
    }
}