{ "woocommerce" :
KVK-nummer veld in de WooCommerce checkout
Kort antwoord
WooCommerce heeft geen KVK-veld. Je voegt het zelf toe: in de klassieke checkout via het filter woocommerce_billing_fields, valideren in woocommerce_after_checkout_validation en opslaan op de order. Wij leveren geen WooCommerce-plugin, wel een REST API en een widget die je in die hooks aanroept.
# server-side check bij checkout
curl ".../v1/lookup/68750110" \
-H "Authorization: Bearer KEY"
{
"name": "Acme B.V.",
"isActive": true,
"vat": {
"number": "NL123456789B01",
"valid": true
}
}
Waar de bedrijfsdata in WooCommerce moet landen
WooCommerce kent geen KVK-nummer. Er is een billing_company-veld en dat is vrije tekst. Zodra je zakelijk verkoopt, heb je drie plekken nodig waar de data terechtkomt.
| Plek | Wat er hoort te staan | Waarom |
|---|---|---|
| Checkout field | KVK-nummer, ingevoerd of gekozen | Invoer en validatie |
| Order meta | KVK-nummer, statutaire naam, BTW-nummer | Factuur en administratie |
| Customer meta | Hetzelfde, als default | Tweede bestelling zonder overtypen |
Het punt dat vaak wordt overgeslagen: de order is een momentopname. Als je alleen het KVK-nummer op de order bewaart en de naam later opnieuw ophaalt, klopt je factuur uit 2024 niet meer nadat het bedrijf in 2026 van naam is veranderd. Schrijf de naam en het adres weg op de order, niet alleen de sleutel.
De klassieke checkout: veld, validatie, opslag
Drie hooks, in deze volgorde. Zet ze in een site-specifieke plugin, niet in functions.php van een thema dat je later vervangt.
add_filter( 'woocommerce_billing_fields', function ( $fields ) {
$fields['billing_kvk'] = [
'label' => 'KVK-nummer',
'required' => false,
'class' => [ 'form-row-wide' ],
'priority' => 35,
];
return $fields;
} );
add_action( 'woocommerce_after_checkout_validation', function ( $data, $errors ) {
$kvk = trim( $data['billing_kvk'] ?? '' );
if ( $kvk === '' ) {
return;
}
if ( ! preg_match( '/^\d{8}$/', $kvk ) ) {
$errors->add( 'billing_kvk', 'Een KVK-nummer bestaat uit 8 cijfers.' );
return;
}
$res = wp_remote_get( "https://api.kvkbase.nl/v1/lookup/{$kvk}", [
'timeout' => 3,
'headers' => [ 'Authorization' => 'Bearer ' . KVKBASE_KEY ],
] );
if ( is_wp_error( $res ) || wp_remote_retrieve_response_code( $res ) >= 500 ) {
return; // API onbereikbaar: laat de order door, markeer hem later.
}
if ( wp_remote_retrieve_response_code( $res ) === 404 ) {
$errors->add( 'billing_kvk', 'Dit KVK-nummer staat niet in het Handelsregister.' );
}
}, 10, 2 );
add_action( 'woocommerce_checkout_create_order', function ( $order, $data ) {
if ( ! empty( $data['billing_kvk'] ) ) {
$order->update_meta_data( '_billing_kvk', wc_clean( $data['billing_kvk'] ) );
}
}, 10, 2 );
De return bij een 5xx of netwerkfout is bewust. Een checkout die blokkeert omdat een externe API traag is, kost je omzet. Laat de order door en zet er een order note of een status-flag op voor handmatige controle.
Blocks checkout is een tweede implementatie
Sinds de blocks checkout de standaard is, draait het formulier op React en worden de klassieke filters niet meer uitgevoerd. Daar registreer je het veld via de Additional Checkout Fields API, op woocommerce_init, met een eigen namespace. Twee dingen om te weten:
- Het veld wordt opgeslagen onder een genamespacede meta key, niet onder
_billing_kvk. Een rapportage of factuurplugin die op je oude key kijkt, geeft lege kolommen. - Server-side validatie hangt daar aan de validatiehooks van die API, niet aan
woocommerce_after_checkout_validation.
Draai je beide checkouts naast elkaar, bijvoorbeeld blocks op de shop en klassiek voor een oude flow, schrijf dan in beide gevallen weg naar dezelfde eigen meta key. Anders bouw je twee keer een rapportage.
De widget als invoerhulp
Wil je dat de klant op bedrijfsnaam zoekt in plaats van een nummer overtypt, dan hang je de widget aan het input-veld. Eén script tag, met CSS-selectors naar de velden die hij mag invullen:
<script
src="https://widget.kvkbase.nl/v1/widget.js"
data-apikey="PUBLIC_KEY"
data-target="#billing_kvk"
data-autofill="true"
data-name-target="#billing_company"
data-city-target="#billing_city"
data-postal-target="#billing_postcode"
data-vat-target="#billing_vat"
></script>
De widget vult velden in de browser. Dat is invoergemak, geen validatie: alles wat een browser invult, kan een browser ook veranderen. Doe de controle die telt server-side in de validatiehook hierboven, met een key die niet in je paginabron staat. De data-apikey is per definitie publiek.
Op de klassieke checkout werkt dit direct. Op de blocks checkout bestaat het input-element nog niet als het script laadt, dus een simpele selector vindt niets. Daar hang je de widget op na het renderen van het veld, of je gebruikt de API rechtstreeks vanuit je eigen block-component.
Wat er in productie stukgaat
De klant plakt een vestigingsnummer. Op facturen en in bevestigingsmails staat vaak het 12-cijferige vestigingsnummer in plaats van het 8-cijferige KVK-nummer. Je regex vangt dat, maar je foutmelding moet uitleggen welk nummer je wel wil, anders geeft de klant op.
Een bestaand bedrijf geeft 404. Uitgeschreven inschrijvingen verdwijnen uit het register. Behandel NOT_FOUND als “niet meer actief”, niet als “typefout”, en laat de klant doorgaan met een handmatige controle als het om een bestaande klant gaat.
VIES is onbereikbaar. De BTW-validatie loopt via de lidstaatservice en die valt regelmatig uit. Je krijgt dan UPSTREAM_ERROR en geen valid: true. Blokkeer daar nooit de checkout op: verwerk de order met btw en corrigeer achteraf als de verlegging alsnog geldig blijkt. Meer over dat mechanisme staat in BTW-nummer valideren via VIES.
Een bulk-backfill loopt tegen de rate limit. Bestaande orders verrijken met een foreach over 3.000 klanten haalt binnen een minuut de limiet. Gebruik POST /v1/lookup/batch en verwerk in chunks via een cron-actie, in plaats van één losse lookup per rij.
Veelgestelde vragen
Hebben jullie een WooCommerce-plugin?
Moet het KVK-veld verplicht zijn?
Werkt dit ook in de nieuwe blocks checkout?
Kan ik het BTW-nummer automatisch invullen?
Bijgewerkt:
Eén call geeft je het hele bedrijf
KVK-data, het afgeleide BTW-nummer en een live VIES-controle in één request. Het gratis plan geeft je 50 lookups per maand, zonder creditcard.
- 50
- gratis lookups per maand
- 1
- request in plaats van drie
- 0
- creditcards, contracten of salesgesprekken