App Store Refund Management

Dans les coulisses du CONSUMPTION_REQUEST d’Apple : la demi-journée qui décide de votre remboursement

Chaque remboursement sur l’App Store relève de la décision d’Apple, mais un CONSUMPTION_REQUEST vous laisse un délai fixe pour répondre avec des faits concrets sur l’achat. Répondez correctement et les demandes infondées sont refusées. Restez silencieux et seule la version du client fait foi auprès d’Apple.

5 min read
Dans les coulisses du CONSUMPTION_REQUEST d’Apple : la demi-journée qui décide de votre remboursement

Chaque remboursement sur l’App Store relève de la décision d’Apple, mais Apple préfère ne pas la prendre sans informations. Une demande de remboursement met le processus en pause, interroge votre serveur, et ouvre un délai fixe pendant lequel vous pouvez répondre avec des faits sur l’achat. Répondez de façon étayée et les demandes infondées sont refusées. Restez silencieux et seule la version du client fait foi auprès d’Apple.

Points clés

  • Les demandes de remboursement sur l’App Store déclenchent l’envoi par Apple d’une notification CONSUMPTION_REQUEST à votre serveur, puis une attente allant jusqu’à 12 heures avant de statuer, le temps de recevoir des preuves.

  • Répondre signifie appeler l’endpoint Send Consumption Information avec un payload compact : consentement, statut de livraison, présence éventuelle d’un échantillon, part consommée, et résultat souhaité.

  • Ne rien envoyer constitue déjà une réponse. Apple se base alors uniquement sur la déclaration du client et son historique de compte.

  • Le consentement fonctionne comme un verrou absolu. La documentation d’Apple précise explicitement qu’il ne faut pas répondre du tout lorsque le client n’a pas accepté le partage de ses données de consommation.

  • Pour les abonnements à renouvellement automatique, le pourcentage de consommation est calculé par Apple à partir du temps écoulé, et fournir votre propre valeur génère une erreur.

  • Aucun processus manuel ne tient dans ce délai. Les développeurs qui en profitent sont ceux dont la réponse est assemblée et envoyée automatiquement.

Chaque remboursement sur l’App Store commence de la même façon : quelqu’un se rend sur reportaproblem.apple.com, sélectionne un achat, et choisit un motif.

La notification qui reste le plus souvent sans réponse

Les applications configurées pour App Store Server Notifications V2 reçoivent une notification CONSUMPTION_REQUEST dès qu’un remboursement est demandé. Ce payload contient la transaction, le produit, et, depuis 2024, le motif choisi par le client : UNINTENDED_PURCHASE, FULFILLMENT_ISSUE, UNSATISFIED_WITH_PURCHASE, LEGAL, ou OTHER.

Douze heures démarrent à partir de ce moment, durant lesquelles vous pouvez appeler l’endpoint Send Consumption Information pour faire valoir votre position. Cet endpoint demande volontairement très peu de choses : cinq champs ne portant que des indicateurs et des chiffres.

  • customerConsented indique à Apple si le client a accepté le partage de ses données d’utilisation. Une valeur typique est true.

  • deliveryStatus indique à Apple si l’achat est arrivé et a fonctionné. Une valeur typique est DELIVERED.

  • sampleContentProvided indique à Apple si un échantillon gratuit ou un essai était disponible au préalable. Une valeur typique est true.

  • consumptionPercentage indique à Apple la part consommée, exprimée en milliunités, où 100000 signifie 100 pour cent. Une valeur typique est 67500.

  • refundPreference indique à Apple le résultat que vous privilégiez : accorder, refuser, ou aucune préférence. Une valeur typique est DECLINE.

consumptionPercentage a un périmètre limité : les consommables, les achats uniques, et les abonnements non reconductibles. Pour les abonnements à renouvellement automatique, Apple le calcule à partir du temps écoulé dans la période de facturation, et toute valeur que vous fournissez est rejetée.

Ce qu’Apple fait de ce que vous envoyez

Les informations de consommation sont explicitement utilisées par Apple comme un élément de décision sur l’issue du remboursement. Si vous n’envoyez rien, la décision repose uniquement sur ce qu’a affirmé le client et son historique de compte. Si vous envoyez des preuves, les remboursements contestés sont refusés avec une fréquence réelle.

Construire soi-même le chemin de réponse, de bout en bout

Rien dans cette séquence n’est secret. Tout doit cependant fonctionner sans intervention humaine, à trois heures du matin.

1. Faire arriver les notifications

Dans App Store Connect, ouvrez la page App Information de votre application et configurez une Production Server URL sous App Store Server Notifications, en choisissant Version 2. Les consumption requests ne passent pas par la V1. Chaque notification, remboursements compris, arrive alors à cette URL par POST sous forme de payload JWS signé.

2. Générer la bonne clé

L’authentification des réponses utilise une clé In-App Purchase, créée sous Users and Access, dans la section Integrations. C’est un type de clé distinct, et la clé API App Store Connect qui se trouve à côté n’authentifiera pas ces appels. Le fichier .p8 se télécharge exactement une fois, après quoi vous générez un JWT ES256 à courte durée de vie pour chaque requête.

3. Vérifier, rapprocher, puis décider

Les notifications CONSUMPTION_REQUEST reçues doivent voir leur chaîne de signature JWS validée par rapport aux certificats racine d’Apple avant d’accorder la moindre confiance à leur contenu. Ensuite, reliez la transaction à un utilisateur, idéalement via l’UUID appAccountToken que vous avez attaché lors de l’achat, et récupérez son usage réel. Fixez ensuite une préférence : accordez les situations de bonne foi, contestez celles où le produit a clairement été consommé.

4. Envoyer la réponse avant la fermeture du délai

Envoyez ces cinq champs en PUT vers l’endpoint Send Consumption Information, pour cet identifiant de transaction, dans les 12 heures. Deux erreurs piègent presque tout le monde. Les milliunités régissent le pourcentage, donc 100 % correspond à 100000 et non à un million. Et le consentement conditionne tout le reste, car la documentation d’Apple indique elle-même qu’il ne faut pas répondre du tout en l’absence de consentement du client. Intégrez cette clause de consentement à vos conditions d’utilisation avant de mettre quoi que ce soit de tout cela en production.

Pourquoi tant de développeurs perdent par défaut

Une demi-journée est implacable pour tout ce qui dépend d’une intervention humaine. Les notifications arrivent à 3 heures du matin, un samedi. Ce qu’elles exigent, c’est un serveur capable de valider la chaîne de signature JWS d’Apple, de relier la transaction à un utilisateur, de calculer un pourcentage de consommation en milliunités, et d’appeler une API authentifiée par JWT. Pour chaque demande. Indéfiniment.

En pratique, la liste des étapes est la suivante :

  • Mettre en place App Store Server Notifications V2, sans quoi la demande ne vous parvient jamais.

  • Valider le payload signé par rapport à la chaîne de certificats d’Apple avant de lui accorder la moindre confiance.

  • Relier la transaction à un utilisateur dans votre propre système, généralement via l’appAccountToken attaché lors de l’achat.

  • Calculer un pourcentage de consommation à partir d’un usage réellement enregistré plutôt que d’une estimation.

  • Appeler Send Consumption Information avec une clé In-App Purchase tant que le délai est encore ouvert.

Refund Sensor existe pour prendre en charge cette tâche, en envoyant une réponse complète et étayée bien avant la fin du délai, sans réveiller personne.

Où ces règles sont documentées

Questions fréquentes

Le remboursement est quand même décidé, mais uniquement à partir de la déclaration du client et de son historique de compte. Vous perdez la seule occasion de démontrer que l’achat est bien arrivé et a été largement utilisé. En pratique, les demandes sans réponse sont approuvées bien plus souvent.

Oui. customerConsented doit être à true, et le consentement derrière ce champ doit être réel, généralement recueilli dans celui de vos documents juridiques qui couvre le partage des données. La documentation d’Apple indique elle-même aux développeurs de laisser la notification sans réponse lorsque ce consentement n’existe pas.

Seulement pour les abonnements non reconductibles. Pour les abonnements à renouvellement automatique, Apple calcule la consommation à partir du temps écoulé dans la période de facturation en cours, et l’API refuse tout pourcentage que vous fournissez. Votre préférence de remboursement conserve malgré tout son importance.

Une clé In-App Purchase, générée dans App Store Connect sous Users and Access, dans Integrations. Elle est différente de la clé API App Store Connect, et son fichier .p8 n’est téléchargeable qu’une seule fois, au moment de la création.

En production, vous disposez de 12 heures à partir de la notification. En sandbox, seulement 5 minutes, ce qui est un signal assez clair sur ce qu’Apple attend : de l’automatisation plutôt qu’une personne.

#consumption request#send consumption information#app store server notifications#refunds#storekit#ios
Refund SensorRefund Sensor TeamRefund defense for App Store and Google Play developers