应用内集成指南(适用于外部支付)

本文档介绍了如何集成 Play 结算库 API,以便在符合条件的应用中提供外部支付方式。如需详细了解此计划, 请参阅计划要求

Play 结算库设置

向您的 Android 应用添加 Play 结算库依赖项。如需使用 外部支付 API,您需要使用 8.3 或更高版本。如果您需要从较早版本 迁移,请先按照 迁移指南中的说明进行升级,然后再开始集成。

初始化结算客户端

集成流程的最初步骤与 Google Play 结算服务集成指南中所述的一些步骤相同,在 初始化您的 BillingClient时需进行一些调整:

以下示例演示了如何通过这些调整来初始化 BillingClient:

Kotlin

val purchasesUpdatedListener =
    PurchasesUpdatedListener { billingResult, purchases ->
        // Handle new Google Play purchase.
    }

val developerProvidedBillingListener =
    DeveloperProvidedBillingListener { details ->
        // Handle user selection for developer provided billing option.
    }

val billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableBillingProgram(
        EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build())
    .build()

Java

private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() {
    @Override
    public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
        // Handle new Google Play purchase.
    }
};

private DeveloperProvidedBillingListener developerProvidedBillingListener =
    new DeveloperProvidedBillingListener() {
        @Override
        public void onUserSelectedDeveloperBilling(
            DeveloperProvidedBillingDetails details) {
            // Handle user selection for developer provided billing option.
        }
    };

private BillingClient billingClient = BillingClient.newBuilder(context)
    .setListener(purchasesUpdatedListener)
    .enablePendingPurchases()
    .enableBillingProgram(
        EnableBillingProgramParams.newBuilder()
            .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
            .setDeveloperProvidedBillingListener(developerProvidedBillingListener)
            .build())
    .build();

连接到 Google Play

初始化 BillingClient 后,请按照 连接到 Google Play 中的说明连接到 Google Play

检查用户是否符合条件

连接到 Google Play 后,您可以通过调用 方法来检查用户是否符合 isBillingProgramAvailableAsync()外部支付计划的条件。如果用户符合条件,此方法会返回 BillingResponseCode.OK。 以下示例演示了如何检查用户是否符合条件:

Kotlin

billingClient.isBillingProgramAvailableAsync(
  BillingProgram.EXTERNAL_PAYMENTS,
  object : BillingProgramAvailabilityListener {
    override fun onBillingProgramAvailabilityResponse(
      billingProgram: Int, billingResult: BillingResult) {
        if (billingResult.responseCode != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors,
            // handling external payments unavailable, etc.
            return
        }

        // External payments are available. Can proceed with generating an
        // external transaction token.
})

Java

billingClient.isBillingProgramAvailableAsync(
  BillingProgram.EXTERNAL_PAYMENTS,
  new BillingProgramAvailabilityListener() {
    @Override
    public void onBillingProgramAvailabilityResponse(
      int billingProgram, BillingResult billingResult) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors,
            // handling external payments unavailable, etc.
            return;
        }

        // External payments are available. Can proceed with generating an external transaction token.
      }

    });

如需详细了解您的应用应如何 响应其他响应代码,请参阅响应处理部分。如果您使用的是 Kotlin 扩展,则您 可以使用 Kotlin 协程,因此您无需定义单独的监听器。

显示可购买的商品

您可以采用集成 Google Play 结算系统的相同方式向用户显示可购买的商品。当用户看到可供购买的 商品并选择购买时,请启动外部 支付流程(如 启动外部支付流程部分所述)。

准备外部交易令牌

如需向 Google Play 报告外部交易,您必须拥有从 Play 结算库生成的外部交易令牌。每次用户通过外部支付 API 访问外部网站或应用时,都必须生成新的外部交易令牌。这可以通过调用 createBillingProgramReportingDetailsAsync API 来完成。令牌应在调用 launchBillingFlow 之前立即生成。

Kotlin

val params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .build()

billingClient.createBillingProgramReportingDetailsAsync(
  params,
  object : BillingProgramReportingDetailsListener {
    override fun onCreateBillingProgramReportingDetailsResponse(
      billingResult: BillingResult,
      billingProgramReportingDetails: BillingProgramReportingDetails?) {
        if (billingResult.responseCode != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors.
            return
        }
        val externalTransactionToken =
            billingProgramReportingDetails?.externalTransactionToken
        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
    }
})

Java

BillingProgramReportingDetailsParams params =
    BillingProgramReportingDetailsParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .build();

billingClient.createBillingProgramReportingDetailsAsync(
  params,
  new BillingProgramReportingDetailsListener() {
    @Override
    public void onCreateBillingProgramReportingDetailsResponse(
      BillingResult billingResult,
      @Nullable BillingProgramReportingDetails
        billingProgramReportingDetails) {
        if (billingResult.getResponseCode() != BillingResponseCode.OK) {
            // Handle failures such as retrying due to network errors.
            return;
        }

        String transactionToken =
          billingProgramReportingDetails.getExternalTransactionToken();

        // Persist the external transaction token locally. Pass it to
        // the external website using DeveloperBillingOptionParams when
        // launchBillingFlow is called.
      }
});

如果您使用的是 Kotlin 扩展,则可以使用 Kotlin 协程,因此您 无需定义单独的监听器。

启动外部支付流程

通过调用 launchBillingFlow() 启动外部支付流程,这与通过 Google Play 结算 系统集成启动购买流程类似,但需要提供额外的参数 DeveloperBillingOptionParams,以表明您的应用希望为此购买交易启用外部支付流程。

DeveloperBillingOptionParams 必须包含以下内容:

当您的应用调用 launchBillingFlow() 并提供 DeveloperBillingOptionParams 时,Google Play 结算系统会执行以下检查:

  • 系统会检查用户的 Google Play 国家/地区是否是支持外部支付方式的国家/地区 (即是否是受支持的国家/地区)。如果用户的 Google Play 国家/地区受支持,Google Play 会根据 BillingClient 的配置以及是否提供了 DeveloperBillingOptionParams 来检查是否启用了外部支付方式。
    • 如果启用了外部支付方式,购买流程会显示用户选择体验。
    • 如果未启用外部支付方式,购买流程会显示标准的 Google Play 结算系统用户体验,无需用户选择。
  • 如果用户的 Google Play 国家/地区不是受支持的国家/地区,购买流程会显示标准的 Google Play 结算系统用户体验,无需用户选择。

用户的 Play 国家/地区受支持

用户的 Play 国家/地区不受支持

已启用外部支付方式(BillingClient 设置launchBillingFlow

用户会看到用户选择体验

用户会看到标准的 Google Play 结算系统用户体验

未启用外部支付方式(在 BillingClient 设置期间未启用,或未向 launchBillingFlow 提供 DeveloperBillingOptionParams)

用户会看到标准的 Google Play 结算系统用户体验

用户会看到标准的 Google Play 结算系统用户体验

以下代码段演示了如何构造 DeveloperBillingOptionParams

Kotlin

val developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .setLinkUri(Uri.parse("https://www.example.com/external/purchase"))
        .setLaunchMode(
            DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
        .build()

Java

DeveloperBillingOptionParams developerBillingOptionParams =
    DeveloperBillingOptionParams.newBuilder()
        .setBillingProgram(BillingProgram.EXTERNAL_PAYMENTS)
        .setLinkUri(Uri.parse("https://www.example.com/external/purchase"))
        .setLaunchMode(
            DeveloperBillingOptionParams.LaunchMode.LAUNCH_IN_EXTERNAL_BROWSER_OR_APP)
        .build();

处理用户选择

购买流程其余部分的处理方式不尽相同,具体取决于用户选择的是 Google Play 结算系统还是在您的网站上支付。

当用户选择在您的网站上或在支付应用中支付时

如果用户选择在您的网站上支付,Google Play 会调用 DeveloperProvidedBillingListener来通知应用用户选择在 您的网站上或在支付应用中支付。具体而言,系统会调用 onUserSelectedDeveloperBilling()方法。

如果您的应用将 launchMode 设置为 LAUNCH_IN_EXTERNAL_BROWSER_OR_APP,则 Google Play 将启动链接。如果 launchMode 设置为 CALLER_WILL_LAUNCH_LINK,则您的应用负责启动链接。 将用户链接到支付应用时,您有责任检查用户是否已在其设备上安装该支付应用。

后端集成指南中所述 ,使用此令牌可报告这一选择产生的任何交易。

当用户选择 Google Play 结算系统时

如果用户选择 Google Play 结算系统,则可以继续通过 Google Play 进行购买交易。

  • 如需详细了解如何通过 Google Play 结算系统处理新的应用内购买交易,请参阅库集成指南中的处理购买交易
  • 如需获得关于订阅购买交易的更多指南,请参阅订阅管理指南中的新订阅

处理订阅变更

对于使用外部支付方式的开发者,需要通过 Google Play 结算系统处理购买交易或使用 externalTransactionId 报告购买交易,具体取决于用户的选择。在订阅到期之前,通过开发者的网站来处理的对现有订阅的变更可通过同一结算系统实现。

本部分介绍了如何处理一些常见的订阅变更场景。

升级和降级流程

订阅方案变更(包括升级和降级流程)的处理方式应有所不同,具体取决于订阅最初是通过 Google Play 结算系统购买的,还是通过开发者的网站购买的。

依赖于现有订阅、共用相同的支付方式并采用相同的定期收费方式的加购项将作为升级来处理。对于其他加购项,用户应该能够选择要使用的结算系统。如 启动外部支付流程中所述,使用 launchBillingFlow() 启动新的购买体验。

通过开发者的网站或支付应用购买的订阅

对于最初在用户选择后通过开发者的网站或支付应用购买的订阅,请求升级或降级的用户应通过开发者的网站或支付应用继续操作,无需用户再次选择。

为此,当用户请求升级或降级时,请调用 launchBillingFlow()。请使用 setOriginalExternalTransactionId()提供原始购买交易的外部交易 ID,而不是在 SubscriptionUpdateParams对象下指定其他参数。

在此调用中,还必须提供 DeveloperBillingOptionParams。采用这种方式不会显示用户选择界面,因为系统会保留原始购买交易的相关用户选择以用于升级和降级。您必须为此交易生成 新的外部交易令牌,如此处所述

在使用开发者的网站或 支付应用完成升级或降级后,您需要使用通过之前针对新订阅 购买交易的调用所获得的外部 交易令牌来报告新交易

通过 Google Play 结算系统购买的订阅

同样,如果用户选择通过 Google Play 的 结算系统购买其当前订阅,系统应向该用户显示 标准的 Google Play 结算流程。在对 launchBillingFlow 的调用中,不得设置 DeveloperBillingOptionParams

订阅取消和恢复

用户应该能够随时取消订阅。用户取消订阅后,使用权可能直到付费期结束才会终止。例如,如果用户在月中取消了月度订阅,可以在剩下的大约 2 周内继续使用该服务,直到其使用权限被撤消为止。在此期间,订阅在技术层面上仍处于活跃状态,因此用户可以使用该服务。

在这一活跃期内,用户决定撤消取消订阅操作的情况并不少见。在本指南中,此情况称为“恢复”。以下部分介绍了如何在外部支付 API 集成中处理恢复场景。

通过开发者的网站购买的订阅

如果您有一项已取消的订阅的外部交易 ID,则无需调用 launchBillingFlow() 即可恢复该订阅,因此它不应被用于此类激活。如果用户在已取消的订阅的有效期内恢复订阅,则不会发生任何交易;如果当前周期到期后发生下次续订,您只需继续报告续订即可。这包括以下情形:用户在恢复期间会收到赠送金额或获享特殊续订价格(例如,一项旨在鼓励用户继续订阅的促销活动)。

通过 Google Play 结算系统购买的订阅

通常,用户可以在 Google Play 结算系统中恢复订阅。 对于最初通过 Google Play 的 结算系统购买的订阅,用户可以在订阅处于活跃状态时通过 Google Play 的 重新订阅 功能选择撤消之前的取消操作。在这种情况下,您会在后端收到 SUBSCRIPTION_RESTARTED 实时开发者通知,并且系统不会发放新的购买令牌,而会使用原始令牌来继续订阅。如需了解如何管理 Google Play 结算系统中的恢复,请参阅订阅管理指南中的 恢复。

您还可以通过调用 launchBillingFlow(),从应用中触发 Google Play 结算系统中的恢复订阅流程。如需了解实现方法,请参阅 订阅到期之前 - 应用内。如果用户完成了原始购买交易的用户选择流程(已取消,但仍处于活跃状态),系统会自动检测用户的选择,并显示用于恢复这些购买交易的界面。系统会提示用户通过 Google Play 确认重新购买相应订阅,但用户无需再次经历用户选择流程。在这种情况下,系统会为用户发放新的购买令牌。您的后端会收到 SUBSCRIPTION_PURCHASED 实时开发者通知,并且新购买交易状态的 linkedPurchaseToken 值会设为升级或降级情形下的状态,采用被取消的订阅之前所用的购买令牌。

重新订阅

如果订阅完全过期,无论是由于被取消还是未恢复且付款遭拒(账号冻结),如果用户想要重获使用权,必须重新订阅。

也可通过该应用来实现重新订阅,处理方法与标准订阅方式类似。用户应该能够选择要使用的结算系统。launchBillingFlow() 在这种情况下可能会被调用,如 启动外部支付流程中所述。

响应处理

发生错误时,isBillingProgramAvailableAsync()createBillingProgramReportingDetailsAsync()launchBillingFlow() 方法可能会提供 BillingResponseCode(而不是 BillingResponseCode.OK)。请考虑按如下方式处理这些响应代码:

测试外部支付链接

应使用许可测试人员来测试您的外部支付集成。 您不会收到由许可测试人员账号发起的交易的账单。如需详细了解如何 配置许可测试人员,请参阅 使用应用许可来测试应用内购结算功能

后续步骤

完成应用内集成后,您就可以集成您的 后端了。