Google Play Refund Management

Oubliez un appel d'accusé de réception Google Play, et la vente se défait d'elle-même en trois jours

Un achat est validé, puis trois jours plus tard, Google Play le rembourse et le révoque — sans intervention du client, sans agent du support, juste un callback que votre serveur n'a jamais envoyé. Voici la règle exacte, pourquoi certains achats lui échappent, et ce que chaque vente disparue coûte réellement.

5 min read
Oubliez un appel d'accusé de réception Google Play, et la vente se défait d'elle-même en trois jours

Un achat est validé, le client reçoit son produit, et trois jours plus tard, tout disparaît. Google Play annule la transaction et retire le droit d'accès, sans que le client le demande et sans qu'un seul membre de votre équipe support touche à quoi que ce soit. L'achat a échoué silencieusement parce que votre serveur n'a jamais informé Google qu'il avait été traité.

C'est toute la règle : accusez réception d'un achat Google Play sous trois jours, sinon Google le rembourse automatiquement et le révoque. À chaque fois, sans exception. Parmi toutes les façons dont une vente peut être annulée sur l'une ou l'autre des boutiques, celle-ci fait partie des très rares qui dépendent entièrement de votre propre intégration, ce qui en fait aussi l'une des manières les plus discrètes de perdre des revenus.

Ce n'est ni un contrôle antifraude, ni une décision de politique interne. C'est un callback qui ne s'est jamais déclenché. La correction est minime, l'argent perdu en l'ignorant ne l'est pas : il vaut donc la peine de savoir exactement ce que dit la règle, pourquoi certains achats lui échappent, et ce que chaque vente disparue entraîne avec elle.

Ce que la documentation de Google exige réellement

Play Billing exige que votre application informe Google une fois qu'elle a accordé le droit d'accès et indiqué à l'utilisateur que l'achat a abouti. La documentation de Google fixe un chiffre précis : cette notification « doit être effectuée sous trois jours afin que l'achat ne soit pas automatiquement remboursé et le droit d'accès révoqué ». La documentation sur les produits à usage unique répète la même consigne sans nuance. Oubliez l'accusé de réception et « l'utilisateur reçoit automatiquement un remboursement, et Google Play révoque l'achat ». L'achat initial d'un abonnement suit exactement la même règle.

L'accusé de réception n'est pas une simple formalité administrative. C'est le seul signal dont dispose Google pour savoir que la livraison a réellement eu lieu. Sans signal, Google considère que rien n'a été livré, et annule donc l'ensemble de la transaction pour l'acheteur sans vous consulter. L'acheteur voit un remboursement inattendu. Vous voyez une vente disparaître de vos comptes.

Points clés à retenir

  • Laissez une vente non confirmée pendant 72 heures et l'annulation se produit d'elle-même : l'acheteur est remboursé, le droit d'accès retiré, sans que personne ne soit consulté. Aucun client n'a déclenché cela. C'est votre backend qui l'a fait, en ne disant rien, et votre backend est tout aussi capable de l'empêcher.

  • C'est l'atteinte de l'état PURCHASED qui déclenche le compte à rebours, ce qui rend le moment du paiement lui-même sans importance pour votre délai. Tout ce qui reste à l'état PENDING n'a aucun minuteur associé et ne mérite encore aucun appel de confirmation.

  • Deux appels permettent de remplir cette obligation. Exécutez purchases.products.consume pour un produit consommable, ou faites appel à purchases.products.acknowledge et purchases.subscriptions.acknowledge pour tout ce qui n'en est pas un. Google considère chacun comme une preuve que le produit a bien été livré.

  • Pour les abonnements, cette démarche n'est requise qu'une seule fois, à la souscription. Chaque cycle de facturation suivant est réglé par Google lui-même, marqué comme confirmé sans que votre code n'ait à intervenir.

  • Vous vendez un forfait prépayé de moins de sept jours ? Votre délai se réduit à cinquante pour cent de la durée du forfait. Produit plus court, mèche plus courte.

  • Seul le prix payé retourne à l'acheteur. Le temps de calcul, les dépenses d'API de modèles, les factures de stockage, les versements aux créateurs : cet argent a quitté votre compte au moment de la livraison, et rien n'en revient. Le préjudice réel dépasse largement ce que la ligne de remboursement indique.

  • Rien de tel n'existe sur iOS. StoreKit représente une transaction inachevée à chaque lancement et attend patiemment, sans jamais annuler la transaction. Ce risque particulier n'existe que sur Google Play, et nulle part ailleurs.

Le délai ne commence pas au moment du paiement

Appuyer sur « acheter » ne déclenche pas le minuteur. L'état de l'achat doit d'abord passer à PURCHASED, et certains achats restent à l'état PENDING avant cela. C'est le cas des moyens de paiement en espèces, des virements bancaires lents et des demandes d'autorisation parentale. Google l'indique clairement : « La fenêtre d'accusé de réception de trois jours ne commence que lorsque l'état de l'achat passe de PENDING à PURCHASED. »

Cela a deux implications pour la façon dont vous construisez votre flux. N'accordez le droit d'accès qu'une fois l'état PURCHASED atteint, jamais à l'état PENDING, sous peine de livrer un produit contre un paiement qui pourrait ne jamais arriver. Et n'accusez pas non plus réception d'un achat PENDING, car il n'y a encore rien à acquitter. Appelez enablePendingPurchases() lors de la configuration du BillingClient, attendez la transition d'état, et ne commencez le décompte qu'une fois l'état PURCHASED atteint.

Considérez PENDING comme « pas encore vendu ». Rien n'est dû : ni droit d'accès, ni accusé de réception, ni revenu comptabilisé. Dès que l'état bascule vers PURCHASED, le droit d'accès et le compte à rebours de trois jours deviennent tous deux votre responsabilité.

Choisir le bon appel API selon ce que vous avez vendu

Deux voies d'API permettent de respecter le délai, et celle qui s'applique dépend de ce que vous avez vendu. Les deux remplissent l'exigence de façon équivalente. Ce qui les distingue, c'est ce qu'elles font ensuite au produit.

Les produits consommables sont consommés. C'est le rôle de purchases.products.consume sur un backend sécurisé, ou de consumeAsync() depuis la Play Billing Library côté client. Consommer remplit un double rôle, puisque cela satisfait l'exigence d'accusé de réception et rend l'article de nouveau achetable. C'est exactement ce qu'il faut pour des pièces, des crédits, ou toute génération ponctuelle qu'un client pourrait acheter à répétition.

Les produits non consommables et les abonnements font à la place l'objet d'un accusé de réception, via purchases.products.acknowledge, purchases.subscriptions.acknowledge, ou acknowledgePurchase() côté client. Cela respecte le délai, mais ne rend pas l'article de nouveau achetable.

Voici comment chaque type de produit correspond à un appel et un délai :

  • Pour un consommable, appelez purchases.products.consume ou consumeAsync(). Cela rend aussi l'article de nouveau achetable, et votre délai est de trois jours à partir de PURCHASED.

  • Pour un non-consommable, appelez purchases.products.acknowledge ou acknowledgePurchase(). Le droit d'accès est confirmé sans possibilité de rachat, et votre délai est de trois jours à partir de PURCHASED.

  • Pour l'achat initial d'un abonnement, appelez purchases.subscriptions.acknowledge ou acknowledgePurchase(). Cela confirme le nouvel abonnement, et votre délai est de trois jours à partir de PURCHASED.

  • Pour un renouvellement d'abonnement, aucun appel n'est nécessaire. Google le marque comme accusé de réception de lui-même, il n'y a donc aucun délai.

  • Pour un forfait prépayé de moins d'une semaine, utilisez les mêmes appels d'accusé de réception, mais votre délai se réduit à la moitié de la durée du forfait.

L'obligation s'arrête au premier paiement

Les renouvellements d'abonnement n'ont besoin d'aucun accusé de réception. Google le précise directement : « vous n'avez pas besoin d'accuser réception des renouvellements d'abonnement », et marque chacun d'eux comme acquitté de lui-même. C'est uniquement le tout premier achat d'un abonnement qui arrive dans un état d'accusé de réception en attente et qui reste de votre responsabilité jusqu'à ce que vous le traitiez. Vérifiez l'état de l'accusé de réception côté serveur, ou utilisez isAcknowledged() côté client, avant d'agir. Ainsi, vous n'enverrez jamais d'appel d'accusé de réception en double.

Un délai plus serré pour les forfaits prépayés de courte durée

Les forfaits prépayés d'une semaine ou plus suivent la règle standard des trois jours. Ceux qui sont plus courts n'y sont pas soumis. La documentation de Google précise que les forfaits « d'une durée inférieure à une semaine doivent faire l'objet d'un accusé de réception dans un délai égal à la moitié de la durée du forfait ». Un forfait prépayé de trois jours vous laisse une journée et demie, pas la fenêtre complète. Si des recharges prépayées courtes font partie de votre catalogue, le chemin d'accusé de réception doit être rapide et piloté côté serveur, jamais dépendant de la réouverture de l'application par le client.

Où l'appel d'accusé de réception se perd habituellement

Personne ne saute délibérément cette étape. Elle disparaît parce que la logique d'accusé de réception est rattachée au mauvais déclencheur. L'anti-pattern classique est un client qui n'accuse réception que lorsque le flux d'achat revient au premier plan. Cela couvre un client qui termine son achat et continue d'utiliser l'application juste après. Cela ne couvre personne d'autre.

Les développeurs rencontrent ce problème en permanence. Les fils de discussion de la communauté de développeurs de Google eux-mêmes suivent à chaque fois le même scénario : une variante d'un utilisateur automatiquement remboursé trois jours après son achat, ou une demande désespérée pour comprendre pourquoi les paiements s'annulent systématiquement au troisième jour. Le diagnostic change rarement : l'appel d'accusé de réception était rattaché à une action utilisateur qui ne s'est jamais produite, et ne s'est donc tout simplement jamais déclenché.

Les essais gratuits et le client qui n'ouvre plus jamais l'application

La version la plus désagréable de ce problème concerne un essai gratuit, ou un achat effectué dans les derniers instants avant que quelqu'un ne ferme votre application pour la toute dernière fois. Lorsque l'accusé de réception attend la prochaine ouverture de l'application et qu'aucune prochaine ouverture ne se produit jamais, l'achat finit simplement par expirer. Google le rembourse et le révoque au troisième jour. Pour un essai qui était en passe de se convertir, vous perdez la première facturation que vous n'avez jamais pu prélever, et un droit d'accès client s'évapore discrètement avec elle. Ni l'un ni l'autre n'apparaît dans votre file de support. Les deux apparaissent comme un achat annulé, à condition d'aller vérifier.

Un accusé de réception qui dépend de la prochaine ouverture de l'application est une vente que vous perdez à chaque fois qu'un client reste absent pendant trois jours. Les essais et les achats en un clic sont justement les moments où les clients restent absents.

La véritable facture derrière un remboursement non acquitté

La ligne de remboursement sous-estime ce que vous avez réellement perdu. Google annule la vente, vous rendez le prix payé, et c'est le chiffre que tout le monde voit. Ce n'est pas la facture complète.

Prenez un produit consommable qui déclenche un véritable travail dès qu'il est acheté. Un lot de générations d'images, une série d'appels à l'API d'un fournisseur de modèle, un export vidéo, un versement dû à un créateur. Vous avez payé ce calcul, ces appels d'API, ce stockage et ces versements au moment de leur utilisation. Le remboursement rend le prix de vente au client. Il ne vous rend pas la facture du fournisseur. Un coût réel est sorti de votre poche, et rien n'est revenu en échange.

Pour les abonnements et les essais, la perte correspond à la première facturation jamais encaissée, plus une relation client terminée avant même d'avoir commencé. Et l'enjeu est sur le point de s'accentuer. À partir du 3 août 2026, Google Play fera porter aux développeurs le prix d'achat des rétrofacturations et les frais bancaires pour les commandes passées après cette date, ce qui rend toute fuite évitable d'autant plus urgente à colmater dès maintenant plutôt que plus tard. Un remboursement non acquitté n'est pas une rétrofacturation, mais il enseigne la même leçon. L'argent déjà dépensé n'est pas automatiquement de l'argent que vous conservez.

Construire l'étape d'accusé de réception pour qu'elle ne puisse pas être oubliée

Le schéma fiable retire entièrement votre application du chemin critique. Exécutez-le sur votre backend, piloté par des notifications, et non par le fait que quelqu'un rouvre ou non un écran.

  • Abonnez-vous aux notifications développeur en temps réel. Un événement d'achat de produit à usage unique, ou un événement d'achat d'abonnement, atteint votre serveur dès l'instant où Google enregistre la vente, que l'application soit en cours d'exécution ou non.

  • Validez le jeton d'achat via la Play Developer API et confirmez que l'état indique bien PURCHASED plutôt que PENDING.

  • Enregistrez le droit d'accès dans votre propre système, rattaché au compte de ce client.

  • Consommez ou accusez réception sans délai. Les consommables sont consommés, les non-consommables et les abonnements initiaux font l'objet d'un accusé de réception. Vérifiez d'abord l'état de l'accusé de réception afin que l'appel ne parte jamais deux fois.

  • Conservez un rattrapage côté client. Appeler queryPurchasesAsync() dans onResume() permet de récupérer tout ce qui s'est réglé pendant que l'application était fermée. Considérez cela comme une assurance, pas comme la voie principale.

Tout l'intérêt est que l'accusé de réception se déclenche à partir d'un événement que Google vous transmet, plutôt que d'une action utilisateur que vous n'avez aucun moyen de garantir. Quelqu'un qui achète une fois et ne revient jamais reste malgré tout entièrement couvert, parce que votre serveur a déjà fait le travail dès que l'achat a été enregistré.

Un filet de sécurité pour ce qui passe malgré tout

Aussi bien construit que soit le pipeline, il mérite encore un filet de sécurité en dessous. La Voided Purchases API de Google recense les commandes ayant abouti à un remboursement, une révocation ou une rétrofacturation, et isole en particulier le scénario où la cause était un achat qui « n'a jamais fait l'objet d'un accusé de réception de la part du développeur, et peut donc ne pas exister dans les registres du développeur ». Interrogez-la à intervalles réguliers et vous pourrez retirer l'accès à toute personne dont la commande a été discrètement annulée par Google sans que vous le sachiez. Attention toutefois à la limite : seuls les 30 derniers jours sont récupérables, ce qui en fait une tâche planifiée plutôt que quelque chose que vous traitez une fois par trimestre.

iOS n'a jamais été conçu pour vous faire ça

Passez du côté de l'App Store, et rien de tout cela ne s'applique. Apple a conçu sa propre étape de clôture, consistant à terminer une transaction, sauf que la pénalité pour l'avoir omise joue dans le sens inverse. Une transaction inachevée reste en attente dans la file d'Apple. Elle réapparaît à chaque lancement de l'application, et de nouveau chaque fois que l'observateur se rattache, vous offrant des occasions répétées de livrer ce que le client a payé. Apple n'émet aucune annulation pour autant. Rien qui ressemble à un déclencheur de remboursement à 72 heures n'existe sur cette plateforme.

C'est exactement pour cela qu'un seul et même modèle mental ne peut pas s'appliquer aux deux boutiques. Android vous impose un compte à rebours et une vente qui s'évapore si vous le manquez. iOS vous offre un rappel persistant et un temps illimité pour y répondre. Transposez les habitudes iOS dans une base de code Android, et tôt ou tard, vous vous retrouverez face à un amas de commandes annulées que personne dans l'équipe ne saura expliquer.

Combler cette brèche, c'est précisément le travail de Refund Sensor. La confirmation se déclenche directement à partir de la notification de la boutique, quelques instants après sa réception, tandis qu'un processus de réconciliation permanent avec la Voided Purchases API retire l'accès partout où Google a déjà annulé une commande à votre insu. Un compte à rebours que vous auriez pu manquer devient une case déjà cochée avant même que vous pensiez à vérifier.

Où ces règles sont documentées

Questions fréquentes

Votre serveur n'a jamais envoyé l'appel d'accusé de réception à temps. Dès qu'un achat reste non acquitté au-delà du délai de trois jours à partir de l'atteinte de l'état PURCHASED, Google annule la vente et retire automatiquement le droit d'accès. Ce n'est pas quelque chose que le client a fait, et ce n'est pas une pénalité imposée par Google. C'est un appel d'accusé de réception manquant, et accuser réception côté serveur à partir de la notification de la boutique élimine complètement le problème.

Les deux arrêtent le compte à rebours de trois jours, mais ils laissent le produit dans des états différents. Consommer, via purchases.products.consume ou consumeAsync(), s'applique aux consommables. Cela respecte le délai et remet l'article en vente. Accuser réception, via purchases.products.acknowledge, purchases.subscriptions.acknowledge, ou acknowledgePurchase(), s'applique aux non-consommables et aux abonnements. Cela confirme le droit d'accès sans libérer le produit pour un nouvel achat.

Non, seul le premier achat. Google n'exige pas d'accusé de réception pour les renouvellements et les marque automatiquement comme acquittés. Seul l'achat initial de l'abonnement, qui arrive dans un état d'accusé de réception en attente, reste de votre responsabilité jusqu'à ce que vous le traitiez.

Non, attendez l'état PURCHASED. Un achat à l'état PENDING, comme un paiement en espèces ou une demande d'autorisation parentale, n'a pas encore du tout déclenché le compte à rebours de trois jours. N'accordez le droit d'accès et n'envoyez l'accusé de réception qu'une fois que l'état est réellement passé de PENDING à PURCHASED.

Non, et il vaut mieux le savoir avant de supposer qu'Android et iOS se comportent de la même façon. Une transaction StoreKit inachevée est simplement redélivrée à chaque lancement de l'application jusqu'à ce que vous la terminiez. Apple ne la rembourse jamais automatiquement. Le remboursement automatique à trois jours est propre à Google Play, et les deux plateformes nécessitent donc un traitement différent.

Le remboursement en lui-même ne peut pas être annulé. Ce que vous pouvez faire, c'est réconcilier. La Voided Purchases API fait remonter les achats remboursés et révoqués des 30 derniers jours et signale ceux qui ont été annulés spécifiquement parce qu'ils n'ont jamais fait l'objet d'un accusé de réception, afin que vous puissiez révoquer le droit d'accès que vous aviez accordé. Pour la suite, c'est le fait d'accuser réception à partir de la notification de la boutique qui empêche le prochain achat de vous échapper.

#billing#acknowledgement#refunds#in-app purchases#android
Refund SensorRefund Sensor TeamRefund defense for App Store and Google Play developers