Cet article explique comment intégrer la bibliothèque Google Play Billing à votre application pour commencer à vendre des produits.
Cycle de vie d'un achat
Voici un parcours d'achat standard pour un achat ou un abonnement ponctuels.
- Montrez aux utilisateurs ce qu'ils peuvent acheter.
- Lancez le parcours d'achat pour que l'utilisateur accepte l'achat.
- Vérifiez l'achat sur votre serveur.
- Fournissez le contenu à l'utilisateur.
- Confirmez la livraison du contenu. Pour les produits consommables, utilisez l'achat afin que l'utilisateur puisse l'acheter à nouveau.
Les abonnements sont renouvelés automatiquement jusqu'à ce qu'ils soient résiliés. Un abonnement peut présenter les états suivants :
- Actif : l'utilisateur est en règle et a accès à l'abonnement.
- Annulé : l'utilisateur a annulé l'abonnement, mais a toujours accès jusqu'à sa date d'expiration.
- En délai de grâce : l'utilisateur a rencontré un problème de paiement, mais a toujours accès à l'élément pendant que Google tente à nouveau le mode de paiement.
- En attente : l'utilisateur a rencontré un problème de paiement et n'y a plus accès pendant que Google tente à nouveau le mode de paiement.
- Suspendu : l'utilisateur a suspendu son accès et n'y a pas accès tant qu'il ne l'a pas réactivé.
- Expiré : l'utilisateur a résilié son abonnement et n'y a plus accès. L'utilisateur est considéré comme perdu après l'expiration.
Initialiser une connexion à Google Play
La première étape pour intégrer le système de facturation de Google Play consiste à ajouter la bibliothèque Google Play Billing à votre application et à initialiser une connexion.
Ajouter la dépendance de la bibliothèque Google Play Billing
Ajoutez la dépendance Google Play Billing au fichier build.gradle
de votre application, comme indiqué ci-dessous :
Groovy
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing:$billing_version") }
Si vous utilisez Kotlin, le module KTX de la bibliothèque Google Play Billing contient des extensions et des coroutines Kotlin qui vous permettent d'écrire du code Kotlin idiomatique lors de l'utilisation de la bibliothèque Google Play Billing. Pour inclure ces extensions dans votre projet, ajoutez la dépendance suivante au fichier build.gradle
de votre application, comme indiqué ci-dessous :
Groovy
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
Initialiser un BillingClient
Une fois que vous avez ajouté une dépendance à la bibliothèque Google Play Billing, vous devez initialiser une instance BillingClient
. BillingClient
est l'interface principale de communication entre la bibliothèque Google Play Billing et le reste de votre application. BillingClient
fournit des méthodes pratiques, synchrones et asynchrones, utiles pour de nombreuses opérations de facturation courantes. Nous vous recommandons vivement d'avoir une connexion BillingClient
active simultanément pour éviter plusieurs rappels PurchasesUpdatedListener
liés à un seul événement.
Pour créer un BillingClient
, utilisez newBuilder()
. Vous pouvez transmettre n'importe quel contexte à newBuilder()
, et BillingClient
l'utilise pour obtenir un contexte d'application.
Vous n'avez donc plus à vous soucier des fuites de mémoire. Pour recevoir des mises à jour pour les achats, vous devez également appeler setListener()
, en transmettant une référence à PurchasesUpdatedListener
. Cet écouteur reçoit des mises à jour pour tous les achats dans votre application.
Kotlin
private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases -> // To be implemented in a later section. } private var billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) // Configure other settings. .build()
Java
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() { @Override public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { // To be implemented in a later section. } }; private BillingClient billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) // Configure other settings. .build();
Se connecter à Google Play
Après avoir créé un BillingClient
, vous devez établir une connexion à Google Play.
Pour vous connecter à Google Play, appelez startConnection()
. Le processus de connexion est asynchrone. Vous devez implémenter BillingClientStateListener
pour recevoir un rappel une fois que la configuration du client est terminée et est prête à envoyer d'autres requêtes.
Vous devez également mettre en œuvre une logique de nouvelle tentative pour gérer les connexions perdues à Google Play.
Pour implémenter une logique de nouvelle tentative, contournez la méthode de rappel onBillingServiceDisconnected()
et assurez-vous que BillingClient
appelle la méthode startConnection()
pour vous reconnecter à Google Play avant d'envoyer d'autres requêtes.
L'exemple suivant montre comment démarrer une connexion et tester si elle est fonctionnelle :
Kotlin
billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult) { if (billingResult.responseCode == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } override fun onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } })
Java
billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // The BillingClient is ready. You can query purchases here. } } @Override public void onBillingServiceDisconnected() { // Try to restart the connection on the next request to // Google Play by calling the startConnection() method. } });
Afficher les produits disponibles à l'achat
Une fois la connexion à Google Play établie, vous pouvez interroger les produits disponibles et les présenter à vos utilisateurs.
L'interrogation des informations détaillées sur un produit est une étape importante avant de présenter vos produits aux utilisateurs, car elle renvoie des informations localisées sur le produit. Pour les abonnements, assurez-vous que l'affichage du produit respecte toutes les règles de Google Play.
Pour interroger les informations sur un produit intégré, appelez queryProductDetailsAsync()
.
Pour gérer le résultat de l'opération asynchrone, vous devez également spécifier un écouteur qui implémente l'interface ProductDetailsResponseListener
.
Vous pouvez ensuite contourner onProductDetailsResponse()
, qui avertit l'écouteur lorsque la requête est terminée, comme illustré dans l'exemple suivant :
Kotlin
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build() billingClient.queryProductDetailsAsync(queryProductDetailsParams) { billingResult, productDetailsList -> // check billingResult // process returned productDetailsList }
Java
QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) { // check billingResult // process returned productDetailsList } } )
Lorsque vous interrogez les informations détaillées sur un produit, transmettez une instance de QueryProductDetailsParams
qui spécifie une liste de chaînes d'ID produit créées dans la Google Play Console avec un élément ProductType
. ProductType
peut être de type ProductType.INAPP
pour des produits ponctuels ou de type ProductType.SUBS
pour les abonnements.
Interroger avec des extensions Kotlin
Si vous utilisez des extensions Kotlin, vous pouvez interroger les informations détaillées sur un produit intégré en appelant la fonction d'extension queryProductDetails()
.
queryProductDetails()
exploite les coroutines Kotlin. Vous n'avez donc pas besoin de définir un écouteur distinct. Au lieu de cela, la fonction est suspendue jusqu'à la fin de l'interrogation, après quoi vous pouvez traiter le résultat :
suspend fun processPurchases() {
val productList = listOf(
QueryProductDetailsParams.Product.newBuilder()
.setProductId("product_id_example")
.setProductType(BillingClient.ProductType.SUBS)
.build()
)
val params = QueryProductDetailsParams.newBuilder()
params.setProductList(productList)
// leverage queryProductDetails Kotlin extension function
val productDetailsResult = withContext(Dispatchers.IO) {
billingClient.queryProductDetails(params.build())
}
// Process the result.
}
Dans de rares cas, certains appareils ne peuvent pas prendre en charge ProductDetails
ni queryProductDetailsAsync()
, généralement en raison de versions obsolètes des services Google Play. Pour assurer la compatibilité dans ce scénario, découvrez comment utiliser les fonctionnalités de rétrocompatibilité dans le guide de migration de la bibliothèque Play Billing 5.
Traiter le résultat
La bibliothèque Google Play Billing stocke les résultats de la requête dans un List
d'objets ProductDetails
. Vous pouvez ensuite appeler diverses méthodes sur chaque objet ProductDetails
de la liste pour afficher des informations pertinentes sur un produit intégré, telles que son prix ou sa description. Pour afficher des informations détaillées disponibles sur le produit, consultez la liste des méthodes de la classe ProductDetails
.
Avant de proposer un article à la vente, vérifiez que l'utilisateur n'en est pas déjà le propriétaire. Si l'utilisateur dispose d'un consommable qui se trouve toujours dans sa bibliothèque d'articles, il doit le consommer avant de pouvoir l'acheter à nouveau.
Avant de proposer un abonnement, vérifiez que l'utilisateur n'est pas déjà abonné. Notez également ce qui suit :
queryProductDetailsAsync()
renvoie les détails des produits sur abonnement et un maximum de 50 offres par abonnement.queryProductDetailsAsync()
renvoie uniquement les offres pour lesquelles l'utilisateur est éligible. Si l'utilisateur tente d'acheter une offre pour laquelle il n'est pas éligible (par exemple, si l'application affiche une liste obsolète d'offres éligibles), Google Play informe l'utilisateur qu'il n'est pas éligible. L'utilisateur peut alors choisir d'acheter le forfait de base à la place.
Lancer le parcours d'achat
Pour démarrer une demande d'achat depuis votre application, appelez la méthode launchBillingFlow()
à partir du thread principal de votre application. Cette méthode transmet une référence à un objet BillingFlowParams
contenant l'objet ProductDetails
approprié obtenu lors de l'appel de queryProductDetailsAsync()
. Pour créer un objet BillingFlowParams
, utilisez la classe BillingFlowParams.Builder
.
Kotlin
// An activity reference from which the billing flow will be launched. val activity : Activity = ...; val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // For One-time product, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call ProductDetails.subscriptionOfferDetails() // for a list of offers that are available to the user .setOfferToken(selectedOfferToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build() // Launch the billing flow val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Java
// An activity reference from which the billing flow will be launched. Activity activity = ...; ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // For one-time products, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call // ProductDetails.subscriptionOfferDetails() for a list of offers // that are available to the user. .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
La méthode launchBillingFlow()
renvoie l'un des codes de réponse recensés dans BillingClient.BillingResponseCode
. Assurez-vous que ce résultat ne comporte aucune erreur lors du lancement du parcours d'achat. Un BillingResponseCode
de type OK
indique un lancement réussi.
Lors d'un appel réussi à launchBillingFlow()
, le système affiche l'écran d'achat Google Play. La figure 1 illustre l'écran d'achat d'un abonnement :
Google Play appelle onPurchasesUpdated()
pour transmettre le résultat de l'opération d'achat à un écouteur qui implémente l'interface PurchasesUpdatedListener
. L'écouteur est spécifié à l'aide de la méthode setListener()
lors de l'initialisation du BillingClient.
Vous devez implémenter onPurchasesUpdated()
pour gérer les éventuels codes de réponse. L'exemple suivant montre comment contourner onPurchasesUpdated()
:
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { handlePurchase(purchase) } } else if (billingResult.responseCode == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
Java
@Override void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { if (billingResult.getResponseCode() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } } else if (billingResult.getResponseCode() == BillingResponseCode.USER_CANCELED) { // Handle an error caused by a user cancelling the purchase flow. } else { // Handle any other error codes. } }
Un achat réussi génère un écran de confirmation d'achat Google Play semblable à la figure 2.
Un achat réussi génère également un jeton d'achat, c'est-à-dire un identifiant unique qui représente l'utilisateur et l'ID du produit intégré qu'il a acheté. Vos applications peuvent stocker le jeton d'achat localement, mais nous vous recommandons de le transmettre à votre serveur backend sécurisé, où vous pourrez ensuite vérifier l'achat et vous protéger contre la fraude. Ce processus est décrit plus en détail dans la section suivante.
L'utilisateur reçoit également un reçu par e-mail contenant un ID de commande ou un ID unique de la transaction. Les utilisateurs reçoivent un e-mail contenant un ID de commande unique pour chaque achat de produit ponctuel, ainsi que pour l'achat initial de l'abonnement et les renouvellements automatiques récurrents ultérieurs. Vous pouvez utiliser cet ID de commande pour gérer les remboursements dans la Google Play Console.
Indiquer un prix personnalisé
Si votre application peut être distribuée aux utilisateurs de l'Union européenne, utilisez la méthode setIsOfferPersonalized()
pour indiquer aux utilisateurs que le prix d'un article a été personnalisé à l'aide de la prise de décision automatisée.
Vous devez consulter Art. 6 (1) (ea) de la directive sur les droits des consommateurs (2011/83/UE) pour déterminer si le prix que vous proposez aux utilisateurs est personnalisé.
setIsOfferPersonalized()
accepte une entrée booléenne. Si true
, l'interface utilisateur Google Play indique que le prix a été personnalisé. Si false
, l'interface utilisateur omet ce message. La valeur par défaut est false
.
Pour obtenir plus d'informations, consultez le Centre d'aide consommateur.
Traiter les achats
Une fois qu'un utilisateur a effectué un achat, votre application doit le traiter.
Dans la plupart des cas, votre application est informée des achats via votre PurchasesUpdatedListener
. Toutefois, dans certains cas, votre application est informée des achats en appelant BillingClient.queryPurchasesAsync()
, comme décrit dans la section Récupération des achats.
De plus, si vous avez un client Notifications en temps réel pour les développeurs dans votre backend sécurisé, vous pouvez enregistrer de nouveaux achats en recevant une subscriptionNotification
ou une oneTimeProductNotification
vous avertissant d'un nouvel achat. Après avoir reçu ces notifications, appelez l'API Google Play Developer pour obtenir l'état complet et mettre à jour l'état de votre backend.
Pour traiter un achat, votre application doit :
- Vérifier l'achat.
- Fournir le contenu à l'utilisateur et confirmer la livraison. Dans certains cas, marquer l'article comme consommé pour que l'utilisateur puisse l'acheter à nouveau.
Pour vérifier un achat, vérifiez d'abord que l'état de l'achat est PURCHASED
. Si l'achat est PENDING
, vous devez le traiter comme décrit dans Gérer les transactions en attente. Pour les achats reçus de onPurchasesUpdated()
ou queryPurchasesAsync()
, vous devez vérifier l'achat plus précisément afin de vous assurer de sa légitimité avant que votre application accorde les droits d'accès. Pour savoir comment vérifier correctement un achat, consultez Vérifier les achats avant d'accorder des droits.
Une fois l'achat vérifié, votre application est prête à accorder un droit d'accès à l'utilisateur. Le compte utilisateur associé à l'achat peut être identifié à l'aide du ProductPurchase.obfuscatedExternalAccountId
renvoyé par Purchases.products:get
pour les achats de produits intégrés et du SubscriptionPurchase.obfuscatedExternalAccountId
renvoyé par Purchases.subscriptions:get
pour les abonnements côté serveur ; ou le obfuscatedAccountId
à partir de Purchase.getAccountIdentifiers()
côté client, s'il a été défini avec setObfuscatedAccountId
lors de l'achat.
Une fois les droits d'accès accordés, votre application doit confirmer l'achat. Cette confirmation indique à Google Play que vous avez accordé les droits d'accès à l'achat.
Le processus permettant d'accorder des droits d'accès et de confirmer l'achat dépend de la nature de l'achat : consommable, non consommable ou abonnement.
Produits consommables
Pour les consommables, si votre application dispose d'un backend sécurisé, nous vous recommandons d'utiliser Purchases.products:consume
pour consommer de manière fiable les achats. Assurez-vous que l'achat n'a pas déjà été consommé en vérifiant le consumptionState
à partir du résultat de l'appel de Purchases.products:get
. Si votre application est côté client uniquement sans backend, utilisez consumeAsync()
à partir de la bibliothèque Google Play Billing. Les deux méthodes répondent aux exigences de confirmation et indiquent que votre application a accordé des droits à l'utilisateur.
Ces méthodes permettent également à votre application de proposer à nouveau à la vente le produit ponctuel correspondant au jeton d'achat indiqué. Avec consumeAsync()
, vous devez également transmettre un objet qui implémente l'interface ConsumeResponseListener
. Cet objet gère le résultat de l'opération de consommation. Vous pouvez contourner la méthode onConsumeResponse()
, que la bibliothèque Google Play Billing appelle une fois l'opération terminée.
L'exemple suivant illustre la consommation d'un produit avec la bibliothèque Google Play Billing à l'aide du jeton d'achat associé :
Kotlin
suspend fun handlePurchase(purchase: Purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. val purchase : Purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() val consumeResult = withContext(Dispatchers.IO) { client.consumePurchase(consumeParams) } }
Java
void handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. Purchase purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); ConsumeResponseListener listener = new ConsumeResponseListener() { @Override public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Handle the success of the consume operation. } } }; billingClient.consumeAsync(consumeParams, listener); }
Produits non consommables
Pour confirmer les achats de produits non consommables, si votre application dispose d'un backend sécurisé, nous vous recommandons d'utiliser Purchases.products:acknowledge
pour confirmer de manière fiable les achats. Assurez-vous que l'achat n'a pas déjà été confirmé en vérifiant le acknowledgementState
à partir du résultat de l'appel de Purchases.products:get
.
Si votre application est côté client uniquement, utilisez BillingClient.acknowledgePurchase()
depuis la bibliothèque Google Play Billing. Avant de confirmer un achat, votre application doit vérifier s'il a déjà été confirmé à l'aide de la méthode isAcknowledged()
dans la bibliothèque Google Play Billing.
L'exemple suivant montre comment confirmer un achat à l'aide de la bibliothèque Google Play Billing :
Kotlin
val client: BillingClient = ... val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ... suspend fun handlePurchase() { if (purchase.purchaseState === PurchaseState.PURCHASED) { if (!purchase.isAcknowledged) { val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.purchaseToken) val ackPurchaseResult = withContext(Dispatchers.IO) { client.acknowledgePurchase(acknowledgePurchaseParams.build()) } } } }
Java
BillingClient client = ... AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ... void handlePurchase(Purchase purchase) { if (purchase.getPurchaseState() == PurchaseState.PURCHASED) { if (!purchase.isAcknowledged()) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
Abonnements
Les abonnements sont traités de la même manière que les produits non consommables. Si possible, utilisez Purchases.subscriptions.acknowledge
depuis l'API Google Play Developer pour confirmer l'achat de manière fiable à partir de votre backend sécurisé. Déterminez si l'achat n'a pas déjà été confirmé en vérifiant le acknowledgementState
dans la ressource d'achat de Purchases.subscriptions:get
. Sinon, vous pouvez confirmer un abonnement à l'aide de BillingClient.acknowledgePurchase()
dans la bibliothèque Google Play Billing après avoir vérifié isAcknowledged()
. Tous les achats initiaux d'abonnements doivent être confirmés. Il n'est pas nécessaire de confirmer le renouvellement de l'abonnement. Pour en savoir plus sur la confirmation des abonnements, consultez la rubrique Vendre des abonnements.
Récupérer les achats
Pour vous assurer que votre application traite tous les achats, il n'est pas suffisant d'utiliser un PurchasesUpdatedListener
en ce qui concerne les mises à jour d'achats. Il est possible que votre application ne soit pas à jour quant à la totalité des achats effectués par un utilisateur. Voici quelques situations lors desquelles votre application peut perdre de vue un achat ou en ignorer l'existence :
- Problèmes de réseau lors de l'achat : un utilisateur effectue un achat et reçoit la confirmation de Google, mais son appareil perd la connectivité réseau avant que son appareil ne reçoive une notification de l'achat via
PurchasesUpdatedListener
. - Plusieurs appareils : un utilisateur achète un article sur un appareil, puis s'attend à pouvoir le voir lorsqu'il change d'appareil.
- Gérer les achats effectués en dehors de votre application : certains achats, par exemple l'utilisation d'offres promotionnelles, peuvent être effectués en dehors de votre application.
Pour gérer ces situations, assurez-vous que votre application appelle BillingClient.queryPurchasesAsync()
dans votre méthode onResume()
pour vous assurer que tous les achats sont bien traités comme décrit dans Traiter les achats.
L'exemple suivant montre comment récupérer les achats d'abonnement d'un utilisateur.
Notez que queryPurchasesAsync()
ne renvoie que les abonnements actifs et les achats ponctuels non consommés.
Kotlin
val params = QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) // uses queryPurchasesAsync Kotlin extension function val purchasesResult = billingClient.queryPurchasesAsync(params.build()) // check purchasesResult.billingResult // process returned purchasesResult.purchasesList, e.g. display the plans user owns
Java
billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) .build(), new PurchasesResponseListener() { public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) { // check billingResult // process returned purchase list, e.g. display the plans user owns } } );
Gérer les achats effectués en dehors de votre application
Certains achats peuvent être effectués en dehors de votre application, par exemple l'utilisation d'offres promotionnelles ou les rappels d'abandon de panier pour les achats in-app (IAP) Google Play Jeux. Lorsqu'un utilisateur effectue un achat en dehors de votre application, il s'attend à ce que celle-ci affiche un message dans l'application ou utilise un mécanisme de notification pour l'informer que l'application a bien reçu et traité l'achat. Voici quelques-uns des mécanismes acceptés :
- Afficher un pop-up dans l'application
- Transmettre le message dans une zone de message dans l'application et indiquer clairement qu'un nouveau message s'y trouve.
- Utiliser un message de notification de l'OS.
N'oubliez pas qu'il est possible qu'un achat soit reconnu par votre application, peu importe l'état dans lequel elle se trouve. Il est même possible que votre application ne soit même pas installée lors de l'achat. Les utilisateurs s'attendent à recevoir leur achat lorsqu'ils réactivent l'application, quel que soit l'état de l'application.
Vous devez détecter les achats, quel que soit l'état de leur application au moment où ils ont été effectués. Toutefois, dans certains cas, il peut être acceptable de ne pas informer immédiatement l'utilisateur que l'article a été reçu. Par exemple :
- En plein milieu d'un jeu, l'affichage d'un message peut distraire l'utilisateur. Dans ce cas, vous devez prévenir l'utilisateur une fois la partie terminée.
- Pendant les cinématiques, l'affichage d'un message peut distraire l'utilisateur. Dans ce cas, vous devez avertir l'utilisateur une fois la cinématique terminée.
- Au cours du tutoriel de départ et de la configuration d'un jeu. Nous vous recommandons d'informer immédiatement les nouveaux utilisateurs de la récompense reçue dès qu'ils ouvrent le jeu ou lors de la configuration initiale de l'utilisateur. Cependant, il est possible d'attendre que la séquence de jeu principale soit disponible pour avertir l'utilisateur.
Tenez toujours compte de l'utilisateur lorsque vous décidez quand et comment informer vos utilisateurs des achats effectués en dehors de votre application. Chaque fois qu'un utilisateur ne reçoit pas immédiatement une notification, il peut se sentir perdu et cesser d'utiliser votre application, contacter l'assistance utilisateur ou s'en plaindre sur les réseaux sociaux.
Rappels d'abandon du panier sur la page d'accueil de Google Play Jeux (activés par défaut)
Pour les développeurs de jeux qui monétisent leurs contenus via IAP, la fonctionnalité de rappel d'abandon du panier est un moyen de vendre des unités de gestion des stocks (SKU) actives dans la Google Play Console en dehors de votre application, qui encourage les utilisateurs à terminer leurs achats précédemment abandonnés lorsqu'ils naviguent sur le Google Play Store. Ces achats sont effectués en dehors de votre application, depuis la page d'accueil de Google Play Jeux dans le Google Play Store.
Cette fonctionnalité est activée par défaut pour aider les utilisateurs à reprendre là où ils s'étaient arrêtés et les développeurs à maximiser leurs ventes. Toutefois, vous pouvez désactiver cette fonctionnalité pour votre application en envoyant le formulaire de désactivation de la fonctionnalité de rappel d'abandon du panier. Pour connaître les bonnes pratiques de gestion des codes SKU dans la Google Play Console, consultez la section Créer un produit intégré à l'application.
Les images suivantes illustrent le rappel d'abandon du panier qui s'affiche sur le Google Play Store:
Traiter les transactions en attente
Google Play accepte les transactions en attente ou celles nécessitant une ou plusieurs étapes supplémentaires entre le moment où l'utilisateur effectue un achat et le traitement du mode de paiement associé. Votre application ne doit pas accorder de droit à ces types d'achats tant que Google ne vous a pas informé que le mode de paiement de l'utilisateur a été débité.
Par exemple, un utilisateur peut lancer une transaction en choisissant un magasin physique dans lequel il paiera plus tard en espèces. L'utilisateur reçoit un code par notification et par e-mail. Lorsque l'utilisateur arrive au magasin physique, il peut passer par le caissier pour utiliser le code et payer en espèces. Google vous informe ensuite, vous et l'utilisateur, que le paiement a été reçu. Votre application peut alors accorder des droits à l'utilisateur.
Appelez enablePendingPurchases()
lors de l'initialisation de BillingClient
pour activer les transactions en attente pour votre application. Votre application doit activer et prendre en charge les transactions en attente pour les produits uniques. Avant d'ajouter une assistance, assurez-vous de bien comprendre le cycle de vie des achats pour les transactions en attente.
Lorsque votre application reçoit un nouvel achat, via votre PurchasesUpdatedListener
ou suite à un appel queryPurchasesAsync()
, utilisez la méthode getPurchaseState()
pour déterminer si l'état d'achat est PURCHASED
ou PENDING
. Vous devez accorder des droits d'accès uniquement lorsque l'état est PURCHASED
.
Si votre application est en cours d'exécution lorsque l'utilisateur effectue l'achat, votre PurchasesUpdatedListener
est appelé à nouveau et PurchaseState
est désormais PURCHASED
. À ce stade, votre application peut traiter l'achat à l'aide de la méthode standard de traitement des achats. Votre application doit également appeler queryPurchasesAsync()
dans la méthode onResume()
de votre application pour gérer les achats qui sont passés à l'état PURCHASED
lorsque votre application n'était pas en cours d'exécution.
Lorsque l'achat passe de PENDING
à PURCHASED
, votre client Notifications en temps réel pour les développeurs reçoit une notification ONE_TIME_PRODUCT_PURCHASED
ou SUBSCRIPTION_PURCHASED
. Si l'achat est annulé, vous recevez une notification ONE_TIME_PRODUCT_CANCELED
ou SUBSCRIPTION_PENDING_PURCHASE_CANCELED
. Cela peut se produire si votre client n'effectue pas le paiement dans le délai requis. Notez que vous pouvez toujours utiliser l'API Google Play Developer pour vérifier l'état actuel d'un achat.
Gérer les achats de quantités multiples
Compatible avec les versions 4.0 et ultérieures de la bibliothèque Google Play Billing, Google Play permet aux clients d'acheter plus d'un produit intégré dans l'application en une seule transaction en spécifiant une quantité dans le panier d'achat. Votre application doit gérer les achats de quantités multiples et accorder des droits en fonction de la quantité d'achats spécifiée.
Pour respecter les achats de quantités multiples, la logique de provisionnement de votre application doit vérifier une quantité d'articles. Vous pouvez accéder à un champ quantity
à partir de l'une des API suivantes :
getQuantity()
dans la bibliothèque Google Play Billing.Purchases.products.quantity
de l'API Google Play Developer.
Une fois que vous avez ajouté une logique pour gérer les achats de quantités multiples, vous devez activer la fonctionnalité de quantités multiples pour le produit correspondant sur la page de gestion des produits intégrés à l'application de la Google Play Console.
Interroger la configuration de facturation de l'utilisateur
getBillingConfigAsync()
indique le pays de l'utilisateur sur Google Play.
Vous pouvez interroger la configuration de facturation de l'utilisateur après avoir créé un BillingClient
. L'extrait de code suivant explique comment appeler getBillingConfigAsync()
. Gérez la réponse en implémentant le BillingConfigResponseListener
. Cet écouteur reçoit des mises à jour pour toutes les requêtes de configuration de facturation lancées à partir de votre application.
Si le BillingResult
renvoyé ne contient aucune erreur, vous pouvez vérifier le champ countryCode
dans l'objet BillingConfig
pour obtenir le pays de l'utilisateur dans Google Play.
Kotlin
// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(getBillingConfigParams,
object : BillingConfigResponseListener {
override fun onBillingConfigResponse(
billingResult: BillingResult,
billingConfig: BillingConfig?
) {
if (billingResult.responseCode == BillingResponseCode.OK
&& billingConfig != null) {
val countryCode = billingConfig.countryCode
...
} else {
// TODO: Handle errors
}
}
})
Java
// Use the default GetBillingConfigParams.
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(getBillingConfigParams,
new BillingConfigResponseListener() {
public void onBillingConfigResponse(
BillingResult billingResult, BillingConfig billingConfig) {
if (billingResult.getResponseCode() == BillingResponseCode.OK
&& billingConfig != null) {
String countryCode = billingConfig.getCountryCode();
...
} else {
// TODO: Handle errors
}
}
});