Alle artikelen
Deep dive7 min leestijd

Koppel een appAccountToken aan elke App Store-aankoop, anders kun je de terugbetaling niet verdedigen

Apple stuurt je server een CONSUMPTION_REQUEST wanneer een klant om een terugbetaling vraagt, maar de transactie zegt nooit wie diegene is. appAccountToken is de UUID die een aankoop terugkoppelt aan je gebruiker. Stel hem in en je kunt Apple met echte gegevens antwoorden. Sla hem over en je gokt.

Een genummerde messing sleutel ligt op een donker grootboek naast een smartphone die een aankoopbon toont, en illustreert hoe een appAccountToken een App Store-aankoop koppelt aan een gebruikersaccount

Belangrijkste inzichten

  • appAccountToken is een UUID die je aan een App Store-aankoop koppelt, zodat de resulterende transactie terugwijst naar precies de gebruiker in je eigen systeem. Apple bewaart hem op de transactie en geeft hem overal terug waar die transactie verschijnt.
  • De enige opmaakregel die Apple afdwingt, is dat de waarde een geldige UUID is. Geef je iets anders door, een id, een e-mail, een samengevoegde tekenreeks, dan laat StoreKit hem stil vallen en geeft appAccountToken terug als nil.
  • In StoreKit 2 stel je hem in met één aankoopoptie, Product.PurchaseOption.appAccountToken(_:), met een stabiele UUID die je voor dat account hebt gegenereerd en opgeslagen.
  • Stel hem één keer in bij de oorspronkelijke aankoop en Apple draagt hetzelfde token mee over elke verlenging, elke incassopoging en elke upgrade in de abonnementsketen.
  • Sinds 2025 laat het Set App Account Token-eindpunt je server een token koppelen aan aankopen buiten je app, zoals het inwisselen van aanbiedingscodes en gepromote aankopen, die de in-app-flow nooit kon bereiken.
  • appAccountToken is wat Apples CONSUMPTION_REQUEST beantwoordbaar maakt. Zonder hem kun je de terugbetaling niet koppelen aan de klant wiens gebruik je binnen het venster van 12 uur moet beschrijven.
  • Een terugbetaling die je niet kunt identificeren, is een terugbetaling die je niet kunt verdedigen. Je geeft geld terug op aankopen die je met bewijs had kunnen behouden, plus de rekenkracht, API-aanroepen en uitbetalingen die je al hebt uitgegeven om ze te leveren.

Een klant vraagt Apple om een terugbetaling, Apple stuurt je server een CONSUMPTION_REQUEST, en je hebt twaalf uur om te antwoorden met echte gegevens over hoe die persoon het product heeft gebruikt. Dan open je de melding en besef je dat je geen idee hebt wie diegene is. De transactie draagt een originalTransactionId en een product-id, maar niets dat wijst naar het account in je eigen database. Precies dat gat sluit appAccountToken, en als je hem niet bij de aankoop hebt ingesteld, kun je hem achteraf niet meer sluiten voor die verkoop.

appAccountToken is een UUID die je aan een aankoop koppelt, zodat de resulterende App Store-transactie een verwijzing draagt naar precies de gebruiker in je systeem. Stel hem in, en elke terugbetalingsvraag die Apple ooit over die klant stelt, komt binnen met diens identiteit erbij. Sla hem over en je gokt. Hier staat wat het veld is, hoe je het instelt, welk nieuw eindpunt aankopen buiten je app redt, en wat de ontbrekende koppeling echt kost wanneer er een terugbetaling binnenkomt.

Wat appAccountToken eigenlijk is

appAccountToken is een ondoorzichtige UUID die je genereert en op het moment van de aankoop aan StoreKit doorgeeft. Apple bewaart hem op de transactie en geeft hem terug in de transactie-informatie voor die aankoop, en daar blijft hij. In Apples woorden is het "de UUID die de transactie koppelt aan het account van de gebruiker in je eigen dienst." De enige opmaakregel is dat het een UUID moet zijn. Apple leest hem niet, valideert niet waarnaar hij verwijst, en het maakt Apple niet uit wat hij aan jouw kant betekent. Het is een koppeling die jij beheert.

Omdat hij op de transactie leeft, komt hij overal terug waar de transactie terugkomt. De ondertekende transactie in een servermelding, het antwoord van Get Transaction Info van de App Store Server API, en elke verlenging in een abonnementsketen dragen allemaal hetzelfde token als je het bij de oorspronkelijke aankoop hebt ingesteld. Eén UUID, één keer gekoppeld, volgt de facturering van de klant gedurende de hele relatie.

Het moet een echte UUID zijn, anders verdwijnt hij stil

De ene regel die Apple afdwingt, is het formaat. StoreKit 2 vereist een RFC 4122 UUID. Geef je een samengevoegde tekenreeks, een integer-id of een e-mailadres door, dan gooit StoreKit geen fout. Het laat de waarde vallen en de transactie komt terug met appAccountToken op nil. Ontwikkelaars lopen hier voortdurend tegenaan, en het symptoom is altijd hetzelfde, een of andere variant van "appAccountToken is missing in the transaction payload" op Apples eigen forums, bijna altijd omdat de doorgegeven waarde geen geldige UUID was. Genereer een echte UUID aan de serverkant, sla hem op bij het account, en geef StoreKit nooit iets anders.

Hoe je hem instelt bij de aankoop

In StoreKit 2 is het één aankoopoptie. Genereer de UUID op je server wanneer de gebruiker zich aanmeldt of voor het eerst bij het afrekenen komt, sla hem op in het accountrecord, en geef diezelfde waarde door aan de aankoopaanroep.

De signatuur is Product.PurchaseOption.appAccountToken(_ token: UUID), en een aankoop ziet eruit als try await product.purchase(options: [.appAccountToken(token)]). Wanneer de transactie terugkomt, geverifieerd via de App Store Server API of geleverd door een servermelding, draagt hij die UUID, en je server zoekt de klant op met één query.

Gebruik één stabiel token per account

Genereer geen nieuw token voor elke aankoop van dezelfde gebruiker. Apple geeft het token terug bij verlengingen, incassopogingen en upgrades in dezelfde keten, dus een stabiele UUID per account geeft je een schone draad van de eerste aankoop door elke toekomstige gebeurtenis. Een token dat per aankoop verandert, breekt die draad en ondermijnt het hele doel. Eén account, één token, elke keer hergebruikt wanneer dat account koopt.

Het eindpunt dat aankopen buiten de app redt

Tot 2025 zat er een gat. Als een klant een aanbiedingscode inwisselde of een gepromote in-app-aankoop rechtstreeks vanuit de App Store deed, draaide je app nooit de aankoop-flow, dus was er nergens om appAccountToken in te stellen. Die transacties kwamen anoniem binnen en bleven dat.

WWDC 2025 sloot het gat met het Set App Account Token-eindpunt. Je server roept PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken aan op de App Store Server API met de UUID in de body, en Apple stelt het token in op die transactie. Het werkt voor elk producttype, dekt het inwisselen van aanbiedingscodes en gepromote aankopen, en de waarde die je verstuurt overschrijft elk token dat al op de transactie staat. Je kunt een aankoop nu achteraf koppelen, vanaf je server, zonder dat hij ooit door je app gaat.

Een stapel papieren verkoopbonnen op een donker bureau met de regel voor de klantnaam leeggelaten, één belicht door een warme spotlight, illustreert een App Store-aankoop die binnenkomt zonder appAccountToken om de koper te identificeren
AankoopkanaalWaar je appAccountToken insteltOpmerkingen
In-app-aankoopStoreKit-aankoopoptie op het moment van kopenProduct.PurchaseOption.appAccountToken(UUID)
Inwisselen van aanbiedingscodeSet App Account Token-eindpunt, aan de serverkantGeen in-app-flow om in te haken, dus stel hem achteraf in
Gepromote in-app-aankoop vanuit de App StoreSet App Account Token-eindpunt, aan de serverkantDe aankoop gebeurt buiten je app
AbonnementsverlengingNiets te doenWordt automatisch overgenomen van de oorspronkelijke aankoop

Waar de ontbrekende koppeling je geld kost

Het punt van het token zijn geen nette administratie. Het is dat Apples ene terugbetalingsvraag aan ontwikkelaars, de CONSUMPTION_REQUEST, alleen beantwoordbaar is als je de klant kunt vinden waarover hij gaat.

Wanneer een koper om een terugbetaling vraagt op een verbruiksartikel of een niet-verlengbaar abonnement, stuurt Apple je server een CONSUMPTION_REQUEST-melding en geeft je twaalf uur om te antwoorden met Send Consumption Information. Je antwoord bestaat uit gegevens over die specifieke klant: hoeveel van het product hij heeft verbruikt, hoe lang zijn account bestaat, wat zijn totale uitgaven zijn, wat zijn leverstatus is. appAccountToken is zelf een van de velden in dat verzoek, en belangrijker nog, het is de manier waarop de transactie van de melding wordt gekoppeld aan het account wiens gebruik je op het punt staat te beschrijven. Geen token, geen opzoeken, geen accuraat antwoord.

Wat een leeg antwoord echt kost

Een niet-geïdentificeerde terugbetaling dwingt een slechte keuze af. Je kunt het verbruiksverzoek met niets beantwoorden, wat gelezen wordt als laag verbruik en Apple naar het toekennen van de terugbetaling duwt, ook bij klanten die het product intensief gebruikten. Of je gokt. Hoe dan ook betaal je aankopen terug die je met bewijs had kunnen verdedigen, en je hebt de echte kosten om ze te leveren al betaald.

Die kosten zijn niet de verkoopprijs. Een verbruiksartikel dat een reeks model-API-aanroepen uitvoerde, afbeeldingen genereerde, een video exporteerde of een creator-uitbetaling in gang zette, gaf echt geld uit op het moment dat het werd geleverd. De terugbetaling geeft de betaling van de klant terug. Ze geeft de factuur van de leverancier niet terug. Vermenigvuldig één niet-identificeerbare klant met elke terugbetaling die hij indient, en met elke seriële terugbetaler die erop rekent dat je niet weet wie hij is, en het token dat je oversloeg wordt de duurste regel code die je nooit hebt geschreven.

Hetzelfde idee bestaat op Android, onder een andere naam

Google Play lost hetzelfde probleem op met setObfuscatedAccountId, dat een accountidentificatie aan een aankoop koppelt, zodat Google's terugboekingsbeoordeling via orders.reviewrefund tegen een echte gebruiker kan worden beantwoord. Andere store, andere mechaniek, dezelfde les: koppel identiteit bij de aankoop of je kunt het geschil later niet verdedigen. In de App Store is dat gereedschap appAccountToken, en het moet een UUID zijn.

Drie gewoontes die het token op zijn plek houden

  • Genereer een UUID per account en sla hem op. Eén stabiel token per klant, aangemaakt bij aanmelding of bij de eerste afrekening, opgeslagen op zijn record en hergebruikt voor elke aankoop.
  • Valideer voordat je hem doorgeeft. Bevestig in je aankoopcode dat de waarde een echte UUID is, zodat een misvormde id nooit stil een nil-token op de transactie kan worden.
  • Vul aankopen buiten de app aan. Wanneer er een servermelding binnenkomt voor het inwisselen van een aanbiedingscode of een gepromote aankoop zonder token, roep dan het Set App Account Token-eindpunt aan om het juiste te koppelen.

Doe die drie en elke transactie die Apple je ooit stuurt, terugbetalingsverzoeken inbegrepen, komt al gekoppeld binnen aan de klant waartoe hij behoort.

Dit is het fundament waar RefundHalt op steunt. We lezen appAccountToken uit elke transactie en servermelding, koppelen hem aan het gebruik dat we voor dat account toch al bijhouden, en beantwoorden Apples verbruiksverzoek binnen het venster van twaalf uur met de echte cijfers van de klant. Het token is de draad. Stel hem één keer in en je terugbetalingsverdediging heeft iets om zich aan vast te houden.

Veelgestelde vragen

Wat is appAccountToken in de App Store?
appAccountToken is een UUID die je genereert en via StoreKit aan een aankoop koppelt, zodat de resulterende App Store-transactie terugwijst naar een specifiek gebruikersaccount in je eigen systeem. Apple bewaart hem op de transactie en geeft hem terug in de transactie-informatie, servermeldingen en elke verlenging in dezelfde keten, waardoor je elke toekomstige gebeurtenis, een terugbetalingsverzoek inbegrepen, aan de juiste klant kunt koppelen.
Waarom is mijn appAccountToken nil of ontbreekt hij?
Bijna altijd omdat de waarde die je doorgaf geen geldige UUID was. StoreKit 2 vereist een RFC 4122 UUID en laat al het andere stil vallen, dus een samengevoegde tekenreeks, een integer-id of een e-mail komt terug als een nil appAccountToken terwijl de aankoop toch slaagt. De andere veelvoorkomende oorzaak is een aankoop buiten je app, zoals het inwisselen van een aanbiedingscode, waar geen in-app-flow liep om het token in te stellen.
Kan ik appAccountToken instellen na de aankoop, voor aanbiedingscodes?
Ja, sinds 2025. Het Set App Account Token-eindpunt op de App Store Server API laat je server het token op een bestaande transactie koppelen of overschrijven door PUT /inApps/v1/transactions/{originalTransactionId}/appAccountToken aan te roepen met de UUID in de body. Het werkt voor elk producttype en is gebouwd voor aankopen buiten je app, zoals het inwisselen van aanbiedingscodes en gepromote in-app-aankopen.
Moet appAccountToken een UUID zijn?
Ja. De ene opmaakregel die Apple afdwingt, is dat de waarde een geldige UUID is. Verder is hij ondoorzichtig, dus hij kan verwijzen naar welke accountsleutel je ook wilt aan jouw kant, maar als het geen UUID is, bewaart StoreKit hem niet en komt de transactie terug met appAccountToken op nil.
Hoe helpt appAccountToken bij terugbetalingen?
Wanneer een klant om een terugbetaling vraagt, stuurt Apple een CONSUMPTION_REQUEST en geeft je twaalf uur om te antwoorden met gegevens over die specifieke koper. appAccountToken is de manier waarop je de transactie van de melding koppelt aan het account wiens gebruik je moet rapporteren, en het is een van de velden in het verbruiksverzoek zelf. Zonder hem kun je niet antwoorden met echt gebruik, dus neigt Apple ernaar terugbetalingen toe te kennen die je met bewijs had kunnen betwisten.
Moet appAccountToken voor elke aankoop anders zijn?
Nee. Gebruik één stabiele UUID per account en hergebruik hem voor elke aankoop die die gebruiker doet. Apple draagt het token mee over verlengingen en upgrades in een abonnementsketen, dus een stabiel token geeft je een schone koppeling in de tijd. Een token dat per aankoop verandert, breekt die koppeling en maakt het moeilijker om transacties terug te koppelen aan dezelfde klant.

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.