top of page

Jak zakodować fakturę w Wix

Jak zakodować fakturę w Wix: walidacja NIP, pola firmowe i zapis do CRM (Velo, krok po kroku)

Cel:

  • Klient zaznacza „Chcę fakturę” w trakcie zakupów.

  • Gdy to zrobi, pojawiają się Nazwa firmy i NIP (wymagane tylko wtedy).

  • NIP jest sprawdzany (walidacja) – błędny numer blokuje przejście dalej.

  • Dane zapisują się do Wix Contacts (CRM), żeby były spójne przy kolejnych zamówieniach i na dokumentach.

Uwaga: Strony koszyka i kasy (checkout) w Wix mają ograniczone możliwości modyfikacji. Dlatego najprościej zrobić krótką stronę „Dane do faktury” (pre-checkout), którą klient odwiedza tuż przed koszykiem/kasą albo w trakcie. Zebrane dane zapisujemy do CRM i wykorzystujemy później w fakturach.

Część 0 — Jednorazowe przygotowanie

0.1. Włącz tryb Velo (Dev Mode)

  1. Zaloguj się do Edytora (Wix Studio lub klasyczny Editor X/Wix Editor).

  2. W górnym pasku kliknij Dev Mode → Turn on Dev Mode.

    • Pojawi się panel Code Files (po lewej) i zakładka Page Code (u dołu).

0.2. Utwórz stronę „Dane do faktury” (pre-checkout)

  1. Add Page → nazwa: Dane do faktury.

  2. To będzie krótki formularz z checkboxem i dwoma polami tekstowymi.

0.3. Dodaj elementy na stronie

Na stronie „Dane do faktury” wstaw:

  • Checkbox (ID: #invoiceCheckbox) – etykieta: Chcę fakturę.

  • Text Input (ID: #companyInput) – placeholder: Nazwa firmy (na fakturę).

  • Text Input (ID: #nipInput) – placeholder: NIP (10 cyfr, bez spacji).

  • Button (ID: #continueBtn) – tekst: Kontynuuj do kasy.

Jak nadać ID? Zaznacz element → panel Properties → ID.Ustaw #companyInput i #nipInput jako ukryte na start (Hidden on load).

0.4. (Opcjonalnie) Dodaj pole na e-mail

Jeśli dopuszczasz zakup jako gość (bez logowania), dodaj:

  • Text Input (ID: #emailInput) – placeholder: E-mail do faktury.To pozwoli nam utworzyć/zaktualizować kontakt w CRM nawet bez konta członkowskiego.

0.5. Przygotuj pola w CRM (Wix Contacts)

W Kontakty/Contacts dodaj dwa pola niestandardowe:

  • invoiceCompanyName (Tekst) – Nazwa firmy (na fakturę)

  • invoiceNIP (Tekst) – NIP (na fakturę)

Nazwy zapamiętaj – użyjemy ich w kodzie.

Część 1 — Walidacja NIP (frontend)

Otwórz Page Code na stronie „Dane do faktury” i wklej:


// --- Walidacja NIP (Polska) ---

function normalizeDigits(value) {

return (value || '').replace(/\D/g, '');

}


export function isValidNIP(raw) {

const nip = normalizeDigits(raw);

if (nip.length !== 10) return false;

const weights = [6, 5, 7, 2, 3, 4, 5, 6, 7];

const digits = nip.split('').map(d => parseInt(d, 10));

const checksum = digits

.slice(0, 9)

.reduce((sum, d, i) => sum + d * weights[i], 0) % 11;

return checksum === digits[9];

}


To jest „serce” walidacji – sprawdza długość i sumę kontrolną NIP.


Część 2 — Logika interfejsu (pokazywanie pól + blokada przycisku)

W tym samym Page Code dopisz, JS:


import wixWindow from 'wix-window';


$w.onReady(() => {

// 1) Ukryj pola firmowe na starcie (dla bezpieczeństwa)

$w('#companyInput').hide();

$w('#nipInput').hide();


// 2) Gdy użytkownik zaznaczy "Chcę fakturę", pokaż i ustaw wymagania

$w('#invoiceCheckbox').onChange((ev) => {

const needInvoice = ev.target.checked;


if (needInvoice) {

$w('#companyInput').show();

$w('#nipInput').show();

} else {

$w('#companyInput').hide();

$w('#nipInput').hide();

clearNipError();

}

validateForm();

});


// 3) Walidacja NIP „w locie”

$w('#nipInput').onInput(() => {

validateForm();

});


// 4) Obsługa przycisku „Kontynuuj do kasy”

$w('#continueBtn').onClick(onContinueClick);


function clearNipError() {

$w('#nipInput').resetValidityIndication();

}


function setNipError(msg) {

$w('#nipInput').updateValidityIndication({

valid: false,

validationMessage: msg || 'Nieprawidłowy NIP (10 cyfr).'

});

}


function validateForm() {

const needInvoice = $w('#invoiceCheckbox').checked;

const companyVal = ($w('#companyInput').value || '').trim();

const nipVal = ($w('#nipInput').value || '').trim();


if (!needInvoice) {

$w('#continueBtn').enable();

return;

}


// Wymagalność przy zaznaczonym checkboxie

if (!companyVal) {

$w('#continueBtn').disable();

return;

}


if (!isValidNIP(nipVal)) {

setNipError();

$w('#continueBtn').disable();

return;

}


clearNipError();

$w('#continueBtn').enable();

}

});


Co to robi:

  • Pola firmowe są widoczne tylko gdy klient chce fakturę.

  • NIP jest sprawdzany na bieżąco; błędny → blokujemy przycisk.

  • Funkcja onContinueClick zostanie dopisana w kolejnym kroku.

Jeśli wolisz użyć przycisku systemowego checkoutu, umieść ten formularz przed koszykiem (pre-checkout). Dzięki temu nie ingerujesz w natywny przycisk kasy.

Część 3 — Zapis danych do CRM (frontend → backend)

3.1. Frontend: wywołanie funkcji backendowej

Na końcu Page Code dopisz JS:


import { saveInvoiceDataForContact } from 'backend/invoice-utils';


export async function onContinueClick(event) {

const needInvoice = $w('#invoiceCheckbox').checked;


// Jeśli nie trzeba faktury — idziemy dalej do kasy/strony koszyka

if (!needInvoice) {

goToCheckout();

return;

}


const company = ($w('#companyInput').value || '').trim();

const nip = ($w('#nipInput').value || '').trim();

const email = ($w('#emailInput')?.value || '').trim(); // może nie istnieć, jeśli nie dodasz pola e-mail


// Ostatnia kontrola

if (!company || !isValidNIP(nip)) {

// Pokaż drobną informację dla użytkownika

wixWindow.openLightbox("Błąd", { message: "Uzupełnij poprawnie nazwę firmy i NIP." }).catch(()=>{});

return;

}


try {

// Zapisz do CRM (backend)

await saveInvoiceDataForContact({ company, nip, email });


// Dalej do koszyka/kasy

goToCheckout();

} catch (e) {

console.error(e);

wixWindow.openLightbox("Błąd", { message: "Nie udało się zapisać danych do faktury. Spróbuj ponownie." }).catch(()=>{});

}

}


function goToCheckout() {

// Przekieruj tam, gdzie zaczyna się Twój proces zakupowy:

// - na koszyk: /cart

// - bezpośrednio do kasy (jeśli masz link): /checkout

wixLocation.to('/cart'); // lub '/checkout'

}


Jeśli wyświetlanie lightboxa jest dla Ciebie za ciężkie, zamiast tego pokaż mały tekst błędu obok przycisku.

Uwaga: potrzebujesz importu wix-location na górze pliku, jeśli używasz wixLocation:

Plik JS

import wixLocation from 'wix-location';


3.2. Backend: funkcja zapisująca dane do kontaktu

W panelu Code Files dodaj nowy plik:/backend/invoice-utils.jsw (ważne: .jsw – web-module, by frontend mógł go wywołać)

Wklej JS Plik:


import { currentMember } from 'wix-members-backend';

import wixCrm from 'wix-crm-backend';


/**

* Zapisuje/aktualizuje dane do faktury w kontakcie CRM.

* Priorytet:

* 1) Jeżeli użytkownik jest zalogowany (ma contactId) → aktualizujemy jego kontakt.

* 2) Jeżeli nie jest zalogowany, ale podał email → tworzymy/aktualizujemy kontakt po emailu.

*/

export async function saveInvoiceDataForContact({ company, nip, email }) {

if (!company || !nip) {

throw new Error('Brak wymaganych danych: company/nip.');

}


// 1) Próba przez zalogowanego członka

const member = await currentMember.getMember().catch(() => null);

const contactId = member?.contactId;


if (contactId) {

await updateContact(contactId, { company, nip });

return { ok: true, via: 'member' };

}


// 2) Gość: potrzebujemy e-maila, aby utworzyć/znaleźć kontakt

if (!email) {

throw new Error('Brak contactId i brak email – nie możemy zidentyfikować kontaktu.');

}


// Spróbuj znaleźć istniejący kontakt po e-mailu (w praktyce używa się search, tu – prosto: create lub update)

const created = await wixCrm.createContact({

info: {

emails: [email],

company,

extendedFields: {

// Uwaga: extendedFields (custom fields) różnią się nazwami kluczy – dopasuj do Twojej konfiguracji

'invoiceCompanyName': company,

'invoiceNIP': nip

}

}

});


// Jeśli kontakt już istniał, createContact potrafi go zmergować/zwrócić właściwy rekord.

// Na wszelki wypadek wykonamy update (idempotentnie):

await updateContact(created.contactId, { company, nip });


return { ok: true, via: 'email' };

}


async function updateContact(contactId, { company, nip }) {

// Uaktualnij standardowe pole Company + custom fields (dopasuj klucze do swoich!)

await wixCrm.updateContact(contactId, {

company,

extendedFields: {

'invoiceCompanyName': company,

'invoiceNIP': nip

}

});

}


Ważne: nazwy pól niestandardowych w extendedFields muszą odpowiadać dokładnie temu, co masz w CRM (klucze techniczne). Jeśli używasz kreatora pól, podejrzyj ich Field Key i podmień.


Część 4 — Powiązanie z fakturą (prezentacja na dokumencie)

Skoro mamy dane w CRM, w dalszym kroku (gdy klient finalizuje zakup) dane rozliczeniowe trafiają do zamówienia i dokumentów. Aby Nazwa firmy i NIP były widoczne na fakturze:

  1. Upewnij się, że w Checkout Settings masz włączone zbieranie Billing Details.

  2. Nazwa firmy powinna trafić do głównej linii danych rozliczeniowych (Billing name/Company).

  3. NIP wpisuj jako dodatkową linię adresową (np. Address line 2) z prefiksem „NIP: …”.

  4. Jeśli masz własny szablon potwierdzeń/emaili – dodaj tam sekcję, która pokazuje „Nazwa firmy (na fakturę)” i „NIP”.

Różne szablony potrafią rożnie drukować linie adresowe. Zrób test (patrz niżej). Jeśli NIP się nie drukuje, zamień pole, do którego go zapisujesz, na inne pole adresowe, które szablon na pewno pokazuje.

Część 5 — Test od A do Z (obowiązkowy)

  1. Opublikuj witrynę.

  2. Wejdź na /dane-do-faktury (Twoja strona pre-checkout).

  3. Zaznacz „Chcę fakturę”, wpisz:

    • Nazwa firmy: Przykładowa Sp. z o.o.

    • NIP: 1234563218 (przykład działającego numeru kontrolnego; możesz sprawdzić różne)

    • (Jeśli testujesz jako gość) E-mail: test@example.com

  4. Kliknij Kontynuuj do kasy → powinno przenieść Cię do /cart lub /checkout.

  5. Dokończ testowy zakup (sandbox lub najtańszy produkt).

  6. W Panelu → Kontakty sprawdź, czy przy kontakcie są pola:

    • invoiceCompanyName = Przykładowa Sp. z o.o.

    • invoiceNIP = 1234563218

  7. W Panelu → Faktury/Invoices – sprawdź dokument:

    • w sekcji nabywcy widzisz Nazwa firmy i NIP (jako dodatkowa linia).

Jeśli NIP się nie drukuje na fakturze:

  • Zmień mapowanie – np. zapisz NIP do innej linii adresowej (Address line 1/2) albo do pola, które Twój szablon faktury na pewno wyświetla.

  • Zrób jeszcze jeden testowy zakup (zmiany w checkout często pokazują efekt dopiero przy nowym zamówieniu).


Najczęstsze problemy i szybkie rozwiązania

  • Gość bez e-maila: backend nie ma jak zapisać kontaktu. Wymagaj e-maila w pre-checkout lub wyświetl prośbę o zalogowanie.

  • Błąd „Brak contactId i brak email”: dodaj #emailInput i walidację „to pole jest wymagane, jeśli klient chce fakturę”.

  • Niepoprawny NIP: skrypt zablokuje przycisk. Dopisz w podpowiedzi pola NIP: „10 cyfr, bez spacji i myślników”.

  • Dane nie widać w fakturze: zamień pole mapowania NIP na inną widoczną linię w Billing Details; niektóre szablony ukrywają pewne linie.

  • Pola nie mają ID: nadaj ID w Properties; bez tego kod nie zadziała.


Checklista dla Ciebie

  •  Włączony Dev Mode, strona Dane do faktury gotowa.

  •  Elementy mają ID: #invoiceCheckbox, #companyInput, #nipInput, #continueBtn, (opcjonalnie #emailInput).

  •  Walidacja NIP działa i blokuje przycisk, gdy numer jest błędny.

  •  Pola CRM utworzone: invoiceCompanyName, invoiceNIP (i ich klucze zgodne w kodzie).

  •  Plik backend /backend/invoice-utils.jsw istnieje; zapis do kontaktu działa (dla zalogowanego i gościa z e-mailem).

  •  Mapowanie do Billing Details powoduje, że Nazwa firmy i NIP drukują się na fakturze.

  •  Zrobiony pełny test zakupu i kontrola dokumentu.


Jak zakodować fakturę w Wix: walidacja NIP, pola firmowe i zapis do CRM (Velo, krok po kroku)

bottom of page