Het detecteren van terugbetalingen in StoreKit 2 komt neer op één eigenschap van de transactie, en dat is revocationDate
Wanneer Apple een van uw klanten terugbetaalt, zit de terugbetaling al in uw app op de revocationDate van de transactie, voordat uw servertaak draait. Hier leest u waar het detecteren van terugbetalingen in StoreKit 2 op het toestel opduikt, wat revocationDate en revocationReason u vertellen, en waarom de client er is voor snelheid en de server voor de waarheid.

Belangrijkste inzichten
- In StoreKit 2 draagt een terugbetaalde aankoop een revocationDate ongelijk aan nil op zijn Transaction, zodat uw app de terugbetaling zelf kan detecteren, zonder uw server aan te roepen.
- revocationDate wordt gezet wanneer de App Store een transactie terugbetaalt of wanneer een klant die verliest via Family Sharing, dus een datum ongelijk aan nil is niet altijd een terugbetaling.
- revocationReason vertelt u waarom: developerIssue betekent dat de klant een probleem in uw app noemde, en other dekt elke overige reden voor terugbetaling.
- Transaction.currentEntitlements sluit terugbetaalde en ingetrokken aankopen al uit, dus de schoonste toegangscontrole aan de clientzijde is simpelweg of een product daar nog verschijnt.
- Transaction.updates levert een terugbetaling die plaatsvond terwijl uw app gesloten was alleen als u bij het opstarten begint te luisteren, dus een ontbrekende Task betekent een gemiste terugbetaling.
- Detectie aan de clientzijde vuurt alleen terwijl de app open is, en daarom blijft App Store Server Notifications V2 REFUND het gezaghebbende signaal dat u ervoor behoedt te betalen om een terugbetaalde gebruiker te bedienen.
- Een terugbetaling kan worden teruggedraaid, en wanneer dat gebeurt, worden de intrekkingsvelden uit de transactie verwijderd en wordt van u verwacht dat u de toegang herstelt die u had afgesneden.
De meeste apps horen over een terugbetaling van Apple via hun server, door een App Store Server Notification, en merken nooit dat diezelfde terugbetaling al in de app zit. Ze staat op de transactie, in een eigenschap genaamd revocationDate, en door die te lezen kan uw app de toegang van een terugbetaalde klant afsnijden de volgende keer dat hij hem opent, in plaats van te wachten op een backendtaak. Het detecteren van terugbetalingen in StoreKit 2 is een signaal aan de clientzijde dat de meeste teams overslaan. Hier staat precies waar een terugbetaling op het toestel opduikt, wat ze u vertelt, wat niet, en waarom ze naast uw serverberichten hoort en niet in plaats daarvan.
Waar een terugbetaling opduikt in StoreKit 2
StoreKit 2 geeft u transacties als ondertekende waarden, en een terugbetaling verwijdert de transactie niet. Ze markeert die. Twee eigenschappen op de Transaction dragen de markering, en beide blijven nil gedurende het hele leven van een gezonde aankoop. Wanneer een ervan ongelijk aan nil wordt, heeft de App Store de aankoop teruggenomen.
revocationDate is het veld dat omslaat
revocationDate is een optionele Date. Apples eigen beschrijving is exact: het is de datum waarop de App Store de transactie terugbetaalde of die introk uit Family Sharing. Voor een aankoop die nog goed is, is het nil. Op het moment dat een terugbetaling wordt verwerkt, houdt het de tijdstempel van die terugbetaling vast. Die ene controle, is revocationDate ongelijk aan nil, is het geheel van terugbetalingsdetectie aan de clientzijde. Al het andere is nuance die daarbovenop is gestapeld.
revocationReason vertelt u waarom Apple hem introk
revocationReason staat naast de datum en verklaart de oorzaak. StoreKit geeft die twee waarden die van belang zijn voor terugbetalingen. developerIssue betekent dat de klant Apple vertelde dat de terugbetaling te wijten was aan een werkelijk of vermeend probleem in uw app. other dekt elke overige reden. Een derde waarde, upgradedToBundle, is helemaal geen terugbetaling; die markeert een transactie die de App Store introk omdat de klant overstapte naar een abonnementsbundel. Lees de reden voordat u handelt, want developerIssue is degene die het waard is te tellen: een cluster daarvan is uw eigen product dat u vertelt waar het brak.
| Eigenschap | Type | Wat een waarde ongelijk aan nil betekent |
|---|---|---|
revocationDate | Date? | De App Store betaalde deze transactie terug, of trok die in via Family Sharing, op deze datum |
revocationReason is developerIssue | reden | De klant noemde een werkelijk of vermeend probleem in uw app |
revocationReason is other | reden | De terugbetaling gebeurde om een andere reden die Apple niet specificeert |
revocationReason is upgradedToBundle | reden | Geen terugbetaling; de transactie werd ingetrokken omdat de klant overstapte naar een abonnementsbundel |
currentEntitlements laat een terugbetaalde aankoop al vallen
U hoeft de intrekkingsvelden niet altijd zelf te lezen. Transaction.currentEntitlements is de reeks aankopen waarop een klant nu nog recht heeft, en Apple bouwt die zo dat degene die u niet zou moeten honoreren eruit blijven. Een product dat de App Store heeft terugbetaald of ingetrokken verschijnt er niet in. Evenmin verlopen abonnementen, of verbruiksartikelen, die weg zijn zodra ze op zijn.
Dat maakt currentEntitlements de schoonste toegangscontrole. Vraag hem wat de klant bezit, verleen precies dat, en een terugbetaling verwijdert het recht voor u zonder ook maar één revocationDate-controle. De intrekkingsvelden zijn voor wanneer u het detail wilt, de datum en de reden, om de gebeurtenis te loggen of erop te reageren. De rechtenlijst is voor de simpele vraag of het licht aanblijft.
Het detecteren van terugbetalingen in StoreKit 2 in de praktijk, bij het opstarten en terwijl de app draait
Er zijn twee momenten waarop uw app een terugbetaling op het toestel kan opvangen, en ze vragen om verschillende code. Het ene is terwijl de app open is en een terugbetaling live of op een ander toestel plaatsvindt. Het andere is bij het opstarten, waarbij alles wordt ingehaald wat veranderde terwijl u gesloten was. Mis het tweede en uw terugbetalingsdetectie in StoreKit 2 heeft een gat precies daar waar de meeste terugbetalingen vallen, want klanten hebben uw app zelden open wanneer ze er een aanvragen.
Begin bij het opstarten te luisteren, anders mist u de terugbetalingen die gesloten plaatsvonden
Transaction.updates is de asynchrone reeks die een transactie uitzendt telkens wanneer het systeem er een aanmaakt of bijwerkt buiten uw app of op een ander toestel, een terugbetaling inbegrepen. Apples instructie is bot: start een Task die die doorloopt zodra uw app opstart, anders mist u mogelijk de transacties die die maar één keer bij het opstarten levert. Een terugbetaling die 's nachts binnenkwam arriveert via updates de volgende keer dat de app opent, maar alleen als er al een luisteraar draait om die te ontvangen. Geen luisteraar, geen gebeurtenis, en de terugbetaling blijft onzichtbaar totdat iets anders die verzoent.
Een aankoop op hetzelfde toestel komt niet via updates binnen
Eén valstrik vangt mensen die terugbetalingen met de hand testen. Een gewone aankoop gedaan op hetzelfde toestel arriveert niet via updates; StoreKit geeft die rechtstreeks terug uit het resultaat van de aankoopaanroep. updates is voor de wijzigingen buiten de normale weg: terugbetalingen, goedkeuringen via Ask to Buy, inwisselingen van aanbiedingscodes en elders gedane aankopen. Bouw uw terugbetalingsafhandeling dus rond updates en currentEntitlements, niet rond de aankoopstroom, want de terugbetaling zal nooit teruglopen langs het pad dat de verkoop nam.

Wat detectie aan de clientzijde niet voor u kan doen
Terugbetalingen op het toestel lezen is snel en gratis, maar het heeft een plafond, en doen alsof dat er niet is, is hoe omzet weglekt. Het toestel weet alleen wat StoreKit het heeft verteld, en StoreKit spreekt alleen terwijl uw app draait. Een klant die een terugbetaling krijgt en uw app nooit meer opent, is een klant die uw controle aan de clientzijde nooit ziet.
Een revocationDate is niet altijd een terugbetaling
Hetzelfde veld slaat om voor Family Sharing. Wanneer een klant de toegang tot een gedeelde aankoop verliest, doordat de organisator hem verwijderde of het delen eindigde, krijgt die transactie ook een revocationDate. Een datum ongelijk aan nil betekent dus dat de klant deze aankoop niet meer heeft, wat precies is wat u nodig hebt voor toegangscontrole, maar het betekent niet altijd dat er geld terugkwam. Als u terugbetalingen telt voor de omzet, scheid dan de Family Sharing-intrekkingen van de echte voordat u het getal vertrouwt.
Een terugbetaling kan worden teruggedraaid
Een terugbetaling is niet altijd definitief. Apple kan er een terugdraaien, en wanneer dat gebeurt, worden de intrekkingsvelden uit de transactie verwijderd en is de aankoop weer geldig. Als u de toegang bij de terugbetaling afsneed, wordt van u verwacht dat u die bij de terugdraaiing herstelt. Op het toestel verschijnt dat als nog een updates-gebeurtenis met een schone transactie; op uw server is het een aparte REFUND_REVERSED-melding. Handel alleen de terugbetaling af en u laat een betalende klant stranden zonder toegang en met een werkende bon.
Wat een late intrekking werkelijk kost
Een terugbetaling is zelden alleen de verkoopprijs die uw rekening verlaat. Tegen de tijd dat die is afgerond hebt u meestal al echt geld uitgegeven om die aankoop te bedienen, en die uitgave komt niet terug. De gegenereerde afbeeldingen kosten GPU-minuten. De chatantwoorden kosten aanroepen van model-API's die u per token werden aangerekend. De uploads kosten opslag die u nog steeds betaalt om te bewaren. Als de aankoop een uitbetaling aan een maker financierde, is dat geld al de deur uit. Niets daarvan draait om met de terugbetaling.
Detectie aan de clientzijde verkleint het venster op het ene deel dat u nog kunt sturen, de toekomstige uitgaven. Hoe eerder u weet dat een aankoop is terugbetaald, hoe eerder u stopt die te bedienen. Maar het toestel vertelt het u alleen terwijl de app open is, dus een terugbetaalde gebruiker die nooit terugkomt behoudt alle toegang aan de serverzijde die u verleende, en kost u stilletjes elke keer dat een achtergrondtaak of een gesynchroniseerd toestel namens hem handelt. De client maakt de intrekking snel. Hij maakt die niet gegarandeerd.
Gebruik de client voor snelheid en de server voor de waarheid
Het schone ontwerp gebruikt beide signalen voor waar elk goed in is. Op het toestel geven Transaction.updates en currentEntitlements u een onmiddellijke, lokale reactie op het moment dat een terugbetaalde klant de app opent, goed voor de interface en om rechtenwijzigingen af te ronden zonder een heen-en-weerreis. Op de server sturen App Store Server Notifications V2 een REFUND-bericht dat aankomt of de app ooit weer geopend wordt of niet, en dat is het enige signaal dat uw backend betrouwbaar ervan weerhoudt geld uit te geven aan een terugbetaald account.
| Signaal | Waar het leeft | Vuurt wanneer | Vertrouw erop dat het |
|---|---|---|---|
revocationDate op een transactie | Toestel, StoreKit 2 | Uw app de transactie leest | U vertelt dat een specifieke aankoop is terugbetaald of ingetrokken |
Transaction.updates | Toestel, StoreKit 2 | Een terugbetaling binnenkomt terwijl de app draait, of bij het opstarten als u luistert | Onmiddellijk reageert voor een klant die aanwezig is |
currentEntitlements | Toestel, StoreKit 2 | U controleert wat de klant nu bezit | De toegang bewaakt zonder dat u zelf terugbetalingen bijhoudt |
REFUND-melding | Uw server, App Store Server Notifications V2 | Apple de terugbetaling verwerkt, app open of niet | Uitgaven aan de serverzijde stopt voor een klant die nooit terugkeert |
Bedraad de toestelsignalen voor de klant die de telefoon vasthoudt, en de servermelding voor degene die dat niet doet. De terugbetaling verschijnt met opzet op beide plekken. Slechts een van beide lezen is hoe een terugbetaald account u blijft kosten nadat de verkoop al weg is.
Veelgestelde vragen
- Hoe detecteer ik een terugbetaling in StoreKit 2?
- Controleer de revocationDate van de transactie. Die is nil voor een geldige aankoop en houdt een datum vast zodra de App Store de transactie terugbetaalt, dus een revocationDate ongelijk aan nil is het signaal dat een aankoop is terugbetaald of ingetrokken.
- Wat is het verschil tussen revocationDate en revocationReason?
- revocationDate is wanneer de App Store de aankoop terugnam, en revocationReason is waarom. De reden is developerIssue wanneer de klant een probleem in uw app noemde en other voor al het andere.
- Verschijnt een terugbetaalde aankoop nog in currentEntitlements?
- Nee. Transaction.currentEntitlements sluit aankopen uit die de App Store heeft terugbetaald of ingetrokken, dus een terugbetaald product valt vanzelf uit de rechten van de klant, wat het een veilige toegangscontrole maakt.
- Vertelt StoreKit mijn app over een terugbetaling die plaatsvond terwijl de app gesloten was?
- Alleen als u vanaf het opstarten luistert. Transaction.updates levert die wijzigingen eenmaal bij het opstarten, dus u moet een Task starten die die doorloopt zodra uw app opstart, anders wordt de terugbetaling gemist totdat iets anders die verzoent.
- Is terugbetalingsdetectie aan de clientzijde op zichzelf genoeg?
- Nee. Het toestel hoort alleen over een terugbetaling terwijl uw app draait, dus een klant die de app nooit meer opent is er onzichtbaar voor. App Store Server Notifications V2 REFUND is het signaal dat u hoe dan ook bereikt.
- Betekent een revocationDate altijd dat de klant werd terugbetaald?
- Nee. revocationDate wordt ook gezet wanneer een klant een aankoop verliest via Family Sharing, dus een datum ongelijk aan nil betekent dat hij de aankoop niet meer heeft maar niet altijd dat er geld werd teruggegeven.
Bronnen en verder lezen
- Apple Developer: Transaction.revocationDate (StoreKit)
- Apple Developer: Transaction.RevocationReason (StoreKit)
- Apple Developer: Transaction.currentEntitlements (StoreKit)
- Apple Developer: Transaction.updates (StoreKit)
- Apple Developer: App Store Server Notifications V2 notificationType (REFUND, REFUND_REVERSED)
- Apple Developer Tech Talk: Support customers with StoreKit 2 and App Store Server API
RefundHalt
De terugbetalingsautopiloot voor de App Store en Google Play
Lees verder
Elk App Store- en Google Play-restitutievenster is een aftelklok, en zo veel uur geeft elk venster je
Elke restitutie in de App Store en Google Play start een klok, en de meeste lopen zonder jou door. Apple's kortste restitutievenster is 12 uur, Google's chargeback-venster is 24, en vanaf 3 augustus 2026 is een gemist chargeback-venster een rekening, niet alleen een verloren verkoop. Hier is elke deadline die je account raakt.
Een melding van een geannuleerde aankoop laat je Google Play-server de toegang intrekken op het moment dat een terugbetaling binnenkomt
Google Play kan je server direct een melding van een geannuleerde aankoop sturen zodra een aankoop wordt terugbetaald, teruggeboekt of geannuleerd. Ze draagt een purchaseToken, orderId, productType en refundType, en betekent één ding, trek de toegang in. Zo lees je haar en sluit je haar aan.