Analiza las interrupciones de compras de productos en la Facturación Play

1. Introducción

En este codelab, te enfocarás en crear un producto único, integrar tu app con la Biblioteca de Facturación Play (PBL) y analizar los motivos de los abandonos de compras.

Nota: Para completar este codelab correctamente, debes tener acceso a la función Varias opciones y ofertas de compra para productos únicos. Esta función está en el Programa de Acceso Anticipado (PAA). Los productos y las funciones del PAA están disponibles "tal como están" y pueden estar sujetos a asistencia limitada. Para acceder al PAA, envía una solicitud con el formulario de interés sobre el PAA para productos únicos . Sin embargo, si solo quieres comprender cómo analizar los abandonos de compras con los códigos de respuesta de la Facturación Play, navega directamente a la sección Analiza los abandonos de compras de este codelab.

Público

Este codelab está dirigido a desarrolladores de apps para Android que usan la Biblioteca de Facturación Play (PBL) o que quieren usarla para monetizar sus productos únicos.

Qué aprenderás

  • Cómo crear productos únicos en Google Play Console
  • Cómo integrar tu app con PBL
  • Cómo procesar compras de productos únicos consumibles y no consumibles en PBL
  • Cómo analizar los abandonos de compras

Qué necesitarás

2. Compila la app de ejemplo

La app de ejemplo está diseñada para ser una app para Android completamente funcional que tiene el código fuente completo que muestra los siguientes aspectos:

  • Integración de la app con PBL
  • Recuperación de productos únicos
  • Inicio de flujos de compra para los productos únicos
  • Situaciones de compra que generan las siguientes respuestas de facturación:
    • BILLING_UNAVAILABLE
    • USER_CANCELLED
    • OK
    • ITEM_ALREADY_OWNED

En el siguiente video de demostración, se muestra cómo se verá y se comportará la app de ejemplo después de que se implemente y se ejecute.

Requisitos previos

Antes de compilar y de implementar la app de ejemplo, haz lo siguiente:

Compilación

El objetivo de este paso de compilación es generar un archivo de Android App Bundle firmado de la app de ejemplo.

Para generar el Android App Bundle, sigue estos pasos:

  1. Descarga la app de ejemplo desde GitHub.
  2. Compila la app de ejemplo. Antes de compilar, cambia el nombre del paquete de la app de ejemplo y, luego, compila. Si tienes paquetes de otras apps en Play Console, asegúrate de que el nombre del paquete que proporcionas para la app de ejemplo sea único.

    Nota: La compilación de la app de ejemplo solo crea un archivo APK que puedes usar para pruebas locales. Sin embargo, la ejecución de la app no recupera productos ni precios porque los productos no se configuraron en Play Console, lo que harás más adelante en este codelab.
  3. Genera un Android App Bundle firmado.
    1. Genera una clave de carga y un almacén de claves.
    2. Firma la app con la clave de carga.
    3. Cómo configurar la firma de apps de Play

El siguiente paso es subir el Android App Bundle a Google Play Console.

3. Crea un producto único en Play Console

Para crear productos únicos en Google Play Console, debes tener una app en Play Console. Crea una app en Play Console y, luego, sube el paquete de aplicación firmado que creaste anteriormente.

Crea una app

Para crear una app, haz lo siguiente:

  1. Accede a Google Play Console con tu cuenta de desarrollador.
  2. Haz clic en Crear app. Se abrirá la página Crear app.
  3. Ingresa un nombre de app, selecciona el idioma predeterminado y otros detalles relacionados con la app.
  4. Haz clic en Crear app. Se creará una app en Google Play Console.

Ahora puedes subir el paquete de aplicación firmado de la app de ejemplo.

Sube el paquete de aplicación firmado

  1. Sube el paquete de aplicación firmado al segmento de pruebas internas de Google Play Console. Solo después de subirlo, podrás configurar las funciones relacionadas con la monetización en Play Console.
  2. Haz clic en Probar y lanzar > Pruebas > Versión interna > Crear una versión nueva.
  3. Ingresa un nombre de versión y sube el archivo del paquete de aplicación firmado.
  4. Haz clic en Siguiente y, luego, en Guardar y publicar.

Ahora puedes crear tus productos únicos.

Crea un producto único

Para crear un producto único, sigue estos pasos:

  1. En el Google Play Console, en el menú de navegación de la izquierda, ve a Monetizar con Play > Productos > Productos únicos.
  2. Haz clic en Crear un producto único.
  3. Ingresa los siguientes detalles del producto:
    • ID del producto: Ingresa un ID de producto único. Ingresa one_time_product_01.
    • Etiquetas(opcional): Agrega etiquetas relevantes.
    • Nombre: Ingresa un nombre de producto. Por ejemplo, Product name.
    • Descripción: Ingresa una descripción del producto. Por ejemplo, Product description.
    • Una imagen de ícono que quieras agregar(opcional): Sube un ícono que represente tu producto.
    Nota: Para los fines de este codelab, puedes omitir la configuración de la sección Impuestos, cumplimiento y programas.
  4. Haz clic en Siguiente.
  5. Agrega una opción de compra y configura su disponibilidad regional. Un producto único necesita al menos una opción de compra, que define cómo se otorga el derecho, su precio y su disponibilidad regional. Para este codelab, agregaremos la opción estándar Comprar para el producto.En la sección Opción de compra, ingresa los siguientes detalles:
    • ID de la opción de compra: Ingresa un ID de opción de compra. Por ejemplo, buy.
    • Tipo de compra: Selecciona Comprar.
    • Etiquetas(opcional): Agrega etiquetas específicas para esta opción de compra.
    • Haz clic en Opciones avanzadas (opcional) para configurar las opciones avanzadas. Para los fines de este codelab, puedes omitir la configuración de las opciones avanzadas.
  6. En la sección Disponibilidad y precios, haz clic en Establecer precios > Editar los precios de forma masiva.
  7. Selecciona la opción País o región. Se seleccionarán todas las regiones.
  8. Haz clic en Continuar. Se abrirá un diálogo para ingresar un precio. Ingresa 10 USD y, luego, haz clic en Aplicar.
  9. Haz clic en Guardar y, luego, en Activar. Se creará y activará la opción de compra.

Para los fines de este codelab, crea 3 productos únicos adicionales con los siguientes IDs de producto:

  • consumable_product_01
  • consumable_product_02
  • consumable_product_03

La app de ejemplo está configurada para usar estos IDs de producto. Puedes proporcionar diferentes IDs de producto, en cuyo caso, deberás modificar la app de ejemplo para usar el ID de producto que proporcionaste.

Abre la app de ejemplo en Google Play Console y navega a Monetizar con Play > Productos > Productos únicos. Luego, haz clic en Crear un producto único y repite los pasos del 3 al 9.

Video de creación de productos únicos

En el siguiente video de ejemplo, se muestran los pasos de creación de productos únicos que se describieron anteriormente.

4. Realiza la integración con PBL

Ahora, veremos cómo integrar tu app con la Biblioteca de Facturación Play (PBL). En esta sección, se describen los pasos de alto nivel para la integración y se proporciona un fragmento de código para cada uno de los pasos. Puedes usar estos fragmentos como guía para implementar tu integración real.

Para integrar tu app con PBL, sigue estos pasos:

  1. Agrega la dependencia de la Biblioteca de Facturación Play a la app de ejemplo.
    dependencies {
    val billing_version = "8.0.0"
    
    implementation("com.android.billingclient:billing-ktx:$billing_version")
    }
    
  2. Inicializa el BillingClient. El BillingClient es el SDK del cliente que reside en tu app y se comunica con la Biblioteca de Facturación Play. En el siguiente fragmento de código, se muestra cómo inicializar el cliente de facturación.
    protected BillingClient createBillingClient() {
    return BillingClient.newBuilder(activity)
        .setListener(purchasesUpdatedListener)
        .enablePendingPurchases(PendingPurchasesParams.newBuilder().enableOneTimeProducts().build())
        .enableAutoServiceReconnection()
        .build();
    }
    
  3. Conéctate a Google Play.En el siguiente fragmento de código, se muestra cómo conectarse a Google Play.
    public void startBillingConnection(ImmutableList<Product> productList) {
    Log.i(TAG, "Product list sent: " + productList);
    Log.i(TAG, "Starting connection");
    billingClient.startConnection(
        new BillingClientStateListener() {
          @Override
          public void onBillingSetupFinished(BillingResult billingResult) {
            if (billingResult.getResponseCode() == BillingResponseCode.OK) {
              // Query product details to get the product details list.
              queryProductDetails(productList);
            } else {
              // BillingClient.enableAutoServiceReconnection() will retry the connection on
              // transient errors automatically.
              // We don't need to retry on terminal errors (e.g., BILLING_UNAVAILABLE,
              // DEVELOPER_ERROR).
              Log.e(TAG, "Billing connection failed: " + billingResult.getDebugMessage());
              Log.e(TAG, "Billing response code: " + billingResult.getResponseCode());
            }
          }
    
          @Override
          public void onBillingServiceDisconnected() {
            Log.e(TAG, "Billing Service connection lost.");
          }
        });
    }
    
  4. Recupera los detalles del producto único.Después de integrar tu app con PBL, debes recuperar los detalles del producto único en tu app. En el siguiente fragmento de código, se muestra cómo recuperar los detalles del producto único en tu app.
    private void queryProductDetails(ImmutableList<Product> productList) {
    Log.i(TAG, "Querying products for: " + productList);
    QueryProductDetailsParams queryProductDetailsParams =
        QueryProductDetailsParams.newBuilder().setProductList(productList).build();
    billingClient.queryProductDetailsAsync(
        queryProductDetailsParams,
        new ProductDetailsResponseListener() {
          @Override
          public void onProductDetailsResponse(
              BillingResult billingResult, QueryProductDetailsResult productDetailsResponse) {
            // check billingResult
            Log.i(TAG, "Billing result after querying: " + billingResult.getResponseCode());
            // process returned productDetailsList
            Log.i(
                TAG,
                "Print unfetched products: " + productDetailsResponse.getUnfetchedProductList());
            setupProductDetailsMap(productDetailsResponse.getProductDetailsList());
            billingServiceClientListener.onProductDetailsFetched(productDetailsMap);
          }
        });
    }
    
    Si recuperas ProductDetails, obtendrás una respuesta similar a la siguiente:
    {
        "productId": "consumable_product_01",
        "type": "inapp",
        "title": "Shadow Coat (Yolo's Realm | Play Samples)",
        "name": "Shadow Coat",
        "description": "A sleek, obsidian coat for stealth and ambushes",
        "skuDetailsToken": "<---skuDetailsToken--->",
        "oneTimePurchaseOfferDetails": {},
        "oneTimePurchaseOfferDetailsList": [
            {
                "priceAmountMicros": 1990000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$1.99",
                "offerIdToken": "<--offerIdToken-->",
                "purchaseOptionId": "buy",
                "offerTags": []
            }
        ]
    },
    {
        "productId": "consumable_product_02",
        "type": "inapp",
        "title": "Emperor Den (Yolo's Realm | Play Samples)",
        "name": "Emperor Den",
        "description": "A fair lair glowing with molten rock and embers",
        "skuDetailsToken": "<---skuDetailsToken--->",
        "oneTimePurchaseOfferDetails": {},
        "oneTimePurchaseOfferDetailsList": [
            {
                "priceAmountMicros": 2990000,
                "priceCurrencyCode": "USD",
                "formattedPrice": "$2.99",
                "offerIdToken": "<--offerIdToken-->",
                "purchaseOptionId": "buy",
                "offerTags": []
            }
        ]
    }
    
  5. Inicia el flujo de facturación.
    public void launchBillingFlow(String productId) {
    ProductDetails productDetails = productDetailsMap.get(productId);
    if (productDetails == null) {
      Log.e(
          TAG, "Cannot launch billing flow: ProductDetails not found for productId: " + productId);
      billingServiceClientListener.onBillingResponse(
          BillingResponseCode.ITEM_UNAVAILABLE,
          BillingResult.newBuilder().setResponseCode(BillingResponseCode.ITEM_UNAVAILABLE).build());
      return;
    }
    ImmutableList<ProductDetailsParams> productDetailsParamsList =
        ImmutableList.of(
            ProductDetailsParams.newBuilder().setProductDetails(productDetails).build());
    
    BillingFlowParams billingFlowParams =
        BillingFlowParams.newBuilder()
            .setProductDetailsParamsList(productDetailsParamsList)
            .build();
    
    billingClient.launchBillingFlow(activity, billingFlowParams);
    }
    
  6. Detecta y procesa las compras. Como parte de este paso, debes hacer lo siguiente:
    1. Verificar la compra
    2. Otorgar derechos al usuario
    3. Notificar al usuario
    4. Notificar a Google sobre el proceso de compra
    De estos, los pasos a, b y c deben realizarse en tu backend y, por lo tanto, están fuera del alcance de este codelab.En el siguiente fragmento, se muestra cómo notificar a Google sobre un producto único consumible:
    private void handlePurchase(Purchase purchase) {
    // Step 1: Send the purchase to your secure backend to verify the purchase following
    // https://developer.android.com/google/play/billing/security#verify
    
    // Step 2: Update your entitlement storage with the purchase. If purchase is
    // in PENDING state then ensure the entitlement is marked as pending and the
    // user does not receive benefits yet. It is recommended that this step is
    // done on your secure backend and can combine in the API call to your
    // backend in step 1.
    
    // Step 3: Notify the user using appropriate messaging.
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
      for (String product : purchase.getProducts()) {
        Log.d(TAG, product + " purchased successfully! ");
      }
    }
    
    // Step 4: Notify Google the purchase was processed.
    // For one-time products, acknowledge the purchase.
    // This sample app (client-only) uses billingClient.acknowledgePurchase().
    // For consumable one-time products, consume the purchase
    // This sample app (client-only) uses billingClient.consumeAsync()
    // If you have a secure backend, you must acknowledge purchases on your server using the
    // server-side API.
    // See https://developer.android.com/google/play/billing/security#acknowledge
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED && !purchase.isAcknowledged()) {
    
      if (shouldConsume(purchase)) {
        ConsumeParams consumeParams =
            ConsumeParams.newBuilder().setPurchaseToken(purchase.getPurchaseToken()).build();
        billingClient.consumeAsync(consumeParams, consumeResponseListener);
    
      } else {
        AcknowledgePurchaseParams acknowledgePurchaseParams =
            AcknowledgePurchaseParams.newBuilder()
                .setPurchaseToken(purchase.getPurchaseToken())
                .build();
        billingClient.acknowledgePurchase(
            acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
      }
     }
    }
    

5. Analiza los abandonos de compras

Hasta ahora en el codelab, las respuestas de la Facturación Play se enfocaron en situaciones limitadas, como las respuestas USER_CANCELLED, BILLING_UNAVAILABLE, OK y ITEM_ALREADY_OWNED. Sin embargo, la Facturación Play puede mostrar 13 códigos de respuesta diferentes que pueden activarse por varios factores del mundo real.

En esta sección, se explican las causas de las respuestas de error USER_CANCELLED y BILLING_UNAVAILABLE, y se sugieren posibles acciones correctivas que puedes implementar.

Código de error de respuesta USER_CANCELED

Este código de respuesta indica que el usuario abandonó la IU del flujo de compra antes de completar la compra.

Causas posibles

¿Qué acciones puedes realizar?

  • Podría indicar usuarios con baja intención que son sensibles a los precios.
  • La compra está pendiente o se rechazó el pago.

Código de error de respuesta BILLING_UNAVAILABLE

Este código de respuesta significa que no se pudo completar la compra debido a un problema con el proveedor de pagos del usuario o la forma de pago elegida. Por ejemplo, la tarjeta de crédito del usuario venció o el usuario se encuentra en un país no admitido. Este código no indica un error con el sistema de Facturación Play en sí.

Causas posibles

¿Qué acciones puedes realizar?

  • La app de Play Store del dispositivo del usuario está desactualizada.
  • El usuario se encuentra en un país en el que no se admite Play.
  • El usuario es un usuario empresarial, y su administrador no permite que los usuarios realicen compras.
  • Google Play no puede aplicar cargos en la forma de pago del usuario. Por ejemplo, es posible que la tarjeta de crédito del usuario haya vencido.
  • Supervisa las tendencias de los problemas del sistema y en regiones específicas.
  • Considera migrar a PBL 8, ya que admite el código de subrespuesta PAYMENT_DECLINED_DUE_TO_INSUFFICIENT_FUNDS más detallado. Si recibes este código de respuesta, considera notificar a los usuarios sobre la falla o sugerir formas de pago alternativas.
  • Este código de respuesta está diseñado para reintentos, lo que te permite implementar estrategias de reintento adecuadas.
    Es poco probable que los reintentos automáticos sean de ayuda en este caso. Sin embargo, un reintento manual puede ser útil si el usuario soluciona la condición que causó el problema. Por ejemplo, si el usuario actualiza su versión de Play Store a una versión admitida, podría funcionar un reintento manual de la operación inicial.

    Si recibes este código de respuesta cuando el usuario no está en una sesión, no tiene sentido volver a intentarlo. Cuando recibes una respuesta `BILLING_UNAVAILABLE` como resultado del flujo de compra, es muy probable que el usuario haya recibido comentarios de Google Play durante el proceso de compra y que esté al tanto de qué problema hubo. En este caso, podrías mostrar un mensaje de error que advierta que hubo un problema junto con el botón `Reintentar` para darle al usuario la opción de volver a intentarlo de forma manual después de resolver el problema.

Estrategias de reintento para códigos de error de respuesta

Las estrategias de reintento eficaces para errores recuperables de la Biblioteca de Facturación Play (PBL) varían según el contexto, como las interacciones del usuario en la sesión (como durante una compra) en comparación con las operaciones en segundo plano (como consultar compras en la reanudación de la app). Es importante implementar estas estrategias porque ciertos valores de BillingResponseCode indican problemas temporales que se pueden resolver volviendo a intentarlo, mientras que otros son permanentes y no requieren reintentos.

Para los errores que se producen cuando el usuario está en una sesión, se recomienda una estrategia de reintento simple con una cantidad máxima de intentos establecida para minimizar la interrupción de la experiencia del usuario. Por el contrario, para las operaciones en segundo plano , como confirmar compras nuevas, que no requieren una ejecución inmediata, el retroceso exponencial es el enfoque recomendado.

Para obtener información detallada sobre códigos de respuesta específicos y sus estrategias de reintento recomendadas correspondientes, consulta Cómo administrar códigos de respuesta BillingResult.

6. Próximos pasos

Documentos de referencia

7. ¡Felicitaciones!

¡Felicitaciones! Navegaste correctamente por Google Play Console para crear un nuevo producto único, probar códigos de respuesta de facturación y analizar los abandonos de compras.

Encuesta

Valoramos mucho tus comentarios sobre este codelab. Considera tomarte unos minutos para completar nuestra encuesta.