EetCpp

EetCpp is a Qt 6/CMake implementation of the Czech EET v4 protocol. The library is intended to run on Windows, macOS and Linux on amd64 and arm64.

The current implementation is a new v4 API. EET v3 is not supported.

Requirements

  • CMake 3.24 or newer
  • C++17 compiler
  • Qt 6.5 or newer (Core, Network, Test)
  • xmlsec1 with an OpenSSL backend
  • libxml2
  • OpenSSL 3 or newer is recommended

Build and test

Build outside the source tree:

cmake -S . -B /tmp/EetCpp-build -DCMAKE_PREFIX_PATH=/path/to/qt
cmake --build /tmp/EetCpp-build
ctest --test-dir /tmp/EetCpp-build --output-on-failure

The Playground CLI is enabled by default. Disable it with -DEETCPP_BUILD_PLAYGROUND=OFF.

The test suite covers:

  • fixed-point amounts and v4 request validation,
  • v4 XML and SOAP generation,
  • XML signature creation and independent verification,
  • tamper detection,
  • EET response and SOAP Fault parsing,
  • HTTPS client input validation,
  • CA EET client input validation.
  • CA EET workflow against a local TLS mock server, including JWT-bearing requests, polling, PKCS#12 download and acknowledgement.
  • EET v4 HTTPS end-to-end flow against a local TLS mock server, including request signature verification and signed POK response parsing.

EET v4 API

The public headers are:

  • eetv4request.h - typed sale request and exact fixed-point amounts,
  • eetv4xml.h - v4 Trzba XML,
  • eetv4soap.h - unsigned SOAP 1.1 envelope,
  • eetv4signer.h - PKCS#12 signing and response signature verification,
  • eetv4response.h - Odpoved, Potvrzeni, Chyba and SOAP Fault parsing,
  • eetv4client.h - HTTPS sale client,
  • eetca.h - CA EET certificate-renewal workflow.

The client deliberately does not log or return complete SOAP messages on errors. Callers must protect PKCS#12 files and passwords.

Playground

The CLI is built as EetCppPlayground. The wrapper scripts scripts/eet-playground.sh and scripts/eet-playground.ps1 can be used from Unix shells and PowerShell. Set EETCPP_PLAYGROUND if the executable is not on PATH.

Preflight

The preflight command validates the HTTPS endpoint, reads the PKCS#12 file and actually opens it with the supplied password by creating a probe signature. The password is read only from an environment variable:

export EET_PKCS12_PASSWORD='do-not-commit-this'

./EetCppPlayground preflight \
  --endpoint 'https://example.test/eet' \
  --certificate ./certificate.p12 \
  --password-env EET_PKCS12_PASSWORD

Send a verification-mode sale

./EetCppPlayground send-sale \
  --endpoint 'https://example.test/eet' \
  --certificate ./certificate.p12 \
  --password-env EET_PKCS12_PASSWORD \
  --eic CZ123456789 \
  --unit 1 \
  --register KASA1 \
  --receipt PLAYGROUND-001 \
  --amount 100.00 \
  --verification

Use --sale-at and --sent-at for explicit ISO 8601 timestamps. The CLI prints only a success/POK, EET error, SOAP Fault and warning codes. It does not print passwords, JWTs, private keys or SOAP XML.

CA EET certificate workflow

EetCaClient implements the JWT-authenticated CA API:

  1. requestRenewal() submits a renewal request.
  2. requestStatus() polls INPROCESS, ISSUED, DELIVERING, FINISHED or REJECTED.
  3. listUnfinished() finds unfinished requests.
  4. claimDownload() retrieves the base64 PKCS#12 and its password.
  5. acknowledgeDownload() permanently confirms and closes the download.

The JWT uses RS256 and the x5t#S256 thumbprint of the signing certificate. The API endpoints are selected through EetCaClientConfig::apiBaseUrl:

  • test: https://ca.test.caeet.gov.cz/api
  • trial: https://ca.zkus.caeet.gov.cz/api
  • production: https://ca.caeet.gov.cz/api

The result of claimDownload() is sensitive. Do not log it, cache it, or store it in source control. The current CA client does not persist the download; the application must decide how to store it securely.

The Playground exposes the same workflow without printing sensitive values:

export EET_CA_PASSWORD='...'
export EET_CA_URL='https://ca.test.caeet.gov.cz/api'

./EetCppPlayground ca-renew \
  --api-url "$EET_CA_URL" \
  --signing-certificate ./old-certificate.p12 \
  --signing-password-env EET_CA_PASSWORD

./EetCppPlayground ca-list \
  --api-url "$EET_CA_URL" \
  --signing-certificate ./old-certificate.p12 \
  --signing-password-env EET_CA_PASSWORD

Use the UUID returned by ca-renew or ca-list with ca-status. Once the status is ISSUED or DELIVERING, download into explicitly chosen files:

./EetCppPlayground ca-claim \
  --api-url "$EET_CA_URL" \
  --signing-certificate ./old-certificate.p12 \
  --signing-password-env EET_CA_PASSWORD \
  --request-id '00000000-0000-4000-8000-000000000000' \
  --output-p12 ./new-certificate.p12 \
  --output-password ./new-certificate.password

./EetCppPlayground ca-ack \
  --api-url "$EET_CA_URL" \
  --signing-certificate ./old-certificate.p12 \
  --signing-password-env EET_CA_PASSWORD \
  --request-id '00000000-0000-4000-8000-000000000000'

The CA commands require the signing password only through an environment variable. ca-claim writes the PKCS#12 and password with owner-only file permissions where supported; review the output directory and move the files to the application's secure certificate store before acknowledging download.

Testing against the official test environment

Follow this procedure only after obtaining the official test values:

  • EET v4 test endpoint,
  • test PKCS#12 certificate and its password,
  • EIC, unit ID and cash-register ID authorized for that certificate.

The repository includes .env.example as a variable template. Copy it to a secure location outside the repository, fill in those official values and never commit the copy, PKCS#12 files, passwords or generated output.

1. Build the Playground and run local tests

cmake -S . -B /tmp/EetCpp-build -DCMAKE_PREFIX_PATH=/path/to/qt
cmake --build /tmp/EetCpp-build
ctest --test-dir /tmp/EetCpp-build --output-on-failure

2. Export the test configuration

On Unix, set EETCPP_PLAYGROUND to the built executable, then load the secure configuration:

export EETCPP_PLAYGROUND=/tmp/EetCpp-build/playground/EetCppPlayground
set -a
. /secure/path/eetcpp-test.env
set +a

On PowerShell:

$env:EETCPP_PLAYGROUND = "C:\path\to\EetCppPlayground.exe"
$env:EET_ENDPOINT = "https://replace-with-official-eet-test-endpoint"
$env:EET_PKCS12_PATH = "C:\secure\eet-test-certificate.p12"
# Set EET_PKCS12_PASSWORD through the CI secret store or the local
# PowerShell secret-management policy; do not put it in this file.

3. Run preflight

This verifies the HTTPS endpoint and confirms that the PKCS#12 certificate can be opened and used to create a probe signature. It does not submit a sale.

./scripts/eet-preflight.sh
./scripts/eet-preflight.ps1

4. Submit one verification-mode sale

Set a new EET_RECEIPT_NUMBER for every retry, then send exactly one verification sale:

./scripts/eet-send-verification.sh
./scripts/eet-send-verification.ps1

The scripts always pass --verification; they must not be used for a production sale. A successful result includes a POK. An EET application error, SOAP Fault or TLS failure is printed as a sanitized error and should be resolved before retrying.

5. Handle output and credentials safely

If a command fails, preserve only the exit code and the sanitized error message. Do not attach full HTTP/SOAP captures to issues. Redact certificate serials, request identifiers and endpoint query parameters if the environment contains identifying information.

After testing, remove the PKCS#12 and configuration from temporary machines or move them to the application's approved secure certificate store.

Tools and safe usage

The repository uses the following tools:

  • CMake configures the library and the Playground.
  • CTest runs the complete automated suite.
  • EetCppPlayground performs explicit manual preflight and test-sale operations.
  • Bash/PowerShell wrappers make the Playground usable in scripts.
  • Qt6 Network performs HTTPS requests and applies the platform TLS trust store.
  • xmlsec1/OpenSSL create and verify XML signatures and JWT signatures.
  • local TLS mock server exercises the CA workflow without contacting a government endpoint.
  • EET TLS mock server exercises the complete sale request/response path without contacting a government endpoint.

Do not pass passwords as command-line arguments. Prefer environment variables provided by a secret manager or an ephemeral shell session. Do not commit PKCS#12 files, private keys, JWTs, certificates containing private material, or full SOAP request/response captures.

Current implementation boundaries

  • The CA API client is implemented and covered by local validation tests, but its complete workflow is covered by a local TLS mock server and it has not been run against a live CA environment in this repository.
  • Live EET testing requires an official test endpoint and valid test credentials/certificate.
  • Cross-platform CI and packaging for all six OS/architecture combinations are planned next.
S
Description
No description provided
Readme
141 KiB
Languages
C++ 90.8%
CMake 5.6%
PowerShell 1.5%
Shell 1.1%
QMake 0.6%
Other 0.4%