Hoe koppel je een pinterminal aan je eigen software?
Kort antwoord
Je software stuurt het bedrag via de API van je betaaldienstverlener naar een specifieke terminal, de klant betaalt daar, en de uitkomst komt terug via de API en een webhook. Dat werkt via de cloud of via het lokale netwerk. Wil je de telefoon zelf als terminal gebruiken (Tap to Pay), dan heb je een native app nodig.
Een losse pinautomaat naast de kassa werkt prima, tot je merkt hoe vaak het bedrag twee keer wordt ingetikt. Eén keer in je eigen systeem, één keer op de terminal. Een tikfout, een vergeten korting of een betaling die op de terminal wel en in je administratie niet bestaat, en aan het eind van de dag klopt de kas niet. Wie zijn eigen kassa, verhuursysteem of buitendienst-app heeft, wil daarom dat de software de terminal aanstuurt.
Dat kan inmiddels bij alle grote betaaldienstverleners, en sinds een paar jaar kan ook een gewone telefoon als terminal dienen. In dit artikel leg ik uit welke vormen er zijn, hoe je software met een terminal praat, wat Tap to Pay technisch vraagt, en waar zelfgebouwde koppelingen in de praktijk op stuklopen.
Drie manieren om fysiek af te rekenen
Voordat je een koppeling bouwt, is het goed om helder te hebben welke vorm je eigenlijk zoekt. Er zijn er grofweg drie.
- Losse terminal: de medewerker tikt het bedrag zelf in. Geen koppeling, dus ook geen relatie tussen de betaling en de bestelling of reservering in je systeem. Prima voor een kleine winkel, lastig zodra je wilt kunnen afletteren.
- Gekoppelde terminal: je software stuurt het bedrag naar een fysieke terminal, en krijgt de uitkomst terug. De betaling hangt direct aan de verkoop of de boeking. Dit is de standaard voor een eigen kassa of balie.
- Tap to Pay: een telefoon of tablet met NFC wordt zelf de terminal. De klant houdt zijn kaart of telefoon tegen het toestel van de medewerker. Geen extra hardware, wel een eigen app.
| Kenmerk | Losse terminal | Gekoppelde terminal | Tap to Pay |
|---|---|---|---|
| Bedrag invoeren | Handmatig op de terminal | Door je software | Door je app |
| Koppeling aan bestelling | Geen | Direct | Direct |
| Kassa in de browser | Niet van toepassing | Ja, via een cloudkoppeling | Nee, native app nodig |
| Extra hardware | Terminal | Terminal | Geen, alleen een geschikt toestel |
| Typisch gebruik | Kleine winkel | Balie, kassa, horeca | Buitendienst, verhuur, evenementen |
Cloud of lokaal: hoe je software met de terminal praat
Bij een gekoppelde terminal zijn er twee manieren waarop je kassa en terminal elkaar bereiken. Adyen beschrijft ze in zijn integratiedocumentatie helder, en het onderscheid geldt in grote lijnen bij elke aanbieder.
Cloudkoppeling
Je software stuurt het betaalverzoek via internet naar de betaaldienstverlener, die het doorzet naar de juiste terminal. De terminal hoeft geen vast IP-adres te hebben en je hoeft niets op het netwerk van de locatie in te richten. Adyen noemt dit de makkelijkste route om te bouwen, met als kanttekening dat niet elke toepassing ermee kan.
Bij Mollie werkt het zo: je maakt een gewone betaling aan, met als methode pointofsale en het terminalId van het apparaat. De terminals haal je op via de Terminals API, en ze hangen aan een betaalprofiel, wat handig is als je meerdere locaties hebt. Stripe heeft daarvoor de server-driven integratie: je backend praat met de Stripe API, die de smart reader aanstuurt en je via webhooks de status meldt.
$payment = $mollie->payments->create([
'amount' => ['currency' => 'EUR', 'value' => $amount],
'description' => 'Verhuur 4812',
'method' => 'pointofsale',
'terminalId' => $terminalId,
'webhookUrl' => $webhookUrl,
]);
Het grote voordeel voor maatwerk: omdat alles via je server loopt, kan je kassascherm gewoon een webapplicatie zijn. Een tablet met een browser is genoeg.
Lokale koppeling
Hier praat je kassa rechtstreeks met de terminal over het netwerk op locatie. Je krijgt het resultaat direct terug en je bent minder afhankelijk van de internetverbinding tussen jou en de betaaldienstverlener. Adyen noemt deze vorm mogelijk robuuster, maar de prijs is complexiteit: je moet het lokale verkeer zelf beveiligen en de terminals hebben een vast adres op het netwerk nodig. En Adyen helpt je uitdrukkelijk niet bij netwerkproblemen op je eigen locatie.
De terminal is zelden het probleem. Het netwerk op de locatie en de vraag wat je software doet als het antwoord uitblijft, dat zijn de problemen.
Tap to Pay: de telefoon als terminal
Tap to Pay op iPhone is sinds augustus 2023 beschikbaar in Nederland, en ook op Android bestaat een vergelijkbare functie. Voor een medewerker in de buitendienst, bij de uitgifte van verhuurmateriaal of aan de rand van een evenemententerrein is dat aantrekkelijk: geen extra apparaat, gewoon de telefoon die er al is.
Technisch zit hier wel de grootste beperking. Tap to Pay gebruikt de NFC-chip van het toestel, en daar kan alleen een native app bij. Stripe levert Tap to Pay bijvoorbeeld via zijn iOS- en React Native-SDK, en de server-driven route ondersteunt juist geen mobiele lezers. Een kassa die in de browser draait, kan de telefoon dus niet als terminal gebruiken.
Wil je Tap to Pay in je eigen app, reken dan op deze stappen:
- Toestemming bij Apple: je vraagt een aparte Tap to Pay-entitlement aan, eerst voor ontwikkeling en na het testen opnieuw voor distributie.
- Geschikte toestellen: een iPhone XS of nieuwer met een recente iOS-versie. Pincode-invoer op het scherm wordt ondersteund vanaf iOS 16.4.
- Uitleg in de app: Apple verplicht een instructiescherm dat laat zien hoe je de kaart tegen het toestel houdt, en beoordeelt je app daar ook op.
- Een terugvaloptie: sommige kaarten of bedragen vragen om een extra verificatie die via Tap to Pay niet lukt. Zorg dat er een tweede route is, zoals een betaallink.
Moet je daarvoor een volledige app bouwen? Niet per se. Een kleine native schil rond je bestaande webapplicatie kan genoeg zijn, zolang het afrekenen zelf in de native laag gebeurt. Over de afweging tussen native en cross-platform schreef ik eerder in native vs cross-platform.
Een terminalbetaling is een toestand, geen moment
Het meeste werk in een terminalkoppeling zit niet in het versturen van het bedrag, maar in wat er daarna gebeurt. Een klant kan twijfelen, een kaart kan geweigerd worden, de verbinding kan halverwege wegvallen. Je software moet al die situaties kennen.
- Eindstatussen: bij Mollie zijn dat
paid,failedencanceled. Rond de verkoop pas af bij een betaalde status, en toon bij een mislukte betaling de reden die de betaaldienstverlener meegeeft. - Webhook als signaal, niet als bewijs: een webhook vertelt je dat er iets veranderd is. Haal daarna zelf de betaling op om de status te controleren, voordat je de verkoop vastlegt.
- Onbekende uitkomst: valt de verbinding weg, laat de verkoop dan open staan en vraag de status opnieuw op met het betaalnummer. Opnieuw afrekenen is de snelste weg naar een klant die twee keer betaalt.
- Dubbele meldingen: dezelfde statusmelding komt vroeg of laat twee keer binnen. Verwerk ze idempotent, zodat een herhaalde melding niets verandert.
- Eén terminal, één betaling: stuur geen nieuw verzoek naar een terminal die nog met een vorige betaling bezig is. Houd per terminal bij of hij vrij is.
Contactloos betalen zonder pincode kent bovendien grenzen. Boven bepaalde bedragen of na een aantal opeenvolgende betalingen vraagt de bank alsnog om verificatie. Hoe die regels van sterke klantauthenticatie werken, lees je in wat is 3D Secure en SCA.
Valkuilen die ik in de praktijk zie
- Geen testomgeving ingericht: zowel Mollie als Stripe bieden testterminals of gesimuleerde lezers. Bouw de hele flow eerst daartegen, inclusief mislukte en afgebroken betalingen.
- Terminal per locatie vergeten: bij meerdere vestigingen moet je software weten welke terminal bij welke balie hoort. Leg dat vast in je eigen beheer, niet in het hoofd van de medewerker.
- Terugbetalen alleen aan de terminal: bouw retouren en terugbetalingen via de API, gekoppeld aan de oorspronkelijke betaling. Anders verlies je het spoor in je administratie.
- Afletteren als bijzaak: uitbetalingen van je betaaldienstverlener komen gebundeld binnen. Zorg dat elke terminalbetaling een kenmerk heeft waarmee je hem later automatisch aflettert.
- Offline niet doordacht: een terminal zonder verbinding rekent niet af. Op een terrein of in een kelder hoort dat in het ontwerp, niet in de eerste storing. Zie ook local-first software.
Mijn kijk op terminals in maatwerk
Ik merk dat de terminal vaak als laatste puzzelstuk wordt gezien: eerst het systeem bouwen, en dan zien we wel hoe er betaald wordt. Dat is precies omgekeerd. De vraag waar en hoe je klant betaalt, bepaalt of je een webapplicatie kunt bouwen of een native app nodig hebt, welke betaaldienstverlener past en hoe je datamodel eruitziet.
Mijn voorkeur ligt meestal bij een cloudkoppeling met een kassa in de browser. Dat is het eenvoudigst te onderhouden, je hoeft niets op locatie in te richten en een nieuwe balie is een kwestie van een terminal toevoegen. Tap to Pay is een mooie aanvulling voor wie onderweg afrekent, maar ik zou er pas aan beginnen als duidelijk is dat de buitendienst er echt om vraagt. De extra app en de beoordeling bij Apple zijn geen klein project.
— Jasper
Zo helpt Coding Agency hierbij
Wij koppelen pinterminals van onder meer Adyen, Mollie en Stripe aan maatwerksoftware: een eigen kassa, een balie in een verhuursysteem of een app voor de buitendienst. Met betaalstatussen die je software zelf bijhoudt, idempotente verwerking van meldingen en betalingen die vanzelf in je administratie landen.
Twijfel je of een gekoppelde terminal of Tap to Pay beter past bij hoe jouw klanten betalen? Neem contact op voor een vrijblijvend gesprek.