Comment vérifier l’achat pour l’application Android côté serveur (google play dans la facturation de l’application v3)

J’ai une application simple (nécessite une connexion utilisateur avec un compte). Je propose des fonctionnalités haut de gamme pour les utilisateurs payants, comme plus de contenu d’actualités.

Je dois enregistrer si l’utilisateur a acheté cet article dans la firebase database de mon serveur. Lorsque je fournis du contenu de données à l’appareil de l’utilisateur, je peux alors vérifier le statut de l’utilisateur et fournir un contenu différent pour l’utilisateur payant.

J’ai vérifié l’échantillon officiel Trivialdrive fourni par Google, il ne fournit aucun exemple de code pour la vérification côté serveur, voici mes questions.

  1. J’ai trouvé que l’exemple utilisait la clé publique de mon application pour vérifier l’achat, cela ne semble pas bon, je pense que je peux déplacer le processus de vérification sur mon serveur avec les identifiants utilisateur pour vérifier si l’utilisateur achète, puis mettre à jour la firebase database.
  2. Il y a aussi une API d’achat que je peux utiliser pour interroger, ce dont j’ai besoin est de passer le buyToken de l’utilisateur dans le serveur.

Je ne suis pas sûr de la méthode à suivre pour vérifier l’achat de l’utilisateur et marquer le statut de l’utilisateur dans ma firebase database, peut-être les deux?

Et je crains qu’il y ait une situation, si un utilisateur a acheté cet article de Google Play, mais pour une raison quelconque, juste à ce moment, lorsque mon application a lancé la vérification sur mon serveur, la connexion réseau est interrompue ou mon propre serveur est arrêté . l’utilisateur a juste payé l’argent dans Google Play mais je n’ai pas enregistré l’achat sur mon serveur? Que dois-je faire, comment puis-je faire face à cette situation.

Il semble que ce que vous cherchez est un moyen de vérifier si l’utilisateur dispose des fonctionnalités premium activées sur son compte, c’est donc là que je commencerais.

Assurez-vous que votre firebase database contient un indicateur indiquant si l’utilisateur dispose de fonctionnalités premium et l’inclut dans la charge de réponse de l’API lors de la demande d’informations sur le compte. Ce drapeau sera votre autorité principale pour les “fonctionnalités premium”.

Lorsqu’un utilisateur effectue un achat intégré à l’application, placez les détails (jeton, numéro de commande et identifiant de produit) en cache sur le client (par exemple, l’application), puis envoyez-les à votre API.

Votre API doit alors envoyer le purchaseToken à l’ API de développeur Google Play pour validation.

Quelques choses peuvent arriver d’ici:

  1. Le ticket de caisse est valide, votre API répond au client avec un code de statut 200 Ok
  2. Le reçu est invalide, votre API répond au client avec un code d’état 400 Bad Request
  3. L’API Google Play est en panne, votre API répond avec un code d’état 502 Bad Gateway

Dans le cas de 1. ou 2. (codes d’état 2xx ou 4xx), votre client efface le cache des détails d’achat car il n’en a plus besoin, car l’API a indiqué qu’il avait été reçu.

Une fois la validation réussie (cas 1), vous devez définir l’indicateur premium sur true pour l’utilisateur.

Dans le cas de 3. (code d’état 5xx) ou de délai d’attente du réseau, le client devrait continuer d’essayer jusqu’à ce qu’il reçoive un code d’état 2xx ou 4xx de votre API.

Selon vos besoins, vous pouvez le faire attendre quelques secondes avant de le renvoyer ou simplement envoyer les détails à votre API chaque fois que l’application est relancée ou sort de l’arrière-plan si les détails d’achat sont présents dans le cache de l’application.

Cette approche doit prendre en compte les délais d’expiration du réseau, les serveurs indisponibles, etc.

Il y a maintenant quelques questions à considérer:

Que doit-il se passer immédiatement après un achat? L’application doit-elle attendre que la validation réussisse avant de fournir du contenu premium ou devrait-elle accorder un access provisoire et la supprimer si la validation échoue?

Accorder un access provisoire à des fonctionnalités premium facilite le processus pour la majorité de vos utilisateurs, mais vous accorderez également l’access à un certain nombre d’utilisateurs frauduleux pendant que votre API valide le purchaseToken .

Pour le dire autrement: L’achat est valide jusqu’à preuve du contraire frauduleux ou; frauduleux jusqu’à preuve du contraire?

Afin d’identifier si l’utilisateur dispose toujours d’un abonnement valide au moment du renouvellement de sa période d’abonnement, vous devez planifier une nouvelle validation sur le expiryTimeMillis purchaseToken pour qu’il s’exécute à la date d’ expiryTimeMillis qui a été renvoyée dans le résultat .

Si l’ expiryTimeMillis est dans le passé, vous pouvez définir l’indicateur premium sur false. Si c’est à l’avenir, reprogrammez-le à nouveau pour le nouveau expiryTimeMillis .

Enfin, pour vous assurer que l’utilisateur dispose d’un access premium (ou non), votre application doit interroger votre API sur les détails des utilisateurs lors du lancement de l’application ou lorsque celle-ci est en arrière-plan.

Vous pouvez essayer d’utiliser Purchases.subscriptions: obtenez côté serveur. Il prend packageName, subscriptionId et token comme parameters et requirejs une autorisation .

Vérifie si l’achat d’abonnement d’un utilisateur est valide et renvoie son heure d’expiration.

En cas de succès, cette méthode renvoie une ressource Purchases.subscriptions dans le corps de la réponse.

Exemple complet d’utilisation de Google API Client Library pour PHP :

  1. Configurez votre projet Google et accédez à Google Play pour votre compte de service, comme décrit dans la réponse de Marc ici https://stackoverflow.com/a/35138885/1046909 .

  2. Installez la bibliothèque: https://developers.google.com/api-client-library/php/start/installation .

  3. Vous pouvez maintenant vérifier votre reçu de la manière suivante:

     $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); 

    Après cela, $ buy est une instance de Google_Service_AndroidPublisher_SubscriptionPurchase

     $purchase->getAutoRenewing(); $purchase->getCancelReason(); ... 

La documentation à ce sujet est déroutante et étrangement verbeuse avec les choses qui sont presque sans importance, tout en laissant la documentation réellement importante presque non liée et très difficile à trouver. Cela devrait fonctionner très bien sur la plate-forme serveur la plus populaire capable d’exécuter les bibliothèques client google api, notamment Java, Python, .Net et NodeJS. Remarque: j’ai testé uniquement le client Python api, comme indiqué ci-dessous.

Étapes nécessaires:

  1. Créez un projet API à partir du lien API Access de votre console Google Play

  2. Créez un nouveau compte de service, enregistrez la clé privée JSON générée. Vous devrez prendre ce fichier sur votre serveur.

  3. Appuyez sur Terminé dans la section Compte de service de la console de lecture pour actualiser, puis autoriser l’access au compte de service.

  4. Accédez à une bibliothèque client Google API pour votre plate-forme de serveur à l’ adresse https://developers.google.com/api-client-library.

  5. Utilisez la bibliothèque client de votre plate-forme pour créer une interface de service et lisez directement le résultat de votre vérification d’achat.

Vous n’avez pas besoin de vous préoccuper des étendues d’autorisation, de faire des appels de requêtes personnalisées, d’actualiser les jetons d’access, etc. La bibliothèque cliente de l’API s’occupe de tout. Voici un exemple d’utilisation de la bibliothèque python pour vérifier un abonnement:

Tout d’abord, installez le client google api dans votre pipenv comme ceci:

 $ pipenv install google-api-python-client 

Vous pouvez ensuite configurer les informations d’identification du client API à l’aide du fichier json de clé privée pour authentifier le compte de service.

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

Vous pouvez désormais vérifier directement les achats d’abonnements ou les achats de produits à l’aide de la bibliothèque.

 #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 documentation de l’interface de service de plate-forme pour l’API de développeur de jeu n’est pas facile à trouver, pour certains, c’est carrément difficile à trouver . Voici les liens pour les plateformes populaires que j’ai trouvées:

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

Je réponds à cette préoccupation

la connexion réseau est en panne ou mon propre serveur est en panne, l’utilisateur vient de payer l’argent dans Google Play mais je n’ai pas enregistré l’achat sur mon serveur? Que dois-je faire, comment puis-je faire face à cette situation.

La situation est la suivante:

L’abc utilisateur de l’article des achats utilisateur en utilisant Google Play Service -> retourner OK -> ne parvient pas à vérifier avec le serveur pour certaines raisons telles que l’absence de connexion Internet.

La solution est:

Du côté du client, avant d’afficher le bouton «Google Wallet», vous vérifiez si l’élément «abc» appartient déjà.

  • Si oui, vérifiez à nouveau avec le serveur
  • Si non, affichez le bouton “Google Wallet”.

Achat achat = 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