rewrite for eet 2.0 api version v4
This commit is contained in:
@@ -0,0 +1,278 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user