Files
EetCpp/README.md
T

279 lines
9.1 KiB
Markdown

# 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.