web-dev-qa-db-fra.com

Comment vérifier l'achat pour Android app côté serveur (google play dans application billing v3)

J'ai une application simple (nécessite une connexion utilisateur avec un compte). Je propose certaines fonctionnalités premium aux utilisateurs payants, telles que davantage de contenu d'actualités.

Je dois enregistrer si l'utilisateur a acheté cet article dans la base de données de mon serveur. Lorsque je fournis du contenu de données au périphérique de l'utilisateur, je peux alors vérifier le statut de l'utilisateur et fournir un contenu différent pour l'utilisateur payé.

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 à l'intérieur pour vérifier l'achat. Cela n'a pas l'air bien. Je pense que je peux simplement déplacer le processus de vérification sur mon serveur combiné aux informations d'identification de connexion de l'utilisateur pour voir si l'achat de l'utilisateur est terminé, puis mettre à jour la base de données.
  2. En outre, il existe API d'achat Je peux utiliser pour interroger, ce dont j'ai besoin, c'est de transmettre le buyToken de l'utilisateur au serveur.

Je ne suis pas sûr de la méthode à utiliser pour vérifier l'achat de l'utilisateur et marquer son statut dans ma base de données, peut-être les deux?

Et je crains qu'il n'y ait une situation, si un utilisateur a acheté cet élément de Google Play, mais pour une raison quelconque, juste à ce moment-là, lorsque mon application a lancé la vérification sur mon serveur, la connexion réseau est en panne ou mon propre serveur est en panne , l'utilisateur vient de payer l'argent sur Google Play mais je n'ai pas enregistré l'achat sur mon serveur? Que dois-je faire, comment puis-je gérer cette situation?.

76
virsir

Il semble que ce que vous recherchez est un moyen de vérifier si les fonctionnalités premium de l’utilisateur sont activées sur son compte. C’est donc là que je commencerais;

Assurez-vous que la base de données contient un indicateur indiquant si l'utilisateur dispose de fonctionnalités premium et incluez-le dans la charge de réponse de l'API lors de la demande d'informations de compte. Ce drapeau sera votre principale autorité pour les "fonctionnalités premium".

Lorsqu'un utilisateur effectue un achat intégré à l'application, mettez en cache les détails (jeton, identifiant de commande et identifiant de produit) localement sur le client (c'est-à-dire l'application), puis envoyez-les à votre API.

Votre API doit ensuite envoyer la purchaseToken à la API de développeur Google Play pour validation.

Quelques choses pourraient arriver d'ici:

  1. Le reçu 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. API Google Play 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 de l'achat car il n'en a plus besoin, car l'API a indiqué qu'il avait été reçu.

En cas de validation réussie (cas 1.), vous devez définir le drapeau premium sur la valeur true pour l'utilisateur.

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

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

Cette approche devrait prendre en charge les délais d’expiration du réseau, la non disponibilité des serveurs, etc.

Il y a maintenant quelques questions à prendre en compte:

Que devrait-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 doit-elle provisoirement accorder l’accès et la supprimer si la validation échoue?

L’octroi d’un accès provisoire aux fonctionnalités premium simplifie le processus pour la majorité de vos utilisateurs, mais vous autoriserez également l’accès à un certain nombre d’utilisateurs frauduleux pendant que votre API valide le purchaseToken.

En d'autres termes: l'achat est valable jusqu'à preuve du contraire frauduleux ou; frauduleux jusqu'à preuve du contraire?

Afin de déterminer si l'utilisateur dispose toujours d'un abonnement valide lorsque sa période d'abonnement doit être renouvelée, vous devez planifier une revalidation sur la purchaseToken pour qu'elle s'exécute sur la expiryTimeMillis qui a été renvoyée dans le résultat .

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

Enfin, pour vous assurer que l'utilisateur dispose (ou non) d'un accès privilégié, votre application doit interroger votre API pour obtenir les détails de l'utilisateur au lancement de l'application ou lorsqu'elle sort de l'arrière-plan.

126
Marc Greenstock

Exemple complet d’utilisation de bibliothèque Google API 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, $ purchase est une instance de Google_Service_AndroidPublisher_SubscriptionPurchase

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

Vous pouvez essayer d'utiliser Purchases.subscriptions: get côté serveur. Il prend packageName, subscriptionId et token en tant que paramètres et requiert autorisation .

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

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

12
random

La documentation à ce sujet prête à confusion et étrangement verbeuse avec des choses presque sans conséquence, tout en laissant la documentation réellement importante presque sans lien et extrêmement difficile à trouver. Cela devrait fonctionner parfaitement sur la plate-forme de serveur la plus répandue pouvant exécuter les bibliothèques clientes Google Api, notamment Java, Python, .Net et NodeJS. Remarque: j'ai testé uniquement le client api Python, comme indiqué ci-dessous.

Étapes nécessaires:

  1. Créez un projet d'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 aurez besoin de prendre ce fichier sur votre serveur.

  3. Appuyez sur Terminé dans la section du compte de service de la console Play pour l'actualiser, puis accordez l'accès au compte de service.

  4. Obtenez une bibliothèque cliente Google Api pour votre plate-forme serveur auprès de https://developers.google.com/api-client-library

  5. Utilisez la bibliothèque cliente de votre plate-forme particulière pour créer une interface de service et lisez directement le résultat de votre vérification des achats.

Vous faites not vous devez vous préoccuper des portées d'autorisation, faire des appels personnalisés, actualiser les jetons d'accès, etc. la bibliothèque cliente 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 pipeline comme ceci:

$ pipenv install google-api-python-client

Ensuite, vous pouvez 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 maintenant vérifier les achats par abonnement ou les achats de produits directement depuis 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 liée de manière facile à trouver; pour certains, elle 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)

8
Dhiraj Gupta