Поддержка покупок потребляемых надстроек

В этой статье рассказывается, как использовать методы класса StoreContext в пространстве имен Windows.Services.Store для управления покупкой пользователями потребляемых надстроек в приложениях UWP. Используйте потребляемые надстройки для элементов, которые можно приобретать, использовать и снова приобретать. Это особенно удобно при покупке виртуальной валюты для игр (золота, монет и др.), которую можно потом использовать в процессе игры.

Примечание

Пространство имен Windows.Services.Store впервые появилось в Windows 10 версии 1607 и может использоваться только в проектах, предназначенных для Windows 10 Anniversary Edition (10.0; сборка 14393) или более поздней версии в Visual Studio. Если приложение предназначено для предыдущих версий Windows 10, необходимо использовать пространство имен Windows.ApplicationModel.Store, а не пространство имен Windows.Services.Store. Дополнительные сведения см. в этой статье.

Обзор потребляемых надстроек

Приложения могут предлагать два типа потребляемых надстроек, которые отличаются способом управления покупками:

  • Потребляемый элемент, управляемый разработчиком. Для этого типа потребляемых элементов вы отвечаете за отслеживание баланса пользователя для элементов, представляемых настройкой, а также за сообщение Магазину о том, что купленная надстройка израсходована, после того как пользователь израсходует все элементы. Пользователь не может снова приобрести надстройку, пока ваше приложение не сообщит об израсходовании предыдущей покупки.

    Например, если ваша надстройка представляет 100 игровых монет и пользователь израсходовал 10 монет, ваше приложение или служба должны поддерживать для пользователя новый баланс остатка в 90 монет. Когда пользователь израсходует все 100 монет, ваше приложение должно сообщить, что надстройка израсходована, после чего пользователь снова сможет приобрести 100 монет из надстройки.

  • Потребляемый объект, управляемый магазином. Для этого типа потребляемых надстроек учет баланса пользователя производится Магазином. Когда пользователь использует какие-либо элементы, вы должны сообщить Магазину, что эти элементы израсходованы, после чего Магазин обновляет баланс пользователя. Пользователь может приобрести надстройку сколько угодно раз (для этого не требуется сначала использовать элементы). Приложение может в любой момент запросить текущий баланс пользователя в Store.

    Например, если надстройка представляет начальную сумму в 100 игровых монет и пользователь израсходовал 50 монет, приложение сообщает Store, что израсходованы 50 единиц надстройки, и Store обновляет баланс. Если пользователь затем снова приобретает надстройку, чтобы получить еще 100 монет, общее число монет составит 150.

    Примечание

    Потребляемые надстройки, управляемые Store, были представлены в Windows 10 (версия 1607).

Чтобы предложить пользователю потребляемую надстройку, следуйте приведенному ниже общему процессу.

  1. Разрешите пользователями приобретать надстройку из приложения.
  2. Когда пользователь израсходует надстройку (например, истратит монеты в игре), сообщите, что надстройка израсходована.

В любой момент можно также получить оставшийся баланс для потребляемого элемента, управляемого Магазином.

Предварительные требования

Для этих примеров необходимо выполнение следующих предварительных условий.

В коде из этих примеров предполагается следующее:

  • Код выполняется в контексте страницы Page, которая содержит ProgressRing с именем workingProgressRing и TextBlock с именем textBlock. Эти объекты используются для индикации выполнения асинхронной операции и отображения выводимых сообщений, соответственно.
  • Файл кода содержит оператор using для пространства имен Windows.Services.Store.
  • Приложение — однопользовательское и выполняется только в контексте пользователя, запустившего его. Подробнее см. в разделе Покупки из приложения и пробные версии.

Полный пример приложения см. в разделе Пример для Магазина.

Примечание

Если у вас есть классическое приложение, которое использует мост для классических приложений, вам может потребоваться добавить дополнительный код, не показанный в этих примерах, для настройки объекта StoreContext. Дополнительные сведения см. в разделе Использование класса StoreContext в классическом приложении, в котором применяется мост для классических приложений.

Сообщение о том, что потребляемая надстройка израсходована

После того как пользователь приобрел надстройку из приложения и израсходовал ее, приложение должно сообщить об израсходовании надстройки, вызвав метод ReportConsumableFulfillmentAsync класса StoreContext. Этому методу необходимо передать следующую информацию:

  • Код продукта в Магазине для надстройки, об израсходовании которой требуется сообщить.
  • Единицы надстройки, об израсходовании которой требуется сообщить.
    • В случае потребляемого элемента, управляемого разработчиком, укажите для параметра quantity значение «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;
    }
}

Получение оставшегося баланса для потребляемого элемента, управляемого Магазином

Этот пример демонстрирует использование метода GetConsumableBalanceRemainingAsync класса StoreContext для получения оставшегося баланса потребляемой надстройки, управляемой Магазином.

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