Práctica de aplicaciones en el extranjero: sistema de facturación de Google Play

Autor: Ye Zhichen

Hoy en día, la popularidad de buscar aplicaciones en el extranjero continúa sin disminuir y es una dirección de mercado elegida por muchas empresas y desarrolladores individuales. Para lograr rentabilidad, además de la publicidad, el método más común de monetización, las aplicaciones ofrecen diversos bienes virtuales o servicios de membresía para atraer a los usuarios a pagar. En este momento, el sistema de facturación de Google Play es el terminal Android. Un canal de pago que la aplicación debe usar

Google 对 Google Play 结算系统的简介: El sistema de facturación de Google Play es un servicio que le permite vender productos y contenidos digitales en su aplicación de Android, ya sea que desee monetizar mediante compras únicas u ofrecer suscripciones a sus servicios. Google Play ofrece un conjunto completo de API para la integración tanto con su aplicación de Android como con su servidor backend que desbloquea la familiaridad y seguridad de las compras de Google Play para sus usuarios.

En otras palabras: Google Play Billing es un servicio que nos permite vender productos y contenidos digitales en aplicaciones de Android. Ya sea que queramos generar ingresos a partir de compras únicas o brindar a los usuarios un servicio de suscripción, puede ayudarnos a hacerlo. Google Play proporciona un conjunto completo de API que se pueden integrar en aplicaciones de Android y servidores backend para brindar a los usuarios transacciones de compra seguras y familiares en Google Play.

Durante el último año, fui responsable del desarrollo de un proyecto en el extranjero y, en el proceso, también me conecté al sistema de liquidación de Google Play. Al principio, como no entendía cada concepto lo suficientemente bien y el proceso de pago general era bastante diferente de los diversos servicios de pago comúnmente utilizados en China, tomé muchos desvíos.

Aquí escribiré un artículo para presentar en detalle el sistema de facturación de Google Play, espero que te resulte útil.

I. Descripción general

Si desea mostrar y vender productos a los usuarios a través del sistema de liquidación de Google Play, naturalmente debe crear productos primero. Hay dos formas de crear productos:

  • Crear manualmente en Google Play Console
  • Creado en código a través de la API para desarrolladores de Google Play

Los productos creados en Google Play son todos productos virtuales. Cada producto representa un beneficio proporcionado por la aplicación a los usuarios, y cada producto contiene un identificador único, es decir, ProductId. En los negocios, necesitamos usar reglas de nomenclatura de ProductId para definir el producto específico. tipos de derechos e intereses representados por el producto

Cada producto se puede dividir en dos tipos:

  • Artículos desechables. Los productos que los usuarios obtienen mediante un pago único pertenecen al sistema de compra y corresponden a la biblioteca de liquidación de Google Play.BillingClient.ProductType.INAPP
  • Productos de suscripción. Los productos que los usuarios pagan repetidamente en un período fijo se basan en suscripción y corresponden a la biblioteca de liquidación de Google Play.BillingClient.ProductType.SUBS

Después de que el usuario compra el producto, la aplicación también debe cancelar el pedido. El proceso de elaboración está relacionado con el tipo de producto y se divide en dos tipos:

  • Confirmar transacción. No importa qué tipo de producto se compre, la aplicación debe confirmar primero la transacción . Si la confirmación no se completa dentro del tiempo limitado, Google Play revocará automáticamente la transacción y reembolsará al usuario. Google Play debe realizar la operación de "confirmar transacción" para garantizar que la aplicación haya proporcionado al usuario derechos e intereses y tratar de evitar la situación en la que el usuario haya pagado pero la aplicación no le haya otorgado derechos. . La operación de confirmación puede ser implementada por el servidor o terminal móvil, correspondiente a acknowledgePurchasela operación
  • Consumir bienes. Los productos consumibles están dirigidos a productos consumibles entre los productos desechables, es decir, sobre ellos se realizan operaciones de consumo . Al realizar la operación de consumo, el usuario podrá posteriormente volver a adquirir el producto. La operación de consumo puede ser implementada por el servidor o terminal móvil, correspondiente a consumePurchasela operación

2. Productos desechables

Los productos únicos también se denominan productos in-app, que son productos de compra única y se pueden subdividir en dos subtipos:

  • Bienes de consumo. Es decir, este producto se puede consumir después de la compra, permitiendo al usuario realizar compras repetidas. Por ejemplo, este producto se puede utilizar para representar monedas de oro en el juego. Después de que el usuario utilice las monedas de oro, los derechos representados por el producto dejarán de ser válidos. El usuario deberá comprar el producto nuevamente para obtener monedas de oro nuevamente.
  • Bienes no consumibles. En otras palabras, este producto no es consumible después de la compra y los usuarios pueden obtener permanentemente los derechos e intereses representados por el producto. Por ejemplo, este producto se puede utilizar para representar los derechos de visualización de un determinado curso. Siempre que el usuario compre el producto, podrá disfrutar de los derechos de visualización del curso de forma permanente.

Si un producto único es consumible o no consumible depende de la definición comercial de la aplicación. En Google Play Console, se denominan uniformemente productos dentro de la aplicación y no hay opción para distinguir subtipos al crear productos únicos. .

Suponiendo que nuestra definición comercial de un artículo de una sola vez es consumible, entonces podemos consumePurchaserealizar una operación de "consumo" en él ejecutándolo en el momento adecuado. Por ejemplo, si el usuario obtiene monedas de oro del juego comprando un producto único, y el usuario usa estas monedas de oro para comprar accesorios del juego en el proceso posterior, el desarrollador debe ejecutar al mismo tiempo para consumir el producto, haciendo consumePurchaseasí El producto no es válido. Los usuarios también pueden volver a comprar este producto más tarde.

En el caso de los bienes no consumibles, en términos comerciales, representan ciertos derechos e intereses de los que el usuario puede disfrutar de forma permanente. Mientras se compren los bienes, los derechos e intereses no se perderán, por lo que el usuario no debe volver a comprarlos. Naturalmente, no hay necesidad ni posibilidad de consumirlo.

3. Productos de suscripción

Los productos de suscripción son productos que requieren que los usuarios paguen regularmente en un período fijo. Durante el período de pago, los usuarios pueden disfrutar de los derechos representados por el producto. El escenario de aplicación más común son varios servicios de membresía: los usuarios pagan mensualmente y la aplicación les brinda funciones únicas durante cada ciclo de suscripción hasta que el usuario cancela la suscripción.

Los productos de suscripción incluyen cuatro conceptos importantes:

  • plan basico
  • Tipo de renovación
  • descuento
  • etapa de fijación de precios

plan basico

Plan básico, también conocido como BasePaln, cada producto de suscripción debe contener uno o más planes básicos antes de que los usuarios puedan comprarlo.

El plan básico se utiliza para definir las reglas de venta de productos, incluido el ciclo de liquidación, el tipo de renovación, el precio de suscripción, la estrategia de descuento, etc. Por ejemplo, un producto de suscripción puede proporcionar dos planes básicos, pago mensual y pago anual , para que los usuarios elijan. Se establecen diferentes precios para cada ciclo y los usuarios pueden elegir diferentes planes para suscribirse según sus preferencias.

Tipo de renovación

Cada plan básico debe especificar un tipo de renovación, que se utiliza para especificar el método de pago del usuario.

Hay dos tipos de renovaciones:

  • Renovar automáticamente. Deducir activamente el pago de los usuarios al final de cada ciclo de liquidación, extendiendo así automáticamente el período de los derechos de uso. Las operaciones pagas son pasivas para los usuarios.
  • Pagado por adelantado. No habrá renovación ni pago automático, los usuarios deberán realizar pagos activos para posponer la fecha de vencimiento de los derechos para disfrutar del contenido de la suscripción de forma ininterrumpida. La operación de pago es proactiva para los usuarios.

descuento

Los descuentos, también conocidos como Ofertas, solo se pueden configurar para planes básicos de renovación automática .

Cada plan básico renovable automáticamente puede establecer múltiples descuentos al mismo tiempo, lo que permite a los usuarios disfrutar de un cierto descuento en el precio al comienzo de la suscripción o usarlo de forma gratuita directamente, atrayendo así a los usuarios a comprar.

Existen tres tipos de Ofertas, es decir, tres estrategias preferenciales. Por ejemplo, suponiendo que exista un plan de suscripción mensual básico, podemos agregar las siguientes tres ofertas para que los usuarios elijan:

  • Prueba gratis. Los usuarios pueden probarlo gratis dentro de los primeros siete días y luego pagar oficialmente mensualmente después de siete días.
  • Pago unico. Los usuarios pagan una tarifa de suscripción de tres meses por adelantado de una sola vez y disfrutan de un descuento del 30% sobre el precio total. Después de tres meses, los usuarios pueden suscribirse mensualmente al precio original.
  • Descuentos por pagos recurrentes. Los usuarios aún se suscriben mensualmente, pero pueden disfrutar de un 20% de descuento cada vez que pagan durante los primeros tres meses. Después de tres meses, pueden suscribirse mensualmente al precio original.

etapa de precio

Las fases de precios, también conocidas como PricingPhases, pueden considerarse como un atributo interno de la Oferta.

Dado que una Oferta puede contener múltiples estrategias preferenciales al mismo tiempo, cuando un usuario disfruta de una Oferta, el precio que debe pagar cambiará varias veces con el tiempo. Cada período de tiempo corresponde a un precio diferente. PricingPhases se utiliza para Indica las reglas de cobro para Oferta en cada periodo de tiempo

Por ejemplo, un plan básico con renovación mensual automática incluye una oferta que incluye una prueba gratuita de siete días. Entonces, las etapas de precios de esta Oferta son:

  • Los usuarios disfrutan primero de una prueba gratuita de siete días.
  • Después de siete días, los usuarios pagarán mensualmente al precio original.

Si agregas a esta Oferta una estrategia preferencial de “30% de descuento y pago periódico de un mes”, la etapa de precios de la Oferta pasará a ser:

  • Los usuarios disfrutan primero de una prueba gratuita de siete días.
  • Después de siete días, el usuario paga un 30% de descuento sobre el precio original y obtiene un período de suscripción de un mes.
  • Después de un mes, los usuarios pagarán mensualmente al precio original.

Por lo tanto, la etapa de precio determina las tarifas que los usuarios deben gastar en diferentes períodos de tiempo. Cada Oferta puede sumar hasta dos etapas de precio, es decir, se producen hasta tres cambios de precio y los usuarios recibirán los cambios de precio en orden.

Resumir

Google Play ofrece un alto grado de libertad a la hora de configurar el Plan Base y la Oferta. El período de pago para la renovación automática de BasePlan puede variar de una semana a un año, y el período de pago para BasePlan prepago puede variar de un día a un año. El período de descuento y el precio de descuento de cada estrategia de descuento también se pueden establecer de manera flexible. Podemos intentar aumentar la tasa de pago del usuario estableciendo una variedad de diferentes duraciones de ciclo y estrategias de descuento para que los usuarios elijan.

Además, cada producto basado en suscripción puede crear hasta 250 planes y ofertas básicos, pero no se pueden activar más de 50 planes y ofertas básicos al mismo tiempo. Los planes y ofertas básicos adicionales deben estar en estado borrador o inactivo.

4. SDK de facturación

Después de comprender los conceptos básicos anteriores, veamos cómo estos conceptos se corresponden con el SDK de facturación.

Todos los ejemplos de código de este artículo utilizan la última versión del SDK del sistema de liquidación actual de Google Play en el lado de Android y son versiones de rutinas. Los lectores deben tener cierta comprensión de las rutinas.

dependencies {
    val billingVersion = "6.0.1"
    implementation("com.android.billingclient:billing-ktx:$billingVersion")
}

Todo el proceso de pago se puede resumir de la siguiente manera:

  1. Establezca una conexión con Google Play a través de BillingClient y vincule la interfaz PurchasesUpdatedListener para obtener resultados de pago de devolución de llamada.
  2. Consulte información localizada del producto, concretamente ProductDetails, a través de BillingClient para obtener la descripción del producto, el plan básico, la información de precios, la estrategia de descuento y otros atributos.
  3. Según los ProductDetails encontrados, inicie una solicitud de pago a BillingClient y active la ventana emergente de pago.
  4. Obtenga el resultado del pago en PurchasesUpdatedListener y determine el estado de pago del usuario
  5. Una vez que se determine que el pago del usuario fue exitoso, el producto será confirmado o consumido según el tipo de producto.

Cliente de facturación

BillingClient es la interfaz principal para que la biblioteca de liquidación de Google Play se comunique con la App. Antes de que la Aplicación pueda realizar cualquier operación relacionada con el pago, debe establecer una conexión con Google Play a través de BillingClient. Al inicializar la instancia de BillingClient, debe vincular PurchasesUpdatedListener al mismo tiempo para recibir notificaciones de devolución de llamada de los resultados del pago. Debido a esto, la aplicación solo puede mantener como máximo una conexión BillingClient activa al mismo período de tiempo para evitar que el mismo evento de pago devuelva múltiples PurchasesUpdatedListener al mismo tiempo.

private val purchasesUpdatedListener =
    PurchasesUpdatedListener { billingResult: BillingResult, purchases: List<Purchase>? ->

    }

private lateinit var billingClient: BillingClient

suspend fun startConnection(context: Context) {
    billingClient = buildBillingClient(context = context, purchasesUpdatedListener)
    startConnection(billingClient = mBillingClient)
}

private fun buildBillingClient(
    context: Context,
    listener: PurchasesUpdatedListener
): BillingClient {
    return BillingClient.newBuilder(context)
        .setListener(listener)
        .enablePendingPurchases()
        .build()
}

private suspend fun startConnection(billingClient: BillingClient): BillingResult? {
    return withContext(context = Dispatchers.Default) {
        if (billingClient.isReady) {
            return@withContext null
        }
        return@withContext suspendCancellableCoroutine { continuation ->
            billingClient.startConnection(object : BillingClientStateListener {
                override fun onBillingSetupFinished(billingResult: BillingResult) {
                    if (!continuation.isCompleted) {
                        continuation.resume(value = billingResult)
                    }
                }

                override fun onBillingServiceDisconnected() {
                    if (!continuation.isCompleted) {
                        continuation.resume(value = null)
                    }
                }
            })
        }
    }
}

Detalles de producto

ProductDetails también son los detalles del producto. Ya sea un producto único o un producto de suscripción, ProductDetails se utiliza para incluir información específica del producto.

Consultar ProductDetails requiere dos parámetros de consulta: ProductId y tipo de producto. El tipo de producto es producto único INAPP y producto de suscripción SUBS .

private suspend fun queryProductDetails() {
    //查询一次性商品
    queryProductDetails(
        billingClient = mBillingClient,
        productIdList = setOf("1", "2"),
        productType = BillingClient.ProductType.INAPP
    )
    //查询订阅型商品
    queryProductDetails(
        billingClient = mBillingClient,
        productIdList = setOf("1", "2"),
        productType = BillingClient.ProductType.SUBS
    )
}

private suspend fun queryProductDetails(
    billingClient: BillingClient,
    productIdList: Set<String>,
    productType: String
): List<ProductDetails>? {
    return withContext(context = Dispatchers.Default) {
        if (!billingClient.isReady || productIdList.isEmpty()) {
            return@withContext null
        }
        val productDetailParamsList = productIdList.map {
            QueryProductDetailsParams
                .Product
                .newBuilder()
                .setProductId(it)
                .setProductType(productType)
                .build()
        }
        val queryProductDetailsParams = QueryProductDetailsParams
            .newBuilder()
            .setProductList(productDetailParamsList)
            .build()
        val productDetailsResult = billingClient.queryProductDetails(queryProductDetailsParams)
        productDetailsResult.productDetailsList
    }
}

La estructura de datos de ProductDetails es la siguiente y podemos confiar en esta información para mostrar los detalles del producto al usuario. Los dos campos oneTimePurchaseOfferDetails y subscribeOfferDetails se utilizan para llevar la información de precios de productos únicos y productos de suscripción, respectivamente.

{
	"productId": "",
	"productType": "",
	"title": "",
	"name": "",
	"description": "",
	"oneTimePurchaseOfferDetails": {},
	"subscriptionOfferDetails": []
}

Compra únicaOfertaDetalles

oneTimePurchaseOfferDetails corresponde a los detalles de productos únicos, la estructura de datos es relativamente simple, principalmente la información de precios.

{
	"priceAmountMicros": 548000000,
	"priceCurrencyCode": "HKD",
	"formattedPrice": "HK$548.00"
}

Cabe señalar que la información de precios devuelta por Google Play está localizada y los detalles se devolverán automáticamente según el país y la región correspondientes a la cuenta de Google Play del dispositivo actual. Por lo tanto, el código de moneda del precio del producto y el producto formateado El precio priceCurrencyCodevariará formattedPricedebido a las circunstancias reales.

suscripciónOfertaDetalles

subscribeOfferDetails corresponde a los detalles del producto de suscripción

Dado que los productos de suscripción pueden contener varios Planes Base y cada Plan Base puede contener varias Ofertas, el tipo de datos correspondiente del campo subscribeOfferDetails en ProductDetails es List<SubscriptionOfferDetails>. Cada SubscriptionOfferDetails corresponde a una Oferta y cada Oferta está asociada a un Plan Base. Google Play devuelve información de precios en unidades de Oferta.

[
    {
        "basePlanId": "yearly",
        "offerId": null,
        "offerToken": "xxx",
        "pricingPhases": {
            "pricingPhaseList": [
                {
                    "formattedPrice": "HK$469.00",
                    "priceAmountMicros": 469000000,
                    "priceCurrencyCode": "HKD",
                    "billingPeriod": "P1Y",
                    "billingCycleCount": 0,
                    "recurrenceMode": 1
                }
            ]
        }
    },
    {
        "basePlanId": "yearly",
        "offerId": "xxx",
        "offerToken": "xxx",
        "pricingPhases": {
            "pricingPhaseList": [
                {
                    "formattedPrice": "免費",
                    "priceAmountMicros": 0,
                    "priceCurrencyCode": "HKD",
                    "billingPeriod": "P1W",
                    "billingCycleCount": 1,
                    "recurrenceMode": 2
                },
                {
                    "formattedPrice": "HK$469.00",
                    "priceAmountMicros": 469000000,
                    "priceCurrencyCode": "HKD",
                    "billingPeriod": "P1Y",
                    "billingCycleCount": 0,
                    "recurrenceMode": 1
                }
            ]
        }
    }
]

Como se mencionó anteriormente, la Oferta incluye el concepto de PricingPhases, concepto que se refleja en el Json anterior, del cual se puede interpretar la siguiente información del producto:

  • Este producto contiene un Plan base con un ID anual y un total de dos Ofertas.
  • OfferToken se utiliza para identificar de forma única cada oferta y es único.
  • billingPeriod se utiliza para representar el período de facturación, especificado en formato ISO 8601. Por ejemplo, P1W representa una semana, P1Y representa un año y P1M3D representa un mes más tres días.
  • billingCycleCount se utiliza para representar el número de ciclos en el ciclo de facturación. Por ejemplo, las primeras PricingPhases de la segunda oferta anterior significan que los usuarios pueden probar gratis durante una semana; si billingCycleCount es 2, significa que los usuarios pueden probar gratis durante dos semanas.
  • recurrenceMode se utiliza para representar el modo de recurrencia de la etapa del precio. Cuando el valor es 1 o 3, el valor de billingCycleCount será 0.
    • Un valor de 1 significa que se repetirá dentro de un ciclo de facturación infinito a menos que el usuario lo cancele activamente.
    • Un valor de 2 significa que la facturación se repetirá dentro del período especificado por billingCycleCount.
    • Un valor de 3 indica un cargo único y no se repetirá.
  • El ID de oferta de la primera Oferta es nulo, lo que significa que esta Oferta no contiene la estrategia preferencial real, sino que en realidad representa el precio original de BasePlan, por lo que pricingPhaseList tendrá un solo valor. Y como el período de facturación es P1Y, significa que el ciclo de pago del Plan Base asociado es de un año. Después de seleccionar esta oferta, los usuarios deben pagar directamente el precio original de 469,00 HK$ para suscribirse.
  • El ID de oferta de la segunda Oferta no es nulo, lo que indica que esta Oferta contiene una estrategia preferencial real, por lo que el tamaño de pricingPhaseList será mayor que uno. Esta oferta permite a los usuarios probarla gratis durante una semana y luego suscribirse al mismo precio y período que la primera oferta.

Por lo tanto, si desea interpretar la estrategia de precios de BasePlan y la estrategia preferencial de la oferta, debe combinar todos los campos para el análisis. En primer lugar, independientemente de si especificamos una estrategia de descuento para BasePlan cuando lo creamos, Google Play tratará el precio original de BasePlan como una Oferta y lo devolverá. En este caso, la Oferta solo tendrá una etapa de precios. Para una estrategia de descuento real, se debe establecer su ID de oferta y, naturalmente, no será nulo y habrá hasta tres etapas de fijación de precios. Necesitamos distinguir entre Ofertas "falsas" y Ofertas "reales". Luego, utilice pricingPhases para analizar el ciclo de suscripción y el precio de BasePlan, la estrategia de descuento de la Oferta y cómo se establece específicamente la etapa de precio de la Oferta. De esta manera, podemos mostrar completamente la información de precios de todo el producto al usuario.

lanzamientoFlujo de facturación

launchBillingFlow se utiliza para abrir la ventana emergente de pago para iniciar operaciones de pago, según el tipo de producto su método de llamada se divide en dos tipos:

Si desea comprar un producto único, los parámetros de pago solo necesitan ProductDetails.

private suspend fun launchBilling(
    activity: Activity,
    billingClient: BillingClient,
    productDetails: ProductDetails
): BillingResult {
    return withContext(context = Dispatchers.Main.immediate) {
        val productDetailsParams = BillingFlowParams
            .ProductDetailsParams
            .newBuilder()
            .setProductDetails(productDetails)
            .build()
        val billingFlowParams = BillingFlowParams
            .newBuilder()
            .setProductDetailsParamsList(listOf(productDetailsParams))
            .build()
        billingClient.launchBillingFlow(activity, billingFlowParams)
    }
}

Si desea comprar un producto de suscripción, debe pasar ProductDetails y offerToken al mismo tiempo.

Dado que un producto de suscripción puede contener múltiples Planes Base y múltiples Ofertas al mismo tiempo, las estrategias de descuento de cada Oferta son diferentes. Por lo tanto, cuando la Aplicación inicia una operación de pago, necesita utilizar el token de oferta para indicar qué Plan Base desea comprar el usuario y qué Oferta selecciona. Y dado que Google Play también considerará el precio original de BasePlan como una oferta y lo devolverá, podemos elegir si queremos que los usuarios disfruten del descuento y el grado de libertad es relativamente alto.

private suspend fun launchBilling(
    activity: Activity,
    billingClient: BillingClient,
    productDetails: ProductDetails,
    offerToken: String
): BillingResult {
    return withContext(context = Dispatchers.Main.immediate) {
        val productDetailsParams = BillingFlowParams
            .ProductDetailsParams
            .newBuilder()
            .setProductDetails(productDetails)
            .setOfferToken(offerToken)
            .build()
        val billingFlowParams = BillingFlowParams
            .newBuilder()
            .setProductDetailsParamsList(listOf(productDetailsParams))
            .build()
        billingClient.launchBillingFlow(activity, billingFlowParams)
    }
}

Después de eso, obtenemos el resultado del pago del usuario en la devolución de llamada de PurchasesUpdatedListener.

Si el usuario ha pagado correctamente, Compra contendrá la información específica de este pedido, incluido ProductId, OrderId, Cantidad, PurchaseTime, etc.

private val purchasesUpdatedListener =
    PurchasesUpdatedListener { billingResult: BillingResult, purchases: List<Purchase>? ->
        when (billingResult.responseCode) {
            BillingClient.BillingResponseCode.OK -> {
                if (!purchases.isNullOrEmpty()) {
                    purchases.forEach {
                        when (it.purchaseState) {
                            Purchase.PurchaseState.PURCHASED -> {
                                //用户支付成功
                            }

                            Purchase.PurchaseState.PENDING -> {
                                //用户仅是预创建了订单,还未真正付款
                            }

                            Purchase.PurchaseState.UNSPECIFIED_STATE -> {
                                //未知
                            }
                        }
                    }
                }
            }

            BillingClient.BillingResponseCode.USER_CANCELED -> {
                //用户取消支付
            }

            else -> {

            }
        }
    }

reconocerComprar

Una vez que el pago del usuario se haya realizado correctamente, es necesario confirmar el pedido; de lo contrario, Google Play reembolsará al usuario en un tiempo limitado.

private suspend fun acknowledgePurchase(
    billingClient: BillingClient,
    purchase: Purchase
): Boolean {
    return withContext(context = Dispatchers.Default) {
        if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED) {
            return@withContext false
        }
        if (purchase.isAcknowledged) {
            return@withContext true
        }
        if (!billingClient.isReady) {
            return@withContext false
        }
        val acknowledgePurchaseParams = AcknowledgePurchaseParams
            .newBuilder()
            .setPurchaseToken(purchase.purchaseToken)
            .build()
        val acknowledgePurchase = billingClient.acknowledgePurchase(acknowledgePurchaseParams)
        acknowledgePurchase.responseCode == BillingClient.BillingResponseCode.OK
    }
}

consumirComprar

Si el usuario compra un producto consumible de una sola vez, entonces debe elegir una oportunidad para realizar operaciones de consumo en el pedido en función del negocio real.

private suspend fun consumePurchase(
    billingClient: BillingClient,
    purchase: Purchase
): Boolean {
    return withContext(context = Dispatchers.Default) {
        if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED) {
            return@withContext false
        }
        if (!billingClient.isReady) {
            return@withContext false
        }
        val consumeParams = ConsumeParams
            .newBuilder()
            .setPurchaseToken(purchase.purchaseToken)
            .build()
        val consumeResult = billingClient.consumePurchase(consumeParams)
        consumeResult.billingResult.responseCode == BillingClient.BillingResponseCode.OK
    }
}

5. Autenticación

Después de que un usuario compra un producto, debe considerar cómo autenticarlo. Si la autenticación falla o es incorrecta, no solo traerá una mala experiencia a los usuarios y atraerá quejas de los mismos, sino que también puede causar pérdidas financieras inconmensurables al proyecto.

En términos generales, cuando un usuario utiliza una aplicación, la aplicación creará una identidad de usuario bajo su propio sistema de cuenta para el usuario actual, al que podemos llamar appUser. Cuando un usuario compra un producto, el pedido también estará vinculado a la cuenta de Google Play utilizada para pagar el dispositivo actual, a la que podemos llamar gpUser.

De esta forma, este pedido se relacionará con los usuarios desde dos perspectivas diferentes. Esto también trae una pregunta a la cadena: ¿A nombre de qué usuario deben registrarse los derechos que representa el producto? appUser o gpUser?

Ambas opciones tienen sus pros y sus contras.

Montado bajo el nombre appUser:

  • Ventajas: los derechos de los usuarios son claros y claros, y el estado de los derechos de los usuarios se puede aislar con precisión.
  • Desventajas: En países extranjeros, es muy común comprar bienes virtuales como turista. Si la aplicación solo permite a los usuarios oficiales (con una dirección de correo electrónico o un número de teléfono vinculado) comprar bienes, es muy probable que la mayoría de los posibles usuarios de pago sean perdido. Por lo tanto, si el usuario de la aplicación es un turista, cuando el usuario desinstala la aplicación, cambia o reinicia el dispositivo, es posible que el usuario pago ya no pueda recuperar el pedido.

Montado bajo el nombre gpUser:

  • Ventajas: incluso si el usuario desinstala la aplicación, cambia o restablece el dispositivo, siempre que el dispositivo actual esté conectado con la cuenta de Google Play utilizada para el pago, la aplicación puede recuperar toda la información del pedido queryPurchasesAsyncbajo el nombre de la cuenta a través del SDK de facturación. método, sin preocuparse por derechos e intereses.Situación perdida. La misma cuenta de Google Play también puede compartir los derechos de la aplicación en diferentes dispositivos y la experiencia del usuario es la mejor.
  • Desventajas: la aplicación no puede obtener la identidad única de gpUser y es probable que se produzca la reventa de cuentas. Varios usuarios comparten la misma cuenta de Google Play para disfrutar de los derechos e intereses del mismo orden.

Por lo tanto, la aplicación debe decidir si permite a los turistas realizar compras en función de su tipo de negocio y atributos de usuario. ¿En qué dimensión el usuario debe autenticar su identidad?, cuando se descubre que el mismo pedido es válido en múltiples dispositivos, y cómo. para evitar pérdidas de activos

6. Finalmente

Este artículo lo explica principalmente desde la perspectiva del terminal móvil. Aunque el sistema de liquidación de Google Play también permite que todo el proceso de pago y autenticación del usuario se complete directamente sin la participación del servicio back-end de la aplicación, por razones de seguridad, es mejor a La información del pedido se guarda sincrónicamente en el servidor y el servidor verifica el pedido antes de decidir si emitir los derechos. Además, los usuarios pueden cancelar o restaurar suscripciones directamente desde Google Play sin pasar por la App. La App no ​​puede conocer los cambios de estado del pedido en tiempo real. En este momento, Google Play solo notificará al desarrollador en tiempo real de dichos cambios . Los cambios se notifican al servidor. En este caso, también se requiere la participación del servidor para registrar completamente todo el cambio de estado de pago del usuario.

notas de estudio de Android

Artículo sobre optimización del rendimiento de Android: https://qr18.cn/FVlo89
Artículo sobre vehículos de Android: https://qr18.cn/F05ZCM
Notas de estudio de seguridad inversa de Android: Artículo sobre https://qr18.cn/CQ5TcL
principios subyacentes del marco de trabajo de Android: Artículo https://qr18.cn/AQpN4J
de audio y video de Android: https://qr18.cn/Ei3VPD
Artículo del grupo de la familia Jetpack (incluido Compose): https://qr18.cn/A0gajp
Artículo de Kotlin: https://qr18.cn/CdjtAF
Artículo de Gradle: https://qr18.cn/DzrmMB
Notas de análisis del código fuente de OkHttp: https://qr18.cn/Cw0pBD
Artículo de Flutter : https://qr18.cn/DIvKma
Ocho cuerpos de conocimiento de Android: https://qr18.cn/CyxarU
Notas principales de Android: https://qr21.cn/CaZQLo
Preguntas de la entrevista de Android de años anteriores: https://qr18.cn/CKV8OZ
Las últimas preguntas de la entrevista de Android en 2023: https://qr18.cn/CgxrRy
Ejercicios de entrevista para el puesto de desarrollo de vehículos de Android: https://qr18.cn/FTlyCJ
Preguntas de la entrevista en audio y video:https://qr18.cn/AcV6Ap

Supongo que te gusta

Origin blog.csdn.net/weixin_61845324/article/details/132760296
Recomendado
Clasificación