Cómo verificar la compra para la aplicación de Android en el lado del servidor (google play en la aplicación de facturación v3)

96

Tengo una aplicación simple (necesita inicio de sesión de usuario con cuenta). Proporciono algunas funciones premium para usuarios pagos, como más contenido de noticias.

Necesito registrar si el usuario compró este artículo en la base de datos de mi servidor. Cuando proporciono contenido de datos al dispositivo del usuario, puedo verificar el estado del usuario y proporcionar contenido diferente para el usuario pago.

Verifiqué la muestra oficial de Trivialdrive proporcionada por Google, no proporciona ningún código de muestra para la verificación del lado del servidor, aquí están mis preguntas.

  1. Encontré que la muestra usa la clave pública de mi aplicación en el interior para verificar la compra, no se ve bien, creo que puedo mover el proceso de verificación a mi servidor combinado con las credenciales de inicio de sesión del usuario para ver si la compra del usuario se completó y luego actualizar la base de datos.
  2. También hay una API de compra que puedo usar para consultar, lo que necesito es pasar el purchaseToken del usuario al servidor.

No estoy seguro de qué método debo seguir para verificar la compra del usuario y marcar el estado del usuario en mi base de datos, ¿quizás ambos?

Y me temo que hay una situación, si un usuario compró este artículo en Google Play, pero por alguna razón, justo en ese momento, cuando mi aplicación inició la verificación en mi servidor, la conexión de red no funciona o mi propio servidor no funciona , ¿El usuario acaba de pagar el dinero en Google Play pero no registré la compra en mi servidor? ¿Qué debo hacer? ¿Cómo puedo lidiar con esta situación?

virsir
fuente
Probablemente debería eliminar la bandera de ios de esta pregunta.
Gustavo Guevara

Respuestas:

160

Parece que lo que estás buscando es una forma de comprobar si el usuario tiene funciones premium habilitadas en su cuenta, así que aquí es donde empezaría;

Asegúrese de que haya una bandera de algún tipo en su base de datos que indique si el usuario tiene funciones premium e inclúyala en la carga útil de respuesta de la API cuando solicite información de la cuenta. Esta bandera será su autoridad principal para las "funciones premium".

Cuando un usuario realiza una compra en la aplicación, almacena en caché los detalles (token, identificación del pedido e identificación del producto) localmente en el cliente (es decir, la aplicación) y luego envíalo a tu API.

Luego, su API debe enviar el purchaseTokena la API de desarrollador de Google Play para su validación.

Algunas cosas pueden suceder desde aquí:

  1. El recibo es válido, su API responde al cliente con un código de estado 200 Ok
  2. El recibo no es válido, su API responde al cliente con un código de estado 400 Bad Request
  3. La API de Google Play está inactiva, su API responde con un código de estado 502 Bad Gateway

En el caso de 1. o 2. (códigos de estado 2xx o 4xx), su cliente borra el caché de los detalles de la compra porque ya no lo necesita porque la API ha indicado que se ha recibido.

Tras una validación exitosa (caso 1), debe establecer el premiumindicador en verdadero para el usuario.

En el caso de 3. (código de estado 5xx) o un tiempo de espera de la red, el cliente debe seguir intentándolo hasta que reciba un código de estado 2xx o 4xx de su API.

Dependiendo de sus requisitos, puede hacer que espere unos segundos antes de enviar nuevamente o simplemente enviar los detalles a su API cuando la aplicación se inicie nuevamente o salga del segundo plano si los detalles de la compra están presentes en el caché de la aplicación.

Este enfoque debe ocuparse de los tiempos de espera de la red, los servidores no están disponibles, etc.

Ahora hay algunas preguntas que debe considerar:

¿Qué debería suceder inmediatamente después de una compra? ¿Debería la aplicación esperar hasta que la validación sea exitosa antes de proporcionar contenido premium o debería otorgar acceso tentativamente y quitarlo si la validación falla?

Otorgar acceso tentativo a funciones premium simplifica el proceso para la mayoría de sus usuarios, pero también otorgará acceso a varios usuarios fraudulentos mientras su API valida el purchaseToken.

Para decirlo de otra manera: la compra es válida hasta que se pruebe que es fraudulenta o; fraudulento hasta que se demuestre su validez?

Para identificar si el usuario todavía tiene una suscripción válida cuando su período de suscripción llegue para la renovación, deberá programar una revalidación en el purchaseTokenpara que se ejecute en el expiryTimeMillisque se devolvió en el resultado .

Si expiryTimeMillisestá en el pasado, puede establecer el premiumindicador en falso. Si es en el futuro, vuelva a programarlo para el nuevo expiryTimeMillis.

Por último, para asegurarse de que el usuario tenga acceso premium (o no), su aplicación debe consultar su API para obtener los detalles de los usuarios al iniciar la aplicación o cuando sale del segundo plano.

Marc Greenstock
fuente
Para la aplicación paga, ¿cómo obtendré el recibo de Google?
Merbin Joe
2
¡Hola! ¿No hay forma de acceder al historial de suscripciones en Google? ¿Cómo evitar perder el hecho de que ya se usó cubscription comprado en el caso de que la aplicación se bloquee en el momento de almacenar purchaseToken?
scythargon
2
Tengo un problema similar ... en lugar de permitir que la aplicación envíe el token a la API, ¿no sería más confiable indicarle al servidor de desarrolladores de Google que lo haga con una notificación push directamente a mi API?
Gianluca Ghettini
Para las suscripciones que se cancelaron, la API de desarrollador de Google Play seguirá devolviendo 200 después de la cancelación, si se utiliza el mismo token de compra anterior para la validación.
Cezar Cobuz
Entonces, para una suscripción, sugiere que después de la primera llamada en el servidor, almacenemos el token de compra y la identificación del producto, y programemos otra llamada de verificación (vuelva a ejecutar la misma solicitud) cuando ocurra el expiryTimeMillis. ¿Es así como se supone que debemos verificar la validez de la suscripción? ¿Hay alguna guía de Android sobre cómo hacer eso? Apple obtuvo un video de la WWDC al respecto que explica la buena práctica con bastante claridad, pero no puede encontrar mucho sobre Play Store.
schankam
26

La documentación sobre esto es confusa y extrañamente detallada con las cosas que son casi intrascendentes, mientras que deja la documentación realmente importante casi sin vincular y muy difícil de encontrar. Esto debería funcionar muy bien en la plataforma de servidor más popular que puede ejecutar las bibliotecas cliente de google api, incluidas Java, Python, .Net y NodeJS, entre otras. Nota: He probado solo el cliente de la API de Python como se muestra a continuación.

Pasos necesarios:

  1. Cree un proyecto de API, desde el enlace de acceso a API en su consola de Google Play

  2. Cree una nueva cuenta de servicio, guarde la clave privada JSON que se genera. Deberá llevar este archivo a su servidor.

  3. Presione Listo en la sección de la cuenta de servicio de la consola Play para actualizar y luego otorgar acceso a la cuenta de servicio

  4. Obtenga una biblioteca cliente de google api para su plataforma de servidor en https://developers.google.com/api-client-library

  5. Utilice la biblioteca de cliente de su plataforma en particular para crear una interfaz de servicio y leer directamente el resultado de la verificación de su compra.

Usted no tiene que molestarse con ámbitos de autorización, por lo que las peticiones de encargo llamadas, refrescante tokens de acceso, etc., la biblioteca de la API se encarga de todo. Aquí hay un ejemplo de uso de la biblioteca de Python para verificar una suscripción:

Primero, instale el cliente api de Google en su pipenv de esta manera:

$ pipenv install google-api-python-client

Luego, puede configurar las credenciales del cliente api utilizando el archivo json de clave privada para autenticar la cuenta de servicio.

credentials = service_account.Credentials.from_service_account_file("service_account.json")

Ahora puede verificar las compras de suscripciones o las compras de productos usando la biblioteca, directamente.

#Build the "service" interface to the API you want
service = googleapiclient.discovery.build("androidpublisher", "v3", credentials=credentials)

#Use the token your API got from the app to verify the purchase
result = service.purchases().subscriptions().get(packageName="your.app.package.id", subscriptionId="sku.name", token="token-from-app").execute()
#result is a python object that looks like this ->
# {'kind': 'androidpublisher#subscriptionPurchase', 'startTimeMillis': '1534326259450', 'expiryTimeMillis': '1534328356187', 'autoRenewing': False, 'priceCurrencyCode': 'INR', 'priceAmountMicros': '70000000', 'countryCode': 'IN', 'developerPayload': '', 'cancelReason': 1, 'orderId': 'GPA.1234-4567-1234-1234..5', 'purchaseType': 0}

La documentación de la interfaz de servicio de la plataforma para la API de desarrollador de Play no está vinculada de una manera fácil de encontrar, para algunos es francamente difícil de encontrar . Aquí están los enlaces para las plataformas populares que encontré:

Python | Java | .NET | PHP | NodeJS (Github TS) | Ir (Github JSON)

Dhiraj Gupta
fuente
5
De acuerdo, la documentación es horrible ... ¿Alguna idea de cómo hacer esto con Firebase (Firestore) y las funciones de Cloud como backend?
Jeff Padgett
Si sus funciones en la nube están en NodeJS, entonces tal vez podría usar el enlace NodeJS anterior para que funcione la biblioteca del cliente API.
Dhiraj Gupta
17

Ejemplo completo de uso de la biblioteca cliente de API de Google para PHP :

  1. Configure su proyecto de Google y acceda a Google Play para su cuenta de servicio como se describe en la respuesta de Marc aquí https://stackoverflow.com/a/35138885/1046909 .

  2. Instale la biblioteca: https://developers.google.com/api-client-library/php/start/installation .

  3. Ahora puede verificar su recibo de la siguiente manera:

    $client = new \Google_Client();
    $client->setAuthConfig('/path/to/service/account/credentials.json');
    $client->addScope('https://www.googleapis.com/auth/androidpublisher');
    $service = new \Google_Service_AndroidPublisher($client);
    $purchase = $service->purchases_subscriptions->get($packageName, $productId, $token);

    Después de eso, $ purchase es una instancia de Google_Service_AndroidPublisher_SubscriptionPurchase

    $purchase->getAutoRenewing();
    $purchase->getCancelReason();
    ...
MingalevME
fuente
Esto no funciona, sigo obteniendo (401) Se requiere inicio de sesión y setAuthConfig no acepta las credenciales de la cuenta de servicio json
Raulnd
Este funcionó para mí putenv ('GOOGLE_APPLICATION_CREDENTIALS = credentials.json'); $ cliente = nuevo Google_Client (); $ cliente-> useApplicationDefaultCredentials (); $ cliente-> addScope (' googleapis.com/auth/androidpublisher' ); $ servicio = nuevo Google_Service_AndroidPublisher ($ cliente); $ compra = $ servicio-> compras_productos-> obtener ($ packageName, $ productId, $ token); var_dump ($ compra);
Raulnd
Esto es en caso de facturación inapp. ¿Qué pasa si quiero obtener orderId en mi base de datos cada vez que el usuario compra mi aplicación en Play Store en lugar de una aplicación?
Ankesh kumar Jaisansaria
stackoverflow.com/questions/48662787/… Consulte esta pregunta. Estoy buscando respuesta a esta pregunta. Esto también tiene recompensa activa
Ankesh kumar Jaisansaria
@MingalevME ¿Qué pasa si el formato del token no es válido y PHP obtiene un error fatal, cómo puedo detectar este error?
alexx0186
12

Puede intentar usar las suscripciones de compras: obtener del lado del servidor. Toma packageName, subscriptionId y token como parámetros y requiere autorización .

Comprueba si la compra de la suscripción de un usuario es válida y devuelve su fecha de caducidad.

Si tiene éxito, este método devuelve un recurso de suscripciones de compras en el cuerpo de la respuesta.

aleatorio
fuente
9
Tengo serios problemas para que funcione la autorización.
8
Seriamente. Por lo críticas que son las compras para algunas aplicaciones, el soporte y la documentación son estúpidos. Esto es lo que debe hacer en el servidor: github.com/google/… . Más información aquí: stackoverflow.com/questions/35127086/…
usuario
0

Yo respondo a esta inquietud

la conexión de red no funciona o mi propio servidor no funciona, el usuario acaba de pagar el dinero en Google Play, pero no registré la compra en mi servidor. ¿Qué debo hacer? ¿Cómo puedo lidiar con esta situación?

La situación es:

El usuario compra el artículo 'abc' usando el servicio de Google Play -> regresar OK -> no verifica con el servidor por algunas razones, como no tener conexión a Internet.

La solución es:

En el lado del cliente, antes de mostrar el botón 'Google Wallet', verifica si el elemento 'abc' ya es de tu propiedad.

  • si es así, verifique con el servidor nuevamente
  • si no, muestra el botón "Google Wallet".

Compra compra = mInventory.getPurchase ('abc');

if (purchase != null) // Verify with server 

else // show Google Wallet button

https://developer.android.com/google/play/billing/billing_reference.html#getSkuDetails

thanhbinh84
fuente
4
No entiendo por qué validar en el servidor es más seguro que validar en la aplicación. Al final del día, es la aplicación la que desbloquea las funciones, por lo que aún es posible eliminar o invertir el código en la aplicación que verifica si la respuesta del servidor es "OK"
Gianluca Ghettini
2
@GianlucaGhettini porque, a veces, el servidor es lo que proporciona el servicio comprado, no la aplicación, además, la aplicación podría tener ingeniería inversa y luego, con cierta dificultad, el proceso de verificación podría ser pirateado.
Mohyaddin Alaoddin