Kontakt na PC SERVIS:
EO Computers - EO.CZ
V. Kl. Klicpery 715
50401 Nový Bydžov

Telefon606 622 826

EET implementace v PHP

Rád bych se podělil o funkční PHP skript pro odeslání EET účtenky.

Použil jsem volně dostupnou ukázku od Davida Spilky, který udělal skutečně skvělou práci - odkaz, ale skript mi bohužel nefungoval. Několik hodin jsem bojoval s opakující se chybou: Chyba : 3 - XML zpráva nevyhověla kontrole XML schématu.

Další nevýhodou bylo, že skript požaduje mít převedené certifikáty na PEM a KEY. To mi přišlo zbytečně složité. Podařilo se mi tedy skript doplnit o převod z P12 a níže uvádím funkční verzi, která vrací FIK kód. Požaduje pouze p12 certifikát a jeho heslo.

Abyste si mohli ukázku vyzkoušet, pak si stáhněte sadu certifikátu z odkazu http://www.etrzby.cz/cs/technicka-specifikace (EET_CA1_Playground_v1.zip). Z tohoto souboru použijte certifikát EET_CA1_Playground-CZ1212121218.p12 (ten jsem si uložil do složky eet_cert/eet.p12), heslo  k němu je 'eet'.

Pozn.: na serveru potřebujete verzi PHP 5.4.4 a vyšší.

Celý skript si můžete zkopírovat zde:

<?
$certs = [];
$pkcs12 = file_get_contents("eet_cert/eet.p12");

if (!extension_loaded('openssl') || !function_exists('openssl_pkcs12_read')) {
echo("Rozsireni OpenSSL neni dostupne.");
exit;
}

$openSSL = openssl_pkcs12_read($pkcs12, $certs, 'eet'); //heslo
if(!$openSSL)
{
echo("Certifikat se nepodarilo vyexportovat.");
exit;
}

date_default_timezone_set("Europe/Prague");
$dir=dirname($_SERVER["SCRIPT_FILENAME"]);

$eet['url']='https://pg.eet.cz/eet/services/EETServiceSOAP/v3'; // playground
$eet['key']=$certs['pkey'];

$tmp=$certs['cert'];
$tmp=explode('CERTIFICATE-----',$tmp);
$tmp=explode('-----END',$tmp[1]);
$data["certb64"]=$tmp[0];

$bodyTemplate='<soap:Body xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TheBody" xml:id="TheBody"><Trzba xmlns="http://fs.mfcr.cz/eet/schema/v3"><Hlavicka @{dat_odesl} @{overeni} @{prvni_zaslani} @{uuid_zpravy}></Hlavicka><Data @{celk_trzba} @{cerp_zuct} @{cest_sluz} @{dan1} @{dan2} @{dan3} @{dat_trzby} @{dic_popl} @{dic_poverujiciho} @{id_pokl} @{id_provoz} @{porad_cis} @{pouzit_zboz1} @{pouzit_zboz2} @{pouzit_zboz3} @{rezim} @{urceno_cerp_zuct} @{zakl_dan1} @{zakl_dan2} @{zakl_dan3} @{zakl_nepodl_dph}></Data><KontrolniKody><pkp cipher="RSA2048" digest="SHA256" encoding="base64">${pkp}</pkp><bkp digest="SHA1" encoding="base16">${bkp}</bkp></KontrolniKody></Trzba></soap:Body>';

$signatureTemplate='<ds:SignedInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"><ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap"></ec:InclusiveNamespaces></ds:CanonicalizationMethod><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"></ds:SignatureMethod><ds:Reference URI="#TheBody"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:Transform></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"></ds:DigestMethod><ds:DigestValue>${digest}</ds:DigestValue></ds:Reference></ds:SignedInfo>';

$requestTemplate='<?xml version="1.0" encoding="UTF-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soap:mustUnderstand="1"><wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="TheCert">${certb64}</wsse:BinarySecurityToken><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="TheSignature">'.$signatureTemplate.'<ds:SignatureValue>${signature}</ds:SignatureValue><ds:KeyInfo Id="TheKeyInfo"><wsse:SecurityTokenReference wsu:Id="TheSecurityTokenReference"><wsse:Reference URI="#TheCert" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"/></wsse:SecurityTokenReference></ds:KeyInfo></ds:Signature></wsse:Security></SOAP-ENV:Header>${soap_body}</soap:Envelope>';


// priprav si data pro uctenku
$data["dat_odesl"]='';
$data["prvni_zaslani"]='true';
$data["uuid_zpravy"]='';

$data["dic_popl"]='CZ1212121218'; //DIC ponechte, aby Vam ukazka s danym certifikatem fungovala.
$data["id_provoz"]='11';
$data["id_pokl"]='1';
$data["porad_cis"]='1';
$data["dat_trzby"]='';
$data["celk_trzba"]=price(100);
$data["rezim"]='0';
$data["pkp"]='';
$data["bkp"]='';

// generuj datumy
$data["dat_odesl"]=date("c");
if (empty($data["dat_trzby"])) $data["dat_trzby"]=date("c");

if (empty($data["uuid_zpravy"])) $data["uuid_zpravy"]=uuid_v4();// vypočti PKP a BKP
$pkpInput=$data["dic_popl"].'|'.$data["id_provoz"].'|'.$data["id_pokl"].'|'.$data["porad_cis"].'|'.$data["dat_trzby"].'|'.$data["celk_trzba"];
openssl_sign($pkpInput, $signature, $eet['key'], 'SHA256');
$data["pkp"]=base64_encode($signature);
$data["bkp"]=BKB(sha1($signature));

// sestav tělo soap zprávy
$data["soap_body"]=replaceData($bodyTemplate,$data);

// vypočti digest
$data["digest"] = base64_encode(hash('sha256',$data["soap_body"],true));

// sestav podpisovou část a podepiš
$signatureFinal=replaceData($signatureTemplate,$data);
openssl_sign($signatureFinal, $signature, $eet['key'], 'SHA256');
$data["signature"]=base64_encode($signature);

// sestav finální XML zprávu pro EET
$xmlFinal=replaceData($requestTemplate,$data);

// Odešli účtenku
$opts = array(
'http' => array(
'method' => 'POST',
'header' => "Content-Type: text/xml;charset=UTF-8\r\nSOAPAction: http://fs.mfcr.cz/eet/OdeslaniTrzby",
'content' => $xmlFinal
)
);
$context=stream_context_create($opts);
$result=file_get_contents($eet['url'], false, $context);


echo"<textarea rows=80 cols=160>$result</textarea>";


function uuid_v4(){
return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0x0fff)|0x4000,mt_rand(0,0x3fff)|0x8000,mt_rand(0,0xffff),mt_rand(0,0xffff),mt_rand(0,0xffff));
}

function price($value)
{
return number_format($value, 2, '.', '');
}

function BKB($code){
$r='';
for ($i=0;$i<40;$i++)
{
if ($i%8==0&&$i!=0) $r.= '-';
$r.=$code[$i];
}
return $r;
}

function replaceData($template,$data){
foreach ($data as $key => $value) {
$template=str_replace("\${".$key."}",$value,$template);
$template=str_replace("@{".$key."}","$key=\"$value\"",$template);
}
// odstraň prázdná pole
$template=preg_replace("/\\$\\{[a-z_0-9:]+\\}/","",$template);
$template=preg_replace("/ @\\{[a-z_0-9:]+\\}/","",$template);
return $template;
}

?>

Veškeré zásluhy budiž připsány výše zmíněnému Davidu Spilkovi, kterému tímto děkuji.

EO.CZ - nabízíme EET pokladny. Máme důkladně otestovanou a do malých provozoven doporučujeme jednoduchou pokladnu XPOS CHD 3050: https://www.eo.cz/RXEPR03001S-x-pos-registracni-pokladna-chd3050.html


Autor článku: Ing. Marián Hudec - EO Computers - EO.CZ

Zde můžete okomentovat článek nebo nám nechat vzkaz:

Další články

Jak otestovat grafickou kartu Jak otestovat grafickou kartu

Jak otestovat HDD Jak otestovat HDD

Jak otestovat paměti Jak otestovat paměti

Nejlepší ATX zdroj do 700 Kč Nejlepší ATX zdroj do 700 Kč

Jak otestovat flash disk Jak otestovat flash disk

Jak zjistit heslo na WiFi (WEP, WPA) Jak zjistit heslo na WiFi (WEP, WPA)

Jak se připojit na router Jak se připojit na router

Jak otestovat baterii v notebooku Jak otestovat baterii v notebooku

Obnova systému v notebooku pomocí recovery key Obnova systému v notebooku pomocí recovery key

Jak zálohovat data? Zálohujte pomocí Cobian Backup. Jak zálohovat data? Zálohujte pomocí Cobian Backup.

Recenze na čtečku knih Amazon Kindle Paperwhite Recenze na čtečku knih Amazon Kindle Paperwhite

Jak nastavit heslo na WiFi Jak nastavit heslo na WiFi

Jak vytvořit recovery partition (záchranný oddíl) Jak vytvořit recovery partition (záchranný oddíl)

Jak rozbalit soubor RAR Jak rozbalit soubor RAR

Jak nastavit domovskou stránku v prohlížeči Jak nastavit domovskou stránku v prohlížeči

Originální nebo repasované tonery? Originální nebo repasované tonery?

Modrá obrazovka (blue screen) chybové kódy Modrá obrazovka (blue screen) chybové kódy

LCD technologie (TN, IPS, MVA, PVA) LCD technologie (TN, IPS, MVA, PVA)

Windows 8 start (jak přidat start menu) Windows 8 start (jak přidat start menu)

Odblokování telefonů (hard reset) Odblokování telefonů (hard reset)

Výměna displeje Výměna displeje

Politý notebook. Co dělat? Politý notebook. Co dělat?

Jak připojit tablet k internetu Jak připojit tablet k internetu

Jak prodloužit podporu XP do roku 2019? Jak prodloužit podporu XP do roku 2019?

Zapnutí NumLock při startu (LogOn) Zapnutí NumLock při startu (LogOn)

Jak vypnout notifikaci "Stáhnout si Windows 10" Jak vypnout notifikaci "Stáhnout si Windows 10"

Přehled základních typů rozlišení LCD displeje Přehled základních typů rozlišení LCD displeje

Prasklý displej u tabletu Prasklý displej u tabletu

Jak odinstalovat Windows 10 Jak odinstalovat Windows 10

Bezplatný upgrade na Windows 10 Bezplatný upgrade na Windows 10

Kabely USB Type-C - přehled Kabely USB Type-C - přehled

PS/2 klávesnice a myš nejdou ve Windows 10 PS/2 klávesnice a myš nejdou ve Windows 10

Odblokování iphone / ipad Odblokování iphone / ipad

Rychlosti SD / SDHC / SDXC karet Rychlosti SD / SDHC / SDXC karet

Vybíráme herní notebook / na co si dát pozor? Vybíráme herní notebook / na co si dát pozor?


Pošlete nám dotaz:


TOPlist