最大限度发挥 Play 结算服务集成的效用

1. 概览

通过 Google Play 提供的此 Play 结算库集成 Codelab,您可以优化收入来源并放心地发布应用。此结构化 Codelab 将指导您设置、测试和实现可靠的购买交易处理,从而帮助您实现创收目标并提供更顺畅的用户体验。

我们将帮助您为应用和游戏中的订阅和一次性商品设置实时开发者通知 (RTDN) 和 Play Billing Lab。您将了解如何减少订阅者流失;防范欺诈和滥用行为;测试极端情况;模拟、重现和解决潜在问题;以及在不影响用户的情况下尝试优惠和价格变动。

完成本课程后,您将能够实施客户挽回策略、快速解决集成难题、提高投资回报率、提供优质体验,并自信地发布应用和更新。

前提条件

学习内容

  • 如何妥善管理购买生命周期,利用各种技巧来提高购买转化次数和客户留存率,从而帮助优化增长
  • 如何使用 Google Cloud Pub/Sub 设置实时开发者通知 (RTDN),然后利用这些通知来实施用户挽回广告系列和其他生命周期管理策略
  • 如何在后端服务器上设置接收器,以安全地处理通知,并准确跟踪和授权,从而降低意外退款或欺诈和滥用风险
  • 如何使用 Play Billing Lab 测试集成并模拟错误,从而在降低开发成本的同时改善用户体验

所需条件

2. 订阅和单次购买的变现策略

通过应用销售数字商品时,成功的创收策略必须考虑用户体验的方方面面,包括一次性购买和订阅。顺畅的体验可以提高买家的购买意愿并减少客户流失。

一次性购买或订阅的常见购买流程包含多个阶段:

  1. 用户浏览要购买的商品。
  2. 启动购买流程,以便用户完成购买和付款。
  3. 向服务器通知已完成的购买交易
  4. 在您的服务器上验证购买交易。
  5. 向用户提供内容。
  6. 确认内容已传送给用户。对于消耗型商品,请在适当的时间将购买的商品标记为消耗,以便用户能够再次购买商品。

借助应用内集成,您可以启动购买流程并管理此用户体验,但请务必确保您的后端能及时了解用户购买交易的最新权限。这对于跟踪购买交易以及管理用户体验的其他方面(例如跨平台权限)而言非常重要。

实时开发者通知 (RTDN) 可用于识别购买生命周期中的这些不同阶段,既可作为实时效果跟踪工具有效使用,也可作为启用订阅者挽回策略的工具。

例如,假设您的用户刚刚购买了新商品,或者刚刚错过了付款时间,因此订阅已进入宽限期。借助正确的 RTDN,您可以近乎实时地识别出用户的状态发生了变化,并采取相应措施,例如让用户更积极地使用他们刚刚购买的商品,或者向他们发送提醒电子邮件,提示他们更新付款详细信息以继续订阅。

RTDN 也是一种很好的方式,可用于添加额外的服务器端控制,帮助您管理购买交易,即使在用户客户端出现问题时也是如此。假设用户成功购买了商品并收到了 Google 的确认消息,但用户设备在通过购买交易监听器收到购买交易的通知之前失去了网络连接。借助 RTDN,您会通过服务器收到独立通知,从而能够识别购买交易并向用户授予使用权,而不会受到客户端问题的影响,确保购买流程的可靠性。

您可以点击此处详细了解目前支持的所有类型的 RTDN。每种类型的 RTDN 都表示不同的购买状态。务必要实现相应的处理机制,以确保在您的使用情形中按需进行适当的处理。此 Codelab 将通过一个示例向您展示如何在安全后端服务器中处理 RTDN 消息,包括在用户成功完成应用内购买交易时接收消息、验证购买交易并向正确的用户授予使用权。接下来,我们将向您展示如何为应用配置 RTDN。

3. 配置实时开发者通知 (RTDN)

借助实时开发者通知 (RTDN),您可以利用 Google Cloud Pub/Sub 立即对购买状态变化做出反应。Cloud Pub/Sub 是一项全托管式实时消息传递服务,您可以使用该服务在独立的应用之间收发消息。Google Play 使用 Cloud Pub/Sub 发布有关您所订阅主题的推送通知。

如需启用 RTDN,您必须先使用自己的 Google Cloud Platform (GCP) 项目设置 Cloud Pub/Sub,然后再为您的应用启用通知。如果您不熟悉 GCP 和 Cloud Pub/Sub,请参阅快速入门指南

创建主题

如需开始接收通知,您必须创建一个主题,Google Play 会将通知发布到该主题。如需创建主题,请按照创建主题中的说明操作。

创建 Pub/Sub 订阅

如需接收发布到某个主题的消息,您必须创建对该主题的 Pub/Sub 订阅。如需创建 Pub/Sub 订阅,请执行以下操作:

  1. 请阅读 Cloud Pub/Sub 订阅者指南,熟悉如何将订阅配置为 推送订阅拉取订阅。在此 Codelab 中,我们将使用拉取订阅,该订阅要求您的安全后端服务器向 Cloud Pub/Sub 服务器发起请求以检索消息。
  1. 按照添加订阅中的说明来创建订阅。

针对您的主题授予发布权限

Cloud Pub/Sub 要求您向 Google Play 授予向您的主题发布通知的权限。

  1. 打开 Google Cloud 控制台
  2. 选择您的项目,然后在搜索栏中搜索“Pub/Sub”,然后前往 Pub/Sub 配置页面。搜索并进入 Pub/Sub 配置页面
  3. 找到相应主题,然后打开权限设置。打开权限设置
  4. 点击添加正文以添加服务账号 google-play-developer-notifications@system.gserviceaccount.com,然后授予其 Pub/Sub 发布商的角色。添加服务账号 google-play-developer-notifications@system.gserviceaccount.com,然后授予其 Pub/Sub 发布商的角色
  5. 点击保存以完成主题的设置。点击“保存”以完成主题的设置。

为您的应用启用 RTDN

了解如何设置实时开发者通知 (RTDN),以显著增强 Play 结算服务集成。您可以通过个性化消息提高购买可靠性,还可以防范欺诈和滥用行为,从而提高整体投资回报率。

RTDN 可直接从 Google Play 提供即时服务器到服务器更新,以通知订阅续订、新购买交易和付款问题等关键事件。它们有助于您的后端系统自动与用户使用权的真实状态同步,从而突破客户端限制,让您能够立即做出适当的反应。

如何为您的应用启用实时开发者通知:

  1. 打开 Google Play 管理中心
  2. 选择您的应用。
  3. 依次前往通过 Play 创收 > 创收设置
  4. 滚动到实时开发者通知部分。
  5. 勾选启用实时通知
  6. 主题名称字段中,输入您之前配置的完整 Cloud Pub/Sub 主题名称。主题名称应采用 projects/{project_id}/topics/{topic_name} 格式,其中 project_id 是项目的唯一标识符,topic_name 是之前创建的主题的名称。
  7. 点击发送测试消息以发送测试消息。进行发布测试有助于确保一切均已正确设置和配置。如果测试发布成功,则系统会显示一条消息,表明测试发布已成功。如果您已附加该主题的订阅,则应收到测试消息。对于“拉取订阅”,请在 Cloud 控制台中找到该订阅,点击查看消息,然后继续拉取消息。您应该确认提取的任何消息,以避免 Cloud Pub/Sub 重复传送。对于推送订阅,请检查测试消息是否已传送至您的推送端点。成功的响应代码将充当确认消息的作用。如果发布失败,则系统会显示错误。请确保主题名称正确,并且 google-play-developer-notifications@system.gserviceaccount.com 服务账号拥有对该主题的 Pub/Sub 发布商访问权限。
  8. 选择您希望接收的通知类型。
  • 接收与订阅和所有废弃的购买交易相关的通知 - 接收与订阅和废弃的购买交易相关的实时开发者通知。您不会收到有关一次性商品购买交易的通知。
  • 接收与订阅和一次性商品相关的所有通知 - 接收与所有订阅和废弃的购买交易相关的通知。您还会收到一次性商品购买事件,例如 ONE_TIME_PRODUCT_PURCHASEDONE_TIME_PRODUCT_CANCELED。如需详细了解这些购买事件,请参阅单次购买生命周期

a266e5dec5c93cd8.png

  1. 点击保存更改

现在,您已为应用完成实时开发者通知的设置,从而获得相关工具来应对常见挑战,例如通过挽回消息来减少用户流失,以及防范欺诈和滥用行为。在下一部分中,我们将在您的安全后端服务器中构建一个订阅者,以使用发送到您的 Cloud Pub/Sub 主题的消息。

4. 接收通知

为了在应用中提供最佳用户体验,请务必让后端服务器及时了解购买交易的状态。例如,当用户在应用中成功完成付款交易后,应尽快将内容交付到其账号。

这需要及时检测和处理购买交易的完成情况。Play 结算库提供了多种方式来检测应用中的购买交易。检测到已完成的购买交易后,您的应用必须通知后端服务器验证该购买交易,向相应用户授予内容,然后通知 Google 该购买交易已处理完毕。不过,由于各种原因,您的应用可能未能及时检测到购买交易。例如,用户可以成功购买商品并收到 Google 的确认消息,但用户设备在通过 Play 结算库接口收到通知之前失去了网络连接。借助 RTDN,您可以获得额外的服务器端控制功能,即使在用户客户端出现问题时也能管理购买交易。RTDN 可保证在购买状态发生变化时,向您的服务器发送独立通知,让您能够通过第二条路径几乎立即识别购买状态的变化,而不会受到潜在的客户端问题的影响,从而确保购买流程更加可靠。

在本部分中,您将使用 Cloud Pub/Sub 客户端库构建一个订阅者,以使用发送到 Cloud Pub/Sub 主题的消息。这些库有多种语言版本。在以下部分中,我们将向订阅者添加代码,以验证购买交易、向正确用户授予使用权,并在服务器上确认/消耗购买交易。在本 Codelab 中,我们使用的是 Java。

发布到 Cloud Pub/Sub 主题的每条消息都包含一个以 base64 编码的数据字段。

{
 "message": {
   "attributes": {
     "key": "value"
   },
   "data": "eyAidmVyc2lvbiI6IHN0cmluZywgInBhY2thZ2VOYW1lIjogc3RyaW5nLCAiZXZlbnRUaW1lTWlsbGlzIjogbG9uZywgIm9uZVRpbWVQcm9kdWN0Tm90aWZpY2F0aW9uIjogT25lVGltZVByb2R1Y3ROb3RpZmljYXRpb24sICJzdWJzY3JpcHRpb25Ob3RpZmljYXRpb24iOiBTdWJzY3JpcHRpb25Ob3RpZmljYXRpb24sICJ0ZXN0Tm90aWZpY2F0aW9uIjogVGVzdE5vdGlmaWNhdGlvbiB9",
   "messageId": "136969346945"
 },
 "subscription": "projects/myproject/subscriptions/mysubscription"
}

对以 base64 编码的数据字段进行解码后,DeveloperNotification 包含以下字段:

{
 "version": string,
 "packageName": string,
 "eventTimeMillis": long,
 "oneTimeProductNotification": OneTimeProductNotification,
 "subscriptionNotification": SubscriptionNotification,
 "voidedPurchaseNotification": VoidedPurchaseNotification,
 "testNotification": TestNotification
}

如需了解详情,请参阅实时开发者通知参考指南

以下是 NotificationReceiver 的示例代码,用于让您的安全后端服务器处理 Pub/Sub 消息。如需向 Security Command Center 进行身份验证,请设置应用默认凭证,请参阅为本地开发环境设置身份验证

import com.google.cloud.pubsub.v1.AckReplyConsumer;
import com.google.cloud.pubsub.v1.MessageReceiver;
import com.google.cloud.pubsub.v1.Subscriber;
import com.google.pubsub.v1.ProjectSubscriptionName;
import com.google.pubsub.v1.PubsubMessage;
import java.util.Base64;
import org.json.JSONObject;

/** Real-time developer notifications receiver. */
public class NotificationReceiver {

 private NotificationReceiver() {}

 /*
  * Receive notification messages from the subscription.
  *
  * @param projectId The project ID of your Google Cloud Project.
  * @param subscriptionId The subscription ID of the subscriber to the pub/sub topic.
  */
 public static void receiveNotificationMessages(String projectId, String subscriptionId) {
   ProjectSubscriptionName subscriptionName =
       ProjectSubscriptionName.of(projectId, subscriptionId);

   try {
     Subscriber subscriber =
         Subscriber.newBuilder(subscriptionName, new NotificationMessageReceiver()).build();
     // Start the subscriber.
     subscriber.startAsync().awaitRunning();

     subscriber.awaitTerminated();
   } catch (IllegalStateException e) {
     System.out.println("Subscriber stopped: " + e);
   }
 }

 static class NotificationMessageReceiver implements MessageReceiver {

   @Override
   public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
     // Decode the data into a String from the message data field.
     String jsonString = new String(Base64.getDecoder().decode(message.getData().toStringUtf8()));
     // Parse the String into a JSON object.
     JSONObject messageJson = new JSONObject(jsonString);

     // Fetch the value for certain fields.
     String version = messageJson.getString("version");
     String packageName = messageJson.getString("packageName");
     System.out.println("version: " + version);
     System.out.println("packageName: " + packageName);

     // Validate the purchase and grant the entitlement as needed.
     // More details in the following sections.
     // ......

     // Acknowledge the message to avoid repeated delivery.
     consumer.ack();
   }
 }
}

现在,您有了一个通知接收器,可在安全后端服务器中使用发送到 Cloud Pub/Sub 主题的消息。在以下部分中,我们将介绍在后端服务器中处理 RTDN 消息的最佳实践。

5. 在应用内的购买流程中附加用户标识符

当您的服务器收到有关购买状态更新的 RTDN 消息时,需要知道是哪个用户进行了购买交易,以便处理该交易,例如将内容交付给正确的用户。为此,您可以在应用中启动购买流程时,使用 obfuscatedAccountId 附加您拥有的购买用户的任何用户标识符。标识符示例可以是您系统中的用户登录名的混淆版本。设置此参数有助于 Google 检测欺诈行为。此外,如向用户授予使用权中所述,它还可以帮助您确保购买交易归因于正确的用户。

以下代码示例展示了如何在应用中启动购买流程时通过设置 obfuscatedAccountId 附加用户标识符。

// An activity reference from which the billing flow will be launched.
Activity activity = ...;
// A user identifier, e.g. an obfuscated user id in your system.
String obfuscatedAccountId = ...;

ImmutableList<ProductDetailsParams> productDetailsParamsList =
    ImmutableList.of(
        ProductDetailsParams.newBuilder()
            // retrieve a value for "productDetails" by calling queryProductDetailsAsync()
            .setProductDetails(productDetails)
            // set the offer token to specify the offer to purchase when applicable, e.g., subscription products
            // .setOfferToken(offerToken)
            .build()
    );

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(productDetailsParamsList)
    .setObfuscatedAccountId(obfuscatedAccountId)
    .build();

// Launch the billing flow
BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);

如您将在下一部分中看到的那样,在购买流程中设置的用户标识符将包含在购买交易中,可用于向正确的用户授予使用权。

6. 在授予权利前验证购买交易

在本部分中,我们将介绍在安全后端服务器中验证购买交易后再授予权利的最佳实践。

用户购买一次性商品后,安全后端服务器中的 Pub/Sub 订阅者将收到一条 Pub/Sub 消息。您应在后端服务器中执行以下操作:

  1. 从 Pub/Sub 消息中解析 purchaseToken。您应维护一份所有购买交易的所有 purchaseToken 值记录。
  2. 验证当前购买交易的 purchaseToken 值是否与以前的任何 purchaseToken 值都不匹配。purchaseToken 具有全局唯一性,因此您可以放心地使用此值作为数据库中的主键。
  3. 使用 Google Play Developer API 中的 purchases.products:get 端点向 Google 验证购买交易是否合法。
  1. 如果购买交易合法且过去没有使用过,那么您就可以放心地授予对应用内商品或订阅的权利。
  2. 只有在购买交易状态为 PURCHASED 时,您才能授予权利,并确保正确处理 PENDING 购买交易。如需了解详情,请参阅处理待处理的交易

以下代码示例为 Google Play Developer API 创建了一个 API 客户端。稍后我们将使用它来执行 API 调用。

import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.services.androidpublisher.AndroidPublisher;
import com.google.api.services.androidpublisher.AndroidPublisherScopes;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collections;

/** Helper class to initialize the publisher APIs client library. */
public class AndroidPublisherHelper {
 /* Your application name */
 private static final String APPLICATION_NAME = "YourApplicationName";

 /* Load credentials from a JSON key file. Replace with the actual path to your downloaded service
  * account key file.
  */
 private static final String RESOURCES_CLIENT_SECRETS_JSON =
     "/path/to/your/service_account_key.json";

 /** Global instance of the JSON factory. */
 private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();

 /* The API client */
 private static final AndroidPublisher ANDROID_PUBLISHER = init();

 /**
  * Performs all necessary setup steps for running requests against the API.
  *
  * @return the {@link AndroidPublisher} service
  */
 private static AndroidPublisher init(){
   try {
     // Authorization.
     Credential credential =
         GoogleCredential.fromStream(
                 AndroidPublisherHelper.class.getResourceAsStream(RESOURCES_CLIENT_SECRETS_JSON))
             .createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));

     HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();

     // Set up and return API client.
     return new AndroidPublisher.Builder(httpTransport, JSON_FACTORY, credential)
         .setApplicationName(ApplicationConfig.APPLICATION_NAME)
         .build();
   } catch (GeneralSecurityException | IOException ex) {
     throw new RuntimeException("fail to initialize the publisher APIs client library", ex);
   }
 }
}

然后,我们添加了用于进行 API 调用的逻辑,并修改了之前构建的接收器,以验证购买交易并向正确的用户授予使用权。

AndroidPublisherHelper 中,添加以下方法以从 Google Play Developer API 中的 Purchases.products:get 端点获取 ProductPurchase。

 /* Fetch the ProductPurchase for the one-time product purchase from
  * Purchases.products.get endpoint in the Google Play Developer API
  */
 public static ProductPurchase executeProductPurchasesGet(
     String packageName, String sku, String purchaseToken) {
   try {
     ProductPurchase productPurchase =
         ANDROID_PUBLISHER.purchases().products().get(packageName, sku, purchaseToken).execute();
     return productPurchase;
   } catch (IOException ex) {
     log.error("Exception was thrown while getting a product purchase", ex);
     // It is recommended to apply some retry mechanism, such as exponential backoff, to fetch the purchase in case of transient failures.
     return null;
   }
 }

NotificationMessageReceiver 中,验证购买交易,并根据通知中包含的数据,在您的系统中向相应用户授予使用权。您应持续跟踪服务器中的 purchaseToken,以避免重复处理。

 @Override
 public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
   // Decode the data into a String from the message data field.
   String jsonString = new String(Base64.getDecoder().decode(message.getData().toStringUtf8()));
   // Parse the String into a JSON object.
   JSONObject messageJson = new JSONObject(jsonString);

   // Fetch the value for certain fields.
   String version = messageJson.getString("version");
   String packageName = messageJson.getString("packageName");

   // Process notification data based on your business requirements.
   // Process oneTimeProductNotification in the message.
   JSONObject oneTimeProductNotificationJson =
       messageJson.getJSONObject("oneTimeProductNotification");
   if (oneTimeProductNotificationJson != null) {
     String purchaseToken = oneTimeProductNotificationJson.getString("purchaseToken");
     String sku = oneTimeProductNotificationJson.getString("sku");
     int notificationType = oneTimeProductNotificationJson.getInt("notificationType");

     if (notificationType == 1) {
       // ONE_TIME_PRODUCT_PURCHASED - A one-time product was successfully purchased by a user.
       // Verify that the purchaseToken value does not match any previous purchaseToken values in
       // your backend system to avoid duplicate processing.
       ......
       // Fetch the ProductPurchase from Purchases.products.get endpoint
       ProductPurchase productPurchase =
         AndroidPublisherHelper.executeProductPurchasesGet(packageName, sku, purchaseToken);
       if (productPurchase != null && productPurchase.getPurchaseState() == 0) {
         // The purchase is valid and in PURCHASED state.

         // The account Id set in the App when launching the billing flow.
         String obfuscatedExternalAccountId = productPurchase.getObfuscatedExternalAccountId();
         // Grant the entitlement to the correct account for obfuscatedExternalAccountId in your
         // system.
       ......
       }
     }
     // Process subscriptionNotification in the message.
     JSONObject subscriptionNotificationJson = messageJson.getJSONObject("subscriptionNotification");
     if (subscriptionNotificationJson != null) {
       ......
     }
     // Process other notification data in the message as needed.
     ......
   }

   // Acknowledge the message to avoid repeated delivery.
   consumer.ack();
 }

7. 通知 Google 购买交易已处理

授予权利后,您应通过从安全的后端服务器调用 Play Developer API 中的 purchases.products:consumepurchases.products:acknowledge 端点来通知 Google 购买交易已处理完毕,以消耗消耗型商品或确认非消耗型商品。

AndroidPublisherHelper 中,添加以下方法以在 Google Play Developer API 中调用 purchases.products:consumepurchases.products:acknowledge

 /* Consume the one-time product purchase by calling
  * Purchases.products.consume endpoint in the Google Play Developer API
  */
 public static void executeProductPurchasesConsume(
     String packageName, String sku, String purchaseToken) {
   try {
     ANDROID_PUBLISHER
       .purchases().products().consume(packageName, sku, purchaseToken).execute();
   } catch (IOException ex) {
     log.error("Exception was thrown while consuming a product purchase", ex);
     // It is recommended to apply some retry mechanism, such as exponential backoff, to ensure the purchase is correctly consumed in case of transient failures.
   }
 }

 /* Acknowledge the one-time product purchase by calling
  * Purchases.products.acknowledge endpoint in the Google Play Developer API
  */
 public static void executeProductPurchasesAcknowledge(
     String packageName, String sku, String purchaseToken) {
   try {
     ANDROID_PUBLISHER
       .purchases().products().acknowledge(packageName, sku, purchaseToken, new ProductPurchasesAcknowledgeRequest()).execute();
   } catch (IOException ex) {
     log.error("Exception was thrown while acknowledging a product purchase", ex);
     // It is recommended to apply some retry mechanism, such as exponential backoff, to ensure the purchase is correctly acknowledged in case of transient failures.
   }
 }

NotificationMessageReceiver 中,在后端服务器中授予使用权后,消耗消耗型商品购买交易或确认非消耗型商品购买交易。

 @Override
 public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
   ......
       String obfuscatedExternalAccountId = productPurchase.getObfuscatedExternalAccountId();
       // Grant the entitlement to the correct account for obfuscatedExternalAccountId in your
       // system.
       ......
       // If the product is a consumable product, consume the purchase.
       AndroidPublisherHelper.executeProductPurchasesConsume(packageName, sku, purchaseToken);
       // Or if the product is a non-consumable product, acknowledge the purchase.
       // AndroidPublisherHelper.executeProductPurchasesAcknowledge(packageName, sku, purchaseToken);
  ......

 }

必须进行确认,这样才能向 Google Play 告知用户已获得购买交易的权利。您应在授予权利后立即确认购买交易。

太棒了!您已成功与实时开发者通知集成,从而能够可靠地处理购买交易,如本 Codelab 中所示。现在,为了确保一切正常运行,我们来了解一下 Play Billing Lab。这是一款用户友好型工具,旨在帮助您测试 Play 结算服务集成。

8. 使用 Play Billing Lab 进行测试

为了确保顺利发布,您应该在整个开发过程中不断测试集成情况。Play Billing Lab 是一款免费的 Android 应用,可帮助开发者测试其与 Google Play 结算服务的集成,为开发者提供一种简单便捷的方式来测试 Play 结算服务功能,更快地进行集成,并更加信心十足地发布应用。

Play Billing Lab 提供各种测试功能,可帮助您测试不同的场景,包括:

我们会不断为 Play Billing Lab 应用添加新的测试功能。您可以从 Play 商店下载并安装 Play Billing Lab,也可以查看测试集成,详细了解如何使用 Play Billing Lab 进行测试。

使用 Play Billing Lab 测试 BillingResponseCode

在将应用与 Play 结算库集成时,测试所有 BillingResponseCode 流程是一项常见挑战,因为您对 Play 商店与 Play 后端之间的通信没有太多控制权。借助 Play Billing Lab 应用中的响应模拟器功能,您可以为 Play 结算库配置错误代码响应,以测试各种复杂的错误场景。

例如,您在应用中实现了相关逻辑,以便在应用检测到购买交易成功后消耗购买交易。您想测试以下场景:由于网络故障,您的应用未能消耗购买交易,而后端服务器中的 RTDN 接收器接收到消息并正确处理了购买交易。您可以利用响应模拟器来模拟测试场景。以下内容将引导您完成使用 Play Billing Lab 响应模拟器进行测试的步骤。

使用响应模拟器进行测试

使用响应模拟器进行测试时,您的应用将与 Play Billing Lab 通信,以获取您在 Play Billing Lab 响应模拟器中配置的响应代码。

为 Play 结算库启用结算替换测试

如需在响应模拟器与应用之间实现通信,您必须先在应用内为 Play 结算库启用结算替换测试。为此,请将以下元数据标记添加到应用的 AndroidManifest.xml 文件中。

<manifest ... >
  <application ... >
    ...
     <meta-data
      android:name="com.google.android.play.largest_release_audience.NONPRODUCTION"
      android:value="" />
    <meta-data
      android:name="com.google.android.play.billingclient.enableBillingOverridesTesting"
      android:value="true" />
  </application>
</manifest>

使用更新后的 AndroidManifest.xml 文件构建应用。现在,您的应用已准备好使用 Play Billing Lab 响应模拟器。

在测试后将应用部署到生产环境时,您应使用不包含这些元数据标记的单独 AndroidManifest.xml 文件,或确保已从 AndroidManifest.xml 文件中移除这些标记。

模拟 Play 结算库错误

如需使用模拟的 Play 结算库错误进行测试,请先在 Play Billing Lab 应用中配置响应代码,然后在您的应用中执行测试。

配置响应代码

  1. 使用应用的许可测试人员账号登录 Play Billing Lab 应用。下图显示了 Play Billing Lab 信息中心,包括响应模拟器卡片。

Play Billing Lab 信息中心(含响应模拟器)

  1. 点击“响应模拟器”卡片上的管理,即可前往“响应模拟器”界面。
  2. 根据提示,允许 Play Billing Lab 发送通知,以了解应用的连接状态。
  3. 启用“模拟 Play 结算库响应”开关(如果尚未启用)。

c841baa4c96bf306.png

  1. 选择要测试的 Play 结算库 API 的响应代码。如需模拟消耗型购买交易的错误,请为 consumeAsync API 选择一个错误代码。系统会自动保存您的选择。现在,响应模拟器已准备好将所选的响应代码发送到您的应用。

测试应用

现在,您可以测试应用,验证在配置的错误场景中一切是否按预期运行。打开您的应用,然后触发 Play 结算库 API 方法。如果您的应用调用 consumeAsync 来消耗购买交易,则会收到您刚刚配置的错误代码。您可以根据错误代码验证应用是否正常运行,以及后端服务器是否正确处理购买交易。

完成测试后,只需关闭“模拟 Play 结算库响应”开关即可停止模拟响应。

详细了解如何使用 Play Billing Lab 进行测试,或访问帮助中心,详细了解如何使用许可测试人员测试应用内购结算功能。

9. 恭喜!

您已完成本 Codelab,现在可以战略性地优化应用变现,从而改善用户体验,进而提高用户满意度、购买转化次数和订阅者流失率。

借助实时开发者通知和 Play Billing Lab配套应用,您可以主动处理一次性购买交易订阅的购买生命周期事件。

借助这些工具,您可以有效地实施富有吸引力的用户挽回策略,快速解决集成难题,并最终提升用户体验和收入来源,从而自信地发布应用或游戏。

完成此 Codelab 后,您现在已具备管理整个购买历程的技能,并且能够使用 Play Billing Lab 严格测试您的实现,从而确保顺畅的用户体验,并最大限度地提高您在 Google Play 上的创收潜力。