Cómo integrar la Biblioteca de Facturación Google Play a tu app

Monetiza tu juego vendiendo productos digitales con la Facturación Play. El SDK ofrece APIs para mostrar productos disponibles para comprar, iniciar el flujo de compra y procesar las compras. Las llamadas a estas APIs de facturación se realizan con la Cuenta de Google que inició el juego dentro del cliente de Google Play Juegos y no requieren pasos de acceso adicionales.

Si realizaste la integración con la biblioteca de Play Billing de Android, estas APIs de Play Billing deberían resultarte familiares. Los títulos para PC pueden volver a usar cualquier integración del servidor con Play Billing, ya que son las mismas para Android y PC.

Requisitos previos

Paso 1: Consulta las compras anteriores y las compras completadas fuera de tu aplicación

Cuando se inicia tu aplicación o cuando vuelve a entrar en primer plano, consulta las compras. Esto es necesario para detectar las compras que se realizaron fuera de tu juego o para desbloquear el acceso a las compras que el usuario realizó anteriormente.

  1. Consulta las compras con BillingClient::QueryPurchases.

  2. Continúa con el procesamiento de las compras.

// Query for purchases when:
// - Application starts up
// - Application window re-enters the foreground
auto promise = std::make_shared<std::promise<QueryPurchasesResult>>();
billing_client.QueryPurchases([promise](QueryPurchasesResult result) {
   promise->set_value(std::move(result));
});

auto query_purchases_result = promise->get_future().get();
if (query_purchases_result.ok()) {
  auto purchases = query_purchases_result.value().product_purchase_details;
  // Process the purchases
} else {
  // Handle the error
}

Paso 2: Muestra los productos disponibles para comprar

Ya puedes buscar los productos disponibles y mostrarlos a los usuarios. La consulta de detalles de productos es un paso importante antes de mostrar los productos a los usuarios, ya que devuelve información localizada sobre los productos.

Antes de ofrecer un producto en venta, verifica que el usuario no lo tenga. Si el usuario todavía tiene un producto consumible en su historial de compras, debes consumirlo antes de que pueda volver a comprarlo.

  1. Consulta los detalles de los productos con BillingClient::QueryProductDetails. Pasa los IDs de producto que registraste en Google Play Console.
  2. Renderiza el ProductDetails, que incluye el nombre localizado del producto y el precio de la oferta.
  3. Mantén una referencia al offer_token del producto. Se usa para iniciar un flujo de compra de la oferta.
QueryProductDetailsParams params;
params.product_ids.push_back({"example_costmetic_1", ProductType::kTypeInApp});
params.product_ids.push_back({"example_costmetic_1", ProductType::kTypeInApp});
params.product_ids.push_back({"example_battle_pass", ProductType::kTypeInApp});

auto promise = std::make_shared<std::promise<QueryProductDetailsResult>>();
billing_client.QueryProductDetails(params, [promise](QueryProductDetailsResult result) {
   promise->set_value(std::move(result));
});

auto query_product_details_result = promise->get_future().get();
if (query_product_details_result.ok()) {
   auto product_details = query_product_details_result.value().product_details;
   // Display the available products and their offers to the user
} else {
   // Handle the error
}

Paso 3: Inicia un flujo de compra

Cuando el usuario muestra la intención de comprar un producto que le mostraste, significa que ya puedes iniciar el flujo de compra.

  1. Para comenzar, llama a BillingClient::LaunchPurchaseFlow(). Pasa el offer_token que se obtuvo cuando consultaste los detalles del producto.
  2. Una vez que se complete la compra, se llamará a la función de Continuation con el resultado.
  3. Si se realiza correctamente, la Continuation contiene un ProductPurchaseDetails. Continúa con el procesamiento de la compra.
LaunchPurchaseFlowParams params { product_offer.offer_token };

auto promise = std::make_shared<std::promise<LaunchPurchaseFlowResult>>();
billing_client.LaunchPurchaseFlow(params, [promise](LaunchPurchaseFlowResult result) {
   promise->set_value(std::move(result));
});
// The purchase flow has started and is now in progress.

auto launch_purchase_flow_result = promise->get_future().get();

// The purchase flow has now completed.
if (launch_purchase_flow_result.ok()) {
   auto purchase = launch_purchase_flow_result.value().product_purchase_details;
   // Process the purchase
} else if (launch_purchase_flow_result.code() == BillingError::kUserCanceled) {
   // Handle an error caused by the user canceling the purchase flow
} else {
   // Handle any other error codes
}

Paso 4: Procesa una compra

Procesa con un servidor de backend

En el caso de los juegos con un servidor de backend, completa el procesamiento enviando el objeto purchase_token a tu servidor de backend. Completa el resto del procesamiento con las APIs de Play Billing del servidor. Esta integración del servidor es la misma que se realiza para un juego para Android que se integró con la Facturación Google Play.

void ProcessPurchasesWithServer(std::vector<ProductPurchaseDetails> purchases) {
   std::vector<std::string> purchase_tokens;
   for (const auto& purchase : purchases) {
      purchase_tokens.push_back(purchase.purchase_token);
   }

   // Send purchase tokens to backend server for processing
}

Procesa sin un servidor de backend

  1. Para asegurarte de que el pago del usuario no esté pendiente, verifica que ProductPurchaseDetails::purchase_state sea PurchaseState::kPurchaseStatePurchased. Si el estado de la compra es pendiente, notifícale al usuario que debe completar pasos adicionales antes de poder recibir el producto que compró.

  2. Otorga al usuario acceso al producto comprado y actualiza el almacenamiento de derechos de tu juego.

  3. En el caso de las compras de productos no consumibles (productos que solo se pueden comprar una vez), verifica si la compra ya se confirmó con ProductPurchaseDetails::is_acknowledged.

    1. Si no se confirmó la compra, llama a BillingClient::AcknowledgePurchase para notificar a Google que se le otorgará un derecho al producto al usuario.
  4. En el caso de las compras de productos consumibles (productos que se pueden comprar más de una vez), llama a BillingClient::ConsumePurchase para notificar a Google que se le otorga al usuario un derecho al producto.

void ProcessPurchasesWithoutServer(std::vector<ProductPurchaseDetails> purchases) {
   std::vector<std::string> entitled_product_ids;
   for (const auto& purchase : purchases) {
      auto was_successful = ProcessPurchasePurchaseWithoutServer(purchase);
      if (was_successful) {
         entitled_product_ids.push_back(purchase.product_id);
      }
   }

   // Note that non-consumable products that were previously purchased may have
   // been refunded. These purchases will stop being returned by
   // `QueryPurchases()`. If your game has given a user access to one of these
   // products storage they should be revoked.
   //
   // ...
}

bool ProcessPurchasePurchaseWithoutServer(ProductPurchaseDetails purchase) {
   auto is_purchase_completed =
      purchase.purchase_state == PurchaseState::kPurchaseStatePurchased;
   if (!is_purchase_completed) {
      // Notify the user that they need to take additional steps to complete
      // this purchase.
      return false;
   }

   // Determine if the product ID is associated with a consumable product.
   auto is_consumable = IsConsumableProductId(purchase.product_id);
   if (is_consumable) {
      // Grant an entitlement to the product to the user.
      // ...
      // Then, notify Google by consuming the purchase.

      ConsumePurchaseParams params { purchase.purchase_token };
      auto promise = std::make_shared<std::promise<ConsumePurchaseResult>>();
      billing_client.ConsumePurchase(params, [promise](ConsumePurchaseResult result) {
         promise->set_value(std::move(result));
      });

      auto consume_purchase_result = promise->get_future().get();
      if (!consume_purchase_result.ok()) {
         // Examine the failure code & message for more details & notify user
         // of failure.
         // ...
         return false;
      }

      return true;
   }

   // Otherwise the product is assumed to be a non-consumable.

   // Grant an entitlement to the product to the user.
   // ...
   // Then, notify Google by acknowledging the purchase (if not already done).

   if (purchase.is_acknowledged) {
      return true;
   }

   AcknowledgePurchaseParams params { purchase.purchase_token };
   auto promise = std::make_shared<std::promise<AcknowledgePurchaseResult>>();
   billing_client.AcknowledgePurchase(params, [promise](AcknowledgePurchaseResult result) {
      promise->set_value(std::move(result));
   });

   auto acknowledge_purchase_result = promise->get_future().get();
   if (!acknowledge_purchase_result.ok()) {
      // Examine the failure code & message for more details & notify user
      // of failure.
      // ...
      return false;
   }

   return true;
}

Paso 5: Prueba tu integración

Ya está todo listo para probar tu integración con la Facturación Play. Para realizar las pruebas durante la fase de desarrollo, recomendamos aprovechar los verificadores de licencias. Los verificadores con licencia tienen acceso a pagos de prueba que evitan los cargos reales por las compras.

Si deseas obtener instrucciones para configurar verificadores de licencias y un paquete de pruebas manuales, te recomendamos que consultes la documentación sobre cómo probar la integración de la Biblioteca de Facturación Google Play.