Naar de inhoud
SyncMyShop

Platformen

WooCommerce koppeling met ERP, boekhouding, magazijn en leveranciers

Een WooCommerce koppeling stuurt orders en klanten naar je ERP of boekhouding en schrijft voorraad, prijzen en verzendstatus terug in je webshop. WooCommerce draait op je eigen server, dus de grenzen komen uit de REST API, je hosting en je plugins: 10 records per pagina, 100 per batch en webhooks die via wp-cron lopen.

Wat is WooCommerce en wie gebruikt het?

WooCommerce is een open-source webshop die als plugin op WordPress draait. Het draait op je eigen server of bij je hostingpartij, in de versie die jij hebt geïnstalleerd, met de plugins die jij hebt gekozen. Dat maakt elke WooCommerce-shop anders: twee shops op dezelfde versie kunnen andere orderstatussen, andere velden en een andere doorvoer hebben.

Voor een koppeling betekent dat drie dingen. De REST API is bij elke shop hetzelfde: versie 3, beschikbaar vanaf WooCommerce 3.5 en WordPress 4.4. De snelheid hangt af van je hosting. En een deel van de gegevens zit in velden van plugins, die per shop in kaart gebracht moeten worden.

Wat je met WooCommerce koppelt

De webshop is leidend voor orders en nieuwe klanten. Artikelen, voorraad en prijzen komen uit het systeem erachter.

Stroom Richting Endpoint in WooCommerce
Orders WooCommerce naar ERP of boekhouding GET /wp-json/wc/v3/orders
Klanten WooCommerce naar ERP customers, of billing op de order
Voorraad ERP of magazijn naar WooCommerce stock_quantity via products/batch
Prijzen ERP naar WooCommerce regular_price, sale_price
Verzendstatus magazijn naar WooCommerce status en meta_data op de order
Terugbetalingen WooCommerce naar boekhouding orders/<id>/refunds

Voorraad in WooCommerce bestaat uit vier velden per product: manage_stock, stock_quantity, stock_status (instock, outofstock of onbackorder) en backorders (no, notify of yes). Een koppeling die alleen het aantal schrijft terwijl manage_stock uitstaat, verandert niets aan wat de klant ziet. Staat backorders op yes, dan blijft een product met voorraad 0 bestelbaar.

Naast ERP en magazijn is er de leverancier. Voorraad en levertijd uit een leveranciersbestand gaan via dezelfde endpoints de shop in; zie leveranciersvoorraad koppelen en levertijd synchroniseren. De stromen in het algemeen staan op voorraad en beschikbaarheid en orders, klanten en verzending.

Hoe WooCommerce data vrijgeeft

Sleutels, permalinks en HTTPS

Toegang loopt via een Consumer Key en een Consumer Secret, aangemaakt onder WooCommerce, Instellingen, Geavanceerd, REST API. Drie dingen gaan hier in de praktijk mis:

  • Het Consumer Secret wordt één keer getoond. Wie het scherm sluit zonder het te kopiëren, maakt een nieuwe sleutel aan.
  • De sleutel hangt aan een WordPress-gebruiker. Wordt die gebruiker verwijderd, bijvoorbeeld een medewerker die vertrekt, dan werkt de sleutel niet meer en staat de koppeling stil. Maak de sleutel aan op een eigen gebruiker voor de koppeling.
  • Staan de permalinks op Eenvoudig (in oudere versies Standaard), dan bestaan de endpoints onder /wp-json/ niet. Elke andere instelling werkt.

Over HTTPS gaan de sleutels mee als basic authentication. Over HTTP vraagt WooCommerce OAuth 1.0a met een handtekening per verzoek. Wij koppelen alleen over HTTPS.

Pagina's van 10, batches van 100

Een lijst komt standaard terug in pagina's van 10 records; met per_page vraag je er meer. Het totaal staat in de headers X-WP-Total en X-WP-TotalPages. Schrijven kan per record of in een batch: POST /wp-json/wc/v3/products/batch maakt, wijzigt en verwijdert standaard maximaal 100 objecten per verzoek.

De rekensom voor een voorraadronde over 15.000 enkelvoudige producten:

Aanpak Rekensom Verzoeken
Lezen met de standaardpagina 15.000 / 10 1.500
Schrijven per product 15.000 x 1 15.000
Schrijven in batches 15.000 / 100 150
Alleen wijzigingen, 340 producten 340 / 100, naar boven afgerond 4

Duurt een batch van 100 op jouw server 3 seconden (een aanname; meet het op je eigen hosting), dan kost de volledige ronde 150 x 3 = 450 seconden, dus 7,5 minuut. De ronde met alleen de 340 gewijzigde producten kost 12 seconden. Daarom vergelijkt de koppeling eerst met de vorige stand en schrijft hij alleen wat veranderd is. Hoe je zo'n ronde doorrekent staat in doorvoer berekenen.

Variaties tellen anders. Het batch-endpoint voor variaties werkt per hoofdproduct: products/<product_id>/variations/batch. Een shop met 3.000 variabele producten van elk 5 variaties heeft 15.000 voorraadregels, en een volledige ronde kost 3.000 verzoeken in plaats van 150.

Een voorraadronde in batches, een order via de webhook en de controleronde De koppeling vraagt het ERP welke voorraad gewijzigd is en schrijft 340 artikelen in 4 batches naar WooCommerce. WooCommerce meldt een nieuwe order met de webhook order.created; de koppeling antwoordt direct en zet de order in het ERP. Een uur later vraagt de koppeling met modified_after welke orders gewijzigd zijn, als controle op gemiste webhooks. ERP voorraad, orders Koppeling wachtrij WooCommerce REST API v3 voorraad gewijzigd sinds 09:00? 340 artikelen POST products/batch 200 OK 4 batches: 100 + 100 + 100 + 40 webhook order.created 200 OK order 10482 als verkooporder 1 uur later GET orders?modified_after= 2 orders, 1 nog niet verwerkt De controleronde vindt de order waarvan de webhook niet aankwam.
Een voorraadronde in batches van 100, een order via de webhook en de controleronde die gemiste webhooks opvangt.

Geen limiet in de API, wel op je server

De documentatie van de REST API noemt geen rate limit. De limiet die WooCommerce documenteert geldt voor de Store API van winkelwagen en checkout: standaard uit, 25 verzoeken per 10 seconden als hij aanstaat, en alleen op POST. De grens voor een koppeling ligt bij de server: geheugen, het aantal PHP-processen, een beveiligingsplugin of de firewall van de hostingpartij. Een koppeling die 's middags met tien verzoeken tegelijk producten bijwerkt, maakt de shop traag voor klanten. Wij sturen het tempo op de gemeten antwoordtijd en plannen volledige rondes buiten de drukke uren.

Webhooks via wp-cron

WooCommerce heeft webhooks voor orders, klanten, producten en kortingscodes, bijvoorbeeld order.created en product.updated. Elk bericht draagt de header X-WC-Webhook-Signature: een HMAC-SHA256 over de inhoud, base64-gecodeerd. Twee eigenschappen maken een controleronde nodig:

  • De aflevering loopt standaard op de achtergrond via wp-cron. WP-Cron draait alleen als iemand een pagina opvraagt. Op een rustige B2B-shop kan een order van 02:00 dus blijven liggen tot de eerste bezoeker van de ochtend.
  • Na meer dan vijf mislukte afleveringen op rij schakelt WooCommerce de webhook uit. Hij komt niet vanzelf terug.

HPOS

Sinds WooCommerce 8.2 (oktober 2023) staat High-Performance Order Storage standaard aan bij nieuwe installaties. Orders staan dan in eigen tabellen zoals wp_wc_orders, niet meer in de tabellen voor berichten en hun metavelden. Via de REST API maakt dat geen verschil. Een bestaand script dat orders met SQL uit de database haalt, vindt na de overstap niets meer. Vervangen wij zo'n script, dan lezen we via de API.

Waar het bij WooCommerce op vastloopt

Btw in twee of vier decimalen

De API rondt bedragen standaard af op 2 decimalen. De parameter dp bepaalt het aantal. Dat verschil komt in de boekhouding terug. Een regel van € 4,13 exclusief met 21% btw:

btw exact:            4,13 x 0,21 = 0,8673
met dp=2:             0,87   ->  0,87 / 4,13 = 21,07%
met dp=4:             0,8673 ->  0,8673 / 4,13 = 21,00%

Een boekhoudpakket dat het percentage uit de bedragen afleidt, herkent 21,07% niet als het hoge tarief en weigert de regel of boekt hem op de verkeerde btw-code. De koppeling haalt orders op met dp=4 en bepaalt de btw-code uit het tarief, niet uit een teruggerekend percentage. Het veld prices_include_tax op de order zegt of de prijzen inclusief of exclusief zijn ingevoerd. Meer in bedragen en btw mappen.

Variabele producten en SKU's

WooCommerce kent vier producttypen: simple, grouped, external en variable. Bij een variabel product heeft elke variatie een eigen ID en een eigen SKU, en het hoofdproduct is zelf niet bestelbaar. Het ERP kent meestal alleen de artikelen op het niveau van de variatie. De koppeling houdt per SKU bij of het een enkelvoudig product of een variatie is, en onder welk hoofdproduct die valt, want het endpoint verschilt. Een variatie zonder SKU is voor de koppeling niet te vinden en krijgt dus geen voorraad. Zie varianten.

Gastbestellingen en adressen

Een order van een gast heeft customer_id 0. De klantgegevens staan dan alleen in billing op de order. Zonder vaste volgorde van zoeken, bijvoorbeeld eerst op klantnummer, dan op e-mail, dan op btw-nummer, maakt elke gastbestelling een nieuwe debiteur aan. Zie dubbele klanten en debiteuren.

Het adres heeft twee regels, address_1 en address_2, zonder los veld voor huisnummer en toevoeging. Een ERP dat straat, huisnummer en toevoeging apart bewaart, vraagt om een splitsing; zie adresvelden mappen.

Velden van plugins

Factuurnummers, track-and-trace, een btw-nummer bij de checkout, een inkoopreferentie van de klant: in WooCommerce komen ze uit plugins en staan ze in meta_data op de order, elk onder een eigen sleutel. Twee factuurplugins gebruiken twee verschillende sleutels, en een shop die van plugin wisselt heeft oude orders met de ene en nieuwe met de andere. De koppeling legt per sleutel vast wat ermee gebeurt, en in welke volgorde hij zoekt als er meer dan één kandidaat is.

Datums staan in twee velden. date_created staat in de tijdzone van de site, date_created_gmt in GMT. Een order van 00:30 Nederlandse tijd op 1 november staat in GMT op 31 oktober, 23:30. Wie de verkeerde van de twee velden gebruikt, boekt de order in de verkeerde maand. De koppeling gebruikt overal de GMT-velden en rekent bij het boeken om naar Nederlandse tijd.

Systemen die we aan WooCommerce koppelen

De koppeling wordt gebouwd op jouw shop, met jouw plugins en jouw hosting. Per combinatie staat op een eigen pagina wat er specifiek speelt:

De systemen zelf: Exact Online koppeling, AFAS webshop koppeling, Business Central koppeling en Picqer-koppeling. Het overzicht van alle stromen en systemen staat op koppelingen.

Wij bouwen de koppeling voor een vaste prijs, en hosten, draaien en bewaken hem daarna voor een vast bedrag per maand. Voor de livegang draait hij als dry run: je ziet per product welke voorraad en prijs er in WooCommerce zou komen en per order wat er naar je ERP zou gaan, zonder dat er iets wijzigt. Vertel welke systemen achter je shop staan, dan hoor je welke stromen via webhooks kunnen en wat een volledige ronde op jouw hosting kost.

Veelgestelde vragen

Welke versie van WooCommerce heb ik nodig?

Voor de huidige REST API (v3) vraagt WooCommerce minimaal WooCommerce 3.5 en WordPress 4.4. De permalinks moeten op iets anders dan Eenvoudig staan, anders zijn de endpoints niet bereikbaar. De API werkt over HTTP en HTTPS; wij koppelen alleen over HTTPS, zodat de sleutels niet leesbaar over de lijn gaan.

Is een webhook nodig voor een WooCommerce koppeling?

Nee. De koppeling kan op vaste momenten opvragen welke orders sinds de vorige ronde zijn gewijzigd, met het filter modified_after. Een webhook maakt het sneller: de order komt binnen seconden door in plaats van bij de volgende ronde. Wij gebruiken beide. De ronde blijft draaien als controle, omdat WooCommerce een webhook uitschakelt na meer dan vijf mislukte afleveringen op rij. Zie wat is een webhook.

Heeft de WooCommerce REST API een rate limit?

De documentatie van de REST API noemt geen limiet. De rate limiting die WooCommerce wel heeft, hoort bij de Store API van de winkelwagen en de checkout: standaard uit, en als hij aanstaat 25 verzoeken per 10 seconden. In de praktijk bepaalt je server de grens: de PHP-geheugenlimiet, het aantal processen en eventuele beveiligingsplugins of een firewall bij je hostingpartij. De koppeling meet de antwoordtijd en past het tempo daarop aan.

Werkt de koppeling met HPOS?

Ja. Sinds WooCommerce 8.2 van oktober 2023 staat High-Performance Order Storage standaard aan bij nieuwe installaties: orders staan in eigen tabellen in plaats van in de tabellen voor berichten. De koppeling leest en schrijft via de REST API en merkt daar niets van. Een maatwerkscript of plugin die orders rechtstreeks uit de database leest, vindt ze na de overstap niet meer.

Kan WooCommerce klantspecifieke prijzen en staffels aan?

Niet uit zichzelf. Een product of variatie heeft in de REST API twee prijsvelden, regular_price en sale_price. Prijzen per klant, klantgroep of staffel komen van een B2B-plugin, die ze in eigen velden of tabellen bewaart. De koppeling schrijft de prijzen uit je ERP naar de velden van de plugin die jij gebruikt. Zie klantspecifieke prijzen.

Werkt het met plugins zoals WPML of WooCommerce Subscriptions?

Plugins bewaren hun gegevens in meta_data op de order of het product, of in eigen tabellen met eigen endpoints. Bij de bouw lezen we uit welke sleutels jouw plugins gebruiken en leggen we per sleutel vast wat ermee gebeurt. Het veld created_via op de order laat zien waar een order vandaan komt, zodat orders die een plugin aanmaakt een eigen route kunnen krijgen.

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

Leveranciers, producten, orders per dag, een ruwe schatting is prima.

Of mail direct: carsten@syncmyshop.com