Drie App Store terugbetalingsmeldingen komen binnen nadat Apple heeft beslist, en REFUND_REVERSED geeft de verkoop terug
Apple stuurt vier terugbetalingsberichten via App Store Server Notifications V2, en de meeste apps verwerken er maar twee. REFUND zegt dat je moet intrekken, REFUND_DECLINED betekent de verkoop behouden, en REFUND_REVERSED geeft de verkoop terug en vraagt je te herstellen wat je hebt weggenomen. Hier staat wat elke melding vereist.

Belangrijkste inzichten
- Apple stuurt vier terugbetalingsgerelateerde berichten via App Store Server Notifications V2. CONSUMPTION_REQUEST vraagt om je bewijs, en REFUND, REFUND_DECLINED en REFUND_REVERSED melden de uitkomst nadat Apple al heeft beslist.
- Een REFUND-melding betekent dat de App Store de transactie heeft terugbetaald. Ze bevat revocationDate en revocationReason en is je signaal om het recht dat aan die ene transactie is gekoppeld in te trekken, niet elke aankoop van dat product.
- revocationReason heeft twee waarden. 1 betekent dat de terugbetaling is verleend vanwege een probleem met je product, en 0 betekent dat ze om een andere reden is verleend. De probleemwaarde is een kwaliteitssignaal dat het loggen en volgen waard is.
- REFUND_DECLINED betekent dat Apple de terugbetaling van de klant heeft afgewezen. Je behoudt de verkoop en verandert niets, wat alleen veilig is als je de toegang niet hebt ingetrokken voordat de beslissing definitief was.
- REFUND_REVERSED betekent dat Apple een eerder verleende terugbetaling heeft teruggedraaid, meestal nadat de klant deze betwist. De intrekkingsvelden verdwijnen van de transactie, en Apples eigen instructie is dat als je content hebt ingetrokken, je die opnieuw moet inschakelen.
- Beantwoord alle vier de meldingen met HTTP 200. Als je server plat lag en er een miste, laat het Get Refund History endpoint je terugbetaalde transacties per transactie-id opzoeken en afstemmen.
- Een terugbetaling voor een voorbije abonnementsperiode betekent niet altijd dat de toegang moet eindigen. Als een nieuwere betaalde periode nog actief is, sluit intrekken op de oude transactie een klant buiten die bij is.
Apple beslist over je terugbetaling, en daarna blijft het praten. Zodra de uitkomst vaststaat, stuurt de App Store je server een van drie App Store terugbetalingsmeldingen, en elke vraagt om een andere stap. Een REFUND zegt dat het geld weg is en dat je de toegang moet intrekken. Een REFUND_DECLINED zegt dat de klant het verzoek heeft verloren en dat je de verkoop behoudt. Een REFUND_REVERSED zegt dat Apple een reeds verleende terugbetaling heeft teruggedraaid, dus de verkoop is weer van jou en je moet teruggeven wat je ook had weggenomen. De meeste apps zetten de eerste op en negeren de andere twee stilletjes. Zo raakt een betalende klant buitengesloten van iets waarvoor hij heeft betaald.
Deze drie staan los van CONSUMPTION_REQUEST, het enige terugbetalingsbericht dat om een antwoord vraagt. De meldingen na de beslissing willen geen discussie. Ze willen een HTTP 200 en de juiste wijziging in de toegang van de klant. Hier staat wat elke betekent, welke exacte velden de feiten dragen, en waar het geld weglekt als je ze verkeerd afhandelt.
De vier terugbetalingsmeldingen, en welke om een antwoord vraagt
App Store Server Notifications V2 is een enkele feed. Je richt hem op een URL en Apple stuurt er elk meldingstype naartoe, dus je ontvangt al alle vier de terugbetalingsberichten of je ze nu afhandelt of niet. Vier van de types raken terugbetalingen, en slechts een ervan is een vraag.
| Melding | Wat Apple je vertelt | Jouw actie | Antwoord verwacht |
|---|---|---|---|
| CONSUMPTION_REQUEST | Een klant vroeg om een terugbetaling en Apple wil je gegevens | Send Consumption Information binnen 12 uur | Ja, echte gegevens |
| REFUND | De App Store heeft de transactie terugbetaald | Trek het recht voor die transactie in | Nee, HTTP 200 |
| REFUND_DECLINED | De App Store heeft de terugbetaling afgewezen | Behoud toegang, verander niets | Nee, HTTP 200 |
| REFUND_REVERSED | Apple heeft een verleende terugbetaling teruggedraaid | Herstel de content die je introk | Nee, HTTP 200 |
Wat een REFUND-melding je werkelijk vertelt
REFUND wordt geactiveerd wanneer de App Store een transactie met succes aan een klant heeft terugbetaald. Het geldt voor elk aankooptype: een verbruiksartikel, een niet-verbruiksartikel, een automatisch verlengend abonnement en een niet-verlengend abonnement. De ondertekende transactie in de melding draagt nu twee velden die ze voor de terugbetaling niet had, en die twee velden zijn het hele verhaal.
revocationDate en revocationReason dragen de feiten
revocationDate is de UNIX-tijd, in milliseconden, waarop de App Store de transactie heeft terugbetaald of ingetrokken. revocationReason geeft je de categorie van de terugbetaling, en neemt precies twee waarden aan.
| revocationReason | Apples betekenis | Wat je erin moet lezen |
|---|---|---|
| 1 | De terugbetaling werd verleend vanwege een probleem met het product | Een kwaliteits- of leveringssignaal. Log het, volg de trend en zoek naar een patroon in een product of een build |
| 0 | De terugbetaling werd om een andere reden verleend | Een gewone terugbetaling. Trek het recht in en ga verder |
De aanwezigheid van een revocationDate op een transactie is zelf de vlag. Als je later een transactie ophaalt en die een revocationDate heeft, is die aankoop terugbetaald, met of zonder melding. Lees de reden ernaast zodat een golf van terugbetalingen met waarde 1 op een enkele release je niet als ruis ontgaat.
Trek in per transactie, niet per product
De valkuil hier is te veel intrekken. Een REFUND noemt een transactie. Het zegt je niet elke aankoop uit te schakelen die de klant ooit van die product-id heeft gedaan. Apples eigen richtlijn is te controleren welke toegang de klant nog heeft voordat je iets afsnijdt, omdat rechten overlappen. Het klassieke geval is een abonnement: een terugbetaling landt op de verlenging van vorige maand terwijl de verlenging van deze maand actief en volledig betaald is. Trek in op het product en je hebt zojuist een actuele, betalende klant buitengesloten vanwege een terugbetaling voor een periode die al voorbij was.
REFUND_DECLINED betekent dat je al hebt gewonnen, dus maak het niet ongedaan
REFUND_DECLINED komt binnen wanneer de App Store het terugbetalingsverzoek van de klant heeft afgewezen. De klant vroeg, Apple zei nee, en jij behoudt de verkoop. Op het eerste gezicht is er niets te doen, en dat is precies het punt. De fout die deze melding blootlegt is een andere: de toegang te vroeg intrekken.
Als je code op de CONSUMPTION_REQUEST reageert door de toegang van de klant weg te nemen voordat Apple heeft geoordeeld, is een REFUND_DECLINED het moment waarop die beslissing ontploft. Apple hield je geld, en jij sloot een klant buiten wiens terugbetaling werd geweigerd. Die klant betaalt nu voor een product dat hij niet kan gebruiken, opent een supportticket en onthoudt het. De oplossing is een regel, geen functie: trek in bij REFUND, nooit bij het verzoek. REFUND_DECLINED is simpelweg Apple dat bevestigt dat vroeg intrekken de verkeerde keuze zou zijn geweest.
REFUND_REVERSED is de melding die je terugbetaalt
REFUND_REVERSED is degene die vrijwel niemand afhandelt, en het is degene die geld naar jou terugbrengt. Apple stuurt het wanneer het een eerder verleende terugbetaling terugdraait, meestal nadat de klant die terugbetaling betwist. De intrekkingsvelden die een REFUND aan de transactie toevoegde, worden weer verwijderd, zodat de aankoop opnieuw als betaald leest. Apple verwoordt de taak van de ontwikkelaar in een zin: als je app content of diensten heeft ingetrokken als gevolg van de bijbehorende terugbetaling, moet die worden hersteld. Het geldt voor elk aankooptype, van een verbruiksartikel tot een automatisch verlengend abonnement.
Het weken-later-probleem
De echte vraag die ontwikkelaars stellen, op Apples eigen forums, is timing. Een REFUND_REVERSED kan weken na de oorspronkelijke REFUND landen, lang nadat een abonnementsperiode is verlopen. Herstel je de toegang dan? Herstel wat de transactie werkelijk verleent, beperkt tot wat die transactie dekt. Voor een verbruiksartikel of een niet-verbruiksartikel zet je de ontgrendeling weer aan. Voor een abonnementsperiode die al is verstreken, deel je geen nieuwe tijd uit, je corrigeert de administratie zodat de geschiedenis van de klant klopt en elk nog geldig recht weer actief wordt. Herstel de specifieke transactie, en je overlaplogica beslist wat momenteel actief is.

Waar het geld zit in dit goed doen
Elk van deze meldingen komt overeen met een echt getal, en de kosten van verkeerd afhandelen zijn niet alleen de verkoopprijs.
REFUND: stop met betalen om een terugbetaalde klant te bedienen
De verkoopprijs is weg op het moment dat REFUND binnenkomt. Wat je nog kunt sturen zijn de kosten van blijven leveren. Elk uur dat een terugbetaald recht actief blijft, blijf je uitgeven aan de dingen waarvoor de klant niet langer betaalt: rekenkracht, model-API-aanroepen, opslag, en elke aan zijn gebruik gekoppelde uitbetaling aan een maker of partner. Snel intrekken bij REFUND stopt die meter. De melding negeren betekent dat je een product financiert voor iemand die de store al schadeloos heeft gesteld.
REFUND_DECLINED: verander een overwinning niet in een terugbetaling uit goodwill
Wanneer je te vroeg intrekt en de terugbetaling later wordt afgewezen, hield je de verkoop op papier en verloor je hem in de praktijk. De klant die betaalde kan het product niet gebruiken, dus erf je een supportgesprek en, vaak, een discretionaire terugbetaling om het recht te zetten. Dat is tweemaal betalen voor een verkoop die nooit in gevaar was. REFUND_DECLINED correct afhandelen kost niets, en dat is precies waarom de toegang onaangeroerd laten tot REFUND de goedkoopste regel is die je kunt aannemen.
REFUND_REVERSED: de ergste combinatie is dat hun geld en hun toegang allebei weg zijn
Negeer REFUND_REVERSED en je bereikt de slechtste uitkomst op het bord. Je bent betaald, en de klant heeft niets. Hij nam al een keer contact op met zijn bank om de terugbetaling terug te draaien, en iemand die buitengesloten is van een product waarvoor hij nu wordt belast, is iemand die de bank waarschijnlijk een tweede keer belt. Dat volgende geschil kan een kaart-chargeback worden, die bankdefinitief is en meer kost dan de verkoop ooit deed. De toegang herstellen op het moment dat REFUND_REVERSED binnenkomt, is de goedkoopste verzekering in het hele terugbetalingsproces.
Wat je moet opzetten
De afhandeling is klein zodra het model klopt. Koppel rechten aan de transactie-id zodat elke melding naar een aankoop wijst. Bij CONSUMPTION_REQUEST stuur je je gegevens binnen 12 uur. Bij REFUND trek je die transactie in. Bij REFUND_DECLINED doe je niets. Bij REFUND_REVERSED herstel je. Geef bij allemaal snel een HTTP 200 terug en voer de toegangswijziging in je eigen tempo uit.
Voor het gat dat meldingen achterlaten, gebruik je het Get Refund History endpoint. Als je server tijdens een storing plat lag en een REFUND miste, roep je de terugbetalingsopzoeking van de App Store Server API aan voor een transactie-id, op /inApps/v2/refund/lookup/{transactionId}, en lees je de ondertekende transacties met hun revocationDate en revocationReason terug. Het stemt een transactie per keer af en bladert door de terugbetaalde aankopen van een klant, zodat een gemiste webhook niet uitmondt in een permanent verkeerd ingesteld recht.
Dit is het deel dat RefundHalt voor je uitvoert. Het luistert naar alle vier de types, trekt in bij REFUND, houdt de toegang onaangeroerd bij REFUND_DECLINED, en herstelt automatisch bij REFUND_REVERSED, elk gekoppeld aan de exacte transactie. Een teruggedraaide terugbetaling blijft niet in een wachtrij staan terwijl een betalende klant buitengesloten blijft, en een afgewezen terugbetaling activeert nooit een intrekking die je zou moeten terugdraaien.
Veelgestelde vragen
- Wat is het verschil tussen REFUND en REFUND_REVERSED?
- REFUND betekent dat de App Store een transactie heeft terugbetaald en dat je dat recht moet intrekken, terwijl REFUND_REVERSED betekent dat Apple een verleende terugbetaling heeft teruggedraaid en dat je de ingetrokken content moet herstellen. De twee zijn een paar: een aankoop kan REFUND doorlopen en daarna, als het geschil van de klant wordt teruggedraaid, REFUND_REVERSED. Koppel je toegangswijzigingen aan de transactie-id zodat elke melding op de juiste aankoop inwerkt.
- Moet ik iets terugsturen voor een REFUND-melding?
- Nee. Je beantwoordt REFUND, REFUND_DECLINED en REFUND_REVERSED met een HTTP 200 en zonder body. Alleen CONSUMPTION_REQUEST vraagt je gegevens te sturen, en dat doet het via het Send Consumption Information endpoint binnen 12 uur. De andere drie zijn Apple dat een beslissing meldt, geen vraag stelt.
- Wat moet ik doen als ik een REFUND_DECLINED-melding krijg?
- Er verandert niets, omdat de terugbetaling van de klant is geweigerd en jij de verkoop behoudt. De enige manier waarop REFUND_DECLINED werk veroorzaakt, is als je de toegang te vroeg introk, voordat Apple oordeelde. Trek in bij REFUND in plaats van bij de CONSUMPTION_REQUEST, en een REFUND_DECLINED wordt een bevestiging dat de toegang terecht ongemoeid is gelaten.
- Moet ik de toegang herstellen wanneer REFUND_REVERSED weken na de terugbetaling binnenkomt?
- Ja, herstel het recht dat die specifieke transactie verleent. Apple stelt dat als je app content heeft ingetrokken vanwege de bijbehorende terugbetaling, die moet worden hersteld. Voor een verbruiksartikel of niet-verbruiksartikel zet je de ontgrendeling weer aan. Voor een abonnementsperiode die al is verlopen corrigeer je de administratie, verleen je geen nieuwe tijd, dus beslist je overlaplogica nog steeds wat momenteel actief is.
- Hoe vang ik een terugbetalingsmelding op die mijn server heeft gemist?
- Gebruik het Get Refund History endpoint van de App Store Server API, dat terugbetaalde transacties voor een klant opzoekt per transactie-id op /inApps/v2/refund/lookup/{transactionId}. Het geeft ondertekende transacties terug met revocationDate en revocationReason, zodat je na een storing de toegang kunt afstemmen zonder te wachten op een melding die al is afgevuurd. Het verwerkt een transactie-id per aanroep en bladert door de terugbetaalde aankopen van de klant.
Bronnen en verder lezen
RefundHalt
De terugbetalingsautopiloot voor de App Store en Google Play
Lees verder
Elk Apple-restitutieverzoek komt nu met een reden, en consumptionRequestReason is hoe je die leest
Sinds WWDC24 draagt elke Apple CONSUMPTION_REQUEST een consumptionRequestReason, de door de klant zelf opgegeven reden voor het willen van een restitutie. Er zijn vijf waarden, van UNINTENDED_PURCHASE tot LEGAL, en elke zou moeten veranderen wat je binnen je venster van 12 uur terugstuurt. Zo lees je ze allemaal.
De chargeback-beoordeling van Google Play geeft je 24 uur om terug te vechten, dit stuur je
Wanneer een bank een Google Play-betaling terugboekt, stuurt Google een PendingRefundReviewNotification naar je server en start een klok van 24 uur. Beantwoord die via de ReviewRefund API met een terugbetalingsvoorkeur en echt verbruiksbewijs, of het geschil wordt zonder jou beslist. Hier is de hele flow, veld voor veld.