BlogRight arrowTutorialRight ArrowAchats intégrés sous Android, 5e partie : validation des achats côté serveur
BlogRight arrowTutorialRight ArrowAchats intégrés sous Android, 5e partie : validation des achats côté serveur

Achats intégrés sous Android, 5e partie : validation des achats côté serveur

Achats intégrés sous Android, 5e partie : validation des achats côté serveur
Listen to the episode
Achats intégrés sous Android, 5e partie : validation des achats côté serveur

La validation côté serveur peut vous aider à valider l'authenticité des achats. L'appareil envoie une demande aux serveurs de Google pour savoir si l'achat a effectivement eu lieu et s'il est valable.

Dans ce guide, nous allons voir comment configurer la validation côté serveur (server-side) pour les applications (app) fonctionnant sous Android.

Pourquoi valider les achats?

Il convient de noter que la validation côté serveur n'est pas obligatoire : les achats intégrés aux applications fonctionneront toujours sans elle. Elle présente cependant des avantages non négligeables :

  1. Analyse avancée des paiements, ce qui est particulièrement important pour les abonnements puisque tout ce qui se passe après l'activation n'est pas traité par le dispositif. Sans traitement des achats côté serveur, vous ne serez pas en mesure de récupérer l'état actuel de l'abonnement et de savoir si l'utilisateur a renouvelé ou annulé son abonnement, s'il y a des problèmes de paiement, etc.
  2. Pouvoir vérifier l'authenticité de l'achat. Vous aurez la certitude que la transaction n'est pas frauduleuse et que l'utilisateur a réellement payé votre produit.
  3. Abonnements multi-plateformes. Si vous pouvez vérifier l'état de l'abonnement de l'utilisateur en temps réel, vous pouvez le synchroniser avec d'autres plateformes. Par exemple, l'utilisateur qui a acheté l'abonnement à partir d'un appareil iOS pourra l'utiliser sous Android, le Web et d'autres plateformes. 
  4. La possibilité de contrôler l'accès au contenu du côté du serveur, ce qui vous protège des utilisateurs qui tentent d'accéder aux données sans abonnement en exécutant simplement des requêtes au serveur. 

D'après notre expérience, le premier avantage suffit à lui seul à mettre en place le traitement des achats côté serveur.

⭐️ Download our guide on in-app techniques which will make in-app purchases in your app perfect

Validation du paiement

Nous pouvons résumer la validation des paiements (purchase validation) Android avec ce schéma :

Authentification pour les demandes de Google Play Developer API

Pour travailler avec Google Play Developer API, vous devez d'abord générer une clé pour signer les demandes. Tout d'abord, vous devez relier votre compte Google Play Console (où vous gérez votre application) à votre compte Google Cloud (où vous générerez une clé pour la signature des demandes). Une fois que tout est configuré, vous devrez accorder à l'utilisateur des droits de gestion des achats. Il faudrait un article dédié pour décrire ce processus. Heureusement, nous l'avons déjà couvert dans un guide étape par étape que vous trouverez dans Adapty documentation

Notez que vous devrez généralement attendre 24 heures ou plus après avoir généré une clé pour qu'elle commence à fonctionner. Pour éviter cela, il suffit de mettre à jour la description de tout produit ou abonnement intégré à l'application, ce qui activera instantanément la clé. 

Nous utilisons la bibliothèque officielle google-api-python-client pour travailler avec Google Play Developer API. Cette bibliothèque est disponible pour la majorité des langages populaires, et je recommande de l'utiliser car elle prend en charge toutes les méthodes dont vous pourriez avoir besoin.

Validation des transaction d'abonnement :

Contrairement à la validation côté serveur d'iOS, sous Android, la validation des abonnements et des autres produits est mise en œuvre à l'aide de diverses méthodes. Par conséquent, lorsque vous validez une transaction, vous devez savoir si vous avez affaire à un produit ou à un abonnement. En pratique, cela signifie que vous devrez transférer ces données à partir de l'application mobile et conserver l'indicateur dans la base de données au cas où une nouvelle validation du jeton serait nécessaire.

La deuxième différence importante est que si chaque transaction possède son propre jeton dans Android, toutes les transactions iOS utilisent un secret partagé propre à l'application pour stocker l'historique complet de la transaction. Cela signifie que si vous voulez être en mesure de renouveler les achats de l'utilisateur à tout moment, vous devrez stocker tous les jetons d'achat, au lieu d'en choisir un seul arbitrairement.

Pour valider l'abonnement, vous devrez invoquer la méthode  purchases.subscriptions.get.  En gros, c'est un appel à une requête GET :

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}

Tous les paramètres sont obligatoires :

  • packageName: Un identifiant unique pour appli, par exemple, com.adapty.sample_app.
  • subscriptionId: Identifiant de l'abonnement à valider, par exemple, com.adapty.sample_app.weekly_sub.
  • jeton: Jeton de transaction unique. Il apparaît une fois que l'achat est traité du côté de l'application mobile.

Tout d'abord, examinons les messages d'erreur dont vous devez tenir compte pour vous assurer que tout fonctionne comme prévu :

  • 400, Invalid grant: account not found: Ce message d'erreur signifie que la clé d'authentification de la demande a été générée de manière incorrecte. Assurez-vous que vos comptes sont liés, que vous utilisez le bon qui dispose de suffisamment de permissions et que toutes les API requises sont activées. Voir la section ci-dessous pour un guide sur la façon de tout configurer. Remarquez le conseil sur la mise à jour de la description du produit.
  • 400, The purchase token does not match the package name:  Ce message d'erreur est généralement rencontré lors de transactions frauduleuses. Si vous le voyez pendant le test, assurez-vous que vous n'utilisez pas un jeton d'achat d'application qui appartient à une autre application.
  • 403, Quota exceeded for quota metric 'Queries' and limit 'Queries per day' of service 'androidpublisher.googleapis.com': Cela signifie que le quota quotidien de demandes d'API Google a été dépassé. Par défaut, vous pouvez exécuter  jusqu'à 200 000 requêtes par jour. Ce quota peut être augmenté, mais il devrait suffire pour la plupart des applications. Si vous vous heurtez à cette limite, vous devriez probablement revérifier la logique de votre application et vous assurer que tout est correct.
  • 410, The subscription purchase is no longer available for query because it has been expired for too long: Ce message d'erreur apparaît dans les transactions où l'abonnement a expiré depuis plus de 60 jours. Il ne s'agit pas d'un véritable message d'erreur et ne doit pas être traité comme tel.
Start for free

You don't need to write server code yourself,

because we did it for you. Try Adapty SDK!

Start for free

Transaction d'abonnement : 

Si la validation a réussi, vous recevrez  les données de la transaction comme réponse.

Données de transaction (pour un abonnement) :

{
    "expiryTimeMillis": "1631116261362",
    "paymentState": 1,
    "acknowledgementState": 1,
    "kind": "androidpublisher#subscriptionPurchase",
    "orderId": "GPA.3382-9215-9042-70164",
    "startTimeMillis": "1630504367892",
    "autoRenewing": true,
    "priceCurrencyCode": "USD",
    "priceAmountMicros": "1990000",
    "countryCode": "US",
    "developerPayload": ""
}

Pour savoir si l'utilisateur peut accéder aux options premium proposées par l'application - c'est-à-dire s'il dispose d'un abonnement actif - vous devez :

  1. Vérifiez les paramètres startTimeMillis et expiryTimeMillis. L'heure actuelle doit se situer entre ces deux valeurs.
  2. De plus, vous devez vous assurer que le paramètre paymentState n'a pas la valeur '0'. Cela signifie que l'achat de l'abonnement est toujours en cours et qu'il n'est donc pas nécessaire d'accorder à l'utilisateur l'accès à la fonction premium pour le moment. 
  3. Si la transaction possède la propriété autoResumeTimeMillis, l'abonnement est mis en pause. Cela signifie que l'utilisateur ne doit pas se voir accorder l'accès à la fonction premium avant la date spécifiée.

Voyons les principales propriétés d'une transaction d'abonnement :

  • Type: Type de transaction. Pour l'abonnement, il a toujours la valeur androidpublisher#subscriptionPurchase. Grâce à ce paramètre, vous pouvez comprendre si vous avez affaire à un abonnement ou à un produit, et choisir la logique de traitement en conséquence.
  • paymentState: Statut du paiement. Cette propriété n'est pas présente pour les transactions expirées. Les valeurs possibles sont:
    0: Cet achat n'a pas encore été traité. Dans certains pays, l'utilisateur peut payer l'abonnement sur place. En d'autres termes, l'utilisateur déclenchera l'achat de l'abonnement depuis son appareil et le paiera à un terminal situé à proximité. Dans l'ensemble, il s'agit d'un cas assez rare, mais il faut tout de même le garder à l'esprit.

    1: L'abonnement a été acheté.
    2: L'abonnement est dans la période d'essai.
    3: L'abonnement sera revu à la hausse ou à la baisse au cours de la prochaine période. Cela signifie que le plan d'abonnement va changer.
  • acknowledgementState: Statut de la confirmation d'achat. Il s'agit d'un paramètre important qui permet de savoir si l'utilisateur a reçu l'accès à ce pour quoi il a payé. La valeur "0" signifie qu'ils ne l'ont pas fait, et "1" qu'ils l'ont fait. Le développeur est chargé de définir ce statut, ce qui peut être fait à la fois du côté de l'application mobile et du côté du serveur. Si vous n'accusez pas réception de l'achat dans les 3 jours suivant sa réalisation, il sera automatiquement remboursé. Je recommande d'implémenter cette logique : dès que vous recevez une transaction contenant acknowledgementState=0, le paramètre est modifié par le serveur. Je vous dirai comment faire ci-dessous. 
  • orderId: Identifiant unique de la transaction. Chaque achat ou renouvellement d'abonnement aura son propre identifiant, qui pourra être utilisé pour savoir si cette transaction a déjà été traitée précédemment. Chaque identifiant de renouvellement aura une première moitié constante, à laquelle seront ajoutés deux points et le nombre de renouvellements d'abonnement (subscription renewal) (qui commence par 0). Si l'abonnement avait l'identifiant GPA.3382-9215-9042-70164 lors de son activation, alors le premier renouvellement sera identifié par GPA.3382-9215-9042-70164..0, le second par GPA.3382-9215-9042-70164..1, etc. De cette façon, vous pouvez construire des chaînes de transactions et suivre le nombre de renouvellements.
  • startTimeMillis: Date de début de l'abonnement.
  • expiryTimeMillis: Date d'expiration de l'abonnement.
  • autoRenewing: Drapeau indiquant si l'abonnement doit être renouvelé ou non pour la période suivante.
  • priceCurrencyCode: Devise d'achat dans un format à trois lettres, par exemple, USD.
  • priceAmountMicros: Prix d'achat. Pour obtenir la valeur du prix normal, divisez cette valeur par 1000000. C’est-à-dire, 1990000 signifie en fait 1,99. 
  • countryCode: Pays d'achat au format à deux lettres, par exemple, US.
  • purchaseType: Type d'achat. Cette clé ne sera pas présente dans la plupart des cas. Il est toujours important de le prendre en compte, car il vous aide à comprendre si l'achat a été effectué dans un environnement Sandbox. Les valeurs possibles sont :

    0: L'achat a été effectué dans un environnement Sandbox, par conséquent, il ne devrait pas être inclus dans les données d'analyse.
    1: L'achat a été effectué avec un code promo. 
  • autoResumeTimeMillis: Date de renouvellement de l'abonnement. Il n'est présent que pour les abonnements qui ont été précédemment mis en pause. Si ce paramètre est présent, il n'est pas nécessaire d'accorder à l'utilisateur l'accès à la fonction premium avant la date donnée.
  • cancelReason: La raison pour laquelle l'abonnement ne sera pas renouvelé. Les valeurs possibles sont :

    0: L'utilisateur a annulé le renouvellement automatique de l'abonnement.
    1: L'abonnement a été annulé par le système. Cela est le plus souvent dû à un problème de facturation.
    2: L'utilisateur est passé à une autre formule d'abonnement.
    3: Le développeur a annulé l'abonnement.
  • userCancellationTimeMillis: Données relatives à l'annulation du renouvellement de l'abonnement. Il n'est présent que si cancelReason est égal à 0. L'abonnement peut encore être actif - pour s'en assurer, consultez la valeur du paramètre expiryTimeMillis.
  • cancelSurveyResult: Objet qui stocke la raison de l'annulation de l'abonnement (subscription cancellation), qui sera présente si l'utilisateur a laissé un commentaire à ce sujet.
  • introductoryPriceInfo: Objet qui stocke les données sur les prix de lancement. Par exemple, il peut s'agir d'une offre spéciale d'un mois avec 50% de réduction.
  • promotionType: Type de code promotionnel qui a été utilisé pour activer l'abonnement. Les valeurs possibles sont :

    0: Code promo unique.
    1 :
    Code promo personnalisé qui peut être appliqué par plusieurs clients. Ces codes sont généralement utilisés pour les partenariats avec les blogueurs. 
  • promotionCode: Code promo personnalisé qui a été utilisé pour activer l'abonnement. Ce paramètre n'est pas présent pour les codes promotionnels uniques. 
  • priceChange: Objet qui stocke les données relatives aux futurs changements de prix, ainsi que l'accord éventuel de l'utilisateur. 

Accusé de réception de l'abonnement

Comme il a déjà été mentionné ci-dessus, si l'abonnement n'est pas confirmé dans les 3 jours suivant l'achat, il sera annulé et remboursé automatiquement. Pour être honnête, je ne comprends pas vraiment la logique qui se cache derrière, et je n'ai jamais rencontré ce problème dans aucun autre système de traitement des paiements, y compris celui d'iOS. Néanmoins, si vous recevez une transaction contenant acknowledgementState=0, vous devez accuser réception de l'abonnement.

Pour ce faire, vous devez invoquer la méthode purchases.subscriptions.acknowledge. Cette méthode exécute une requête POST

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/subscriptions/{subscriptionId}/tokens/{token}:acknowledge

Les paramètres sont identiques à ceux de la validation des requêtes. Si la requête est exécutée avec succès, l'abonnement sera acquitté, ce qui signifie que vous ne perdrez pas votre argent. 

Si l’abonnement n’a pas encore été entièrement acheté, il n’est pas nécessaire de le confirmer. 

Annulation, révocation, remboursement et report du renouvellement de l’abonnement

En plus de la validation et de la reconnaissance des abonnements, Google Play Developer API peut également être utilisé pour d’autres opérations d’abonnement. Il convient de noter que ceux-ci sont assez rares et, à l’exception du renouvellement, sont pris en charge par Google Play Console. Je vais quand même les énumérer pour vous donner une compréhension générale de la portée des solutions API. Toutes ces requêtes ont les mêmes paramètres requis que les méthodes mentionnées précédemment, à savoir, packageName, subscriptionId, et jeton.

  • Annulation du renouvellement (renewal cancellation). La méthode purchases.subscriptions.cancel. Elle annule le renouvellement automatique de l'abonnement sélectionné. Toutefois, l'abonnement restera disponible pendant toute la période de facturation en cours.
  • Remboursement de l'abonnement (subscription refund). La méthode purchases.subscriptions.refund. Il rembourse l'abonnement. Toutefois, l'utilisateur conservera l'accès à l'abonnement, qui sera automatiquement renouvelé à la période suivante. Dans la plupart des cas, vous devez également révoquer l'abonnement lorsque vous effectuez un remboursement.
  • Révocation de l'abonnement (subscription revocation). La méthode purchases.subscriptions.revoke. Il révoque immédiatement l'abonnement, ce qui signifie que l'utilisateur ne pourra pas accéder aux fonctions premium. L'abonnement ne sera pas renouvelé. Cette méthode est généralement invoquée en même temps que l'émission d'un remboursement.
  • Report de l'achat de l'abonnement (subscription purchase deferral). La méthode purchases.subscriptions.defer. Il prolonge l'abonnement jusqu'à la date spécifiée. Dans la demande, précisez la date d'expiration de l'abonnement, ainsi que la date par laquelle vous souhaitez le remplacer. Ce dernier point doit entraîner une période d'abonnement plus longue que le premier.

Validation du produit (et non de l'abonnement)

La validation du produit est similaire à la validation de l'abonnement. Vous devez invoquer la méthode purchases.products.get  pour exécuter la requête GET.

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}

Nous connaissons déjà tous ces paramètres grâce aux exemples présentés ci-dessus.

Données sur la transaction (pour un produit) :

{
  "purchaseTimeMillis": "1630529397125",
  "purchaseState": 0,
  "consumptionState": 0,
  "developerPayload": "",
  "orderId": "GPA.3374-2691-3583-90384",
  "acknowledgementState": 1,
  "kind": "androidpublisher#productPurchase",
  "regionCode": "RU"
}

Les transactions de produits  comprennent beaucoup moins de propriétés que les transactions d'abonnements. Examinons-en quelques-uns qui sont importants :

  • Type: Type de transaction. Dans les produits, il a toujours la valeur androidpublisher#productPurchase. Grâce à ce paramètre, vous pouvez comprendre si vous avez affaire à un abonnement ou à un produit, et choisir la logique de traitement en conséquence.
  • purchaseState: Statut de paiement. Notez que les valeurs clés ici sont différentes du paramètre paymentState pour les abonnements. Les valeurs possibles sont :
    0: L'achat a été effectué.
    1: L'achat a été annulé. Cela signifie que l'achat était en attente, mais que l'utilisateur ne l'a jamais payé.
    2: L'achat est en cours. Dans certains pays, l'utilisateur peut payer l'abonnement sur place. En d'autres termes, l'utilisateur déclenchera l'achat de l'abonnement depuis son appareil et le paiera à un terminal situé à proximité. Dans l'ensemble, il s'agit d'un cas assez rare, mais il faut tout de même le garder à l'esprit.
  • acknowledgementState: Statut de la confirmation d'achat. Il s'agit d'un paramètre important qui permet de savoir si l'utilisateur a reçu l'accès à ce pour quoi il a payé. La valeur "0" signifie qu'ils ne l'ont pas fait, et "1" qu'ils l'ont fait. Le développeur est chargé de définir ce statut, ce qui peut être fait à la fois du côté de l'application mobile et du côté du serveur. Si vous n'accusez pas réception de l'achat dans les 3 jours suivant sa réalisation, il sera automatiquement remboursé. Je recommande d'implémenter cette logique : dès que vous recevez une transaction contenant acknowledgementState=0, le paramètre est modifié par le serveur. Je vous expliquerai plus loin comment le faire. 
  • consumptionState: État de la consommation du produit. C'est ce qu'iOS appelle un "consommable". Il est défini du côté de l'application mobile. S'il a la valeur "0", cela signifie que le produit n'a pas été consommé ; s'il a la valeur "1", alors il l'a été. Si vous vendez un accès à vie à votre application ou une fonction premium spécifique, alors un tel produit ne devrait pas être consommé, c'est-à-dire qu'il devrait avoir le statut 0. Si vous vendez des pièces que l'utilisateur peut acheter à plusieurs reprises, ces produits doivent être consommés, c'est-à-dire qu'ils doivent avoir le statut 1. consumptionState=0 signifie que le produit ne peut être acheté qu'une seule fois, tandis que consumptionState=1 signifie qu'il peut être acheté plusieurs fois.
  • orderId: Identifiant unique de la transaction. Chaque achat ou renouvellement d'abonnement aura son propre identifiant, qui pourra être utilisé pour savoir si cette transaction a déjà été traitée précédemment.
  • purchaseTimeMillis: Date d'achat.
  • regionCode: Pays d'achat au format à deux lettres, par exemple, US. Notez que le nom de ce paramètre est différent de celui utilisé dans les abonnements, où il s'appelle countryCode. 
  • purchaseType: Type d'achat. Cette clé ne sera pas présente dans la plupart des cas. Il est toujours important de le prendre en compte, car il vous aide à comprendre si l'achat a été effectué dans un environnement Sandbox. Les valeurs possibles sont :
    0: L'achat a été effectué dans un environnement Sandbox, par conséquent, il ne devrait pas être inclus dans les données d'analyse.
    1: L'achat a été effectué avec un code promo.
    2 : L'achat a été accordé pour une action cible, par exemple regarder une publicité intégrée à l'application à la place du paiement.

Comme vous pouvez le constater, la validation du produit est assez similaire à la validation de l'abonnement. Il y a cependant quelques points à noter :

  • La somme n'est pas restituée, bien que cela soit très pratique pour l'analyse.
  • Les valeurs du paramètre purchaseState sont sensiblement différentes des valeurs du paramètre paymentState que l'on trouve dans les abonnements. Il provoquera des bugs s'il n'est pas pris en compte. 
  • regionCode est renvoyé, même s'il s'agit de countryCode pour les abonnements.

Tout comme les achats d'abonnements, les achats de produits doivent faire l'objet d'un accusé de réception. Pour ce faire, invoquez la méthode purchases.products.acknowledge qui exécutera une requête POST

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}:acknowledge

Si l'achat n'a pas encore été effectué, il n'est pas nécessaire de le reconnaître.

Suivi des remboursements pour les abonnements et les produits

Une analyse de haute qualité est impossible sans tenir compte des remboursements. Malheureusement, les données de remboursement ne sont pas présentes dans la transaction et ne sont pas signalées comme un événement distinct, comme c'est le cas dans iOS. Pour recevoir la liste des transactions remboursées, vous devrez invoquer la liste purchases.voidedpurchases.list  régulièrement - par exemple, une fois par jour. Cette méthode permet d'exécuter une requête GET :

https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/voidedpurchases

En réponse à la demande, vous recevrez la liste de toutes les transactions remboursées. Je recommande de rechercher les transactions dans la base de données par le paramètre orderId, plutôt que par le paramètre purchaseToken. Premièrement, cela prendra moins de temps. Ensuite, tous les renouvellements d'abonnement partageront le même jeton, et il vous suffira de récupérer le plus récent.

Notifications du serveur pour les transactions

Les notifications du serveur  (notifications de développeur en temps réel) vous permettent de connaître les événements qui se sont produits du côté de Google, sur votre serveur, et presque en direct. Une fois ceux-ci configurés, vous serez informé des nouveaux achats, des renouvellements, des problèmes de paiement, etc. Cela peut vous aider à collecter de meilleures analyses, ainsi qu'à faciliter la gestion du statut des abonnés.

Pour commencer à recevoir les notifications du serveur, vous devez créer un sujet Google Cloud Pub/Sub, qui enverra les notifications à l'adresse souhaitée. Cette rubrique doit ensuite être indiquée dans la section Configuration de la monétisation de  Google Play Console. Pour un guide détaillé avec des captures d'écran, voir Adapty docs

Notification du serveur :

{
  "message": {
    "data": "eyJ2ZXJzaW9uIjoiMS4wIiwicGFja2FnZU5hbWUiOiJjb20uYWRhcHR5LnNhbXBsZV9hcHAiLCJldmVudFRpbWVNaWxsaXMiOiIxNjMwNTI5Mzk3MTI1Iiwic3Vic2NyaXB0aW9uTm90aWZpY2F0aW9uIjp7InZlcnNpb24iOiIxLjAiLCJub3RpZmljYXRpb25UeXBlIjo2LCJwdXJjaGFzZVRva2VuIjoiY2o3anAuQU8tSjFPelIxMjMiLCJzdWJzY3JpcHRpb25JZCI6ImNvbS5hZGFwdHkuc2FtcGxlX2FwcC53ZWVrbHlfc3ViIn19",
    "messageId": "2829603729517390",
    "message_id": "2829603729517390",
    "publishTime": "2021-09-01T20:49:59.124Z",
    "publish_time": "2021-08-04T20:49:59.124Z"
  },
  "subscription": "projects/935083/subscriptions/adapty-rtdn"
}

Nous sommes surtout concernés par la clé de données qui contient les données de la transaction codées en base64. La clé messageId peut être utilisée pour la déduplication des messages, afin de ne pas avoir à traiter des messages en double. 

Voici une transaction dans une notification du serveur :

{
  "version": "1.0",
  "packageName": "com.adapty.sample_app",
  "eventTimeMillis": "1630529397125",
  "subscriptionNotification": {
    "version": "1.0",
    "notificationType": 6,
    "purchaseToken": "cj7jp.AO-J1OzR123",
    "subscriptionId": "com.adapty.sample_app.weekly_sub"
  }
}

La clé packageName vous aide à comprendre à quelle application appartient cet événement. La clé subscriptionId vous indique quel abonnement est concerné, et purchaseToken vous aide à trouver la transaction spécifique. Avec les abonnements, vous recherchez toujours la dernière transaction de la chaîne de renouvellement, car c'est celle à laquelle appartient cet événement. La clé notificationType contient le type d'événement. À mon avis, ce sont les plus pratiques pour les abonnements:

  • (2) SUBSCRIPTION_RENEWED: L'abonnement a été renouvelé avec succès.
  • (3) SUBSCRIPTION_CANCELED: L'utilisateur a désactivé le renouvellement automatique de l'abonnement. Si le renouvellement automatique est désactivé, vous devrez essayer de faire revenir l'utilisateur en tant qu'abonné actif.
  • (5) SUBSCRIPTION_ON_HOLD, (6) SUBSCRIPTION_IN_GRACE_PERIOD: L'abonnement n'a pas pu être renouvelé en raison de problèmes de paiement. Vous devez en informer l'utilisateur afin que son abonnement ne soit pas annulé automatiquement.
  • (12) SUBSCRIPTION_REVOKED: l'abonnement a été révoqué. Cela signifie que l'utilisateur devrait perdre l'accès aux fonctions premium précédemment accordées par l'abonnement. 

Dans les produits (pas les abonnements), vous recevrez oneTimeProductNotification à la place de la clé subscriptionNotification. Il contiendra également la clé sku au lieu de la clé subscriptionId. En outre, vous ne recevrez jamais que deux types d'événements pour les produits :

  • (1) ONE_TIME_PRODUCT_PURCHASED: Achat réussi du produit.
  • (2) ONE_TIME_PRODUCT_CANCELED: L'achat du produit a été annulé, car l'utilisateur ne l'avait pas payé.

Conclusion

La validation côté serveur permet d'optimiser les données analytiques que vous pourrez collecter pour votre application. Elle rend plus difficile l'accès au contenu premium pour les fraudeurs et peut être utilisée pour mettre en place des abonnements multiplateformes. Cependant, la validation côté serveur peut prendre un certain temps à mettre en œuvre, surtout si une grande précision des données est nécessaire. Pour fournir des données de haute qualité, vous devez tenir compte d'une multitude de cas particuliers, tels que les mises à niveau d'abonnement, les déclassements d'abonnement, les périodes d'essai, les offres promotionnelles et de lancement, les délais de grâce, les remboursements, etc. Vous devez également connaître et prendre en compte tous les détails de la politique, comme le fait que Google ne prélève qu'une commission de 15 % (au lieu de 30 %) sur les abonnements renouvelés pour plus d'un an.

Further reading

How to get paid subscribers for your app: The top reasons mobile app users go from freemium to premium
How to get paid subscribers for your app: The top reasons mobile app users go from freemium to premium
September 15, 2022
15 min read
Why is everyone wrong about unit economics
Why is everyone wrong about unit economics
August 4, 2022
56 min listen
Adapty September Update: A/B Tests versions, Home, CSV Export
Adapty September Update: A/B Tests versions, Home, CSV Export
October 4, 2021
3 min read