Android: validación de recibo de compra inApp google play

92

Estoy usando Google Wallet para mi pasarela de pago, después de comprar el producto, Google me dio una respuesta a continuación que

{ 
 "orderId":"12999763169054705758.1371079406387615", 
 "packageName":"com.example.app",
 "productId":"exampleSku",
 "purchaseTime":1345678900000,
 "purchaseState":0,
 "developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
 "purchaseToken":"rojeslcdyyiapnqcynkjyyjh"
 }

Estoy tratando de hacer uso de la validación de recibo que Google Play recientemente introdujo. En la consola de desarrollador de Google, hice la clave del certificado por cuenta de servicio en el permiso. Pero no sé cómo hacer uso de la validación de recibos después de comprar un producto en Google Play-store.

Entonces, ¿alguien puede ayudarme a hacer la validación del recibo de InAppcompra?

Binil Surendran
fuente
Hola Binil, ¿lo ha completado para la compra de suscripciones?
Anshul Tyagi
su producto de gestión @Anshul Tyag
Binil Surendran
@BinilSurendran .. Mi pregunta es diferente a la suya, pero necesito saber la identificación de correo electrónico que se utilizó para la compra desde la aplicación. ¿Pueden ayudarme a obtener ese correo electrónico, ya que lo necesito para más referencias en mi aplicación
Pallavi
@Pallavi. lo siento, no tengo la idea de obtener la identificación de correo electrónico del comprador. como la respuesta dada por Google después de la compra no tiene email_id
Binil Surendran

Respuestas:

216

Google proporciona validación de recibos a través de la API de desarrollador de Google Play , dentro de la API hay dos puntos finales en los que estará más interesado: Compras.productos: obtener y Compras.suscripciones: obtener .

Purchases.products: get se puede utilizar para verificar la compra de un producto que no se renueva automáticamente, donde Purchases.subscriptions: get es para verificar y volver a verificar las suscripciones de productos que se renuevan automáticamente.

Para utilizar cualquier criterio de valoración se debe conocer el packageName, productId,purchaseToken todos estos se pueden encontrar en la carga útil que ha recibido en la compra. También necesita una access_tokenque puede obtener creando una cuenta de servicio API de Google.

Para comenzar con una cuenta de servicio, primero vaya a la página de configuración de acceso a la API de la consola de desarrollo de Google Play y haga clic en el botón Crear nuevo proyecto:

Cree un nuevo proyecto de API de Google

Ahora debería ver un nuevo proyecto vinculado y algunas secciones nuevas, en la sección Cuenta de servicio, haga clic en el botón Crear cuenta de servicio.

Crea una nueva cuenta de servicio

Se le presentará un cuadro de información con instrucciones para crear su cuenta de servicio. Haga clic en el enlace a Google Developers Console y aparecerá una nueva pestaña.

Abra la Consola de desarrolladores de Google

Ahora haga clic en Crear nueva ID de cliente, seleccione Cuenta de servicio de las opciones y haga clic en Crear ID de cliente.

Cree una nueva identificación de cliente

Se descargará un archivo JSON, este es su JSON Web Token que utilizará para cambiarlo, access_tokenasí que manténgalo seguro.

A continuación, vuelva a cambiar de pestaña a la consola para desarrolladores de Google Play y haga clic en Listo en el cuadro de información. Debería ver su nueva cuenta de servicio en la lista. Haga clic en Otorgar acceso junto al correo electrónico de la cuenta de servicio.

Autorizará el acceso

A continuación, en Elija una función para este usuario, seleccione Finanzas y haga clic en Agregar usuario.

Establecer el rol en Finanzas

Ahora ha configurado su cuenta de servicio y tiene todo el acceso necesario para realizar validaciones de recibo. El siguiente paso es cambiar su JWT por un access_token.

El access_tokenexpira después de una hora de intercambio, por lo que necesita un código de servidor para manejar esto y Google ha proporcionado varias bibliotecas en muchos idiomas para manejar esto (la lista no es exhaustiva):

No entraré en detalles porque hay mucha documentación sobre cómo usar estas bibliotecas, pero mencionaré que desea usar el https://www.googleapis.com/auth/androidpublisheralcance de OAuth2, el client_emailde JWT como issuery la clave pública que puede obtener de private_keyy la frase de contraseña notasecretse utilizará para signing_key.

Una vez que tenga el access_token, estará listo para comenzar (al menos durante la próxima hora, momento en el que querrá solicitar uno nuevo siguiendo el mismo proceso en el párrafo anterior).

Para comprobar el estado de una compra de consumibles (no renovable automáticamente), realice una getsolicitud http a:https://www.googleapis.com/androidpublisher/v2/applications/com.example.app/purchases/products/exampleSku/tokens/rojeslcdyyiapnqcynkjyyjh?access_token=your_access_token

Si obtiene un código de respuesta 200 http, todo salió según lo planeado y su compra fue válida. Un 404 significará que su token no es válido, por lo que la compra probablemente fue un intento de fraude. Un 401 significará que su token de acceso no es válido y un 403 significará que su cuenta de servicio no tiene acceso suficiente, verifique que haya habilitado Finanzas para la cuenta de acceso en la consola de desarrollador de Google Play.

La respuesta de un 200 se verá similar a esto:

{
  "kind": "androidpublisher#productPurchase",
  "purchaseTimeMillis": long,
  "purchaseState": integer,
  "consumptionState": integer,
  "developerPayload": string
}

Para obtener una explicación de cada propiedad, consulte https://developers.google.com/android-publisher/api-ref/purchases/products .

Las suscripciones son similares, sin embargo, el punto final se ve así:

https://www.googleapis.com/androidpublisher/v2/applications/packageName/purchases/subscriptions/subscriptionId/tokens/token?access_token=you_access_token

Y la respuesta debe contener estas propiedades:

{
  "kind": "androidpublisher#subscriptionPurchase",
  "startTimeMillis": long,
  "expiryTimeMillis": long,
  "autoRenewing": boolean
}

Consulte https://developers.google.com/android-publisher/api-ref/purchases/subscriptions para ver las descripciones de las propiedades y tenga en cuenta que startTimeMillisyexpiryTimeMillis estarán sujetos a cambios dependiendo de la duración de la suscripción.

¡Feliz validación!

Marc Greenstock
fuente
Agregué un nuevo usuario en la consola del desarrollador y obtuve un certificado JSON que se obtiene de la consola. ¿Me pueden ayudar a hacer la validación del recibo con el archivo descargado @Marc Greenstock
Binil Surendran
@BinilS Necesitarás ser más específico, ¿en qué idioma del lado del servidor vas a escribir tu código?
Marc Greenstock
estoy usando Java en el lado del servidor @Marc Greenstock
Binil Surendran
3
Esta es la primera vez que veo una guía detallada para implementar la validación de pago del servidor en 2 días de búsqueda. Pulgares hacia arriba. ¿Hay un código de servidor listo para usar en alguna parte? Me parece muy extraño que no pueda encontrar algo así en ningún lado
Anónimo
2
@MarcGreenstock Gracias por la respuesta detallada.
Lavakush
28

La respuesta de Marc es excelente. Solo agregaré que la biblioteca cliente de la API de desarrolladores de Google Play para Java hace que sea mucho más simple cuando se conecta desde su servidor a los servidores de Google Play. La biblioteca maneja automáticamente la actualización del token de autenticación y también proporciona una API con seguridad de tipos para que no tenga que perder el tiempo con las URL.

Así es como configuras el Publishersingleton:

httpTransport = GoogleNetHttpTransport.newTrustedTransport();
jsonFactory = JacksonFactory.getDefaultInstance();      
credential = GoogleCredential.fromStream(getClass().getResourceAsStream("/path/to/your/key.json")).createScoped(Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER));
publisher = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential).setApplicationName(APP_NAME).build();

El siguiente código consulta la compra de un producto:

ProductPurchase product = publisher.purchases().products().get(PACKAGE_NAME, sku, token).execute();
Integer purchaseState = product.getPurchaseState();
product.getPurchaseTimeMillis();
product.getConsumptionState();
product.getDeveloperPayload();

De manera similar, puede consultar las suscripciones:

SubscriptionPurchase sub = publisher.purchases().subscriptions().get(PACKAGE_NAME, sku, token).execute();
sub.getAutoRenewing();
sub.getCancelReason();
...
Jeshurun
fuente
¿Este es un código en un servidor Java o se ejecuta en Android antes de llamar a un servidor arbitrario?
usuario
2
@jeshurun ​​Gracias por el código. A otros lectores APP_NAME = APP_PACKAGE_NAME.
tormenta de nieve el
1
¿Y Python?
Babken Vardanyan
1
¡Gracias! Para mí en lugar de getClass().getResourceAsStream(...usar new FileInputStream(....
António Almeida
Gracias. Muy útil. Sin embargo, también necesitaba agregar: credential.refreshToken();entre obtener la credencial y el editor.
grooble
5

@ marc-greenstock proporcionó una gran respuesta, sin embargo, hay algo muy importante sobre la validación de recibos usando la API de desarrollador de Android de Google Play.

Si tiene algún problema con el uso de esta API y agregó su producto en la aplicación ANTES de otorgar el permiso o vincularlo a su cuenta de servicio, debe abrir "Productos en la aplicación" y realizar alguna actualización. Por ejemplo, puede editar la descripción de su producto y guardar. Debería obtener permiso al instante.

Pasé unas horas pensando qué hice mal ...

Wojciech Kulik
fuente
2

Esta respuesta es excelente. Un problema más con el que nos encontramos al seguir la dirección fue que la cuenta de servicio no apareció en Google Play Console. Terminamos encontrando esta solución para ayudar: la cuenta de servicio no aparece en Google Console después de la creación

Básicamente, vaya a IAM en Google API Console y agregue la nueva cuenta de servicio, luego aparecerá en Google Play Console. captura de pantalla

volando
fuente
¿Puede agregar una descripción aquí? De lo contrario, una vez, si se revoca el enlace, su respuesta se vuelve inválida
Mathews Sunny
1
¿Cuál debería ser la función de la cuenta agregada?
Adi