Open source light implementation of EET client library (Java, C#, UNIX shell). Working client (XMLDSig, WS-Security, SOAP call) with no external dependencies in 16/25kB JAR/DLL file. Get the devel snapshot and !Try It! (Use the code to get latest fixes&features)
EET API v3
EET API v2 - not maintained any more
It is necessary to force git not to normalize line ends. The templates must be binary identical when checking out. Master branch contains template hash validation. In case the hash validation fails (exceptoin during soap message generation), check the files in the templates folder. To reconfigure git not to modify line ends use git config --global core.autocrlf input
and checkout master branch.
Windows TLS problem workaround
Java/C# implementation now works with EET playground v2. No extra dependencies besides the runtime, just the java runtime itself (1.4.2+) or .NET framework. No full release yet - use snapshot or source code.
For details look at
To register a sale it is as easy as this: Java:
@Test
public void simpleRegistrationProcessTest() throws MalformedURLException, IOException{
//set minimal business data & certificate with key loaded from pkcs12 file
EetRegisterRequest request=EetRegisterRequest.builder()
.dic_popl("CZ1212121218")
.id_provoz("1")
.id_pokl("POKLADNA01")
.porad_cis("1")
.dat_trzby("2016-06-30T08:43:28+02:00")
.celk_trzba(100.0)
.rezim(0)
.pkcs12(loadStream(getClass().getResourceAsStream("/01000003.p12")))
.pkcs12password("eet")
.build();
//for receipt printing in online mode
String bkp=request.formatBkp();
assertNotNull(bkp);
//for receipt printing in offline mode
String pkp=request.formatPkp();
assertNotNull(pkp);
//the receipt can be now stored for offline processing
//try send
String requestBody=request.generateSoapRequest();
assertNotNull(requestBody);
String response=request.sendRequest(requestBody, new URL("https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3"));
//extract FIK
assertNotNull(response);
assertTrue(response.contains("Potvrzeni fik="));
//ready to print online receipt
}
C#:
public static void simpleRegistrationProcessTest(){
//set minimal business data & certificate with key loaded from pkcs12 file
EetRegisterRequest request=EetRegisterRequest.builder()
.dic_popl("CZ1212121218")
.id_provoz("1")
.id_pokl("POKLADNA01")
.porad_cis("1")
.dat_trzby("2016-06-30T08:43:28+02:00")
.celk_trzba(100.0)
.rezim(0)
.pkcs12(TestData._01000003)
.pkcs12password("eet")
.build();
//for receipt printing in online mode
String bkp=request.formatBkp();
if (bkp == null) throw new ApplicationException("BKP is null");
//for receipt printing in offline mode
String pkp=request.formatPkp();
if (pkp == null) throw new ApplicationException("PKP is null");
//the receipt can be now stored for offline processing
//try send
String requestBody=request.generateSoapRequest();
if (requestBody == null) throw new ApplicationException("SOAP request is null");
String response=request.sendRequest(requestBody, "https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3);
//extract FIK
if (response == null) throw new ApplicationException("response is null");
if (response.IndexOf("Potvrzeni fik=") < 0) throw new ApplicationException("FIK not found in the response");
//ready to print online receipt
Console.WriteLine("OK!"); //a bit brief :-) but enough
}
Delphi:
Uses ... JclDotNet;
procedure TSDIAppForm.Button2Click(Sender: TObject);
var
Host: TJclClrHost;
Obj: OleVariant;
date:tdatetime; pkp:string;
odpoved,xml:widestring;
f:textfile;
begin
try
Host := TJclClrHost.Create('v4.0.30319');
Host.Start();
Obj := Host.DefaultAppDomain //spojeni s DLL
.CreateInstancefrom('openeet-lite.dll',
'openeet_lite.Builder')
.UnWrap();
obj.dat_trzbys('2016-09-12T08:43:28+02:00'); //moznost zadat datum v textovem tvaru
obj.dic_popl('CZ1212121218');
obj.id_provoz('1');
obj.id_pokl('POKLADNA01');
obj.porad_cis('1');
obj.celk_trzba(100.0);
obj.rezim(0);
obj.pkcs12s('01000003.p12'); // upravena moznost zadani nazvu souboru s p12
obj.pkcs12password('eet');
obj.build;
pkp:=obj.build.FormatPkp;
xml:=obj.build.generateSoapRequest;
assignfile(f,'test.xml');
rewrite(f);
writeln(f,xml);
closefile(f);
odpoved:=obj.build.sendRequest(xml, 'https://pg.eet.cz:443/eet/services/EETServiceSOAP/v3');
assignfile(f,'odpoved.xml');
rewrite(f);
writeln(f,odpoved);
closefile(f);
Host.Stop();
Host.Free;
Except
on E : Exception do
begin
ShowMessage('Exception class name = '+E.ClassName + ' ' + 'Exception message = '+E.Message);
end;
end;
end;
To interact with EET endpoint at least TLS v1.1 is needed. Windows XP does not support TLS 1.0+. The problem canbe solved by SSL/TLS tunneling using stunnel. The tunneeling concept is described in following schema:
[aplikace]------http------>[stunnel]-------https/tls/1.1------->[EET Server]
You can use stunnel distribution tailored to EET needs available in this repo in the stunnel-eet folder. The proposed solution was not tested on WinXP yet. Use issue to let me know whether it works or not.
As XMLDsig&SOAP&WSS are huge standards, it is hard to find fuully compliant implementation on restricted devices. I decided to work around this. The intention of of this work (for now) is to provide "light" implementation of the EET API clien. I will decsribe my approach later (not som much spare time now). For now just short intro. You ucan see working PoC in th shell implementation. The concept is based on XMLDSig processing (see spec). XML is preprocessed from the point of view of canonicalization during compile time and then message is constructed using preprocessing results (templates), some (careful) string replacements and basic crytpo primitives (SHA256, SHA1 and RSASSA_PKCS_1_5)which are widely available on most platforms.
This step take part during library build. It is bound to certain version of the spec and it is automated by calling a script. The "compile time" preprocessing of the example SOAP message produces two blobs.
The final step fills the computed values into xml template and the message is ready to be sent to EET API.
Shell implementation of the EET client - working out of box for the simplest case receipt. Shell experiment available at shell/ - it is able to send valid request to playground EET API.
Follow me on twitter if you want to be notified when something great happens to this repo.