fiskalizacija2
v0.16.1
Published
Croatian fiscalization library for Node.js
Maintainers
Readme
Fiskalizacija2 Node.js Library
Node.js library za fiskalizaciju 2.0 omogućava jednostavno slanje zahtjeva za evidenciju eRačuna i eIzvještavanje.
Podržana je i B2C fiskalizacija računa u krajnjoj potrošnji (Fiskalizacija 1, CIS servis) putem klase Fiskalizacija1Client.
Instalacija
npm i fiskalizacija2
Korištenje
Library pruža klasu FiskalizacijaClient koja prima objekt konfiguracije:
{
service: string, // URL servisa za fiskalizaciju
privateKey: string | Buffer, // Privatni ključ za potpis poruke u PEM formatu
publicCert: string | Buffer, // Javni certifikat u PEM formatu
ca?: string | Buffer, // Opcionalni PEM CA bundle za validaciju SSL/TLS veze
// default: FINA ROOT CA, RDC 2020, RDC 2025
// Eksplicitno postaviti na undefined za korištenje sistemskog truststore-a
timeout?: number, // Opcionalni timeout u milisekundama (default: 30000)
}Metode za slanje zahtjeva su:
evidentirajERacun(IEvidentirajERacunZahtjev)evidentirajNaplatu(IEvidentirajNaplatu)evidentirajOdbijanje(IEvidentirajOdbijanje)evidentirajIsporukuZaKojuNijeIzdanERacun(IEvidentirajIsporukuZaKojuNijeIzdanERacun)
Sve metode vraćaju FiskalizacijaResult objekt koji sadrži:
interface FiskalizacijaResult<Z, O> {
success: boolean; // Uspjeh operacije
error?: IErrorWithMessage; // Greška ako postoji
httpStatusCode?: number; // HTTP status kod
soapReqRaw?: string; // Sirovi SOAP zahtjev
reqObject?: Z; // Objekt zahtjeva
soapResRaw?: string; // Sirovi SOAP odgovor
soapResSignatureValid?: boolean; // Valjanost potpisa odgovora
resObject?: O; // Objekt odgovora, npr. IEvidentirajERacunOdgovor
resErrors?: IErrorWithMessage[]; // Greške u validaciji odgovora regexom (ne prekidaju obradu i ne utječu na success)
}Kreiranje zahtjeva
Sučelja za zahtjeve su:
IEvidentirajERacunZahtjevIEvidentirajIsporukuZaKojuNijeIzdanERacunZahtjevIEvidentirajNaplatuZahtjevIEvidentirajOdbijanjeZahtjev
Moguće generiranje zahtjeva koristeći pomoćne metode:
getEvidentirajERacunZahtjev(vrsta: "I" | "U", eracun: IERacun | IERacun[])getEvidentirajIsporukuZaKojuNijeIzdanERacunZahtjev(racun: IRacun | IRacun[])getEvidentirajNaplatuZahtjev(naplata: INaplata | INaplata[])getEvidentirajOdbijanjeZahtjev(odbijanje: IOdbijanje | IOdbijanje[])
Objekti koji zadovoljavaju sučelja IERacun odnosno IRacun mogu se generirati iz UBL dokumenata Invoice ili CreditNote:
getERacunFromUbl(doc: string | Buffer | XmlDocument | XmlElement, options?: ExtractionOptions): IERacungetRacunFromUbl(doc: string | Buffer | XmlDocument | XmlElement, options?: ExtractionOptions): IRacun
Funkcije prihvaćaju XML kao string, Buffer, ili već parsirane XmlDocument/XmlElement objekte iz libxml2-wasm biblioteke. Automatski prepoznaju i obrađuju StandardBusinessDocument (SBD) omot oko UBL dokumenta.
Kreiranje zahtjeva iz nepotpunih/neispravnih dokumenata
Ako UBL dokument nije u potpunosti ispravan (npr. nedostaju obvezna polja ili polja ne zadovoljavaju regex), metode će baciti ValidationError. Prosljeđivanjem lenient: true opcije moguće je izvući djelomične podatke:
const options = {
lenient: true,
errors: [] // Opcionalno: polje u koje će se prikupiti sve validacijske greške
};
const eRacun = getERacunFromUbl(ublDocument, options);
// IERacun objekt će sadržavati sve podatke koji postoje, neovisno o tome da li zadovoljavaju regex.
// Polja koja nedostaju će biti prazni stringovi/nizoviPrimjeri
FiskalizacijaClient
const client = new FiskalizacijaClient({
service: FiskalizacijaServiceURL.test, // ili FiskalizacijaServiceURL.prod
privateKey: fs.readFileSync('path/to/privateKey.pem'),
publicCert: fs.readFileSync('path/to/publicCert.pem'),
})EvidentirajERacun
const ublDocument = '<Invoice xmlns="...">....</Invoice>'; // UBL XML string ili Buffer
const eRacun = getERacunFromUbl(ublDocument);
const zahtjev = getEvidentirajERacunZahtjev('I', eRacun);
const result = await client.evidentirajERacun(zahtjev);
if (result.success) {
console.log("eRačun uspješno evidentiran:", result.resObject);
} else {
console.error("Greška pri evidentiranju eRačuna:", result.error);
}EvidentirajIsporukuZaKojuNijeIzdanERacun
const ublDocument = '<Invoice xmlns="...">....</Invoice>'; // UBL XML string ili Buffer
const racun = getRacunFromUbl(ublDocument);
const zahtjev = getEvidentirajIsporukuZaKojuNijeIzdanERacunZahtjev(racun);
const result = await client.evidentirajIsporukuZaKojuNijeIzdanERacun(zahtjev);
if (result.success) {
console.log("Isporuka uspješno evidentirana:", result.resObject);
} else {
console.error("Greška pri evidentiranju isporuke:", result.error);
}EvidentirajNaplatu
const naplata: INaplata = {
// Broj dokumenta eRačuna, dio identifikatora eRačuna (BT-1 iz UBL 2.1)
brojDokumenta: "RAC-2025-0001",
// Datum izdavanja eRačuna, dio identifikatora eRačuna (BT-2 iz UBL 2.1)
datumIzdavanja: "2025-01-01",
// OIB ili porezni broj izdavatelja, dio identifikatora eRačuna (BT-31 iz UBL 2.1)
oibPorezniBrojIzdavatelja: "00000000001",
// OIB ili porezni broj primatelja
oibPorezniBrojPrimatelja: "11111111119",
// Datum naplate eRačuna
datumNaplate: "2025-01-15",
// Iznos koji je naplaćen
naplaceniIznos: 100.00,
/**
* Šifra načina plaćanja
* T - transakcijski račun
* O - obračunsko plaćanje
* Z - ostalo
*/
nacinPlacanja: "T"
};
const zahtjev = getEvidentirajNaplatuZahtjev(naplata);
const result = await client.evidentirajNaplatu(zahtjev);
if (result.success) {
console.log("Naplata uspješno evidentirana:", result.resObject);
} else {
console.error("Greška pri evidentiranju naplate:", result.error);
}EvidentirajOdbijanje
const odbijanje: IOdbijanje = {
// Broj dokumenta eRačuna, dio identifikatora eRačuna (BT-1 iz UBL 2.1)
brojDokumenta: "RAC-2025-0001",
// Datum izdavanja eRačuna, dio identifikatora eRačuna (BT-2 iz UBL 2.1)
datumIzdavanja: "2025-01-01",
// OIB ili porezni broj izdavatelja, dio identifikatora eRačuna (BT-31 iz UBL 2.1)
oibPorezniBrojIzdavatelja: "00000000001",
// OIB ili porezni broj primatelja
oibPorezniBrojPrimatelja: "11111111119",
// Datum odbijanja eRačuna
datumOdbijanja: "2025-01-20",
/**
* Šifra vrste razloga odbijanja eRačuna
* N - Neusklađenost podataka koji ne utječu na obračun poreza
* U - Neusklađenost podataka koji utječu na obračun poreza
* O - Ostalo
*/
vrstaRazlogaOdbijanja: "N",
// Razlog odbijanja eRačuna
razlogOdbijanja: "Podaci o kupcu nisu točni",
}
const zahtjev = getEvidentirajOdbijanjeZahtjev(odbijanje);
const result = await client.evidentirajOdbijanje(zahtjev);
if (result.success) {
console.log("Odbijanje uspješno evidentirano:", result.resObject);
} else {
console.error("Greška pri evidentiranju odbijanja:", result.error);
}Fiskalizacija 1 (B2C fiskalizacija računa)
Za fiskalizaciju računa u krajnjoj potrošnji (CIS servis, f73 shema, tehnička specifikacija v2.7) koristi se
klasa Fiskalizacija1Client. Prima isti objekt konfiguracije kao FiskalizacijaClient (default CA bundle se
određuje prema URL-u servisa: za Fiskalizacija1ServiceURL.test koristi se Fina Demo CA).
Poruke zahtjeva se potpisuju metodom RSA-SHA256 sukladno v2.7 specifikacije (RSA-SHA1 testna okolina odbija od 01.07.2026., a produkcijska od 01.01.2027.).
Metode (sve vraćaju FiskalizacijaResult):
racun(IF1RacunZahtjev)- fiskalizacija računa,resObject.Jirsadrži JIRprovjera(IF1ProvjeraZahtjev)- provjera računa dostavljenog Poreznoj upravi (samo testna okolina; rezultati provjere stižu krozGreskes vXXX šiframa, uspjeh = v100)promijeniNacPlac(IF1PromijeniNacPlacZahtjev)- promjena načina plaćanja (isti dan do ponoći)promijeniPodatkeRacuna(IF1PromijeniPodatkeRacunaZahtjev)- promjena načina plaćanja i/ili OIB-a primatelja (isti dan do ponoći)napojnica(IF1NapojnicaZahtjev)- evidentiranje napojniceprijaviRadnoVrijeme(IF1PrijaviRadnoVrijemeZahtjev)- prijava radnih vremena poslovnog prostoraobrisiRadnoVrijeme(IF1ObrisiRadnoVrijemeZahtjev)- brisanje radnih vremena poslovnog prostoradohvatiRadnoVrijeme(IF1DohvatiRadnoVrijemeZahtjev)- dohvat radnih vremena poslovnog prostoraprijaviRadnoVrijemeZaPoslovnice(IF1PrijaviRadnoVrijemeZaPoslovniceZahtjev)- prijava radnog vremena za listu poslovnih prostoraecho(poruka?: string)- provjera dostupnosti servisa
Za svaku metodu postoji i pomoćna funkcija za kreiranje zahtjeva s generiranim zaglavljem
(getF1RacunZahtjev, getF1ProvjeraZahtjev, getF1PromijeniNacPlacZahtjev,
getF1PromijeniPodatkeRacunaZahtjev, getF1NapojnicaZahtjev, getF1PrijaviRadnoVrijemeZahtjev,
getF1ObrisiRadnoVrijemeZahtjev, getF1DohvatiRadnoVrijemeZahtjev,
getF1PrijaviRadnoVrijemeZaPoslovniceZahtjev).
Poslovne validacije (npr. restriktivne greške 176-184) se ne provode na klijentu - servis ih vraća kroz
resObject.Greske (odnosno resObject.PoslovniProstoriOdgovor[].Greske za prijavu po poslovnicama).
Prodaja putem samoposlužnih uređaja fiskalizira se istom racun metodom (dozvoljeni načini plaćanja su
G, K i O), sukladno poglavlju 2.2 tehničke specifikacije.
Zaštitni kod izdavatelja (ZastKod) se automatski izračunava iz privatnog ključa ako nije zadan na računu
(RSA-SHA256 pa MD5, sukladno v2.7). Za ispis na računu prije slanja dostupna je i samostalna funkcija
computeZki (za račune fiskalizirane po starijim verzijama specifikacije podržava i "RSA-SHA1" algoritam).
Kod poruka koje se odnose na već fiskalizirani račun (provjera, promjene, napojnica) treba proslijediti
izvorni ZastKod s računa.
const client = new Fiskalizacija1Client({
service: Fiskalizacija1ServiceURL.test, // ili Fiskalizacija1ServiceURL.prod
privateKey: fs.readFileSync("path/to/fiskalKey.pem"),
publicCert: fs.readFileSync("path/to/fiskalCert.pem")
});
const racun: IF1Racun = {
Oib: "12345678903",
USustPdv: true,
// datum i vrijeme izdavanja računa u formatu dd.MM.yyyyTHH:mm:ss
DatVrijeme: getCurrentF1DateTimeString(),
// P - slijednost na nivou poslovnog prostora, N - na nivou naplatnog uređaja
OznSlijed: "P",
BrRac: {
BrOznRac: "1", // brojčana oznaka računa
OznPosPr: "POSL1", // oznaka poslovnog prostora
OznNapUr: "1" // oznaka naplatnog uređaja
},
Pdv: [{ Stopa: "25.00", Osnovica: "100.00", Iznos: "25.00" }],
IznosUkupno: "125.00",
// G - gotovina, K - kartice, T - transakcijski račun, O - ostalo
NacinPlac: "G",
OibOper: "12345678903",
NakDost: false
};
const zahtjev = getF1RacunZahtjev(racun);
const result = await client.racun(zahtjev);
if (result.success) {
console.log("JIR:", result.resObject.Jir);
console.log("ZKI:", result.reqObject.Racun.ZastKod);
} else {
console.error("Greška pri fiskalizaciji računa:", result.error ?? result.resObject?.Greske);
}Povezani projekti
- fiskalizacija2 - materijali vezani uz Projekt Fiskalizacija 2.0 - fiskalizaciju eRačuna i eIzvještavanje
