Alle artikelen
Deep dive8 min leestijd

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.

Een smartphone gloeit op een donker bureau van een ontwikkelaar naast een mechanische klok, ter illustratie van het detecteren van terugbetalingen in StoreKit 2 dat in een app opduikt

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.

EigenschapTypeWat een waarde ongelijk aan nil betekent
revocationDateDate?De App Store betaalde deze transactie terug, of trok die in via Family Sharing, op deze datum
revocationReason is developerIssueredenDe klant noemde een werkelijk of vermeend probleem in uw app
revocationReason is otherredenDe terugbetaling gebeurde om een andere reden die Apple niet specificeert
revocationReason is upgradedToBundleredenGeen 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.

Een verfrommelde papieren bon op een donker oppervlak met een vage rode stempel eroverheen gedrukt, als beeld voor een terugbetaalde transactie die StoreKit 2 markeert met een intrekkingsdatum

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.

SignaalWaar het leeftVuurt wanneerVertrouw erop dat het
revocationDate op een transactieToestel, StoreKit 2Uw app de transactie leestU vertelt dat een specifieke aankoop is terugbetaald of ingetrokken
Transaction.updatesToestel, StoreKit 2Een terugbetaling binnenkomt terwijl de app draait, of bij het opstarten als u luistertOnmiddellijk reageert voor een klant die aanwezig is
currentEntitlementsToestel, StoreKit 2U controleert wat de klant nu bezitDe toegang bewaakt zonder dat u zelf terugbetalingen bijhoudt
REFUND-meldingUw server, App Store Server Notifications V2Apple de terugbetaling verwerkt, app open of nietUitgaven 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

RefundHalt

De terugbetalingsautopiloot voor de App Store en Google Play

Lees verder

Het volgende terugbetalingsverzoek is al onderweg.

Stel RefundHalt in binnen de tijd die het kost om nog een supportmail te lezen over een terugbetaling die je niet kon betwisten.