OCI en PunchOut
OCI koppeling webshop
Een inkoper komt vanuit zijn inkoopsysteem ingelogd je webshop binnen en draagt zijn winkelmand over in plaats van af te rekenen. Wij bouwen het inlogadres, de sessie en de overdracht op Shopify, Magento, WooCommerce, Shopware of een maatwerk webshop, en draaien en bewaken de koppeling daarna.
Wat er in je webshop verandert
Een OCI-bezoeker gebruikt dezelfde webshop als je andere klanten, met drie verschillen: hoe hij binnenkomt, wat zijn sessie onthoudt en waar zijn winkelmand eindigt.
| Onderdeel | Gewone klant | Inkoper via OCI |
|---|---|---|
| Binnenkomst | Inlogscherm, eigen wachtwoord | Inlogadres dat gebruikersnaam, wachtwoord en HOOK_URL uit de aanroep leest |
| Sessie | Eén sessie per browser | Eén sessie per aanroep, met HOOK_URL en returntarget erbij bewaard |
| Prijzen en assortiment | Van zijn debiteur | Van de debiteur die bij de OCI-gebruikersnaam hoort |
| Einde van de winkelmand | Kassa, betaling, order | Formulier met NEW_ITEM-velden naar HOOK_URL; geen betaling, geen order |
| Order | Direct | Later, na goedkeuring bij de klant, met zijn inkoopordernummer |
De sessie per aanroep is nodig omdat alle inkopers van één klant meestal dezelfde gebruikersnaam delen. Bewaart de webshop de winkelmand per account, dan vullen twee inkopers samen één mandje. De koppeling maakt daarom bij elke aanroep een nieuwe winkelmand en hangt die aan de sessie, niet aan het account.
Wat er in de aanroep staat en hoe het formulier terug eruitziet, staat in wat is een OCI koppeling. Het verloop van de hele bestelling staat op OCI en PunchOut.
Frames en cookies
Sommige inkoopsystemen tonen de webshop in een frame binnen hun eigen scherm. Twee beveiligingen van de browser houden dat standaard tegen.
De eerste is de header waarmee een webshop vastlegt wie hem in een frame mag laden. Shopify stuurt X-Frame-Options: DENY, Magento SAMEORIGIN. Met die waarden blijft het frame leeg.
De tweede is de sessiecookie. Sinds Chrome 80, in 2020, behandelt de browser een cookie zonder SameSite-kenmerk als SameSite=Lax. Een Lax-cookie gaat niet mee met verzoeken vanuit een frame op een ander domein. De inkoper logt goed in, klikt op een artikel en staat weer voor het inlogscherm, of zijn winkelmand is leeg. Een cookie die in zo'n frame moet werken, heeft SameSite=None en Secure nodig, en dus HTTPS.
Voor een klant die een frame gebruikt, antwoordt de webshop zo:
HTTP/1.1 200 OK
Content-Security-Policy: frame-ancestors 'self' https://inkoop.bakkerinstallatie.example
Set-Cookie: sessie=7f3a91c2; Path=/; Secure; HttpOnly; SameSite=None
De regel frame-ancestors noemt het domein van deze ene klant. De webshop blijft voor elk ander domein gesloten.
Per platform
Op 3 oktober 2026 nagelezen in de documentatie van elk platform:
| Platform | Automatisch inloggen | Frame, standaard | Winkelmand uitlezen |
|---|---|---|---|
| Shopify | Alleen op Plus: een identiteitsprovider met OpenID Connect, of Multipass voor winkels die het al hebben | X-Frame-Options: DENY |
GET /cart.js, prijs in centen: 1708 |
| Magento | Eigen inlogadres in een module | SAMEORIGIN, in te stellen in app/etc/env.php |
/V1/carts/mine/items, prijs als getal: 17.08 |
| WooCommerce | Eigen inlogadres in een plugin | Geen header op de winkelpagina's | Store API /wc/store/v1/cart, prijs als tekst in centen: "1708" |
Shopify
De koppeling staat buiten Shopify en meldt de inkoper aan via een identiteitsprovider met OpenID Connect. Shopify herkent de klant aan de claims email en sub en maakt hem aan als hij nog niet bestaat. Dat kan alleen op Shopify Plus, en er is per winkel één actieve identiteitsprovider, dus de inlog verandert voor alle klanten. Winkels die Multipass al gebruiken, houden dat: een token van 15 minuten dat één keer bruikbaar is, via /account/login/multipass/{token}. Voor nieuwe winkels stelt Shopify Multipass niet meer open. De kassa van Shopify blijft buiten beeld: de overdrachtsknop staat op de winkelmandpagina in het thema en is alleen zichtbaar in een OCI-sessie.
De header X-Frame-Options: DENY is op Shopify niet zelf aan te passen. Vraagt het inkoopsysteem om een frame, dan opent de beheerder bij je klant de webshop in een eigen venster, of Shopify zet de bescherming voor jouw winkel uit na een verzoek aan de support.
Prijzen per klant lopen via B2B-catalogi. Shopify B2B is er op Basic, Grow, Advanced en Plus. Op de eerste drie zijn er 3 actieve catalogi; een catalogus direct aan één bedrijf hangen kan alleen op Plus. Meer over het platform: Shopify koppeling.
Magento
Magento draait op je eigen server, dus het inlogadres is een module in de webshop zelf. De module controleert de aanroep, logt de klant in en bewaart HOOK_URL in de sessie. De waarde van x-frame-options staat in app/etc/env.php. Adobe raadt af de webshop in een frame te draaien; de module geeft daarom alleen het domein van de klant vrij. Prijzen per klant komen in Adobe Commerce uit de gedeelde catalogi van de B2B-module. Zie Magento koppeling.
WooCommerce
WordPress stuurt de frameheader alleen op de inlogpagina en in het beheer; de winkelpagina's hebben hem niet, tenzij de hosting of een beveiligingsplugin hem toevoegt. De winkelmand hangt aan de cookie wp_woocommerce_session_, die standaard 2 dagen geldig is voor een bezoeker en 7 dagen voor een ingelogde klant. WooCommerce heeft in de kern één prijs en één actieprijs per product. Prijzen per klant komen dus uit een plugin of rechtstreeks uit je ERP. Zie WooCommerce koppeling.
Shopware en maatwerk
Voor Shopware 6 staan in de Shopware Store extensies voor OCI en cXML, en Shopware noemt PunchOut op de eigen roadmap. Zie Shopware koppeling. Bij een maatwerk webshop krijgt de koppeling een eigen inlogadres en leest hij de winkelmand via de API of de database van de webshop.
Van winkelmand naar OCI-velden
Elk platform bewaart de winkelmand anders, en het inkoopsysteem wil hem in één vast formaat. Dit is een regel uit /cart.js van Shopify:
{
"currency": "EUR",
"total_price": 20496,
"items": [
{
"sku": "10482",
"title": "Wandcontactdoos 2-voudig met randaarde, inbouw, RAL 9010",
"quantity": 12,
"price": 1708,
"line_price": 20496
}
]
}
De koppeling zet daar vier dingen in om:
pricestaat in centen. 1708 / 100 = 17.08 voorNEW_ITEM-PRICE, met een punt en zonder duizendtalscheiding. Controle: 12 × 17,08 = 204,96, gelijk aanline_price20496.titletelt 56 tekens,NEW_ITEM-DESCRIPTION40. De koppeling stuurt de korte omschrijving van het artikel en niet de eerste 40 tekens van de titel.- De regel heeft geen besteleenheid in een code die het inkoopsysteem kent.
NEW_ITEM-UNITkomt uit een eigen veld bij het artikel, bijvoorbeeld een metaveld metPCE. currencystaat één keer op de winkelmand en gaat op elke regel mee alsNEW_ITEM-CURRENCY.
Bij WooCommerce is de som dezelfde met andere invoer: de prijs is de tekst "1708" met currency_minor_unit 2, dus 1708 / 10² = 17.08. Magento levert 17.08 al als getal.
Een artikel dat per 100 wordt verkocht, vraagt een keuze. Kabelbinders van 3,75 per 100 staan in de webshop als één product met aantal 5. Het inkoopsysteem krijgt aantal 500 met NEW_ITEM-PRICEUNIT 100, of aantal 5 met een eenheid voor de verpakking. In beide gevallen is het regelbedrag 5 × 3,75 = 18,75. Welke van de twee het wordt, bepaalt hoe het artikel bij je klant in de administratie komt. De koppeling legt dat per klant vast.
Zonder eigen webshop
Een leverancier zonder webshop kan een OCI-sessie aanbieden met een catalogus die alleen via het inkoopsysteem bereikbaar is. De inkoper ziet artikelen, prijzen en voorraad uit het ERP van de leverancier en draagt zijn winkelmand op dezelfde manier over. De catalogus heeft per artikel minstens de velden van de overdracht nodig: een omschrijving van hoogstens 40 tekens, een eenheid, een prijs per debiteur en een artikelnummer.
Wil je klant geen sessie maar een bestand met je artikelen in zijn eigen systeem, dan is dat een andere route. Het verschil staat in PunchOut of catalogusbestand. Vraagt je klant met AFAS om de koppeling, lees dan OCI koppeling AFAS.
Vertel op welk platform je webshop draait en welk inkoopsysteem je klant gebruikt, dan hoor je wat er voor die combinatie nodig is.
Veelgestelde vragen
Heb ik Shopify Plus nodig voor een OCI koppeling?
Voor automatisch inloggen in de Shopify-webshop zelf wel. Inloggen van buitenaf kan alleen op Shopify Plus: via een eigen identiteitsprovider met OpenID Connect, of via Multipass als de winkel dat al gebruikt. Shopify stelt Multipass niet meer open voor nieuwe winkels. Op Basic, Grow en Advanced loopt de OCI-sessie via een catalogus naast de webshop, gevuld met dezelfde artikelen en prijzen.
Moet mijn webshop in een frame kunnen draaien?
Alleen als het inkoopsysteem van je klant de webshop in een frame toont. AFAS InSite linkt de inkoper door naar de webshop. SAP-omgevingen kunnen de webshop in een frame van het eigen scherm laden en geven dan de parameter returntarget mee. In dat geval moet de webshop het domein van de klant toestaan en de sessiecookie met SameSite=None; Secure zetten.
Kunnen mijn gewone klanten nog gewoon afrekenen?
Ja. De overdrachtsknop verschijnt alleen in een sessie die via het inlogadres is gestart. Een klant die zelf inlogt ziet de kassa zoals altijd, met dezelfde prijzen en hetzelfde assortiment.
Wat gebeurt er met de voorraad in een overgedragen winkelmand?
Niets, tenzij je dat anders regelt. Na de overdracht bestaat er geen order en dus geen reservering. De order komt pas na goedkeuring bij je klant, en dat kan uren of dagen later zijn. Of de koppeling de voorraad al bij de overdracht vasthoudt, leg je per klant vast. Zie reserveren bij goedkeuring.
Welke gegevens uit de winkelmand gaan terug?
Per regel in elk geval de omschrijving, het aantal, de eenheid, de prijs met valuta en jouw artikelnummer. De veldnamen en lengtes zijn die van de OCI-specificatie; welke extra velden een klant leest, verschilt per inkoopsysteem. De volledige lijst staat op OCI en PunchOut.
Vertel wat je nodig hebt
Vertel welke systemen je gebruikt en wat je wilt verbeteren. Je krijgt binnen één werkdag een persoonlijk antwoord. We helpen je de werkzaamheden helder te krijgen en spreken de prijs en planning af voordat je iets toezegt.
- Je weet de prijs en de doorlooptijd voordat je iets toezegt
- Wij zoeken uit welke koppeling het werk uit handen neemt
- Wij verzorgen de bouw, hosting, bewaking en het onderhoud
- Je team krijgt minder overtypwerk en minder uitzoekwerk