279 lines
9.1 KiB
Markdown
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.
|