Как управлять большим каталогом продуктов из приложения (HTML)

[ Эта статья адресована разработчикам приложений среды выполнения Windows для Windows 8.x и Windows Phone 8.x. При разработке приложений для Windows 10 см. раздел последняя документация]

В Windows 8.1 и Windows Phone 8.1 реализовано новое решение для приложений, предлагающих каталоги продуктов из приложения, которые содержат более 200 продуктовых позиций для каждой учетной записи разработчика (ограничение Магазина). Это решение позволяет создавать множество продуктовых позиций для определенных наборов цен. Каждая из этих позиций может представлять сотни продуктов в каталоге.

Для поддержки этой возможности была добавлена новая перегрузка метода RequestProductPurchaseAsync. Она позволяет покупателю воспользоваться предложением, определенным непосредственно в приложении и связанным с продуктовой позицией, реализующей продажу из приложения, в Магазине. Помимо указания связи между предложением и продуктовой позицией во время вызова, ваше приложение должно передать объект ProductPurchaseDisplayProperties, содержащий информацию о предложении из большого каталога. Если эти данные не предоставлены, будет использоваться информация для выставленной продуктовой позиции.

Магазин будет использовать идентификатор OfferId из запроса на покупку только в итоговом классе PurchaseResults. Этот процесс напрямую не меняет информацию, изначально указанную при выставлении продуктовой позиции, реализующей продажу из приложения, в Магазине.

Что необходимо знать

Технологии

Необходимые условия

  • В этом разделе рассказывается о поддержке представления нескольких продуктов для продажи из приложения с использованием одной продуктовой позиции, выставленной в Магазине. Чтобы ознакомиться с продуктами из приложения, см. статью Поддержка покупок продуктов из приложения, из которой вы узнаете о лицензировании и о том, как правильно вносить продукты из приложения в список Магазина.

  • В этом разделе также приводятся ссылки на примеры кода из примера пробной версии приложения и покупки из приложения, который можно найти в коллекции примеров кода на веб-сайте MSDN. Этот пример дает отличную возможность поэкспериментировать с разными способами оплаты, доступными для приложений среды выполнения Windows.

  • Когда вы создадите код для продаж продуктов из приложения и будете проверять его в первый раз, используйте объект CurrentAppSimulator вместо объекта CurrentApp. В этом случае вы сможете проверить логику лицензирования путем имитации обращения к серверу лицензирования вместо вызова реального сервера. Для этого в %userprofile%\AppData\local\packages\<package name>\LocalState\Microsoft\Windows Store\ApiData необходимо изменить файл с именем WindowsStoreProxy.xml. Имитатор Microsoft Visual Studio создает этот файл при первом запуске приложения, либо можно загрузить собственный его вариант во время выполнения. Дополнительную информацию см. в документах по CurrentAppSimulator.

Запрос на покупку для продукта из приложения

Запрос на покупку для конкретного продукта в большом каталоге обрабатывается во многом так же, как любой другой запрос на покупку в приложении. Когда ваше приложение вызывает новую перегрузку метода RequestProductPurchaseAsync, оно предоставляет идентификатор OfferId и объект ProductPurchaseDisplayProperties с наименованием продукта из приложения.

function purchaseAndFulfillOfferAsProduct() {
    var offerId = "1234";
    var displayPropertiesName = "MusicOffer1";
    var displayProperties = new ProductPurchaseDisplayProperties(displayPropertiesName);

    currentApp.requestProductPurchaseAsync("product1", offerId, displayProperties).done(
        function (purchaseResults) {
            if (purchaseResults.status === ProductPurchaseStatus.succeeded) {
                grantFeatureLocally("product1", purchaseResults.transactionId);
                fulfillProduct1("product1", purchaseResults.transactionId, purchaseResults.offerId);
            } else if (purchaseResults.status === ProductPurchaseStatus.notFulfilled) {
                if (isNotLocallyFulfilled("product1", purchaseResults.transactionId)) {
                    grantFeatureLocally("product1", purchaseResults.transactionId);
                }
                fulfillProduct1("product1", purchaseResults.transactionId, purchaseResults.offerId);
            } else if (purchaseResults.status === ProductPurchaseStatus.notPurchased) {
                log("Product 1 was not purchased.", "sample", "status");
            }
        },
        function () {
            log("Unable to buy product 1.", "sample", "error");
        });
}

Сообщение о выполнении продажи продукта из приложения

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

Как уже говорилось, Магазин использует предоставленные данные о предложении только для заполнения класса PurchaseResults и не создает постоянную связь между предложением из большого каталога и продуктовой позицией в Магазине. В результате вы должны отслеживать права пользователя на продукты из большого каталога и предоставлять пользователю контекст, относящийся к продукту (например, название приобретаемого товара или информацию о нем), вне операции RequestProductPurchaseAsync.

Приведенный ниже код демонстрирует вызов функции выполнения и шаблон сообщения пользовательского интерфейса, в который вставлена информация о конкретном предложении. Поскольку эта информация отсутствует, в примере используются данные из ListingInformation продуктовой позиции.

function fulfillProduct1(productId, transactionId, offerId) {
    var displayPropertiesName = document.getElementById("displayPropertiesName").value;
    if (displayPropertiesName === "") {
        displayPropertiesName = product1ListingName;
    }
    var offerIdMsg = " with offer id " + offerId;
    if (!offerId) {
        offerIdMsg = " with no offer id";
    }

    currentApp.reportConsumableFulfillmentAsync(productId, transactionId).done(
        function (result) {
            switch (result) {
                case FulfillmentResult.succeeded:
                    log("You bought and fulfilled " + displayPropertiesName  + offerIdMsg, "sample", "status");
                    break;
                case FulfillmentResult.nothingToFulfill:
                    log("There is no purchased product 1 to fulfill.", "sample", "status");
                    break;
                case FulfillmentResult.purchasePending:
                    log("You bought product 1. The purchase is pending so we cannot fulfill the product.", "sample", "status");
                    break;
                case FulfillmentResult.purchaseReverted:
                    log("You bought product 1. But your purchase has been reverted.", "sample", "status");
                    // Since the user's purchase was revoked, they got their money back.
                    // You may want to revoke the user's access to the consumable content that was granted.
                    break;
                case FulfillmentResult.serverError:
                    log("You bought product 1. There was an error when fulfilling.", "sample", "status");
                    break;
            }
        },
        function (error) {
            log("You bought Product 1. There was an error when attempting to fulfill.", "sample", "error");
        });
}

Связанные разделы

Пример пробной версии приложения и покупки из приложения

Поддержка покупок продуктов из приложения

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

Описание приложения

RequestProductPurchaseAsync

ProductPurchaseDisplayProperties