Habilitar compras de productos consumibles desde la aplicación

Ofrece productos consumibles desde la aplicación (artículos que se pueden comprar, usar y volver a comprar), a través de la plataforma de comercio de la Tienda para proporcionar a tus clientes una experiencia de compra sólida y de confianza. Esto es especialmente útil para cosas como monedas de juego (oro, monedas, etc.) que se pueden comprar y usar para comprar bonificaciones concretas.

Importante

En este artículo se muestra cómo usar miembros del espacio de nombres Windows.ApplicationModel.Store para habilitar compras de productos consumibles desde la aplicación. Este espacio de nombres ya no se actualiza con nuevas características y se recomienda usar el espacio de nombres Windows.Services.Store en su lugar. El espacio de nombres Windows.Services.Store admite los tipos de complementos más recientes, como complementos y suscripciones consumibles administrados por la Tienda, y está diseñado para ser compatible con futuros tipos de productos y características compatibles con el Centro de partners y la Tienda. El espacio de nombres Windows.Services.Store se introdujo en Windows 10, versión 1607, y solo se puede usar en proyectos que tienen como destino Windows 10 Anniversary Edition (10.0; Compilación 14393) o una versión posterior en Visual Studio. Para obtener más información sobre cómo habilitar compras de productos consumibles en la aplicación mediante el espacio de nombres Windows.Services.Store , consulte este artículo.

Requisitos previos

  • Este tema se centra en la compra y los informes de suministro de productos consumibles dentro de la aplicación. Si no estás familiarizado con los productos desde la aplicación, consulta Habilitar compras de productos desde la aplicación para ver información sobre la licencia y cómo incluir de forma adecuada los productos desde la aplicación en la Tienda.
  • Cuando codificas y pruebas nuevos productos desde la aplicación por primera vez, debes usar el objeto CurrentAppSimulator en lugar del objeto CurrentApp. De esta manera, puedes comprobar la lógica de la licencia con llamadas simuladas al servidor de licencias, en lugar de llamar al servidor activo. Para ello, debes personalizar el archivo denominado WindowsStoreProxy.xml en %userprofile%\AppData\local\packages\<package name>\LocalState\Microsoft\Windows Store\ApiData. El simulador de Microsoft Visual Studio crea este archivo la primera vez que se ejecuta la aplicación, aunque también puedes cargar un archivo personalizado en el tiempo de ejecución. Para obtener más información, consulta Uso del archivo WindowsStoreProxy.xml con CurrentAppSimulator.
  • Este tema también hace referencia a los ejemplos de código que se proporcionan en la muestra de la Tienda. Esta muestra es ideal para conseguir experiencia práctica con las diferentes opciones de monetización que se proporcionan para las aplicaciones para la Plataforma universal de Windows (UWP).

Paso 1: Realizar la solicitud de compra

La solicitud de compra inicial se realiza con RequestProductPurchaseAsync, como cualquier otra compra que se lleva a cabo a través de la Tienda. La diferencia de los productos consumibles desde la aplicación es que, tras completar la compra, el cliente no puede volver a comprar el mismo producto hasta que la aplicación haya notificado a la Tienda que la anterior compra de dicho producto se suministró correctamente. Es responsabilidad de tu aplicación suministrar los consumibles comprados y notificar a la Tienda del suministro.

En el siguiente ejemplo se muestra una solicitud de compra de un producto consumible desde la aplicación. Verás comentarios en el código que indican cuándo debería realizar la aplicación el suministro local del producto consumible desde la aplicación en dos casos distintos: cuando la solicitud se realiza correctamente y cuando la solicitud no se realiza correctamente debido a una compra no suministrada del mismo producto.

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;
}

Paso 2: Seguimiento del suministro local del consumible

Cuando se concede al cliente acceso al producto consumible desde la aplicación, es importante realizar un seguimiento del producto suministrado (productId) y de la transacción asociada al mismo (transactionId).

Importante

Tu aplicación es responsable de notificar con precisión el cumplimiento de la Tienda. Este paso es esencial para mantener una experiencia de compra justa y de confianza para tus clientes.

En el siguiente ejemplo, se demuestra el uso de las propiedades PurchaseResults desde la llamada a RequestProductPurchaseAsync en el paso anterior, para identificar el producto comprado que se va a suministrar. Se usa una colección para almacenar la información de los productos en una ubicación a la que después se pueda hacer referencia para confirmar que el suministro local se ha realizado correctamente.

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.
}

En el siguiente ejemplo, se muestra cómo usar la matriz del ejemplo anterior para acceder a los pares id. del producto/ id. de transacción que se usan más tarde cuando se informa del suministro a la Tienda.

Importante

Independientemente de la metodología que use la aplicación para realizar un seguimiento y confirmar el cumplimiento, la aplicación debe demostrar la diligencia debida para asegurarse de que los clientes no se cobran por los elementos que no han recibido.

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

Paso 3: Informar del suministro de productos a la Tienda

Después de completar el suministro local, la aplicación debe hacer una llamada a ReportConsumableFulfillmentAsync que incluya el elemento productId y la transacción en la que estaba incluida la compra del producto.

Importante

Si no se informa de los productos consumibles consumibles cumplidos en la Tienda, el usuario no podrá volver a comprar ese producto hasta que se notifique el cumplimiento de la compra anterior.

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

Paso 4: Identificación de compras sin suministrar

La aplicación puede usar el método GetUnfulfilledConsumablesAsync para buscar en cualquier momento productos consumibles desde la aplicación que no se hayan completado. Se debe llamar a este método con regularidad para buscar consumibles sin suministrar que existan como consecuencia de eventos no anticipados de la aplicación, como una interrupción en la conectividad de red o el cierre de la aplicación.

En el siguiente ejemplo, se demuestra cómo se puede usar GetUnfulfilledConsumablesAsync para enumerar consumibles sin suministrar, y cómo la aplicación puede iterar por esta lista para completar el suministro local.

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.
    }
}