Voor ontwikkelaars
Winkelwagen- en checkout-API
Winkelwagenidentiteit, gevalideerde checkoutinvoer, betaalinitiatie en idempotentie zonder clienttotalen.
Op deze pagina
Bepaal eerst de winkelwagencontext
De API gebruikt TokenCartRepository, niet de sessiewinkelwagen van de storefront. Als Laravel op het request een User vindt, gebruikt de API het gebruikers-ID als winkelwagensleutel. Anders wordt de header X-Cart-Token gebruikt.
Een gasttoken bestaat uit 64 kleine hexadecimale tekens. Bij ontbrekende of ongeldige invoer wordt een nieuw willekeurig token gemaakt. Winkelwagenresponses retourneren het als data.token en als responseheader X-Cart-Token. Bewaar die waarde voor volgende gastverzoeken. Het is een toegangsbewijs voor de winkelwagen, geen Sanctum-inlogtoken. De inhoud blijft na opslag zeven dagen in de cache en verdwijnt als de bijbehorende cachewaarde wordt gewist.
Gastwinkelwagens en ingelogde winkelwagens worden niet automatisch samengevoegd. De openbare winkelwagenroutes voeren zelf geen auth:sanctum uit. Een bearer-header toevoegen is dus geen gedocumenteerde overdracht van gast naar klant. Checkout vereist wel auth:sanctum en leest de winkelwagen van de gevonden gebruiker. Alleen hetzelfde gasttoken meesturen bewijst daarom niet dat checkout dezelfde inhoud ziet. Gebruik voor een ingelogde first-party client dezelfde ondersteunde sessie bij API-winkelwagenverzoeken en checkout. Controleer voor een bearer-only client de werkelijke winkelwagencontext in een integratietest voordat je daarop een aankoopflow bouwt. De huidige routes hebben geen endpoint om een gastwinkelwagen te claimen.
Ook de gewone winkelwagen op de website is afzonderlijk. Een product dat op een webpagina is toegevoegd, staat niet automatisch in de API-winkelwagen. Bron: repositorybinding.
Regels toevoegen, wijzigen en verwijderen
| Handeling | Gevalideerde invoer |
|---|---|
GET /api/v1/cart |
Geen body |
POST /api/v1/cart |
Verplichte integer product_id; nullable integer quantity van 1 tot 99, standaard 1; nullable array selections |
PATCH /api/v1/cart/{lineKey} |
Verplichte integer quantity van 0 tot 99 |
DELETE /api/v1/cart/{lineKey} |
Geen body |
Een aantal van nul verwijdert de regel. Gebruik bij wijzigen en verwijderen de ontvangen line_key, niet het product-ID. Verschillende keuzes kunnen verschillende regels voor hetzelfde product opleveren. Neem optiesleutels en keuzewaarden over uit de catalogusresource. De winkelwagenservice valideert de configuratie en berekent de prijzen.
Gastvoorbeelden met installatiegebonden ID's en het ontvangen token:
curl --request POST 'https://shop.example.test/api/v1/cart' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"product_id":42,"quantity":1,"selections":{}}'
curl 'https://shop.example.test/api/v1/cart' \
--header 'Accept: application/json' \
--header "X-Cart-Token: $CART_TOKEN"
curl --request PATCH "https://shop.example.test/api/v1/cart/$LINE_KEY" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header "X-Cart-Token: $CART_TOKEN" \
--data '{"quantity":2}'
curl --request DELETE "https://shop.example.test/api/v1/cart/$LINE_KEY" \
--header 'Accept: application/json' \
--header "X-Cart-Token: $CART_TOKEN"
Elke handeling retourneert de bijgewerkte winkelwagen:
{
"data": {
"token": "<64-character-cart-token>",
"item_count": 1,
"requires_shipping": false,
"subtotal_amount": 1200,
"currency": "EUR",
"lines": [{
"line_key": "<returned-line-key>",
"product_id": 42,
"label": "Voorbeeldproduct",
"quantity": 1,
"unit_amount": 1200,
"line_total_amount": 1200,
"currency": "EUR",
"selections": []
}]
}
}
Bij een lege winkelwagen kunnen subtotal_amount en currency null zijn. selections bevat de door de server genormaliseerde keuzes; een lege PHP-array wordt [] in JSON. Bedragen zijn uitgedrukt in de kleinste munteenheid. Bereken uit dit voorbeeld geen gezaghebbend besteltotaal.
Bron: AccountController.
Vraag de checkoutvereisten op
GET /api/v1/checkout/requirements leest de huidige API-winkelwagen en retourneert:
Veld onder data |
Structuur |
|---|---|
requirements |
Array met vereiste-ID's |
requires_shipping |
Boolean |
payment_methods |
Array van {id, label, gateway_id?, icon?} |
Core voegt facturatie, betaling en controle toe als vereisten. Andere contributors kunnen capabilitygebonden vereisten toevoegen. Betaalmethoden komen uit de actieve gatewayregistratie. Leg dus geen vaste providerlijst vast en veronderstel niet dat methode-ID en gateway-ID altijd gelijk zijn.
curl 'https://shop.example.test/api/v1/checkout/requirements' \
--header 'Accept: application/json' \
--header "X-Cart-Token: $CART_TOKEN"
Dit verzoek maakt geen bestelling of betaalpoging aan en retourneert geen catalogus met verzendtarieven. Direct afrekenen met de ontwikkelgateway is alleen beschikbaar onder de expliciete niet-productievoorwaarde en als er geen echte gatewaymethoden beschikbaar zijn. Zie AvailablePaymentMethods.
Plaats een bestelling
POST /api/v1/checkout vereist authenticatie en, bij een bearer-token, orders.create. Naam, e-mail en klant-ID komen van de huidige klant, niet uit door de client opgegeven identiteitsvelden. De requestvelden zijn:
| Veld | Regel |
|---|---|
billing |
Verplichte array |
billing.name, billing.line1 |
Verplichte strings, maximaal 255 |
billing.city |
Verplichte string, maximaal 120 |
billing.postal_code |
Verplichte string, maximaal 20 |
billing.country |
Verplichte string, precies twee tekens |
billing.company, billing.line2 |
Nullable strings, maximaal 255 |
billing.region |
Nullable string, maximaal 120 |
billing.phone |
Nullable string, maximaal 40 |
payment_method |
Nullable string, maximaal 40; gebruik een beschikbare methode |
idempotency_key |
Nullable string, maximaal 64 |
shipping |
Nullable adresarray, omgezet naar AddressData |
shipping_same_as_billing |
Optionele boolean, standaard true |
shipping_method_id |
Nullable integer |
discount_code |
Nullable string, maximaal 40 |
custom_properties |
Nullable array |
De controller controleert shipping als array zonder alle geneste factuuradresregels te herhalen. Dat betekent niet dat willekeurige verzendgegevens geldig zijn: AddressData en PlaceOrder voeren hun domeinlogica nog steeds uit. Producten, totalen, valuta, referralvelden en verzendoffertesleutels zijn in deze controller geen toegestane checkoutoverrides.
Onderstaand checkout-request.json is illustratief. Het gaat ervan uit dat de ingelogde API-winkelwagen al gevuld en geconfigureerd is. Dit is geen voorbeeld van een overdracht van een gastwinkelwagen.
{
"idempotency_key": "customer-checkout-example-01",
"billing": {
"name": "Alex Voorbeeld",
"line1": "Voorbeeldstraat 1",
"city": "Brussel",
"postal_code": "1000",
"country": "BE"
},
"shipping_same_as_billing": true,
"payment_method": "<discovered-method-id>",
"custom_properties": {}
}
curl --request POST 'https://shop.example.test/api/v1/checkout' \
--header "Authorization: Bearer $AGOVENA_TOKEN" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data-binary @checkout-request.json
De response is een bestelresource, met regels, betaling, facturen en creditnotasamenvattingen. Een bestelling plaatsen betekent niet automatisch dat die betaald is. Lege of verkeerd geconfigureerde winkelwagens en niet-vervulde domeinvoorwaarden geven validatiefouten.
Gebruik één idempotentiesleutel per bedoelde bestelling. PlaceOrder zoekt eerst een bestaande bestelling van dezelfde eigenaar met die sleutel en kan deze hervatten voordat een nieuwe winkelwagen wordt beoordeeld. Een sleutel opnieuw gebruiken wijzigt de eerdere bestelling niet met de nieuwe body. Deze controller leest de sleutel uit JSON en neemt, anders dan betaalinitiatie, geen Idempotency-Key-header over.
Start een betaling via een gateway
POST /api/v1/orders/{order}/pay vereist orders.pay en een eigen bestelling. Verplichte velden zijn gateway (string, maximaal 40), return_url en cancel_url (URL's, elk maximaal 500 tekens). De optionele idempotency_key is een string van maximaal 64 tekens. Ontbreekt die sleutel in de body, dan accepteert de controller de header Idempotency-Key.
Beide redirect-origins moeten voorkomen in agovena.payments.return_url_origins. De instelling gebruikt AGOVENA_PAYMENT_RETURN_ORIGINS en valt standaard terug op APP_URL. URL's met inloggegevens of fragmenten worden geweigerd. Bij originvergelijking tellen protocol en een expliciete poort mee.
curl --request POST "https://shop.example.test/api/v1/orders/$ORDER_ID/pay" \
--header "Authorization: Bearer $AGOVENA_TOKEN" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: customer-payment-example-01' \
--data '{"gateway":"<registered-gateway-id>","return_url":"https://shop.example.test/payment-return","cancel_url":"https://shop.example.test/payment-cancel"}'
Gebruik terugkeer- en annuleringsroutes die je client echt implementeert. De voorbeeldpaden zijn geen ingebouwde Agovena-routes. De response bevat integer data.attempt_id, string data.status voor de poging, nullable string data.redirect_url en nullable string data.payment_status voor de betaling van de bestelling. Domeinvalidatie uit StartOrderPayment krijgt 422 payment_failed. Eerdere request- of URL-validatie blijft validation_error.
Volg de providerredirect als die aanwezig is, maar bepaal de eindstatus via de bestelling of geverifieerde betaalwebhookverwerking. Gebruik verschillende sleutels voor bestellen en betalen. Start na een onduidelijke netwerktime-out niet zomaar een nieuwe betaalpoging zonder de vorige te controleren.
Bronnen en regressiecontroles
- CheckoutController: invoervelden en responsestructuur.
- PlaceOrder: winkelwagenregels en bestelidempotentie.
- PaymentRedirectUrlValidator: exacte redirectvoorwaarden.
- StorefrontApiTest: gastwinkelwagenopslag, doorgifte van betaalidempotentie en afwijzing van onbetrouwbare redirects.
Voeg voor je eigen integratie expliciet een test voor de overgang van gast naar ingelogde klant toe. De bestaande gastwinkelwagentest bewijst geen volledige bearer-only aankoopflow.