Hoy vamos a aprender a validar compras in app usando Python y una aplicación desarrollada en Android. Servirá para las apps desarrolladas en Android nativo, ionic, kotlin, flutter, react native o la tecnología que quieras.

Lo primero de todo es crear un refresh token y datos de token oauth 2.0 para ello seguimos este tutorial:
https://devcodelight.com/como-obtener-el-refresh-token-de-google-paso-a-paso-oauth-2-0
Ahora vamos a implementar el código que nos permitirá validar las compras:
Primero debemos obtener el token de acceso usando nuestro refresh token (obtenido en el punto anterior).
Para obtener el token de acceso es:
import requests def intercambiar_codigo_por_token(code: str) -> dict: url = "https://oauth2.googleapis.com/token" data = { "code": code, "client_id": "TU_CLIENT_ID", "client_secret": "TU_CLIENT_SECRET", "redirect_uri": "http://localhost:8000/auth/callback", "grant_type": "authorization_code" } response = requests.post(url, data=data) response.raise_for_status() return response.json()
Con esto obtendrás el token de acceso.
Y recibes este:
{ "access_token": "...", "expires_in": 3599, "refresh_token": "...", "scope": "https://www.googleapis.com/auth/androidpublisher", "token_type": "Bearer" }
Y ahora para validar hacemos lo siguiente:
Validar compras de productos:
import requests import json def validate_android_purchase( id_user: str, purchase_token: str, package_name: str, subscription_id: str, access_token: str ) -> str: """ Valida una compra de Google Play (producto in-app). Retorna: - order_id (str) si es válida - "-1" si hay un error en la respuesta de Google - lanza excepción si falla la conexión o la petición """ url = ( f"https://www.googleapis.com/androidpublisher/v3/applications/" f"{package_name}/purchases/products/{subscription_id}/tokens/{purchase_token}" ) headers = { "Authorization": f"Bearer {access_token}", "Accept": "application/json", "User-Agent": "SecurePythonClient/1.0" } try: response = requests.get(url, headers=headers) response.raise_for_status() except requests.HTTPError as e: print(f"HTTP Error: {response.status_code} - {response.reason}") try: print(json.dumps(response.json(), indent=2)) except Exception: print("Error al parsear la respuesta de error") raise except requests.RequestException as e: print(f"Error de conexión: {str(e)}") raise data = response.json() if 'error' in data: return "-1" return data.get("orderId", "NO_ORDER_ID")
Ejemplo de uso:
if __name__ == "__main__": try: order_id = validate_android_purchase( id_user="user_123", purchase_token="PURCHASE_TOKEN_AQUÍ", package_name="com.tu.app", subscription_id="producto_id", access_token="ya29.a0AfH6SMA..." ) print("Order ID:", order_id) except Exception as e: print("Error validando compra:", str(e))
Validar compras de suscripciones:
import requests import json def validate_android_subscription( id_user: str, purchase_token: str, package_name: str, subscription_id: str, access_token: str ) -> dict: """ Valida una suscripción de Google Play. Args: id_user (str): ID interno del usuario (opcional, útil para trazabilidad) purchase_token (str): Token de compra recibido desde la app package_name (str): Nombre del paquete de la app (com.ejemplo.app) subscription_id (str): ID del producto de suscripción access_token (str): Token de acceso OAuth válido Returns: dict con los datos de la suscripción, o lanza excepción si hay error """ url = ( f"https://androidpublisher.googleapis.com/androidpublisher/v3/applications/" f"{package_name}/purchases/subscriptions/{subscription_id}/tokens/{purchase_token}" ) headers = { "Authorization": f"Bearer {access_token}", "Accept": "application/json", "User-Agent": "SecurePythonClient/1.0" } try: response = requests.get(url, headers=headers) response.raise_for_status() except requests.HTTPError as e: print(f"HTTP Error: {response.status_code} - {response.reason}") try: print(json.dumps(response.json(), indent=2)) except Exception: print("Error al parsear la respuesta de error") raise except requests.RequestException as e: print(f"Error de conexión: {str(e)}") raise return response.json()
Ejemplo de uso:
if __name__ == "__main__": try: result = validate_android_subscription( id_user="user_456", purchase_token="TOKEN_DE_COMPRA", package_name="com.ejemplo.app", subscription_id="subs_mensual", access_token="ya29.a0AfH6SMA..." ) print("Suscripción válida:") print(json.dumps(result, indent=2)) except Exception as e: print("Error validando suscripción:", str(e))

Ingeniero en Informática, Investigador, me encanta crear cosas o arreglarlas y darles una nueva vida. Escritor y poeta. Más de 20 APPs publicadas y un libro en Amazon.