Kundvagn & checkout
Kundvagnen är knuten till en plats
En kund väljer alltid en hämtplats och ett hämttillfälle innan något
läggs i kundvagnen. Kundvagnen (sparad i localStorage, inte en
databastabell) kan bara innehålla produkter från producenter som faktiskt
säljer på den valda platsen — byter kunden plats mitt i en pågående
kundvagn töms den, eftersom de gamla varorna inte nödvändigtvis går att
hämta på den nya platsen.
En kundvagn kan innehålla produkter från flera olika producenter, så länge de alla säljer på samma plats. Det är precis det här som gör checkout mer intressant än en vanlig enkel betalning.
Från “Fortsätt till betalning” till bekräftad order
Ordern skapas — innan betalningen
Så fort kunden klickar Fortsätt till betalning valideras hela
kundvagnen på nytt mot databasen (pris, lagersaldo, och att varje
producent fortfarande säljer på den valda platsen — aldrig mot vad
klienten skickade in, eftersom localStorage enkelt kan manipuleras).
Direkt efter valideringen skapas en Order-rad, plus en OrderItem per
vara och en OrderProducerPayout per producent i kundvagnen —
redan nu, innan någon betalning är gjord. Anledningen är att
avgiftsfördelningen (eklos egen avgift, hur mycket varje producent ska
få) ska vara klar och redo i samma ögonblick betalningen faktiskt går
igenom, snarare än att behöva räknas ut i en betalningswebhook.
Ordern får status pending tills betalningen faktiskt bekräftas.
Stripe Checkout tar över
En Stripe Checkout Session skapas för hela kundvagnens totalsumma och visas inbäddad på sidan (inte en omdirigering till stripe.com). Det är här kunden faktiskt skriver in sina kortuppgifter.
Betalningen bekräftas
När betalningen går igenom markeras ordern paid, lagersaldot minskas,
och varje producents andel av pengarna överförs till deras anslutna
Stripe-konto (se Betalningar & utbetalningar för
hur den delen fungerar). En bekräftelse skickas både till kunden och
till varje berörd producent.
Det här bekräftas på två oberoende sätt: Stripes egen webhook (den auktoritativa vägen) och ett fallback-kontroll på bekräftelsesidan direkt efter betalningen. Båda anropar samma idempotenta funktion, så en order kan aldrig råka bli dubbelbehandlad — bara den allra första lyckade bekräftelsen gör något.
Om kunden aldrig fullföljer betalningen
Stänger kunden fliken, avbryter, eller får kortet nekat utan att
försöka igen — ordern som redan skapades i steg 1 ovan blir aldrig
paid. Stripes Checkout Session går automatiskt ut efter 24 timmar om
den inte slutförs, vilket utlöser en egen webhook
(checkout.session.expired) som markerar ordern (och dess
OrderProducerPayout-rader) som expired istället.
En expired order räknas aldrig som en riktig försäljning någonstans
— den är filtrerad bort från producentens Ordrar-sida, men syns ändå
(tydligt märkt “Ej betald”, utan att påstå att något betalats ut) i
Översikt-sidans transaktionslista, så att en producent kan se hur många
checkouter som faktiskt konverterar.
Det finns ingen lokal utveckling-variant av checkout.session.expired
— till skillnad från checkout.session.completed, som har en
fallback-kontroll på bekräftelsesidan, kan en övergiven checkout bara
upptäckas via den riktiga webhooken. Den måste vara riktigt
konfigurerad (rätt events, rätt signeringsnyckel) i både sandbox och
produktion för att den här funktionen ska göra något alls.