Napomena: Zbog promjene u minimalnoj verziji TLS enkripcije od CIS v1.3
ova komponenta zahtjeva .NET 4.5 za komunikaciju sa serverom (detaljnije).
Zbog ove promjene izdan je novi release COM komponente v1.2.1-com
.
.NET (C#) wrapper oko generiranog SOAP klijenta za pozivanje fiskalizacijskog servisa porezne uprave CIS WSDL v1.4
.
Sa Microsoft Wsdl.exe tool-om su generirane proxy klase sa strukturom po WSDL shemi koja je objavljena na stranicama porezne uprave Tehničke specifikacije i koja je uključena u source kôd projekta.
Preko generiranog SOAP klijenta FiskalizacijaService se rade svi SOAP pozivi prema CIS servisu. Kompletna implementacija je u Fiscalization klasi sa dodatkom async metoda u Fiscalization.Async.cs file-u. 😄
Runtime:
- .NET 4.5 (
CIS v1.3
zahtjevaTLS v1.1
iliTLS v1.2
HTTPS enkripciju)
Testirano i sa demo certifikatom Fina okoline 2014/2015.
Postoji release .NET COM komponente sa primjerima za VBA, VBScript i Access.
- uključiti source kôd u postojeći projekt umjesto referenciranja third party dll-a, naravno dostupan i kao NuGet package
- jednostavan upgrade u slučaju promjene sheme CIS servisa uz compile-time check
- svaki poziv servisa treba automatski odraditi generiranje ZKI kôda i potpisivanje, isto tako i provjeru potpisa CIS odgovora, ali imati i opcije
Sign(ICisRequest, X509Certificate2)
iGenerateZki(RacunType, X509Certificate2)
- sve greške koje šalje CIS servis pretvoriti u Exception-e, unificirati logiranje i imati pregled svih grešaka na jednak način
- ne parsirati raw SOAP poruke, a istovremeno omogućiti potpisivanje i logiranje raw poruka
Kako najjednostavnije uključiti kôd u svoj projekt?!
Instalacijom NuGet package-a kreira se Cis folder u projektu sa source kôdom.
PM> Install-Package Cis.Fiscalization
Dovoljno je iskopirati FiskalizacijaService.cs, Fiscalization.cs i/ili Fiscalization.Async.cs.
Sastoji od dvije glavne metode (u dva okusa async i sync) za slanje podataka na servis
public static class Fiscalization
{
// Async .NET 4.5 :: Fiscalization.Async.cs
Task<RacunOdgovor> SendInvoiceAsync(RacunType invoice, X509Certificate2 cert);
Task<ProvjeraOdgovor> CheckInvoiceAsync(RacunType invoice, X509Certificate2 cert)
// Sync :: Fiscalization.cs
RacunOdgovor SendInvoice(RacunType invoice, X509Certificate2 cert);
ProvjeraOdgovor CheckInvoice(RacunType invoice, X509Certificate2 cert);
}
Svaka metoda još opcionalno prima funkciju Action<FiskalizacijaService>
za postavljanje
parametara generiranoj proxy klasi FiskalizacijaService (npr. url, timeout...).
Za RacunType, RacunOdgovor, ProvjeraOdgovor i ostale generirane proxy klase vidi source FiskalizacijaService.cs.
Primjer poziva servisa za slanje računa
// Kreiranje računa za za fiskalizaciju
var invoice = new RacunType()
{
BrRac = new BrojRacunaType()
{
BrOznRac = "1",
OznPosPr = "1",
OznNapUr = "1"
},
DatVrijeme = DateTime.Now.ToString(Fiscalization.DATE_FORMAT_LONG),
IznosUkupno = 3.ToString("N2", CultureInfo.InvariantCulture),
NacinPlac = NacinPlacanjaType.G,
NakDost = false,
Oib = oib,
OibOper = "98642375382",
OznSlijed = OznakaSlijednostiType.N,
Pdv = new[]
{
new PorezType
{
Stopa = 25.ToString("N2", CultureInfo.InvariantCulture),
Osnovica = 2.34.ToString("N2", CultureInfo.InvariantCulture),
Iznos = .56.ToString("N2", CultureInfo.InvariantCulture)
}
},
USustPdv = true
};
X509Certificate2 certificate = ...;
// Generiraj ZKI, potpiši, pošalji račun i provjeri potpis CIS odgovora
RacunOdgovor response = await Fiscalization.SendInvoiceAsync(invoice, certificate);
// Odgovor sa JIR-om i zahtjevom (sa header podacima, potpisom) i poslanim računom
string jir = response.Jir;
RacunZahtjev request = (RacunZahtjev)response.Request; // ICisRequest
var isTrue = request.Racun == invoice;
// ili dodatno sa postavljanjem opcija
// fs == instanca generirane proxy klase FiskalizacijaService
RacunOdgovor response = await Fiscalization.SendInvoiceAsync(invoice, certificate, fs =>
{
// SOAP service settings
// Change service URL
// default = Fiscalization.SERVICE_URL_PRODUCTION
fs.Url = Fiscalization.SERVICE_URL_DEMO;
// Set request timeout in miliseconds
// default = 100s
fs.Timeout = 2000;
// Set response signature checking
// default = true
fs.CheckResponseSignature = true;
});
Od CIS v1.3
verzija protokola za enkripciju preko HTTPS-a je TLS v1.1
ili TLS v1.2
.
Ova komponenta koristi System.Net
za komunikaciju u kojoj su ti protokoli podržani od .NET 4.5 verzije.
.NET 4.6 ima default postavljenu verziju TLS 1.2 dok .NET 4.5 nema pa se to može napraviti na sljedeći način:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
Logiranje se radi preko implementacije partial metode na FiskalizacijaService klasi. Par linija kôda govori 1000 riječi - odlazna i dolazna SOAP poruka kao XmlDocument.
Ovako bi mogao izgledati trace ili file logger
// MyCisLogger.cs
// Implementacija mora biti u projektu gdje i Cis.FiskalizacijaService klasa
namespace Cis
{
public partial class FiskalizacijaService
{
partial void LogResponseRaw(XmlDocument request, XmlDocument response)
{
// Trace logger
Trace.WriteLine(request.OuterXml);
Trace.WriteLine(response.OuterXml);
// File logger
File.AppendAllText(logFileName, request.OuterXml, Encoding.UTF8);
File.AppendAllText(logFileName, response.OuterXml, Encoding.UTF8);
}
}
}
U test projektu je TestEnvironment klasa koja učitava demo certifikat koji nije uključen u projekt; moguće je
- u source-u specificirati OIB, putanju do certifikata (.pfx), lozinku i/ili
- postaviti
FIS_OIB
,CERT_BASE64
iCERT_PWD
environment varijable
SET FIS_OIB=<OIB poslovnog subjekta>
SET CERT_BASE64=<certifikat poslovnog subjekta kao base64 enkodirani string>
SET CERT_PWD=<lozinka certifikata>
start Fiscalization.sln