À propos des abonnements

Cet article explique comment gérer les événements du cycle de vie des abonnements, tels que les renouvellements et les expirations. Il décrit également d'autres fonctionnalités d'abonnement, comme offrir des promotions et permettre aux utilisateurs de gérer leurs propres abonnements.

Si vous n'avez pas configuré de produits sur abonnement pour votre application, consultez Créer et configurer vos produits.

Aperçu des abonnements

Un abonnement représente un ensemble d'avantages auxquels les utilisateurs peuvent accéder pendant une période donnée. Il peut, par exemple, donner à un utilisateur l'accès à un service de streaming musical.

Plusieurs abonnements peuvent être proposés dans la même application, soit pour représenter des avantages complètement différents, soit pour différents niveaux d'un même ensemble d'avantages (niveaux "Silver" ou "Gold", par exemple).

Grâce aux forfaits de base et aux offres, plusieurs configurations sont possibles pour le même produit sur abonnement. Par exemple, vous pouvez créer une offre de bienvenue pour les utilisateurs qui ne se sont jamais abonnés à votre application. Parallèlement, vous pouvez créer une offre de mise à niveau pour les utilisateurs déjà abonnés.

Pour découvrir une présentation détaillée des produits sur abonnement, des forfaits de base et des offres, consultez la documentation correspondante dans le Centre d'aide de la Play Console.

Intégration des forfaits prépayés

Les forfaits prépayés ne sont pas renouvelés automatiquement à l'expiration. Pour prolonger l'accès à son abonnement sans interruption, l'utilisateur doit recharger son forfait prépayé pour le même abonnement.

Pour les recharges de forfait, lancez le processus de facturation comme vous le feriez avec l'achat d'origine. Vous n'avez pas besoin d'indiquer que l'achat correspond ici à une recharge de forfait.

Les recharges de forfait prépayé utilisent toujours le mode de remplacement CHARGE_FULL_PRICE, et vous n'avez pas besoin de définir ce mode explicitement. L'utilisateur paie immédiatement pour une période de facturation complète, et son droit d'accès est prolongé pour la durée spécifiée dans la recharge.

Après une recharge, les champs suivants de l'objet de résultat Purchase sont mis à jour pour refléter l'achat de la recharge de forfait la plus récente :

  • ID de commande
  • Heure d'achat
  • Signature
  • Jeton d'achat
  • Confirmation

Les champs Purchase suivants contiennent toujours les mêmes données que celles de l'achat d'origine :

  • Nom du package
  • État de l'achat
  • Produits
  • Renouvellement automatique

Confirmation d'achat prépayé

Comme pour les abonnements à renouvellement automatique, vous devez confirmer les forfaits prépayés après l'achat. L'achat initial et les recharges de forfait doivent être confirmés. Pour en savoir plus, consultez Traiter les achats.

En raison de la courte durée des forfaits prépayés, il est important de confirmer l'achat dès que possible.

Les forfaits prépayés d'une durée minimale d'une semaine doivent être confirmés dans un délai de trois jours.

Les forfaits prépayés d'une durée inférieure à une semaine doivent être confirmés dans un délai correspondant à la moitié de la durée du forfait. Par exemple, les développeurs ont 1,5 jour pour confirmer un forfait prépayé de trois jours.

Permettre aux utilisateurs de gérer un abonnement à l'aide de liens profonds

Votre application doit inclure un lien sur un écran de paramètres ou de préférences permettant aux utilisateurs de gérer leurs abonnements, que vous pouvez intégrer à l'apparence naturelle de votre application.

Vous pouvez inclure un lien profond depuis votre application vers le centre des abonnements Google Play pour les abonnements n'ayant pas expiré. Vous pouvez le déterminer à l'aide du champ subscriptionState de la ressource d'abonnement. Par conséquent, il existe plusieurs façons de créer des liens profonds vers le centre des abonnements du Play Store.

Utilisez l'URL suivante pour rediriger les utilisateurs vers la page répertoriant tous leurs abonnements, comme illustré dans les figures 1 et 2 :

https://play.google.com/store/account/subscriptions
L'écran des abonnements du Play Store indique l'état de tous les abonnements d'un utilisateur facturés par Google Play.
Figure 1. L'écran des abonnements du Play Store indique l'état de tous les abonnements d'un utilisateur facturés par Google Play.


Appuyez sur un abonnement pour afficher des informations supplémentaires.
Figure 2. Appuyez sur un abonnement pour afficher des informations supplémentaires.

Ce lien profond permet d'aider un utilisateur à restaurer un abonnement résilié à partir du centre des abonnements du Play Store.

Pour créer un lien direct vers la page de gestion d'un abonnement non expiré, indiquez le nom du package et l'élément productId associés à l'abonnement acheté. Pour déterminer de manière programmatique le productId d'un abonnement existant, interrogez le backend de votre application ou appelez BillingClient.queryPurchasesAsync() afin d'obtenir la liste des abonnements associés à un utilisateur particulier. Chaque abonnement contient le productId correspondant dans les informations d'état de l'abonnement. Chaque objet SubscriptionPurchaseLineItem associé à l'achat d'un abonnement contient la valeur productId associée à l'abonnement que l'utilisateur a acheté sur cette ligne.

Utilisez l'URL suivante pour rediriger les utilisateurs vers un écran de gestion des abonnements spécifique, en remplaçant "your-sub-product-id" et "your-app-package" respectivement par productId et le nom du package de l'application :

https://play.google.com/store/account/subscriptions?sku=your-sub-product-id&package=your-app-package

L'utilisateur peut ensuite gérer ses modes de paiement et accéder à des fonctionnalités telles que la résiliation, le réabonnement et la suspension.

Autoriser les utilisateurs à passer à un forfait supérieur ou inférieur, ou à changer d'abonnement

Vous pouvez proposer aux abonnés existants diverses options pour modifier leur abonnement afin de mieux répondre à leurs besoins :

  • Si vous vendez plusieurs niveaux d'abonnement, tels que des abonnements de base et premium, vous pouvez permettre aux utilisateurs de changer de niveau en achetant un autre forfait de base ou une autre offre.
  • Vous pouvez autoriser les utilisateurs à modifier leur période de facturation actuelle, par exemple en passant d'un forfait mensuel à un forfait annuel.
  • Vous pouvez également autoriser les utilisateurs à basculer entre le forfait à renouvellement automatique et le forfait prépayé.

Vous pouvez encourager chacun de ces changements en proposant des offres d'abonnement afin d'offrir une remise aux utilisateurs éligibles. Par exemple, vous pouvez créer une offre proposant une remise de 50 % la première année lors du passage d'un forfait mensuel à un forfait annuel, et la limiter aux utilisateurs abonnés à un forfait mensuel qui n'ont pas acheté cette offre. Pour en savoir plus sur les critères d'éligibilité des offres, consultez le centre d'aide.

La figure 3 illustre un exemple d'application avec trois forfaits différents :

Cette application comporte trois niveaux d'abonnement.
Figure 3. Cette application comporte trois niveaux d'abonnement.

Votre application peut afficher un écran semblable à la figure 3, offrant aux utilisateurs la possibilité de modifier leur abonnement. Dans tous les cas, l'abonnement actuel des utilisateurs et les options dont ils disposent pour le modifier doivent être clairement indiqués.

Lorsque les utilisateurs décident de changer d'abonnement, ou de passer à un forfait supérieur ou inférieur, vous spécifiez un mode de remplacement qui détermine le montant au prorata de la période de facturation en cours et le moment où tout droit d'accès est modifié.

Modes de remplacement

Le tableau suivant répertorie les modes de remplacement disponibles et fournit des exemples d'utilisation.

Mode de remplacement

Description

Exemples d'utilisation

WITH_TIME_PRORATION

L'abonnement passe à un forfait supérieur ou inférieur immédiatement. Le temps restant est ajusté en fonction de la différence de prix, puis crédité sur le nouvel abonnement en repoussant la date de facturation suivante. Il s'agit du comportement par défaut.

Passer à un niveau plus cher, sans paiement supplémentaire immédiat.

CHARGE_PRORATED_PRICE

L'abonnement passe à un niveau supérieur immédiatement, et le cycle de facturation reste le même. La différence de prix pour la période restante est ensuite facturée à l'utilisateur.

Remarque : Cette option n'est disponible que pour le passage à un abonnement de niveau supérieur, où le prix par unité de temps augmente.

Passer à un niveau plus cher, sans modifier la date de facturation.

CHARGE_FULL_PRICE

L'abonnement passe immédiatement au forfait supérieur ou inférieur, et l'utilisateur paie immédiatement le tarif complet du nouveau forfait. La valeur restante de l'abonnement précédent est transférée sur le nouveau forfait ou calculée au prorata de la durée restante au moment du changement de forfait.

Remarque : Si le nouvel abonnement inclut une offre d'essai sans frais ou une offre découverte, l'utilisateur est facturé 0 $ ou le prix de l'offre découverte (selon le cas), au moment du passage au niveau supérieur ou inférieur.

Passer d'une période de facturation plus courte à une période de facturation plus longue.

WITHOUT_PRORATION

L'abonnement passe immédiatement à un forfait supérieur ou inférieur, et le nouveau tarif est facturé lors du renouvellement de l'abonnement. Le cycle de facturation reste le même.

Passer à un niveau d'abonnement supérieur tout en conservant la période sans frais restante.

DEFERRED

L'abonnement ne passe à un forfait supérieur ou inférieur qu'au moment du renouvellement de l'abonnement. Toutefois, le nouvel achat est immédiatement émis avec une date de début ultérieure pour le nouveau droit d'accès. Le développeur peut ainsi autoriser les utilisateurs à apporter des modifications supplémentaires s'ils le souhaitent. Par exemple, il peut revenir au plan d'origine ou initier une nouvelle modification de plan différée.

Revenir à un niveau d'abonnement moins cher.

Pour en savoir plus sur les différentes applications de vente incitative et de récupération des offres de niveau supérieur ou inférieur, consultez le guide des offres et des promotions.

Définir le mode de remplacement pour un achat

Vous pouvez utiliser différents modes de remplacement pour différents types de transitions d'abonnements, en fonction de vos préférences et de la logique métier. Cette section explique comment définir un mode de remplacement en cas de modification d'un abonnement et les limites qui s'appliquent.

Se réabonner ou changer de forfait dans le même abonnement

Vous pouvez spécifier un mode de remplacement par défaut dans la Google Play Console. Ce paramètre vous permet de choisir à quel moment facturer les abonnés actuels s'ils achètent un autre forfait de base ou une autre offre pour le même abonnement, ou s'ils se réabonnent après une résiliation. Les options disponibles sont Facturer immédiatement (qui équivaut à CHARGE_FULL_PRICE) et Facturer à la prochaine date de facturation (qui équivaut à WITHOUT_PRORATION). Il s'agit des seuls modes de remplacement pertinents lorsque vous changez de forfait de base dans le même abonnement.

Par exemple, si vous implémentez une offre de récupération pour le même forfait après la résiliation de l'utilisateur, mais avant la fin de l'abonnement, vous pouvez traiter le nouvel achat comme un achat standard sans indiquer de valeur dans SubscriptionUpdateParams. Le système utilise le mode de remplacement par défaut que vous avez configuré dans l'abonnement et gère automatiquement la transition du forfait de l'ancien achat au nouvel achat.

Changer de forfait ou ignorer le mode de remplacement par défaut

Si l'utilisateur change de produits d'abonnement ou achète un autre abonnement, ou si vous souhaitez ignorer le mode de remplacement par défaut pour une raison quelconque, vous devez spécifier le taux de calcul au prorata au moment de l'exécution dans les paramètres du parcours d'achat.

Pour renseigner correctement SubscriptionUpdateParams dans le cadre de la configuration de votre parcours d'achat au moment de l'exécution, tenez compte des restrictions suivantes :

  • En cas de passage à un abonnement de niveau supérieur ou inférieur, ou en cas de changement de forfait sans modifier le niveau de l'abonnement (passage d'un certain type de forfait prépayé à un autre ou d'un forfait à renouvellement automatique à un forfait prépayé), le seul mode de calcul au prorata autorisé est CHARGE_FULL_PRICE. Si vous spécifiez un autre mode de calcul au prorata, l'achat échoue, et une erreur s'affiche.
  • Lorsque vous passez d'un forfait du même abonnement à un forfait à renouvellement automatique à partir d'un forfait prépayé ou d'un forfait à renouvellement automatique, les modes de calcul au prorata valides sont CHARGE_FULL_PRICE et WITHOUT_PRORATION. Si vous spécifiez un autre mode de calcul au prorata, l'achat échoue, et une erreur s'affiche.

Exemples et comportements de remplacement

Pour comprendre le fonctionnement de chaque mode de calcul au prorata, prenons le scénario suivant :

Samuel a souscrit un abonnement au contenu en ligne de l'application Jardiniers en herbe. Il dispose d'un abonnement mensuel au niveau 1 dont le contenu se limite à du texte. Cet abonnement coûte 2 $ par mois. Il est renouvelé le premier du mois.

Le 15 avril, Samuel choisit de passer à la version annuelle de l'abonnement de niveau 2, qui inclut du contenu vidéo et coûte 36 $ par an.

Lors du changement d'abonnement, le développeur sélectionne un mode de calcul au prorata. La liste suivante décrit l'impact de chaque mode de calcul au prorata sur l'abonnement de Samuel :

WITH_TIME_PRORATION

L'abonnement au niveau 1 de Samuel prend fin immédiatement. Étant donné qu'il a payé pour un mois complet (du 1er au 30 avril), mais qu'il s'est abonné à un forfait supérieur en plein milieu de la période d'abonnement, 1 $ (qui correspond à la moitié restante du mois) est appliqué à son nouvel abonnement. Toutefois, comme ce nouvel abonnement coûte 36 $ par an, le solde de 1 $ ne couvre que 10 jours (du 16 au 25 avril). Par conséquent, le 26 avril, il sera facturé 36 $ pour le nouvel abonnement et 36 $ supplémentaires le 26 avril de chaque année par la suite.

Vous devez appeler le PurchasesUpdatedListener de votre application au moment où l'achat aboutit pour pouvoir le récupérer dans un appel queryPurchasesAsync(). Votre backend reçoit immédiatement une notification en temps réel pour les développeurs SUBSCRIPTION_PURCHASED.

CHARGE_PRORATED_PRICE

Ce mode peut être utilisé, car le prix par unité de temps de l'abonnement de niveau 2 (36 $/an = 3 $/mois) est supérieur à celui du niveau 1 (2 $/mois). L'abonnement au niveau 1 de Samuel prend fin immédiatement. Étant donné qu'il a payé un mois complet, mais n'en a utilisé que la moitié, le montant équivalant à la moitié restante (1 $) est appliqué à son nouvel abonnement. Toutefois, comme ce nouvel abonnement coûte 36 $/an, les 15 jours restants coûtent 1,50 $. La différence de 0,50 $ lui est donc facturée pour son nouvel abonnement. Le 1er mai, Samuel sera facturé 36 $ pour son nouveau niveau d'abonnement, et 36 $ supplémentaires le 1er mai de chaque année par la suite.

Vous devez appeler le PurchasesUpdatedListener de votre application au moment où l'achat aboutit pour pouvoir le récupérer dans un appel queryPurchasesAsync(). Votre backend reçoit immédiatement une notification en temps réel pour les développeurs SUBSCRIPTION_PURCHASED.

WITHOUT_PRORATION

L'abonnement au niveau 1 de Samuel est immédiatement remplacé par le niveau 2, sans frais supplémentaires. Le 1er mai, il est facturé 36 $ pour son nouvel abonnement et devra payer 36 $ supplémentaires le 1er mai de chaque année par la suite.

Vous devez appeler le PurchasesUpdatedListener de votre application au moment où l'achat aboutit pour pouvoir le récupérer dans un appel queryPurchasesAsync(). Votre backend reçoit immédiatement une notification en temps réel pour les développeurs SUBSCRIPTION_PURCHASED.

DEFERRED

L'abonnement au niveau 1 de Samuel continue jusqu'à son expiration le 30 avril. Le 1er mai, l'abonnement au niveau 2 prendra effet, et Samuel sera facturé 36 $ pour son nouveau niveau d'abonnement.

Vous devez appeler le PurchasesUpdatedListener de votre application au moment où l'achat aboutit pour pouvoir le récupérer dans un appel queryPurchasesAsync(). Votre backend reçoit immédiatement une notification en temps réel pour les développeurs SUBSCRIPTION_PURCHASED. Vous devez traiter l'achat de la même manière que tout autre nouvel achat à ce stade. Veillez tout particulièrement à confirmer le nouvel achat. Notez que la startTime du nouvel abonnement est renseignée au moment où le remplacement devient effectif, c'est-à-dire à l'expiration de l'ancien abonnement. Vous recevrez alors une notification en temps réel pour les développeurs SUBSCRIPTION_RENEWED pour le nouvel abonnement. Pour en savoir plus sur le comportement de ReplacementMode.DEFERRED, consultez la section Gérer les remplacements différés.

CHARGE_FULL_PRICE

L'abonnement au niveau 1 de Samuel prend fin immédiatement. Son abonnement au niveau 2 commence aujourd'hui, et il doit payer 36 $. Étant donné qu'il a payé un mois complet, mais n'en a utilisé que la moitié, le montant équivalant à la moitié restante (1 $) est appliqué à son nouvel abonnement. Comme ce nouvel abonnement coûte 36 $/an, il reçoit 1/36e d'année en plus de sa période d'abonnement (ce qui correspond à environ 10 jours). La prochaine facture de Samuel devra donc être payée dans un an et 10 jours à partir d'aujourd'hui pour un montant de 36 $. Ensuite, il sera facturé 36 $ chaque année.

Lorsque vous choisissez un mode de calcul au prorata, veillez à consulter nos recommandations de remplacement.

Déclencher des modifications d'abonnements dans l'application

Votre application peut proposer aux utilisateurs de changer de niveau d'abonnement en suivant la même procédure que pour le lancement d'un parcours d'achat. Toutefois, lors du passage à un niveau supérieur ou inférieur, vous devez fournir des informations sur l'abonnement actuel, l'abonnement futur (niveau supérieur ou inférieur) et le mode de remplacement à utiliser, comme illustré dans l'exemple suivant :

Kotlin

val offerToken = productDetails
        .getSubscriptionOfferDetails(selectedOfferIndex)
        .getOfferToken()

val billingParams = BillingFlowParams.newBuilder().setProductDetailsParamsList(
       listOf(
           BillingFlowParams.ProductDetailsParams.newBuilder()
               .setProductDetails(productDetails)
               .setOfferToken(offerToken)
               .build()
       )
       ).setSubscriptionUpdateParams(
           BillingFlowParams.SubscriptionUpdateParams.newBuilder()
               .setOldPurchaseToken("old_purchase_token")
               .setSubscriptionReplacementMode(
                 BillingFlowParams.ReplacementMode.CHARGE_FULL_PRICE
               )
               .build()
       ).build()

billingClient.launchBillingFlow(
    activity,
    billingParams
   )
// ...

Java

String offerToken = productDetails
    .getSubscriptionOfferDetails(selectedOfferIndex)
    .getOfferToken();

BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
    .setProductDetailsParamsList(
        ImmuableList.of(
            ProductDetailsParams.newBuilder()
                // fetched via queryProductDetailsAsync
                .setProductDetails(productDetails)
                // offerToken can be found in
                // ProductDetails=>SubscriptionOfferDetails
                .setOfferToken(offerToken)
                .build()))
    .setSubscriptionUpdateParams(
        SubscriptionUpdateParams.newBuilder()
            // purchaseToken can be found in Purchase#getPurchaseToken
            .setOldPurchaseToken("old_purchase_token")
            .setSubscriptionReplacementMode(ReplacementMode.CHARGE_FULL_PRICE)
            .build())
    .build();

BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
// ...

Recommandations de remplacement

Le tableau suivant présente les différents scénarios de calcul au prorata, ainsi que des recommandations pour chacun d'eux :

Scénario Mode de remplacement recommandé Résultat
Passer à un niveau d'abonnement plus cher CHARGE_PRORATED_PRICE L'utilisateur reçoit l'accès immédiatement tout en conservant la même période de facturation.
Passer à un niveau d'abonnement moins cher DEFERRED L'utilisateur a déjà payé le niveau supérieur, qui est plus cher. Il conserve donc son accès jusqu'à la prochaine date de facturation.
Passer à un niveau d'abonnement supérieur pendant un essai sans frais et conserver l'essai sans frais WITHOUT_PRORATION L'utilisateur conserve l'accès à l'essai sans frais, mais passe à un niveau supérieur jusqu'à la fin de l'essai.
Passer à un niveau d'abonnement supérieur pendant un essai sans frais avec résiliation de l'essai sans frais CHARGE_PRORATED_PRICE L'utilisateur a immédiatement accès au nouveau niveau, mais ne bénéficie plus d'un essai sans frais.

Gérer les achats de changement d'abonnement

Les changements d'abonnement sont de nouveaux achats pour toutes les conditions d'utilisation. Ils doivent être traités et confirmés comme tels une fois le flux de facturation terminé. En plus de traiter le nouvel achat de manière appropriée, vous devez annuler l'achat remplacé.

Le comportement dans l'application est le même que pour tout nouvel achat. Votre application reçoit le résultat du nouvel achat dans votre PurchasesUpdatedListener, et le nouvel achat est disponible dans queryPurchasesAsync.

L'API Google Play Developer renvoie un linkedPurchaseToken dans la ressource d'abonnement lorsqu'un achat remplace un achat existant. Veillez à invalider le jeton fourni dans linkedPurchaseToken afin que l'ancien jeton ne soit pas utilisé pour accéder à vos services. Consultez Changements de niveau d'abonnement et réinscriptions pour en découvrir comment gérer les changements de niveau d'abonnement.

Lorsque vous recevez le jeton d'achat, suivez le même processus de validation qu'avec un nouveau jeton. Confirmez ces achats avec BillingClient.acknowledgePurchase() depuis la bibliothèque Google Play Billing ou avec Purchases.subscriptions:acknowledge depuis l'API Google Play Developer.

Gérer les remplacements différés

Le mode de remplacement différé vous permet de permettre à un utilisateur d'épuiser les droits d'accès restants de son ancien abonnement avant de passer au nouveau.

Lorsque vous utilisez ReplaceMode.DEFERRED pour un nouvel achat, queryPurchasesAsync() renvoie un nouveau jeton d'achat, après le parcours d'achat, qui reste associé à l'ancien produit jusqu'à ce que le remplacement différé ait lieu à la prochaine date de renouvellement, après quoi le nouveau produit est renvoyé.

Auparavant, vous pouviez offrir cette expérience utilisateur avec le ProrationMode.DEFERRED. Toutefois, ProrationMode.DEFERRED est obsolète avec la bibliothèque Play Billing 6. Consultez le tableau suivant pour comprendre les différences entre les comportements :

Durée

ProrationMode.DEFERRED (obsolète)

ReplacementMode.DEFERRED

Immédiatement après la réussite du parcours d'achat (application)

PurchasesUpdatedListener est appelé après l'achat, et son état indique si le passage au niveau d'abonnement supérieur ou inférieur a réussi.

Le droit à l'ancien abonnement continue jusqu'à la prochaine date de renouvellement. Pour vous assurer que l'application accorde les droits d'accès appropriés, queryPurchasesAsync() renvoie un objet "Purchase" avec le jeton d'achat d'origine et les droits d'accès d'origine jusqu'à ce que le remplacement ait lieu.

Le nouveau jeton d'achat n'est pas affiché. Il ne peut donc pas être traité à ce stade.

PurchasesUpdatedListener est appelé après l'achat, et son état indique si le passage au niveau d'abonnement supérieur ou inférieur a réussi.

queryPurchasesAsync() renvoie immédiatement l'achat avec le nouveau jeton d'achat et le droit d'accès d'origine qui lui est associé.

Le nouveau jeton d'achat apparaît. Il doit donc être traité à ce stade, en tenant compte du moment où le remplacement doit avoir lieu.

Immédiatement après la réussite du parcours d'achat (backend)

La notification en temps réel pour les développeurs SUBSCRIPTION_PURCHASED n'est pas envoyée après le parcours d'achat. Le backend n'est pas encore informé du nouvel achat.

La notification en temps réel pour les développeurs SUBSCRIPTION_PURCHASED avec l'ancien product_id est envoyée immédiatement après le parcours d'achat du nouveau jeton d'achat.

L'appel de la méthode purchases.subscriptionsv2.get avec le nouveau jeton d'achat renvoie un achat dont la valeur "startTime" indique l'heure d'achat avec deux lignes:

  • L'une représentant l'ancien droit d'accès et dotée d'un "expiryTime" à venir. L'ancien droit d'accès ne sera pas renouvelé et dispose d'un droit DeferredItemOverride, qui contient le produit du nouveau droit d'accès. Cela indique un remplacement en attente de l'ancien droit d'accès à son expiration.
  • L'autre représentant le droit d'accès tout juste acheté. Aucune valeur n'est définie pour "expiryTime".

SUBSCRIPTION_EXPIRED est envoyée pour l'ancien jeton d'achat. Lorsque vous appelez la méthode purchases.subscriptionsv2.get avec l'ancien jeton d'achat, il apparaît comme expiré (les droits d'accès de l'ancien forfait sont transférés vers le nouveau pour le temps restant).

Lors du remplacement : premier renouvellement après le parcours d'achat (application)

queryPurchasesAsync() renvoie un nouvel objet "Purchase" avec le nouveau jeton d'achat et les droits d'accès.

Le nouveau jeton d'achat est maintenant visible. Il doit donc être traité.

queryPurchasesAsync() renvoie immédiatement l'achat avec le nouveau jeton d'achat et le nouveau droit d'accès qui lui est associé.

Le nouvel achat devrait déjà avoir été traité au moment de la réussite du parcours d'achat. L'application ne doit donc effectuer aucune action spéciale, à part s'assurer que le droit d'accès approprié est accordé.

Lors du remplacement : premier renouvellement après le parcours d'achat (backend)

Le nouvel achat peut maintenant être traité et confirmé lors de l'envoi de la première notification en temps réel pour les développeurs SUBSCRIPTION_RENEWED.

Le jeton linkedPurchaseToken de la ressource d'abonnement peut servir à déterminer quel utilisateur, le cas échéant, doit recevoir le nouveau forfait dans votre backend d'abonnement.

Un nouvel achat a été traité et confirmé lorsque la notification en temps réel pour les développeurs SUBSCRIPTION_PURCHASED a été envoyée pour le nouveau jeton d'achat et enregistrée en tant que "startTime".

Avec ReplacementMode.DEFERRED, les premiers renouvellements suivent le comportement standard de tout autre renouvellement et vous n'avez pas besoin de gérer une logique spéciale pour les remplacements lorsque cet événement se produit.

Lorsque vous appelez la méthode purchases.subscriptionsv2.get avec le nouveau jeton d'achat, un achat est renvoyé avec deux lignes :

  • L'une représentant l'ancien droit d'accès, avec un "expiryTime" dans le passé et sans valeur définie pour DeferredItemOverride.
  • L'une représentant le nouveau droit d'accès, avec un "expiryTime" à venir et avec l'indicateur "auto_renewing_enabled" activé.

RemplacementMode.DEFERRED doit désormais être utilisé à la place du mode obsolète ProrationMode.DEFERRED, car il présente le même comportement en ce qui concerne les modifications des droits d'accès, mais offre une gestion de l'achat plus cohérente avec les comportements pour d'autres nouveaux achats.

Gestion des utilisateurs

Le recours à des notifications en temps réel pour les développeurs vous permet de détecter en temps réel quand un utilisateur décide de résilier son abonnement. Lorsque cela se produit avant l'expiration de son abonnement, vous pouvez lui envoyer des notifications push ou des messages dans l'application pour lui proposer de se réabonner.

Une fois qu'un utilisateur a résilié son abonnement, vous pouvez essayer de le reconquérir dans votre application ou sur le Play Store. Le tableau suivant décrit plusieurs scénarios d'abonnement, ainsi que les actions que vous pouvez effectuer pour convaincre l'utilisateur de se réabonner, ainsi que les conditions requises dans l'application.

Avant l'expiration de l'abonnement Après l'expiration de l'abonnement
Dans l'application Sur le Play Store Dans l'application Sur le Play Store
Fonctionnalité pour reconquérir les anciens abonnés Abonnement via l'application Restaurer Abonnement via l'application Se réabonner
L'utilisateur passe par le processus de paiement Oui Non Oui Oui
L'abonnement utilisateur reste associé au même SKU L'utilisateur peut s'inscrire avec un SKU identique ou différent Oui L'utilisateur peut s'inscrire avec un SKU identique ou différent Oui
Crée un jeton d'achat Oui Non Oui Oui
Activé par défaut Non Oui, prise en charge requise pour tous les développeurs Non

Applications sans bibliothèque Billing 2.0 ou version ultérieure : non

Applications avec la bibliothèque Billing 2.0 ou version ultérieure : oui. Les développeurs peuvent désactiver cette option dans la console.

Quand l'utilisateur est facturé

Si vous utilisez le même SKU : fin de la période de facturation en cours.

Si vous utilisez un autre SKU : dépend du mode de calcul au prorata.

Fin de la période de facturation en cours Immédiatement Immédiatement
Implémentation requise Fournir une UI de réinscription dans votre application

Détecter un changement d'état d'abonnement

Créer un lien profond vers le Play Store

Fournir une UI de réinscription dans votre application Gérer les achats hors application

Avant l'expiration de l'abonnement (dans l'application)

Pour les abonnements qui ont été résiliés, mais qui n'ont pas encore expiré, vous pouvez autoriser les abonnés à restaurer leur abonnement dans votre application en appliquant le même parcours d'achat de produit intégré à l'application que pour les nouveaux abonnés. Assurez-vous que l'UI indique à l'utilisateur qu'il existe déjà un abonnement. Par exemple, vous pouvez afficher la date d'expiration actuelle et le prix récurrent correspondant à l'utilisateur à l'aide d'un bouton Réactiver.

La plupart du temps, il est préférable d'offrir à l'utilisateur le prix et le SKU auxquels il était déjà abonné. Pour ce faire, procédez comme suit :

  • Initiez un nouvel abonnement avec le même SKU.
  • Le nouvel abonnement remplace l'ancien et se renouvelle à la même date d'expiration. L'ancien abonnement est immédiatement marqué comme ayant expiré.
  • Par exemple, Antoine dispose d'un abonnement à l'appli musicale XXX, lequel doit expirer le 1er août. Le 10 juillet, il se réabonne mensuellement au même prix. Le nouvel abonnement est calculé au prorata du crédit restant. Il est immédiatement actif et se renouvellera également le 1er août.

Si vous souhaitez proposer un autre prix, par exemple un nouvel essai sans frais ou une remise spéciale, vous pouvez proposer un autre SKU à l'utilisateur :

  • Initiez le passage à un niveau supérieur ou inférieur avec cet autre SKU en utilisant le mode de remplacement WITHOUT_PRORATION.
  • Le nouvel abonnement remplace l'ancien et se renouvelle à la même date d'expiration. Le prix du nouveau SKU (y compris le prix découverte) est facturé à l'utilisateur à la date d'expiration d'origine. Si l'ancien abonnement a été créé avec un ID de compte obscurci, ce même ID doit être transmis à BillingFlowParams pour les changements d'abonnement (passage à un niveau supérieur ou inférieur).
  • Par exemple, Antoine dispose d'un abonnement à l'appli musicale XXX, lequel doit expirer le 1er août. Le 10 juillet, il se réabonne annuellement avec un prix découverte. Le nouvel abonnement est immédiatement actif, et le prix de lancement est facturé à l'utilisateur le 1er août.
  • Si vous décidez d'inclure un essai sans frais ou un prix découverte dans le SKU visant à reconquérir un client, désélectionnez l'option Allow one free trial per app (Autoriser un essai sans frais par appli) dans la Google Play Console pour que l'utilisateur ne soit plus limité à un seul essai sans frais par appli.

Une fois le jeton d'achat reçu, traitez l'achat comme vous le feriez avec un nouvel abonnement. De plus, l'API Google Play Developer renvoie un linkedPurchaseToken dans la ressource d'abonnement. Veillez à invalider le jeton fourni dans linkedPurchaseToken afin que l'ancien jeton ne soit pas utilisé pour accéder à vos services.

Avant l'expiration de l'abonnement (sur le Play Store)

Tant que l'abonnement est résilié, mais qu'il reste actif, les utilisateurs peuvent le restaurer dans le centre des abonnements Google Play. Pour ce faire, il leur suffit de cliquer sur Se réabonner (anciennement Restaurer). Le même jeton d'abonnement et d'achat est alors conservé.

Section "Subscriptions" (Abonnements) de l'application Google Play Store affichant un abonnement résilié avec le bouton "Resubscribe" (Se réabonner)
Figure 8. Section Account > Subscriptions (Compte > Abonnements) de l'application Google Play Store affichant un abonnement résilié avec le bouton Resubscribe (Se réabonner)

Pour en savoir plus sur la restauration d'abonnements, consultez la section Restaurations.

Après l'expiration de l'abonnement (dans l'application)

Pour autoriser les personnes dont l'abonnement est arrivé à expiration à se réabonner dans votre application, appliquez le même parcours d'achat de produit intégré que pour les nouveaux abonnés. Notez les points suivants :

  • Pour offrir aux utilisateurs une remise, vous pouvez fournir un ID produit avec un tarif spécial pour votre abonnement, également appelé SKU spécial. Ce SKU vise à reconquérir un client. Vous pouvez proposer cette offre dans votre application ou en informer l'utilisateur en dehors de l'application, par exemple dans un e-mail.
  • Pour lancer un abonnement visant à reconquérir un client, démarrez le parcours d'achat dans votre application Android à l'aide de la bibliothèque Google Play Billing. Le processus est le même que pour un nouvel abonnement, mais vous pouvez déterminer le SKU disponible pour l'utilisateur.
  • Si vous décidez d'inclure un essai sans frais ou un prix découverte dans le SKU visant à reconquérir un client, désélectionnez l'option Allow one free trial per app (Autoriser un essai sans frais par appli) dans la Google Play Console pour que l'utilisateur ne soit plus limité à un seul essai sans frais par appli.
  • Si l'utilisateur se réabonne au même SKU, il ne pourra plus bénéficier des essais sans frais ni du prix découverte. Assurez-vous que votre UI lui indique clairement cet état de fait.

Une fois le jeton d'achat reçu, traitez l'achat comme vous le feriez avec un nouvel abonnement. Vous ne recevrez pas de linkedPurchaseToken dans la ressource d'abonnement.

Après l'expiration de l'abonnement (sur le Play Store)

Si cette option est activée, les utilisateurs peuvent se réabonner au même SKU jusqu'à un an après l'expiration. Pour ce faire, il leur suffit de cliquer sur Se réabonner dans le centre des abonnements Google Play. Un nouvel abonnement et un nouveau jeton d'achat sont alors générés.

Section "Abonnements" de l'application Google Play Store affichant les abonnements résiliés et arrivés à expiration avec les boutons "Se réabonner" et "Supprimer"
Figure 9. Section Account > Subscriptions (Compte > Abonnements) de l'application Google Play Store affichant les abonnements résiliés et arrivés à expiration, avec les boutons Resubscribe (Se réabonner) et Remove (Supprimer)

Le réabonnement est considéré comme un achat hors application. Assurez-vous donc de suivre les bonnes pratiques pour gérer ces types d'achat.

Faire la promotion de votre abonnement

Vous pouvez créer des codes promotionnels afin d'offrir à des utilisateurs spécifiques un essai sans frais prolongé pour un abonnement existant. Pour en savoir plus, consultez Codes promotionnels.

Pour les essais sans frais, Google Play vérifie que l'utilisateur dispose d'un mode de paiement valide avant de commencer l'essai sans frais. Pour certains utilisateurs, cette vérification prend la forme d'une retenue ou d'un débit sur leur mode de paiement. Il s'agit d'une retenue ou d'un débit temporaire, qui sera annulé ou remboursé ultérieurement.

À la fin de la période d'essai, le montant total de l'abonnement est facturé sur le mode de paiement de l'utilisateur.

Si un utilisateur résilie un abonnement pendant l'essai sans frais, l'abonnement reste actif jusqu'à la fin de l'essai et n'est pas facturé à la fin de la période d'essai.

Résilier, rembourser ou révoquer un abonnement

Vous pouvez utiliser l'API Google Play Developer pour résilier, rembourser ou révoquer un abonnement. Cette fonctionnalité est également disponible dans la Google Play Console.

  • Résiliation : les utilisateurs peuvent résilier un abonnement sur Google Play. Vous pouvez également leur proposer de le résilier dans votre application ou sur votre site Web. Votre application doit gérer ces résiliations comme décrit dans la section Résiliations.
  • Remboursement : lorsque vous remboursez un abonnement, l'utilisateur peut continuer à l'utiliser. Un remboursement peut avoir lieu, par exemple, si une erreur technique a empêché l'utilisateur d'accéder à votre produit, mais que l'erreur a été résolue. Notez que pour effectuer un remboursement supérieur au dernier paiement, ou si vous souhaitez réaliser un remboursement partiel, vous devez utiliser la Google Play Console.
  • Révocation : lorsque vous révoquez un abonnement, l'utilisateur en perd immédiatement l'accès. Vous pouvez utiliser cette option si, par exemple, une erreur technique a empêché l'utilisateur d'accéder à votre produit et qu'il ne souhaite pas continuer à l'utiliser. Votre application doit gérer ces résiliations comme décrit dans la section Révocations.

Le tableau suivant illustre les différences entre la résiliation, le remboursement et la révocation.

Met fin au renouvellement Remboursement Révocation de l'accès
Résiliation Oui Non Non
Remboursement Non Oui Non
Révocation Oui Oui Oui

Reporter la facturation d'un abonné

Pour avancer la prochaine date de facturation d'un abonnement à renouvellement automatique, utilisez Purchases.subscriptions:defer dans l'API Google Play Developer. Pendant la période de report, l'utilisateur reste abonné à votre contenu avec un accès complet, mais n'est pas facturé. La date de renouvellement de l'abonnement est mise à jour pour refléter la nouvelle date.

Pour les forfaits prépayés, vous pouvez utiliser l'API de facturation différée pour reporter la date d'expiration.

La facturation différée vous permet d'effectuer les actions suivantes :

  • Proposer aux utilisateurs un accès sans frais en tant qu'offre spéciale, par exemple en leur offrant une semaine sans frais lorsqu'ils achètent un film
  • Proposer un accès sans frais aux clients comme geste commercial

La facturation peut être différée pour une durée allant d'un jour à une année via un appel d'API. Pour différer davantage la facturation, vous pouvez appeler à nouveau l'API avant l'arrivée de la nouvelle date de facturation.

Par exemple, Isabelle dispose d'un abonnement mensuel au contenu en ligne d'une application de pêche. Elle est normalement facturée 1,25 € le premier de chaque mois. En mars, elle a participé à une enquête en ligne pour l'éditeur de l'application. Pour la remercier, l'éditeur lui offre six semaines sans frais et reporte le prochain paiement au 15 mai, soit six semaines après la date de facturation précédemment fixée au 1er avril. Isabelle ne devra rien payer en avril ni début mai, et conservera son accès au contenu. Le 15 mai, des frais d'abonnement standards de 1,25 € commenceront à lui être facturés de nouveau pour le mois. Le prochain renouvellement aura lieu le 15 juin.

Vous pouvez informer l'utilisateur par e-mail ou dans l'application que sa date de facturation a changé.

Gérer les refus de paiement

En cas de problèmes de paiement lors du renouvellement d'un abonnement, Google tentera régulièrement de le renouveler avant de le résilier. Cette période de récupération peut être constituée d'un délai de grâce, suivi d'un blocage de compte. Durant cette période, Google envoie à l'utilisateur des e-mails ainsi que des notifications l'invitant à mettre à jour son mode de paiement.

En cas de refus de paiement, l'abonnement est soumis à un délai de grâce, le cas échéant. Pendant le délai de grâce, assurez-vous que l'utilisateur dispose toujours des droits d'accès à l'abonnement.

À l'expiration du délai de grâce, l'abonnement est soumis à une période de blocage de compte. Pendant le blocage de compte, assurez-vous que l'utilisateur ne dispose plus des droits d'accès à l'abonnement.

Vous pouvez indiquer la durée du délai de grâce ainsi que celle du blocage de compte de chaque forfait de base à renouvellement automatique dans la Google Play Console. Spécifier un délai inférieur aux valeurs par défaut peut réduire le nombre d'abonnements récupérés en cas de refus de paiement.

Pour optimiser les chances de récupération d'un abonnement en cas de refus de paiement, vous pouvez signaler le problème de paiement à l'utilisateur et lui demander de le résoudre.

Vous pouvez soit le faire directement, comme décrit dans les sections Délai de grâce et Blocage de compte, soit implémenter l'API de messagerie dans l'application, dans laquelle Google envoie un message aux utilisateurs de votre appli.

Messagerie dans l'application

Si vous avez activé la messagerie dans l'application avec InAppMessageCategoryId.TRANSACTIONAL, Google Play présente aux utilisateurs un message par jour au cours du délai de grâce et du blocage de compte, et leur donne la possibilité de régler leur achat sans quitter l'application.

Snackbar demandant à l'utilisateur de mettre à jour son mode de paiement
Figure 20. Snackbar demandant à l'utilisateur de mettre à jour son mode de paiement

Nous vous recommandons d'appeler cette API chaque fois que l'utilisateur ouvre l'application pour déterminer si le message doit être affiché.

Si l'utilisateur a récupéré son abonnement, vous recevrez un code de réponse de SUBSCRIPTION_STATUS_UPDATED ainsi qu'un jeton d'achat. Vous devez ensuite utiliser ce jeton d'achat pour appeler l'API Google Play Developer et actualiser l'état de l'abonnement dans votre application.

Intégrer la messagerie dans l'application

BillingClient.showInAppMessages() permet de présenter la messagerie dans l'application aux utilisateurs.

Voici un exemple de déclenchement du flux de messagerie dans l'application :

Kotlin

val inAppMessageParams = InAppMessageParams.newBuilder()
        .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL)
        .build()

billingClient.showInAppMessages(activity,
        inAppMessageParams,
        object : InAppMessageResponseListener() {
            override fun onInAppMessageResponse(inAppMessageResult: InAppMessageResult) {
                if (inAppMessageResult.responseCode == InAppMessageResponseCode.NO_ACTION_NEEDED) {
                    // The flow has finished and there is no action needed from developers.
                } else if (inAppMessageResult.responseCode
                        == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) {
                    // The subscription status changed. For example, a subscription
                    // has been recovered from a suspend state. Developers should
                    // expect the purchase token to be returned with this response
                    // code and use the purchase token with the Google Play
                    // Developer API.
                }
            }
        })

Java

InAppMessageParams inAppMessageParams = InAppMessageParams.newBuilder()
        .addInAppMessageCategoryToShow(InAppMessageCategoryId.TRANSACTIONAL)
        .build();

billingClient.showInAppMessages(activity,
        inAppMessageParams,
        new InAppMessageResponseListener() {
            @Override
            public void onInAppMessageResponse(InAppMessageResult inAppMessageResult) {
                if (inAppMessageResult.responseCode
                        == InAppMessageResponseCode.NO_ACTION_NEEDED) {
                    // The flow has finished and there is no action needed from developers.
                } else if (inAppMessageResult.responseCode
                        == InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED) {
                    // The subscription status changed. For example, a subscription
                    // has been recovered from a suspend state. Developers should
                    // expect the purchase token to be returned with this response
                    // code and use the purchase token with the Google Play
                    // Developer API.
                }
            }
        });