Een betaalformulier dat werkt voor één succesvolle kaart is niet getest — het is gedemonstreerd. De dure defecten leven in de toestanden rond dat succes: de betaling die werd geweigerd en twee keer opnieuw werd geprobeerd, de klant die het authenticatievenster halverwege sloot, de terugbetaling die werd uitgevoerd op een order die nooit was vastgelegd. Een praktische checklist voor het testen van betaalformulieren is daarom een lijst met uitkomsten om te bereiken, geen lijst met velden om in te vullen.
Wat volgt is de volgorde die de meeste bugs per uur inspanning vindt, met de redenering achter elk item en de ontwikkelaarsgerichte zorgen die bepalen of de oplossingen standhouden.
Begin met de toestanden, niet met de velden
De meeste teams beginnen met het testen van invoer: een geldig nummer, een ongeldig nummer, een ontbrekende vervaldatum. Dat vangt interfaceproblemen op, en het is de moeite waard, maar het laat de moeilijkere helft van het systeem onaangeroerd.
De productieve aanpak is het opsommen van de toestanden waarin een order zich kan bevinden en bevestigen dat elk ervan bereikbaar, zichtbaar en correct is. Typische toestanden zijn: wachtend op betaling, geautoriseerd maar niet vastgelegd, vastgelegd, geweigerd met de optie om opnieuw te proberen, definitief geweigerd, authenticatie in behandeling, authenticatie mislukt, halverwege verlaten, volledig terugbetaald, gedeeltelijk terugbetaald, en betwist. Schrijf eerst je eigen lijst op; de gaten erin zijn meestal waar de bugs zitten.
Zodra de lijst bestaat, wordt elk item een vraag met een testbaar antwoord: hoe toont de bestelgeschiedenis van de klant deze toestand, is de beheerweergave het ermee eens, en behandelt de boekhoudkundige export haar correct?
Hoe moet het weigeringspad eruitzien?
Een weigering is niet één gebeurtenis. De klantervaring hangt af van of de weigering herstelbaar is, en de gateway vertelt je meestal welke categorie van toepassing is.
Een weigering door onvoldoende saldo is herstelbaar: de klant kan een andere kaart gebruiken, en het formulier moet alles bewaren wat hij al heeft getypt, inclusief het adres en de contactgegevens, zodat de nieuwe poging een paar seconden kost in plaats van een volledige herinvoer. Een weigering die betekent dat de uitgever met de kaarthouder wil spreken, is niet herstelbaar via je interface, en de gebruiker vertellen het opnieuw te proberen verspilt zijn tijd. Een verwerkingsfout zit ertussenin: die is vaak tijdelijk, en een nieuwe poging is redelijk.
Test elk daarvan afzonderlijk met een kaart die de specifieke uitkomst oplevert, en controleer per geval drie dingen: de melding die de klant ziet, de toestand die in je eigen database wordt vastgelegd, en of de knop voor een nieuwe poging überhaupt wordt aangeboden. Een formulier dat een nieuwe poging aanbiedt voor een definitieve weigering genereert supporttickets, en een formulier dat de nieuwe poging verbergt bij een tijdelijke fout verliest omzet.
Heb je het pad voor nieuwe pogingen getest?
Nieuwe pogingen zijn waar idempotentiefouten opduiken, en ze zijn makkelijk te vergeten omdat een enkele poging perfect werkt.
De scenario’s die het waard zijn om te doorlopen zijn: de klant drukt twee keer snel achter elkaar op de betaalknop; het netwerk valt weg nadat het verzoek is verzonden maar voordat het antwoord aankomt; de klant verlaat de pagina en begint opnieuw vanuit de winkelwagen; en de betaling wordt geauthenticeerd, faalt bij het vastleggen, en wordt daarna opnieuw geprobeerd met een andere kaart. Controleer in elk geval dat er slechts één order bestaat, dat er slechts één afboeking wordt geprobeerd, en dat de toestand die aan de klant wordt getoond overeenkomt met wat de gateway heeft vastgelegd.
Het geval van dubbele inzending is het meest voorkomende en het meest schadelijke. De knop uitschakelen na de eerste druk is op zichzelf niet voldoende, omdat het tweede verzoek al onderweg kan zijn. De duurzame oplossing is een sleutel die één keer per afrekenpoging wordt gegenereerd en door de betaalaanroep wordt gehonoreerd, zodat een herhaling van dezelfde poging het oorspronkelijke resultaat teruggeeft in plaats van een tweede aan te maken.
Terugbetalingen, terugdraaiingen en gedeeltelijke vastleggingen
Deze paden blijven vaak ongetest totdat een klant erom vraagt, wat een slecht moment is om een gat te ontdekken.
Test een volledige terugbetaling en bevestig dat de ordertoestand verandert, de klant wordt geïnformeerd, en het bedrag klopt. Test daarna een gedeeltelijke terugbetaling en controleer dat een latere tweede terugbetaling het oorspronkelijke bedrag niet overschrijdt en dat de bestelgeschiedenis de som correct toont. Test een terugdraaiing, die plaatsvindt wanneer een autorisatie wordt vrijgegeven voordat er iets is vastgelegd, en bevestig dat de klant een annulering ziet in plaats van een afboeking.
Als je stroom het vastleggen van minder dan het geautoriseerde bedrag ondersteunt — gebruikelijk in de horeca, waar een eindrekening verschilt van de voorautorisatie — test dan dat de vrijgave van het verschil ergens zichtbaar is. De bug op dit gebied is bijna altijd een boekhoudkundige: de betaling is geslaagd, de klant is tevreden, en het omzetrapport is een maand lang onjuist.
De checklist
Ruwweg gegroepeerd in de volgorde waarin ze moeten worden uitgevoerd:
- Een geslaagde betaling met een correct gevormde kaart van elk netwerk dat je ondersteunt.
- Een betaling die wordt geweigerd door onvoldoende saldo, met succes opnieuw geprobeerd met een tweede kaart.
- Een betaling die definitief wordt geweigerd, zonder aangeboden nieuwe poging en met een duidelijke uitleg.
- Een tijdelijke verwerkingsfout, na een korte vertraging opnieuw geprobeerd.
- Dubbele inzending van de betaalknop, gecontroleerd op dubbele orders.
- Een weggevallen verbinding na inzending, gecontroleerd op een herstelbare toestand in plaats van een verweesde order.
- Een verlaten afrekenproces, met de order in een toestand die een mens kan uitleggen.
- Authenticatie voltooid, authenticatie mislukt, en authenticatie verlaten.
- Een kaart voorbij de vervalmaand, ingediend op de grens, op de eerste en de laatste dag van geldigheid.
- Een beveiligingscode van de verkeerde lengte voor het gedetecteerde netwerk.
- Autofill, inclusief de browser die een opgeslagen kaart invult en de klant die één veld bewerkt.
- Een volledige terugbetaling, een gedeeltelijke terugbetaling en een tweede gedeeltelijke terugbetaling na de eerste.
- Een sessie die verloopt terwijl het formulier open is, en dan toch wordt ingediend.
- Een zeer langzame verbinding, twee keer ingediend waarbij de tweede aankomt voordat de eerste is voltooid.
- Het volledige formulier invullen met alleen het toetsenbord, en een screenreadercontrole over de foutmeldingen.
Dat is bewust langer dan de meeste lanceringschecklists, omdat de laatste vijf items degene zijn die klanten bereiken wanneer ze worden gemist, en geen ervan ongebruikelijke infrastructuur vereist om te testen.
Voor ontwikkelaars: toestandsmatrix en idempotentiereview
Twee artefacten maken dit beheersbaar. Het eerste is een toestandsmatrix: rijen voor elke toestand die je kunt bereiken, kolommen voor de klantweergave, de beheerweergave, de databaserecord en de verzonden notificatie. Lege cellen zijn de defecten. Het invullen kost een middag en onthult meestal dat twee schermen het oneens zijn over wat een wachtende betaling betekent.
Het tweede is een idempotentiereview van het betaalendpoint zelf. Bevestig dat het verzoek een sleutel draagt die uniek is per afrekenpoging in plaats van per poging op de netwerklaag, dat de sleutel bij de transactie wordt opgeslagen, en dat een herhaald verzoek met dezelfde sleutel de oorspronkelijke uitkomst teruggeeft in plaats van het werk opnieuw te doen. Controleer ook het timeoutpad: als je client opgeeft met wachten, kan de server de afboeking alsnog voltooien, en de klant mag geen fout te zien krijgen voor een betaling die is geslaagd.
Herzie daarnaast hoe het formulier omgaat met data die het niet hoort te bewaren. Kaartnummers die je eigen servers bereiken, moeten in elke weergave worden gemaskeerd, en beveiligingscodes mogen helemaal niet in logs worden geschreven — de gids over beveiligingscodes legt uit waarom die regel absoluut is in plaats van een voorkeur. Vervaldata verdienen hun eigen grenstests, beschreven in de gids over vervaldatums, omdat de laatste dag van de gedrukte maand een klassieke faalplek is.
Beslis ten slotte wat er gebeurt wanneer een gatewayaanroep faalt op een manier die je niet had voorzien. Een betaalstroom heeft een vastgelegd antwoord nodig voor het onbekende geval, en dat moet er een zijn die de klant niet twee keer laat betalen en de order niet onzichtbaar achterlaat.
Waar je nummers voor de checklist haalt
De kaarten in deze checklist vallen in twee groepen. Gevallen die een specifieke gateway-uitkomst nodig hebben — een weigering, een authenticatie-uitdaging — vereisen de testnummers die je betaalprovider voor zijn sandbox documenteert, en de gids over providertestkaarten legt uit hoe die catalogi werken. Al het overige, inclusief elk geval waarin de betaalstap wordt gemockt, kan gegenereerde data gebruiken.
De kaartnummersgenerator produceert nummers voor een gekozen netwerk of een gemengde batch, elk met een vervaldatum en een plaatsvervangende beveiligingscode, zodat een fixtureset binnen een minuut kan worden samengesteld. Elke waarde is structureel geldig en is nooit aan enig account uitgegeven, wat de set veilig maakt om in de repository te bewaren en nutteloos voor wie hem vindt.
Volgende stappen
Neem de checklist hierboven, markeer de items die je al kunt demonstreren en degene die je niet kunt, en behandel de tweede groep als de lanceringsblokkade in plaats van als een backlog. Vul daarna de toestandsmatrix in voor de twee toestanden die je het minst begrijpt, want daar verstoppen zich gewoonlijk de meningsverschillen tussen schermen.