信息
您所需的主题如下所示。但此主题未包含在此库中。

Windows Phone 8 的应用内购买 API 概述

2013/12/5

适用于:仅限于 Windows Phone 8。

本主题概述 Windows Phone 8 的应用内购买 API。

本主题包含以下各节。

通过使用应用内购买,您可以创建销售虚拟产品的应用和游戏来赚取实际收益。Microsoft 服务器承载用户可使用应用内购买功能购买的您的虚拟产品目录,其中包括价格和描述。Microsoft 还提供了一种商业基础结构,包括用户可在全世界受支持的国家和区域使用的支付方式。

在 开发人员中心 中,您针对用户可以进行应用内购买的各个地区,为用户可通过应用内购买购买到的每件产品,输入关于它们的说明和价格。使用此文档中的 API,您可以在应用中列出用户可以在该应用内买到的产品。您无需为处理不同类型的购买设备编写特殊的代码。用于在 Windows Phone 商店 中购买应用和游戏的方法也适用于应用内购买 API。您必须承载和提供与应用内产品相关的任何内容。

产品类型

Windows Phone 8 支持两种类型的应用内产品(用户可以购买):可消耗型耐用型。下表提供有关每种应用内产品的详细信息。这些产品类型在 ProductType 枚举中定义。

应用内产品类型

说明

示例

可消耗型

是指一种可以购买、使用(消耗)和再度购买的产品。

1,000 单位金币

耐用型

用户购买后由用户永远所有的产品。它没有被消耗。

游戏级别

Windows.ApplicationModel.Store

Windows.ApplicationModel.Store 命名空间包含可以用来实现应用中的应用内购买体验的类。您可以使用这些类对您的应用及其应用内产品的许可证状态进行检查和启用应用内购买。该 API 的 Windows Phone 8 版本实现了大部分而非全部的 Windows 8 功能。以下表格列出了 Windows.ApplicationModel.Store 中的类,它们既可以在 Windows 8 中又可以在 Windows Phone 8 中使用。

类

说明

CurrentApp

定义您可以用来获取有关当前应用的许可和列表信息并执行应用内购买的方法和属性。

LicenseInformation

列出用户所拥有的产品的所有许可证。

ListingInformation

列出用户在其所在国家/地区可以从应用中购买的 商店 产品。

ProductLicense

表明用户是否拥有某种具体的应用内产品。

ProductListing

描述信息,包括用户可以在应用中购买的应用内产品的本地化定价、图标、标题和说明。

Windows Phone 8 中的其他应用内购买功能

下表列出了我们专为 Windows Phone 8 而向 Windows.ApplicationModel.Store 命名空间中的一些类型添加的其他方法和属性。

类

成员

说明

CurrentApp

LoadListingInformationByProductIdsAsync(ListingInformation productIds)

为匹配任一指定的产品 ID 的应用内产品异步加载产品列表信息。指定一个空 ID 列表返回所有应用内产品的产品列表信息。

CurrentApp

LoadListingInformationByKeywordsAsync(ListingInformation keywords)

为匹配所有指定的关键字的应用内产品异步加载产品列表信息。指定一个空关键字列表返回所有应用内产品的列表信息。

若为每一个关键字单独调用此 API,则可以为匹配一个或多个关键字的所有应用内产品加载列表信息。

CurrentApp

void ReportProductFulfillment(string productId)

通知 商店,应用已经将所购产品交付给用户。在您使用此方法确认产品交付前,用户不能再次购买相同的产品。这仅仅适用于可消耗型产品。

ProductLicense

bool IsConsumable { get; }

获取关于具有此许可证的产品是否为可消耗型产品的信息。

ProductListing

string Description { get; }

获取应用内产品的说明。

ProductListing

IEnumerable<string> Keywords {get;}

获取该应用内产品的关键字列表。这些关键字可用于过滤产品列表。

ProductListing

ProductType ProductType {get;}

获取应用内产品的类型。它可能是 ProductType.ConsumableProductType.Durable

ProductListing

string Tag {get;}

获取包含有关此应用内产品的自定义信息的标记字符串。

ProductListing

Uri ImageUri { get; }

获取与此应用内产品关联的图像的 URI。

本节包含的一系列代码示例会告诉您如何使用新的 应用内购买 API 来执行以下操作:

  • 为具有具体的产品 ID 的应用内产品加载列表信息

  • 显示购买屏幕并处理不完整购买的异常情况

  • 实现可消耗型应用内产品

  • 使用收据作为服务器上的购买凭证

为具有具体的产品 ID 的应用内产品加载列表信息


async void LoadProductListingsByProductIds()
{
    // First, retrieve the list of some products by their IDs.
    ListingInformation listings = await CurrentApp.LoadListingInformationByProductIdsAsync(
                                    new string[] { "Bag of 50 gold", "Bag of 100 gold" });

    // Then, use the flat list of products as the data source for a
    // list box containing data-bound list items.
    ProductListBox.ItemsSource = listings.ProductListings.Values;
}

显示购买屏幕


async void PurchaseProduct(string productId)
{
    try
    {
        // Kick off purchase; don't ask for a receipt when it returns
        await CurrentApp.RequestProductPurchaseAsync(productId, false);

        // Now that purchase is done, give the user the goods they paid for
        // (DoFulfillment is defined later)
        DoFulfillment();
    }
    catch (Exception ex)
    {
        // When the user does not complete the purchase (e.g. cancels or navigates back from the Purchase Page), an exception with an HRESULT of E_FAIL is expected.
    }
}

实现可消耗型应用内产品


// This should be replaced in your code with a persistent storage mechanism that is tamper-resistant.
int m_goldCount = 0;
int m_silverCount = 0;

//
// Fulfillment of consumable in-app products
public void DoFulfillment()
{
    var productLicenses = CurrentApp.LicenseInformation.ProductLicenses;

    // Check fulfillment for consumable products with hard-coded asset counts
    MaybeGiveMeGold(productLicenses["Bag of 50 gold"], 50);
    MaybeGiveMeGold(productLicenses["Bag of 100 gold"], 100);

    // Check fulfillment for consumable products with variable asset counts
    MaybeGiveMeSilver(productLicenses);
}

// Count is passed in as a parameter
void MaybeGiveMeGold(ProductLicense license, int goldCount)
{
    if (license.IsConsumable && license.IsActive)
    {
        m_goldCount += goldCount;
        CurrentApp.ReportProductFulfillment(license.ProductId);
    }
}

// Count is part of the product ID
void MaybeGiveMeSilver(IReadOnlyDictionary<string, ProductLicense> productLicenses)
{
    Regex bagOfSilver = new Regex(@"Bag\.Silver\.(\d+)");

    foreach (ProductLicense license in productLicenses.Values)
    {
        if (license.IsConsumable && license.IsActive)
        {
            MatchCollection m = bagOfSilver.Matches(license.ProductId);

            if ((m.Count == 2) && (m[1].Success))
            {
                m_silverCount += int.Parse(m[1].Value);
                CurrentApp.ReportProductFulfillment(license.ProductId);
            }
        }
    }
}

使用收据作为服务器上的购买凭证


async Task<bool> LoadLevelAsync(string levelProductId)
{
    ProductLicense license = CurrentApp.LicenseInformation.ProductLicenses[levelProductId];

    if (!license.IsActive)
    {
        // User doesn't own this level
        return false;
    }

    if (!IsLevelDownloaded(levelProductId))
    {
        string receiptXml = await CurrentApp.GetProductReceiptAsync(levelProductId);

        await DownloadLevelAsync(receiptXml);
    }

    // TODO: Load the level
    return true;
}

async Task DownloadLevelAsync(string receiptXml)
{
    var webReq = (HttpWebRequest)WebRequest.Create(sc_DownloadUrl);

    webReq.Method = "POST";

    AddStringToWebRequestStream(webReq, receiptXml);

    WebResponse response = await webReq.GetResponseAsync();

    // TODO: Save the level to disk
}

显示: