# 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: ```sh 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](./scripts/eet-playground.sh) and [scripts/eet-playground.ps1](./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: ```sh 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 ```sh ./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: ```sh 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: ```sh ./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](./.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 ```sh 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: ```sh export EETCPP_PLAYGROUND=/tmp/EetCpp-build/playground/EetCppPlayground set -a . /secure/path/eetcpp-test.env set +a ``` On PowerShell: ```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. ```sh ./scripts/eet-preflight.sh ``` ```powershell ./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: ```sh ./scripts/eet-send-verification.sh ``` ```powershell ./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.