共用方式為


啟用消費性附加元件購買

本文示範如何使用 Windows.Services.Store 命名空間中的 StoreContext 類別的方法,來管理使用者在 UWP 應用程式中消費性附加元件的使用。 針對可以購買、使用然後再次購買的項目,使用消費型附加元件。 這對於可購買的遊戲內貨幣(如金幣、硬幣等),然後用來購買特定的遊戲增強道具特別有用。

注意

Windows.Services.Store 命名空間是在 Windows 10 版本 1607 中引進的,而且只能在目標為 Windows 10 年度版(10.0; 組建 14393) 或 Visual Studio 中的更新版本的專案中使用。 如果您的 app 以舊版 Windows 10 為目標,您必須使用 Windows.ApplicationModel.Store 命名空間,而不是 Windows.Services.Store 命名空間。 如需詳細資訊,請參閱 本文

消費性附加元件概觀

應用程式可以提供兩種類型的可消耗附加項目,這兩種類型在履行管理方式上有所不同:

  • 開發人員管理的消耗品。 針對這種類型的消費性產品,您必須負責追蹤附加元件所代表的用戶物品餘額,並在用戶消耗所有物品後,將附加元件的購買已完成狀態回報給商店。 用戶無法再次購買附加元件,直到您的應用程式回報先前的附加元件購買已完成為止。

    例如,如果您的附加元件在遊戲中代表 100 個硬幣,且使用者取用 10 個硬幣,則您的應用程式或服務必須為用戶維持 90 個硬幣的新剩餘餘額。 用戶取用所有 100 個硬幣之後,您的應用程式必須將附加元件回報為已完成,然後使用者可以再次購買 100 枚硬幣附加元件。

  • 店鋪管理的消耗品。 針對這種類型的消耗性產品,商店會追蹤附加元件代表的項目的用戶餘額。 當使用者取用任何項目時,您必須負責將這些項目報告為已使用至市集,而市集會更新用戶的餘額。 用戶可以無限次購買附加套件(他們不需要先使用這些物品)。 您的應用程式可以隨時查詢市集,以取得使用者的目前餘額。

    例如,如果您的附加元件代表遊戲中 100 個硬幣的初始數量,且使用者耗用 50 個硬幣,則您的應用程式會向市集回報 50 個附加元件已完成,而市集會更新剩餘餘額。 如果用戶接著重新購買您的附加元件以取得 100 個硬幣,他們現在總共會有 150 個硬幣。

    注意

    市集管理的消費性產品是在 Windows 10 版本 1607 中引進的。

若要為使用者提供消費性附加元件,請遵循下列一般程式:

  1. 讓使用者 從您的應用程式購買附加元件
  2. 當使用者取用附加元件時(例如,他們在遊戲中花費硬幣),將附加元件回報為已完成

您可以隨時 取得由商店管理的消費性產品的剩餘餘額

先決條件

這些範例具有下列必要條件:

這些範例中的程式代碼假設:

  • 程式碼在名為 Page 中執行,該 Page 包含一個名為 workingProgressRingProgressRing 及一個名為 textBlockTextBlock。 這些物件用來指出異步操作的發生以及顯示輸出訊息。
  • 程式代碼檔案包含作為 語句,使用了 Windows.Services.Store 命名空間。
  • 應用程式是一個單一使用者的程式,僅限在啟動者的使用者環境中執行。 如需詳細資訊,請參閱 應用程式內購買和試用版

如需完整的範例應用程式,請參閱 Store 範例

注意

如果您有使用 Desktop Bridge的桌面應用程式,您可能需要新增這些範例中未顯示的其他程式碼,以設定 StoreContext 物件。 如需詳細資訊,請參閱使用桌面橋接的桌面應用程式中的 StoreContext 類別

報告消耗品附加功能已履行

使用者 從您的應用程式購買附加元件,而且他們取用您的附加元件之後,您的應用程式必須呼叫 StoreContext 類別的 ReportConsumableFulfillmentAsync 方法,將附加元件回報為已完成。 您必須將下列資訊傳遞至此方法:

  • 市集標識碼 您想要回報為已完成的附加元件。
  • 您想要回報為已完成的附加元件單位。
    • 對於開發者管理的消耗性商品,將 數量 參數設為 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;
    }
}

取得市集管理的消費性產品剩餘餘額

此範例示範如何使用 StoreContext 類別的 GetConsumableBalanceRemainingAsync 方法來取得 Store 管理的消費性附加元件剩餘餘額。

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