应用内购买和试用

Windows SDK 提供可用于实现以下功能的 API,以从通用 Windows 平台 (UWP) 应用获取更多收益:

  • 应用内购买 无论你的应用是否免费,你都可以直接从应用中销售内容或新的应用功能(例如解锁游戏的下一关)。

  • 试用功能 如果你在合作伙伴中心将应用配置为免费试用,则可通过在试用期内排除或限制某些功能吸引客户购买应用的完整版。 也可以在客户购买你的应用之前,启用仅在试用期才会出现的某些功能,如横幅或水印。

本文提供应用内购买和试用在 UWP 应用内的工作原理概述。

选择要使用哪个命名空间

有两个不同的命名空间可用于向 UWP 应用添加应用内购买和试用功能,具体取决于应用面向 Windows 10 的哪个版本。 尽管这些命名空间中的 API 用于相同目标,但它们的设计完全不同,并且代码在两个 API 之间并不兼容。

重要

Windows.ApplicationModel.Store 命名空间不再更新新功能,如果可能,建议你的应用改用 Windows.Services.Store 命名空间。 在使用桌面桥的 Windows 桌面应用程序或使用合作伙伴中心开发沙盒的应用或游戏中,Windows.ApplicationModel.Store 命名空间不受支持(例如,与 Xbox Live 集成的任何游戏都是这种情况)。

基本概念

Microsoft Store 中提供的每一个项目通常称为产品。 大多数开发人员只处理以下类型的产品:应用加载项

加载项是指你在应用的上下文中向客户提供的产品或功能:例如,要在应用或游戏中使用的货币、游戏的新地图或武器、使用无广告应用的功能,或数字内容,如应用的音乐或视频(前提是应用能够提供此类内容)。 每个应用和加载项都有关联的许可证,用于指示用户是否有权使用该应用或加载项。 如果用户有权将该应用或加载项作为试用来使用,则许可证还提供关于该试用的其他信息。

若要在应用中向客户提供加载项,必须在合作伙伴中心为应用定义加载项,以便使 Microsoft Store 知道它。 然后,应用可以使用 Windows.Services.StoreWindows.ApplicationModel.Store 命名空间中的 API 提供加载项,作为应用内购买向用户销售。

UWP 应用可提供以下类型的加载项。

加载项类型 说明
Durable 一个加载项,其持续时间为你在合作伙伴中心指定的生存期。

默认情况下,持久加载项永不过期,在这种情况下,只能购买一次。 如果你为加载项指定特定的持续时间,则用户可以在它过期后重新购买该加载项。

开发人员管理的易耗品 可以购买、使用并在用完后再次购买的加载项。 你负责跟踪用户对加载项表示的项的平衡。

当用户使用与加载项关联的任何项时,你负责维护用户的余额,并负责在用户用完所有项后向 Store 报告加载项的购买情况。 在你的应用将之前的加载项购买报告为已完成前,用户无法再次购买该加载项。

例如,如果加载项在一个游戏中表示 100 个玩家,而用户消耗了 10 个硬币,则应用或服务必须为用户保持 900000000 的新剩余余额。 在用户消耗完全部 100 个硬币后,你的应用必须将加载项报告为已完成,然后用户才可以再次购买 100 个硬币的加载项。

Microsoft Store 管理的易耗品 可以随时购买、使用并再次购买的加载项。 应用商店会跟踪用户对加载项表示的项的余额。

当用户使用与加载项关联的任何项时,你负责将履行的项报告给 Store,而 Store 会更新用户的余额。 用户可以根据需要多次购买加载项(他们不需要首先使用这些项目)。 你的应用可以随时查询用户的当前余量。

例如,如果加载项表示一个游戏的初始数量为 100 个,而用户消耗了 50 个硬币,则应用会向 Store 报告该加载项的 50 个单位已履行,而 Store 会更新剩余余额。 如果用户再次购买你的加载项(增加 100 个硬币),他们现在总共有 150 个硬币。

注意若要使用应用商店管理的易用产品,应用必须面向 Windows 10 周年版 (10.0;Visual Studio 中的内部版本 14393 ) 或更高版本,它必须使用 Windows.Services.Store 命名空间而不是 Windows.ApplicationModel.Store 命名空间。

订阅 一种持久型加载项,客户需要按重复时间间隔付费才能继续使用此加载项。 客户可以随时取消订阅,以免日后继续产生费用。

注意若要使用订阅加载项,应用必须面向 Windows 10 Anniversary Edition (10.0;Visual Studio 中的内部版本 14393 ) 或更高版本,它必须使用 Windows.Services.Store 命名空间而不是 Windows.ApplicationModel.Store 命名空间。

注意

其他类型的加载项,如使用软件包的耐用型加载项(也称为可下载内容或 DLC),仅适用于有限的开发人员群体,本文档中未涉及。

使用 Windows.Services.Store 命名空间的应用内购买和试用

此部分概述了 Windows.Services.Store 命名空间的重要任务和概念。 此命名空间仅适用于面向 Visual Studio 中的 Windows 10 周年纪念版(10.0;版本 14393)或更高版本的应用(这对应于 Windows 10 版本 1607)。 我们建议应用使用 Windows.Services.Store 命名空间,而非使用 Windows.ApplicationModel.Store 命名空间(如可能)。 有关 Windows.ApplicationModel.Store 命名空间的信息,请参阅本文

本部分内容

视频

请观看下面的视频,了解如何在你的应用中使用 Windows.Services.Store 命名空间实现应用内购买。

StoreContext 类入门

Windows.Services.Store 命名空间的主要入口点是 StoreContext 类。 此类提供的方法可用于获取当前应用及其可用加载项的信息、获取当前应用或其加载项的许可证信息、为当前用户购买应用或加载项以及执行其他任务。 若要获取 StoreContext 对象,请执行以下操作之一:

  • 在单用户应用(即,仅在启动该应用的用户上下文中运行的应用),使用静态 GetDefault 方法获取一个 StoreContext 对象,你可以使用该对象访问与用户的 Microsoft Store 相关数据。 大多数通用 Windows 平台 (UWP) 应用是单用户应用。

    Windows.Services.Store.StoreContext context = StoreContext.GetDefault();
    
  • 多用户应用中,使用静态 GetForUser 方法获取一个 StoreContext 对象,你可以使用该对象访问特定用户(使用该应用时使用 Microsoft 帐户登录的用户)的 Microsoft Store 相关数据。 以下示例为第一个可用用户获取 StoreContext 对象。

    var users = await Windows.System.User.FindAllAsync();
    Windows.Services.Store.StoreContext context = StoreContext.GetForUser(users[0]);
    

注意

使用桌面桥的 Windows 桌面应用程序必须执行额外步骤来配置 StoreContext 对象,然后才可以使用此对象。 有关详细信息,请参阅此部分

拥有 StoreContext 对象后,可开始调用此对象的方法来获取当前应用以及加载项的 Microsoft Store 产品信息、检索当前应用及其加载项的许可证信息、为当前用户购买应用或加载项以及执行其他任务。 有关可使用此对象执行的常见任务的详细信息,请参阅以下文章:

有关演示如何使用 StoreContextWindows.Services.Store 命名空间中的其他类型的示例应用,请参阅 Microsoft Store 示例

实现应用内购买

若要使用 Windows.Services.Store 命名空间在应用中向客户提供应用内购买:

  1. 如果应用提供可供客户购买的加载项,请在合作伙伴中心为应用创建加载项提交

  2. 在应用中编写代码以检索应用或应用提供的加载项的产品信息,然后确定许可证是否处于活动状态(即,用户是否具有使用该应用或加载项的许可证)。 如果许可证不处于活动状态,请显示提供应用或加载项以作为应用内购买向用户销售的 UI。

  3. 如果用户选择购买应用或加载项,请使用相应的方法购买该产品:

  4. 按照本文中的测试指南测试实现。

实现试用功能

若要使用 Windows.Services.Store 命名空间排除或限制应用的试用版中的功能:

  1. 在合作伙伴中心将应用配置为免费试用

  2. 在应用中编写代码以检索应用或应用提供的加载项的产品信息,然后确定与应用关联的许可证是否是试用许可证

  3. 如果是试用,则排除或限制应用中的特定功能,然后在用户购买完整许可证时启用这些功能。 有关详细信息和代码示例,请参阅实现应用的试用版

  4. 按照本文中的测试指南测试实现。

测试你的应用内购买或试用实现

如果你的应用使用 Windows.Services.Store 命名空间中的 API 实现应用内购买和试用功能,则你必须将应用发布到 Microsoft Store,然后将此应用下载到开发设备上以使用其许可证进行测试。 请按照下述过程测试你的代码:

  1. 如果应用尚未在 Microsoft Store 中发布和提供,请确保应用满足 Windows 应用认证工具包最低要求、将应用提交到合作伙伴中心,并确保应用通过认证过程。 在测试应用期间,你可以将应用配置为在 Microsoft Store 中隐藏。 请注意正确配置软件包外部测试版。 可能无法下载错误配置的软件包外部测试版。

  2. 接下来,确保已完成以下操作:

  3. 在项目在 Visual Studio 中打开的情况下,单击“项目菜单”,指向“Microsoft Store”,然后单击“将应用与 Microsoft Store 关联”。 完成向导中的说明以将应用项目与合作伙伴中心帐户中要用于测试的应用关联。

    注意

    如果你未将项目与 Microsoft Store 中的应用关联,则 StoreContext 方法会将其返回值的 ExtendedError 属性设置为错误代码值 0x803F6107。 此值指示 Microsoft Store 并不了解关于该应用的任何信息。

  4. 如果你尚未关联,请从 Microsoft Store 安装你在上一步中指定的应用、运行该应用一次,然后关闭此应用。 这可确保将应用的有效许可证安装到你的开发设备。

  5. 在 Visual Studio 中,开始运行或调试你的项目。 你的代码应从与你的本地项目关联的 Microsoft Store 应用中检索应用和加载项数据。 如果系统提示你重新安装该应用,请按照说明操作,然后运行或调试项目。

    注意

    完成这些步骤后,你可以继续更新应用代码并在开发计算机上调试更新的项目,而无需将新的应用包提交到 Microsoft Store。 获取将要用于测试的本地许可证后,只需要将应用的 Microsoft Store 版本下载到开发计算机。 完成测试后,只需要将新的应用包提交到 Microsoft Store,并允许客户使用应用内购买或应用中的试用相关功能。

如果你的应用使用的是 Windows.ApplicationModel.Store 命名空间,则在将应用提交到 Microsoft Store 之前,你可以在应用中使用 CurrentAppSimulator 类模拟许可证信息进行测试。 有关详细信息,请参阅 CurrentApp 和 CurrentAppSimulator 类入门

注意

Windows.Services.Store 命名空间不提供可用于在测试期间模拟许可证信息的类。 如果使用 Windows.Services.Store 命名空间实现应用内购买或试用,你必须将应用发布到 Microsoft Store,然后将此应用下载到开发设备上以使用其许可证进行测试(如上所述)。

应用内购买的收据

Windows.Services.Store 命名空间不在应用代码中提供可用于获取成功购买的交易收据的 API。 这是与使用 Windows.ApplicationModel.Store 命名空间的应用不同的体验,该命名空间可使用客户端 API 检索交易收据

如果使用 Windows.Services.Store 命名空间实现应用内购买并且希望验证给定客户是否已购买某个应用或加载项,可使用 Microsoft Store collection REST API 中的查询产品方法。 此方法的返回数据确认指定客户是否具有对给定产品的权利,并为用户获取产品的交易提供数据。 Microsoft Store 收集 API 使用 Azure AD 身份验证检索此信息。

通过桌面桥使用 StoreContext 类

使用桌面桥的桌面应用程序可使用 StoreContext 类实现应用内购买和试用。 但是,如果你有一个 Win32 桌面应用程序或者一个其窗口句柄 (HWND) 与呈现框架相关联的的桌面应用程序(如 WPF 或 Windows 应用 SDK 应用程序),则该应用程序必须配置 StoreContext 对象,以便为该对象所显示的模式对话框指定哪个应用程序窗口是所有者窗口。

许多 StoreContext 成员(以及通过 StoreContext 对象访问的其他相关类型的成员)针对 Microsoft Store 相关的操作(如购买产品)向用户显示模式对话框。 如果桌面应用程序未配置 StoreContext 对象以指定模式对话框的所有者窗口,则此对象将返回不准确的数据或错误。

若要在使用桌面桥的桌面应用程序中配置 StoreContext 对象,请按照这些步骤操作。

对于 .NET 5 或更高版本

如果应用程序通过 C# 结合使用 .NET 5 或更高版本编写,请执行以下步骤。

  1. 确保将项目文件中的 TargetFramework 属性TargetFramework,该 API 提供对 WinRT.Interop 命名空间的访问权限。 例如:

    <PropertyGroup>
      <!-- You can also target other versions of the Windows SDK and .NET, e.g. "net5.0-windows10.0.19041.0" -->
      <TargetFramework>net6.0-windows10.0.22000.0</TargetFramework>
    </PropertyGroup>
    
  2. 如果你的应用程序是多用户) 应用,请使用Adaptivesourcemanager.getdefault方法获取StoreContext对象 (或GetForUser ,如本文前面的) 所述。 若要使用指定的窗口句柄初始化对话框,请使用 GetWindowHandleInitializeWithWindow 方法 (参阅 检索窗口句柄 (HWND) 显示依赖于 CoreWindow) 的 WinRT UI 对象

    StoreContext context = StoreContext.GetDefault();
    // Obtain window handle by passing in pointer to the window object
    var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(windowObject);
    // Initialize the dialog using wrapper funcion for IInitializeWithWindow
    WinRT.Interop.InitializeWithWindow.Initialize(context, hwnd); 
    

对于早期版本的 .NET 或 C++

如果应用程序使用早期版本的 .NET 或 C++ 编写,请执行以下步骤。

  1. 进行以下操作之一,使你的应用可以访问 IInitializeWithWindow 接口:

    • 如果应用程序使用 C# 或 Visual Basic 之类的托管语言(.NET 5 之前)编写,则在应用代码中使用 ComImport 属性声明 IInitializeWithWindow 接口,如以下 C# 示例所示。 此示例假设代码文件具有 System.Runtime.InteropServices 命名空间的 using 语句。

      [ComImport]
      [Guid("3E68D4BD-7135-4D10-8018-9FB6D9F33FA1")]
      [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
      public interface IInitializeWithWindow
      {
          void Initialize(IntPtr hwnd);
      }
      
    • 如果使用 c + + 编写应用程序,请在代码中添加对 shobjidl.h 标头文件的引用。 此头文件包含 IInitializeWithWindow 接口的声明。

  2. 按照本文前面部分所述,使用 GetDefault 方法(或 GetForUser,如果你的应用是多用户应用)获取 StoreContext 对象并将此对象转换为 IInitializeWithWindow 对象。 然后,调用 IInitializeWithWindow.Initialize 方法,并传递你希望成为所有者(对于 StoreContext 方法显示的任何模式对话框)的窗口的句柄。 以下示例 C# 显示如何将应用主窗口的句柄传递到该方法。 另请参阅检索窗口句柄 (HWND)显示依赖于 CoreWindow 的 WinRT UI 对象

    StoreContext context = StoreContext.GetDefault();
    IInitializeWithWindow initWindow = (IInitializeWithWindow)(object)context;
    initWindow.Initialize(System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle);
    

产品、SKU 和可用性

Microsoft Store 中的每个产品都至少有一个 SKU,而每个 SKU 都至少有一个可用性。 已经为合作伙伴中心的大多数开发人员抽象掉这些概念,大多数开发人员永远不需要为其应用或加载项定义 SKU 或可用性。 但是,由于 Windows.Services.Store 命名空间中的 Microsoft Store 产品的对象模型包括 SKU 和可用性,因此大致了解这些概念对于某些情况可能很有帮助。

对象 说明
Products 产品是指在 Microsoft Store 中提供的任何类型的产品,包括应用或加载项。

商店中的每个产品都有对应的 StoreProduct 对象。 此类提供可用于访问数据的属性,如产品的 Store ID、Store 一览的图像和视频以及定价信息。 它还提供可用于购买产品的方法。

SKU SKU 是带有其自己的说明、价格和其他独特产品详细信息的产品特定版本。 每个应用或加载项都有默认的 SKU。 大多数开发人员拥有针对一个应用的多个 SKU 的唯一情况是,他们要发布应用的完整版和试用版(在 Microsoft Store 目录中,其中每一个版本都是同一个应用的不同 SKU)。

某些发布者可以定义自己的 Sku。 例如,大型游戏发布者可能发布具有以下两个 SKU 的游戏:一个 SKU 在不允许红色血液的市场中显示绿色血液,另一个 SKU 在所有其他市场中显示红色血液。 另外,销售数字视频内容的发布者可能针对一个视频发布两个 SKU,一个 SKU 用于高清版本,另一个 SKU 用于标清版本。

存储区中的每个 SKU 都有对应的 StoreSku 对象。 每个 StoreProduct 都有可用于访问产品 SKU 的 Skus 属性。

可用性 可用性是带有自己独特定价信息的 SKU 的特定版本。 每个 SKU 都有默认的可用性。 某些发布者能够定义他们自己的可用性来为给定 SKU 引入不同的价格选项。

存储区中的每个可用性都有对应的 StoreAvailability 对象。 每个 StoreSku 都有可用于访问 SKU 可用性的 Availabilities 属性。 对于大多数开发人员来说,每个 SKU 都有单个默认可用性。

Store ID

Microsoft Store 中的每个应用、加载项或其他产品都有关联的 Store ID(有时也称为产品 Store ID)。 许多 API 都需要 Store ID 才能执行有关应用或加载项的操作。

Microsoft Store 中的任何产品的 Store ID 都是 12 个字符的字母数字字符串,例如 9NBLGGH4R315。 有多种不同的方法可用于获取 Microsoft Store 中某个产品的 Store ID:

  • 对于应用,你可以在合作伙伴中心的“应用标识”页上获取 Store ID。
  • 对于加载项,你可以在合作伙伴中心的加载项概述页上获取 Store ID。
  • 对于任何产品,还可以使用表示此产品的 StoreProduct 对象的 StoreId 属性以编程方式获取 Store ID。

对于具有 SKU 和可用性的产品,SKU 和可用性还有自己的具有不同格式的 Store ID。

对象 Store ID 格式
SKU 对于 SKU,Store ID 的格式为 <product Store ID>/xxxx,其中 xxxx 是 4 个字符的字母数字字符串,用于标识产品的 SKU。 例如,9NBLGGH4R315/000N。 此 ID 由 StoreSku 对象的 StoreId 属性返回,并且有时称为 SKU 应用商店 ID
可用性 对于可用性,Store ID 的格式为 <product Store ID>/xxxx/yyyyyyyyyyyy,其中 xxxx 是标识产品 SKU 的 4 字符数字字母字符串,而 yyyyyyyyyyyy 是标识 SKU 可用性的 12 字符字母数字字符串。 例如,9NBLGGH4R315/000N/4KW6QZD2VN6X。 此 ID 由 StoreAvailability 对象的 StoreId 属性返回,并且有时称为可用性应用商店 ID

如何在代码中使用加载项的产品 ID

如果要在应用上下文中向客户提供加载项,你必须在合作伙伴中心创建加载项提交时为加载项输入唯一产品 ID。 你可以使用此产品 ID 在代码中引用加载项,但可以使用产品 ID 的特定方案取决于你在应用中实现应用内购买所用的命名空间。

注意

你在合作伙伴中心为加载项输入的产品 ID 不同于此加载项的 Store ID。 Store ID 由合作伙伴中心生成。

使用 Windows.Services.Store 命名空间的应用

如果应用使用的是 Windows.Services.Store 命名空间,你可以借助产品 ID 轻松识别表示加载项的 StoreProduct 或表示加载项许可证的 StoreLicense。 产品 ID 由 StoreProduct.InAppOfferTokenStoreLicense.InAppOfferToken 属性公开。

注意

虽然产品 ID 是在代码中识别加载项的有用方式,但 Windows.Services.Store 命名空间中的大多数操作使用的是加载项的 Store ID,而不是产品 ID。 例如,要以编程方式检索某应用的一个或多个已知加载项,可以向 GetStoreProductsAsync 方法传递加载项的 Store ID(而不是产品 ID)。 同样,要报告易耗型加载项已完成,可以向 ReportConsumableFulfillmentAsync 方法传递加载项的 Store ID(而不是产品 ID)。

使用 Windows.ApplicationModel.Store 命名空间的应用

如果应用使用 Windows.ApplicationModel.Store 命名空间,你需要使用自己在合作伙伴中心向加载项分配的产品 ID 来进行大多数操作。 例如: