Habilitar compras de complementos consumibles

En este artículo se muestra cómo usar métodos de la clase StoreContext en el espacio de nombres Windows.Services.Store para administrar el suministro del usuario de complementos consumibles en las aplicaciones para UWP. Usar complementos consumibles para los elementos que se puedan comprar, usar y volver a comprar. Esto es especialmente útil para cosas como monedas de juego (oro, monedas, etc.) que se pueden comprar y usar para comprar bonificaciones concretas.

Nota:

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. Si la aplicación está destinada a una versión anterior de Windows 10, debes usar el espacio de nombres Windows.ApplicationModel.Store en lugar del espacio de nombres Windows.Services.Store. Para obtener más información, consulte este artículo.

Introducción a los complementos consumibles

Las aplicaciones pueden ofrecer dos tipos de complementos consumibles que difieren en la forma en que se administran los cumplimientos:

  • Consumible administrado por el desarrollador. Para este tipo de consumible, eres responsable de realizar un seguimiento del saldo del usuario de los elementos que representa el complemento, así como de notificar la compra del complemento cuando se complete en la Tienda y una vez que el usuario haya consumido todos los elementos. El usuario no puede comprar el complemento otra vez hasta que la aplicación notifique que la compra del complemento anterior se ha completado.

    Por ejemplo, si el complemento representa 100 monedas en un juego y el usuario consume 10 monedas, la aplicación o el servicio debe mantener el nuevo saldo restante de 90 monedas para el usuario. Cuando el usuario haya consumido las 100 monedas, la aplicación debe notificar el complemento como completado y, a continuación, el usuario puede volver a comprar el complemento de 100 monedas.

  • Consumible administrado por la Tienda. Para este tipo de consumible, la Tienda realiza un seguimiento del saldo del usuario de los elementos que representa el complemento. Cuando el usuario consume algún elemento, debes notificar dichos elementos como completados en la Tienda, tras lo cual la Tienda actualiza el saldo del usuario. El usuario puede comprar el complemento tantas veces como desee (no es necesario consumir primero los artículos). La aplicación puede consultar la Tienda para obtener el saldo actual del usuario en cualquier momento.

    Por ejemplo, si el complemento representa una cantidad inicial de 100 monedas en un juego y el usuario consume 50 monedas, la aplicación informa a la Tienda de que se han cumplido 50 unidades del complemento y la Tienda actualiza el saldo restante. Si el usuario vuelve a comprar el complemento para adquirir 100 monedas más, ahora tendrá 150 monedas en total.

    Nota

    Los consumibles administrados por la Tienda se introdujeron en Windows 10, versión 1607.

Para ofrecer un complemento consumible a un usuario, sigue este proceso general:

  1. Permitir que los usuarios compren el complemento desde la aplicación.
  2. Cuando el usuario consume el complemento (por ejemplo, al gastar monedas en un juego), notifica el complemento como completado.

En cualquier momento, también puedes obtener el saldo restante para un consumible administrado por la tienda.

Requisitos previos

Estos ejemplos cumplen los siguientes requisitos:

  • Un proyecto de Visual Studio para una aplicación de Plataforma universal de Windows (UWP) destinada a Windows 10 Anniversary Edition (10.0; Compilación 14393) o una versión posterior.
  • Has creado un envío de aplicación en el Centro de partners y esta aplicación se publica en la Tienda. Opcionalmente, puedes configurar la aplicación para que no se pueda detectar en la Tienda mientras la prueba. Para obtener más información, consulte nuestra guía de pruebas.
  • Ha creado un complemento consumible para la aplicación en el Centro de partners.

El código de estos ejemplos supone que:

  • El código se ejecuta en el contexto de una página que contiene un elemento ProgressRing denominado workingProgressRing y un elemento TextBlock denominado textBlock. Estos objetos se usan para indicar que se está produciendo una operación asincrónica y para mostrar mensajes de salida, respectivamente.
  • El archivo de código tiene una instrucción using para el espacio de nombres Windows.Services.Store.
  • La aplicación es una de usuario único que se ejecuta solamente en el contexto del usuario que la inició. Para obtener más información, consulta Pruebas y compras desde la aplicación.

Para obtener una aplicación de ejemplo completa, consulta la muestra de la Tienda.

Nota:

Si tienes una aplicación de escritorio que usa el Puente de dispositivo de escritorio, es posible que tengas que agregar código adicional que no se muestra en estos ejemplos para configurar el objeto StoreContext. Para obtener más información, consulta Uso de la clase StoreContext en una aplicación de escritorio que usa el Puente de escritorio.

Notificar un complemento consumible como completado

Después de que el usuario compre el complemento desde la aplicación y de consumir el complemento, la aplicación debe notificar el complemento como completado llamando al método ReportConsumableFulfillmentAsync de la clase StoreContext. Debes pasar la siguiente información a este método:

  • El Id. de la tienda del complemento que quieres notificar como completado.
  • Las unidades del complemento que quieres notificar como completadas.
    • Para los consumibles administrados por el desarrollador, especifica 1 para el parámetro cantidad. Esto alerta a la Tienda de que el consumible se ha suministrado y el cliente puede, a continuación, volver a comprar el consumible. El usuario no puede volver a comprar el consumible hasta que la aplicación haya notificado a la Tienda que se suministró.
    • Para un consumible administrado por la Tienda, especifica el número real de unidades que se hayan consumido. La Tienda actualizará el saldo restante para el consumible.
  • El identificador de seguimiento del suministro. Este es un GUID proporcionado por el desarrollador que identifica la transacción específica a la que la operación de suministro está asociada para realizar un seguimiento. Para obtener más información, consulta las observaciones de ReportConsumableFulfillmentAsync.

Este ejemplo muestra cómo notificar un consumible administrado por la Tienda como completado.

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

Obtener el saldo restante para un consumible administrado por la Tienda

En este ejemplo se muestra cómo usar el método GetConsumableBalanceRemainingAsync de la clase StoreContext para obtener el saldo restante para un complemento consumible administrado por la Tienda.

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