Jak dodać pole NIP w blokowym WooCommerce i zintegrować je z Fakturownią bez wtyczek

czas czytania 5 minuty
Karol Dobrakowski

Autor: Karol Dobrakowski

Pracując na blokowym WooCommerce szybko trafiłem na problem z integracją pola NIP. Okazało się, że to nie kwestia konfiguracji, tylko zmiany sposobu zapisu danych. W tym artykule pokazuję, jak to ogarnąć w praktyce.

Od dłuższego czasu rozwijam sklepy WooCommerce oparte o blokowe podejście i Gutenberga. To jest kierunek, który daje dużą elastyczność i dobrze sprawdza się w pracy z klientami. Wszystko działa świetnie do momentu, aż pojawiają się integracje.

U mnie temat wyszedł przy podłączeniu Fakturowni i próbie przekazania pola NIP. Klient wpisywał dane w checkoutcie, zamówienie zapisywało się poprawnie, ale system fakturowy nie widział numeru NIP.

Na początku wyglądało to jak klasyczny problem z konfiguracją. Szybko jednak okazało się, że sprawa jest trochę głębsza.

Gdzie leży problem

Pierwsza myśl była oczywista. Coś jest źle ustawione. Może klucz pola, może integracja, może wtyczka.

Po chwili debugowania wyszło, że dane w ogóle nie są zapisywane pod tym kluczem, którego oczekuje system zewnętrzny.

I to był moment, w którym zrozumiałem, że to nie jest problem Fakturowni.

To jest efekt tego, jak działa blokowy WooCommerce.

W klasycznym checkoutcie miałem pełną kontrolę nad polami i ich nazwami. W blokowym podejściu Store API generuje własne struktury i prefiksy. W praktyce pole NIP istnieje, ale zapisuje się pod inną nazwą.

Dla WooCommerce to bez znaczenia. Dla integracji to już problem.

Dlaczego standardowe podejście nie działa

Naturalnie próbowałem podejścia, które działało wcześniej. Dodać pole, ustawić odpowiedni klucz, spiąć integrację.

Wszystko wyglądało dobrze, ale efekt był zerowy.

Pole było widoczne, dane trafiały do zamówienia, a integracja dalej ich nie widziała.

To jest właśnie moment, który potrafi wprowadzić w błąd. Bo wizualnie wszystko się zgadza.

Dopiero kiedy zajrzałem w meta danych zamówienia, zobaczyłem, że klucze są inne niż zakładałem.

I wtedy wszystko zaczęło się układać.

Co było przełomem

Najważniejsza zmiana w moim podejściu polegała na tym, że przestałem walczyć z formularzem.

Zamiast tego skupiłem się na momencie zapisu zamówienia.

To tam WooCommerce przetwarza dane i zapisuje je w bazie. I to tam mam realny wpływ na to, jak będą wyglądały meta dane.

To była kluczowa decyzja, która rozwiązała problem nie tylko dla tego jednego projektu.

Dodanie pola NIP w checkoutcie

Na początek dodałem pole NIP w standardowy sposób, korzystając z funkcji WooCommerce dla blokowego checkoutu.

add_action( 'init', function () {

    if ( ! function_exists( 'woocommerce_register_additional_checkout_field' ) ) {
        return;
    }

    woocommerce_register_additional_checkout_field( array(
        'id'       => 'billing_tax_no',
        'label'    => __( 'NIP', 'my-textdomain' ),
        'location' => 'address',
        'type'     => 'text',
    ) );

} );

Tu nie kombinowałem z żadnymi prefiksami ani nazwami. Zostawiłem to WooCommerce, bo i tak nadpisuje sposób zapisu.

Sprawdzenie gdzie trafiają dane

Zanim napisałem finalne rozwiązanie, sprawdziłem dokładnie gdzie trafia NIP.

Dodałem prosty debug na etapie zapisu zamówienia.

add_action(
    'woocommerce_store_api_checkout_update_order_from_request',
    function ( $order, $request ) {

        error_log( print_r( $order->get_meta_data(), true ) );
        error_log( print_r( $request->get_body_params(), true ) );

    },
    10,
    2
);

To pozwoliło mi zobaczyć rzeczywisty klucz, pod którym zapisuje się pole. I to jest coś, co polecam zrobić w każdym projekcie, bo struktura może się różnić.

Właściwe rozwiązanie

Finalnie poszedłem w prosty mechanizm. Pobieram wartość NIP i zapisuję ją pod nowym kluczem, który jest zgodny z wymaganiami integracji.

add_action(
    'woocommerce_store_api_checkout_update_order_from_request',
    function ( $order, $request ) {

        $nip = $order->get_meta(
            '_wc_shipping/thwcfe-block/billing_tax_no',
            true
        );

        if ( ! $nip ) {
            $params = $request->get_body_params();

            if ( isset( $params['extensions']['thwcfe']['billing_tax_no'] ) ) {
                $nip = $params['extensions']['thwcfe']['billing_tax_no'];
            } elseif ( isset( $params['billing_tax_no'] ) ) {
                $nip = $params['billing_tax_no'];
            }
        }

        if ( $nip ) {
            $nip = wc_clean( wp_unslash( $nip ) );

            $order->update_meta_data( 'billing_tax_no', $nip );
        }

    },
    10,
    2
);

Nie nadpisuję danych WooCommerce. Po prostu je kopiuję.

Dzięki temu mam dwa klucze z tą samą wartością. Jeden dla WooCommerce, drugi dla integracji.

Co mi to dało w praktyce

Po wdrożeniu tego rozwiązania problem zniknął od razu. Fakturownia zaczęła poprawnie odczytywać NIP, bez żadnych dodatkowych zmian po swojej stronie.

Co ciekawe, to samo podejście wykorzystałem później przy innych integracjach i zadziałało dokładnie tak samo.

To był moment, w którym upewniłem się, że to nie był jednostkowy przypadek, tylko szerszy schemat.

Rozszerzenie na inne pola

Ten mechanizm bardzo łatwo rozbudować. Jeśli potrzebuję przekazać inne dane, robię dokładnie to samo.

$company = $order->get_meta( '_wc_billing/company', true );

if ( $company ) {
    $order->update_meta_data( 'billing_company', $company );
}

Dzięki temu mogę dostosować WooCommerce do wymagań dowolnego systemu bez ingerowania w checkout.

Najważniejsze wnioski

Największa zmiana to zrozumienie, że w blokowym WooCommerce formularz nie jest już miejscem kontroli nad danymi.

Kontrola przenosi się na etap zapisu zamówienia.

Jeśli to zaakceptujesz i wykorzystasz, integracje przestają być problemem.

Z mojej perspektywy to jedno z ważniejszych odkryć przy pracy z Gutenberg checkoutem, bo pozwala uniknąć wielu godzin szukania problemów tam, gdzie ich po prostu nie ma.

Spis treści