EET 2.0: chyba 4 „Neplatny podpis SOAP zpravy“ a jak ji najít
Kód 4 je kritická chyba: server zprávu odmítne a POK nevydá. Podle specifikace (kap. 2.2.3) se kontroluje vydavatel a platnost pokladního certifikátu včetně CRL a kryptografická platnost podpisu. Tady je osm nejčastějších příčin, seřazených podle toho, jak často na ně narazíte.
Nejrychlejší cesta: vložte svou zprávu do validátoru. Spočítá DigestValue a ověří SignatureValue stejně jako server a ukáže kanonický tvar. Běží v prohlížeči, zpráva nikam neodchází.
1. Certifikát a prostředí nesedí
Testovací certifikát (vydavatel playground EETv2 NCA SubCA) funguje jen na pg.trzbyeet.gov.cz, produkční certifikát z DIS+ jen na trzbyeet.gov.cz. Záměna vrací kód 4, ne srozumitelnější hlášku.
2. Podepisujete jiný text, než posíláte
Nejčastější chyba v praxi. Podpis se počítá nad kanonickým tvarem soap:Body, ale SOAP knihovna, šablona nebo „pretty print“ zprávu po podpisu přeformátuje: přidá mezery a odřádkování, změní pořadí atributů nebo přesune deklarace jmenných prostorů. Pravidlo: serializovat jednou, podepsat a poslat přesně ty bajty.
3. InclusiveNamespaces a PrefixList
Vzorová zpráva FS používá exkluzivní kanonizaci s InclusiveNamespaces PrefixList="v4" pro Body a "soapenv v4" pro SignedInfo. Pokud PrefixList v XML deklarujete, musíte ho použít i při výpočtu, a naopak. Prefix v4 se pak vykreslí už na soap:Body, ne až na v4:Trzba, a otisk je jiný.
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:v4="http://fs.gov.cz/eet/schema/v4"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="id-…"><v4:Trzba>…
Kanonický tvar Body podle vzoru FS: deklarace seřazené podle prefixu, pak atributy, prázdné prvky jako pár značek <a></a>.
4. Podepsaný je jiný element nebo víc elementů
Podepsat se musí právě jeden element: soap:Body (kap. 5.2). Knihovny WS-Security často přidávají wsu:Timestamp a podepisují i ten. Specifikace výslovně doporučuje žádné další hlavičky. Timestamp i WS-Addressing vypněte.
5. Reference neukazuje na Body
ds:Reference URI="#id-…" musí odpovídat wsu:Id na Body a jmenný prostor wsu musí být správný (…oasis-200401-wss-wssecurity-utility-1.0.xsd).
6. Špatné algoritmy
Vyžaduje se xml-exc-c14n# pro kanonizaci i transformaci, xmlenc#sha256 pro otisk a xmldsig-more#rsa-sha256 pro podpis. Výchozí nastavení starších knihoven bývá SHA-1.
7. Certifikát vypršel nebo je zneplatněný
Pokladní certifikát platí 366 dní a FS kontroluje i CRL. Zneplatnění v DIS+ je okamžité a nevratné. Pozor na záměnu: vygenerování nového certifikátu starý nezneplatní, ale ruční zneplatnění (třeba omylem jiného certifikátu) ano.
8. Obsah se změnil až po podpisu
Typicky formátování částky (100 → 100.00) nebo času v jiné vrstvě aplikace, která běží až po podpisu. Validujte a normalizujte data před sestavením zprávy. Formátové chyby částek mimochodem vracejí kód 3 (XML schéma), ne 4.
Jak to debugovat systematicky
- Ověřte si implementaci na oficiální vzorové zprávě
CZ00000019.eet.v4.req.xmlz eet.gov.cz: vaše kanonizace jejího Body musí dát stejný DigestValue a SignatureValue ze vzoru musí být platná nad vaším SignedInfo. - Logujte přesně odeslané bajty a hlavičku odpovědi
X-Global-Transaction-Id. Podpora FS (epodpora@fs.gov.cz) podle ní dohledá konkrétní pokus. - Než pošlete ostrou tržbu, pošlete zprávu v ověřovacím módu (
overeni="true"). Server odpoví kódem 0 a nic neeviduje.
Nechte podpisy na nás
Naše knihovna @evidka/eet2 má kanonizaci ověřenou proti vzorové zprávě FS. Evidka brána pak podpis, frontu i doposílání vyřeší za vás: posíláte jen JSON.
Dokumentace API Integrace na klíčZdroj: Finanční správa – „Formát a struktura údajů o evidované tržbě a popis datového rozhraní“ v1.2 (25. 8. 2026), kap. 2.2.3, 3.5.4 a 5.2; vzorové zprávy na eet.gov.cz/cs/pro-vyvojare.