次の方法で共有


アプリ内製品の大規模なカタログを管理する方法 (HTML)

[ この記事は、Windows ランタイム アプリを作成する Windows 8.x および Windows Phone 8.x 開発者を対象としています。Windows 10 向けの開発を行っている場合は、「最新のドキュメント」をご覧ください]

Windows 8.1 と Windows Phone 8.1 では、開発者アカウントごとの製品数がストアの限度である 200 を超えるようなアプリ内製品カタログのあるアプリを対象として、新しいソリューションが導入されています。このソリューションでは、特定の価格帯に対して少数の製品エントリを作成することができます。個々のエントリは、カタログ内の多数の製品を表すことができます。

この機能を有効にするために、RequestProductPurchaseAsync メソッドの新しいオーバーロードが導入され、ストアに掲載されたアプリ内購入製品に関連する、アプリで定義された販売を購入できます。呼び出し中に販売と製品の関連付けを指定することに加えて、アプリでは、大規模なカタログ販売の詳細を格納する ProductPurchaseDisplayProperties オブジェクトも渡す必要があります。これらの詳細が指定されていない場合、一覧に掲載された製品の詳細が代わりに使われます。

ストアでは、結果の PurchaseResults で、購入要求からの OfferId のみを使います。 このプロセスは、ストアにアプリ内購入製品を掲載したときに最初に提供された情報を直接変更するわけではありません。

理解しておく必要があること

テクノロジ

必要条件

  • このトピックでは、ストアの一覧に表示される 1 つのアプリ内購入製品を使って複数のアプリ内製品を表現することに対する、ストアのサポートについて説明します。アプリ内製品に詳しくない場合は、「アプリ内製品購入の有効化」を読んで、ライセンス情報と、ストアでアプリ内製品を適切に一覧表示する方法を確かめてください。

  • このトピックでは、MSDN ギャラリーの試用アプリとアプリ内購入のサンプルに関するページで提供されているコード例も参照します。このサンプルを利用すると、Windows ランタイム アプリに提供されるさまざまな収益化オプションを体験できます。

  • 新しいアプリ内製品のコード記述やテストを初めて行うときは、CurrentApp オブジェクトではなく、CurrentAppSimulator オブジェクトを使う必要があります。そうすることで、実稼働サーバーを呼び出すのではなく、ライセンス サーバーへのシミュレートされた呼び出しを使って、ライセンス ロジックを検証できます。そのためには、%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 操作の外部でユーザーに提供します。

次のコードは、フルフィルメントの呼び出しと、特定の販売情報が挿入される UI メッセージング パターンを示しています。 この特定の製品情報がない場合、この例では製品の 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