{ "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.

cURL
# 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.

PlekWat er hoort te staanWaarom
Checkout fieldKVK-nummer, ingevoerd of gekozenInvoer en validatie
Order metaKVK-nummer, statutaire naam, BTW-nummerFactuur en administratie
Customer metaHetzelfde, als defaultTweede 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?
Nee. Wij leveren een REST API en een JavaScript-widget. De koppeling met WooCommerce bouw je zelf in een child theme of een kleine site-specifieke plugin, met de standaard checkout hooks. Dat is meestal dertig tot vijftig regels PHP.
Moet het KVK-veld verplicht zijn?
Alleen als je zakelijke klanten verplicht wilt onderscheiden. Op een winkel met zowel consumenten als bedrijven maak je het veld optioneel en toon je het pas als de klant een bedrijfsnaam invult. Een verplicht KVK-veld voor iedereen kost conversie bij particulieren.
Werkt dit ook in de nieuwe blocks checkout?
Niet met dezelfde code. De blocks checkout draait op React en negeert woocommerce_billing_fields. Daar registreer je het veld via de Additional Checkout Fields API, en het komt onder een andere meta key op de order te staan dan bij de klassieke checkout.
Kan ik het BTW-nummer automatisch invullen?
Voor een BV of NV wel. Het BTW-nummer is daar af te leiden als NL plus het KVK-nummer plus B01, en wij controleren dat live tegen VIES voordat we het teruggeven. Voor een eenmanszaak of VOF geldt die afleiding niet, dus dat veld laat je daar leeg en vraag je uit.

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