314 lines
9 KiB
Markdown
314 lines
9 KiB
Markdown
# KSeF API Integration
|
|
|
|
Java integration for the Polish **Krajowy System e-Faktur (KSeF)** - the national e-invoicing system for Poland.
|
|
|
|
## Overview
|
|
|
|
This integration provides secure communication with the KSeF API to upload electronic invoices. It handles the complex multi-step authentication flow and encryption requirements mandated by the Polish tax authorities.
|
|
|
|
- [Environment Endpoints](https://github.com/CIRFMF/ksef-docs/blob/main/srodowiska.md)
|
|
- [KSeF Official Documentation](https://www.gov.pl/web/kas/ksef)
|
|
- [KSeF API Specification](https://api-test.ksef.mf.gov.pl/docs/v2/index.html)
|
|
- [Upload Invoice](https://api-test.ksef.mf.gov.pl/docs/v2/index.html#tag/Wysylka-interaktywna/paths/~1api~1v2~1sessions~1online~1%7BreferenceNumber%7D~1invoices/post)
|
|
- [Facture Details](https://github.com/CIRFMF/ksef-docs/blob/main/sesja-interaktywna.md#2-wys%C5%82anie-faktury)
|
|
- [XML Invoice Example](https://github.com/CIRFMF/ksef-docs/blob/main/faktury/weryfikacja-faktury.md)
|
|
- [QR Code](https://github.com/CIRFMF/ksef-docs/blob/main/kody-qr.md)
|
|
|
|
- [Github Discussions](https://github.com/CIRFMF/ksef-docs/issues/351#issuecomment-3538013805)
|
|
- [Github Discussions](https://github.com/CIRFMF/ksef-docs/issues/399)
|
|
|
|
Test environment endpoint:
|
|
|
|
```
|
|
https://api-test.ksef.mf.gov.pl/api/v2
|
|
```
|
|
|
|
Production endpoint:
|
|
|
|
```
|
|
https://api.ksef.mf.gov.pl/api/v2
|
|
```
|
|
|
|
## Components
|
|
|
|
### 1. KSeFAuthManager
|
|
|
|
Manages authentication and session lifecycle for the KSeF API.
|
|
|
|
**Key Responsibilities:**
|
|
|
|
- Multi-step authentication flow
|
|
- RSA certificate management
|
|
- Session key generation and encryption
|
|
- Access token lifecycle management
|
|
- Session reuse and validation
|
|
|
|
### 2. KSeFAPIService
|
|
|
|
Provides business-level methods for invoice operations.
|
|
|
|
**Key Responsibilities:**
|
|
|
|
- Invoice encryption (AES-256-CBC)
|
|
- Invoice upload to KSeF
|
|
- Hash calculation and validation
|
|
- Error handling and reporting
|
|
|
|
## Authentication Flow
|
|
|
|
The KSeF API requires a sophisticated multi-step authentication process:
|
|
|
|
```
|
|
1. Load Public Keys
|
|
└─> GET /security/public-key-certificates
|
|
|
|
2. Challenge Request
|
|
└─> POST /auth/challenge
|
|
└─> Returns: challenge + timestamp
|
|
|
|
3. Token Authentication
|
|
└─> POST /auth/ksef-token
|
|
└─> Encrypts: token|timestamp with RSA-OAEP SHA-256
|
|
└─> Returns: authToken + referenceNumber
|
|
|
|
4. Token Redemption
|
|
└─> POST /auth/token/redeem
|
|
└─> Returns: accessToken
|
|
|
|
5. Open Interactive Session
|
|
└─> POST /sessions/online
|
|
└─> Generates AES-256 key + IV
|
|
└─> Encrypts session key with RSA
|
|
└─> Returns: sessionRefNumber + validUntil
|
|
```
|
|
|
|
## Invoice Upload Flow
|
|
|
|
Once authenticated, invoices can be uploaded:
|
|
|
|
```
|
|
1. Reuse or Create Session
|
|
└─> Validates existing session or creates new one
|
|
|
|
2. Encrypt Invoice
|
|
└─> AES-256-CBC encryption using session key
|
|
|
|
3. Calculate Hashes
|
|
└─> SHA-256 of original XML
|
|
└─> SHA-256 of encrypted XML
|
|
|
|
4. Upload Invoice
|
|
└─> POST /sessions/online/{sessionRef}/invoices
|
|
└─> Returns: referenceNumber
|
|
```
|
|
|
|
## Security Features
|
|
|
|
### Multi-Layer Encryption
|
|
|
|
- **RSA-OAEP SHA-256**: Token encryption with timestamp binding
|
|
- **RSA-OAEP SHA-1**: Session key encryption
|
|
- **AES-256-CBC**: Invoice content encryption
|
|
|
|
### Security Mechanisms
|
|
|
|
- **Replay Attack Protection**: Timestamp-bound tokens
|
|
- **Session Management**: Automatic session reuse and validation
|
|
- **Certificate Validation**: Dynamic X.509 certificate loading
|
|
- **UTC Timezone Handling**: Prevents timezone-related vulnerabilities
|
|
|
|
## Usage Example
|
|
|
|
```java
|
|
// Initialize Auth Manager
|
|
KSeFAuthManager authManager = new KSeFAuthManager();
|
|
authManager.setKsefToken("your-ksef-token");
|
|
authManager.setKsefNip("1234567890");
|
|
authManager.setKsefEndpoint("https://ksef-test.mf.gov.pl/api/v2");
|
|
authManager.init();
|
|
|
|
// Initialize API Service
|
|
KSeFAPIService apiService = new KSeFAPIService();
|
|
apiService.kseFAuthManager = authManager;
|
|
|
|
// Upload Invoice
|
|
ItemCollection workitem = new ItemCollection();
|
|
FileData fileData = new FileData("invoice.xml", xmlBytes, null, null);
|
|
workitem.addFileData(fileData);
|
|
|
|
String referenceNumber = apiService.uploadInvoice(workitem, "invoice.xml");
|
|
System.out.println("Invoice uploaded: " + referenceNumber);
|
|
```
|
|
|
|
## Configuration
|
|
|
|
Required environment variables:
|
|
|
|
```properties
|
|
ksef.api.token=your-ksef-authentication-token
|
|
ksef.api.nip=your-company-nip-number
|
|
ksef.api.endpoint=https://ksef-test.mf.gov.pl/api/v2
|
|
ksef.api.debug=false
|
|
```
|
|
|
|
## Session Management
|
|
|
|
The `KSeFAuthManager` automatically handles session lifecycle:
|
|
|
|
- **Session Reuse**: Validates `sessionValidUntil` timestamp (UTC)
|
|
- **Auto-Renewal**: Opens new session if current one expired
|
|
- **Thread-Safe**: Uses `@Lock(LockType.WRITE)` for concurrent access
|
|
|
|
## Testing
|
|
|
|
Test environment endpoint:
|
|
|
|
```
|
|
https://ksef-test.mf.gov.pl/api/v2
|
|
```
|
|
|
|
Production endpoint:
|
|
|
|
```
|
|
https://ksef.mf.gov.pl/api/v2
|
|
```
|
|
|
|
See `KSeFAPIServiceTest.java` for complete test examples.
|
|
|
|
## Error Handling
|
|
|
|
The implementation uses `PluginException` for error handling with two error types:
|
|
|
|
- `CONFIG_ERROR`: Configuration or setup issues
|
|
- `API_ERROR`: API communication or response errors
|
|
|
|
## Dependencies
|
|
|
|
- Jakarta EE (EJB, JSON-B)
|
|
- Java 11+ (HttpClient, Crypto APIs)
|
|
- Imixs Workflow (for document management)
|
|
|
|
# Validate XML
|
|
|
|
To validate XML results use xmllint. To install run:
|
|
|
|
```bash
|
|
$ sudo apt install libxml2-utils
|
|
```
|
|
|
|
With the bash script `src/test/resources/ksef/validate_xml.sh` you can test a xml file:
|
|
|
|
```bash
|
|
$ ./validate_xml.sh example-invoice-01.xml
|
|
```
|
|
|
|
or to manual test a xml run:
|
|
|
|
```bash
|
|
$ xmllint --noout --schema 'schemat-FA(3)-v1-0E.xsd' example-invoice-01.xml
|
|
example-invoice-01.xml validates
|
|
```
|
|
|
|
# KSeF FA(3) Invoice Types: VAT vs. KOR
|
|
|
|
This section explains the key differences between regular invoices (VAT) and correction invoices (KOR) in the Polish KSeF system using FA(3) structure.
|
|
|
|
## Invoice Types
|
|
|
|
### VAT - Regular Invoice
|
|
|
|
Standard invoice documenting a sale or service delivery.
|
|
|
|
### KOR - Correction Invoice
|
|
|
|
Invoice that corrects a previously issued invoice (VAT, ZAL, or ROZ).
|
|
|
|
---
|
|
|
|
## Key Differences
|
|
|
|
| Element | VAT Invoice | KOR Invoice |
|
|
| ------------------------- | -------------------------- | --------------------------------------------- |
|
|
| **RodzajFaktury** | `VAT` | `KOR` |
|
|
| **P_2 (Invoice Number)** | `216525` | `216525-KOR` (with suffix) |
|
|
| **P_1 (Invoice Date)** | Original date (2024-04-03) | Correction date (2024-04-15) |
|
|
| **Amount Fields** | Absolute values | **Difference values** (negative or positive) |
|
|
| **DaneFaKorygowanej** | ❌ Not present | ✅ **Required** - references original invoice |
|
|
| **FaWiersz (Line Items)** | Original values | **New/corrected values** |
|
|
|
|
---
|
|
|
|
## Critical: Amount Fields in KOR
|
|
|
|
**KOR invoices show DIFFERENCES, not absolute amounts!**
|
|
|
|
### Example: Correction from 4128.00 → 3500.00 EUR
|
|
|
|
```xml
|
|
<!-- VAT Invoice -->
|
|
<P_13_1>4128.00</P_13_1> <!-- Total Net -->
|
|
<P_14_1>0.00</P_14_1> <!-- Total VAT -->
|
|
<P_15>4128.00</P_15> <!-- Total Gross -->
|
|
```
|
|
|
|
```xml
|
|
<!-- KOR Invoice -->
|
|
<P_13_6_1>-628.00</P_13_6_1> <!-- Difference: 3500 - 4128 = -628 -->
|
|
<P_15>-628.00</P_15> <!-- Difference in Total -->
|
|
```
|
|
|
|
## DaneFaKorygowanej Element
|
|
|
|
**Required in KOR invoices** - Must appear AFTER `<RodzajFaktury>KOR</RodzajFaktury>`
|
|
|
|
```xml
|
|
<DaneFaKorygowanej>
|
|
<DataWystFaKorygowanej>2024-04-03</DataWystFaKorygowanej>
|
|
<NrFaKorygowanej>216525</NrFaKorygowanej>
|
|
<NrKSeF>1</NrKSeF>
|
|
<NrKSeFFaKorygowanej>9552521552-20240403-ABCDEF-123456-AB</NrKSeFFaKorygowanej>
|
|
</DaneFaKorygowanej>
|
|
```
|
|
|
|
| Field | Description |
|
|
| ----------------------- | --------------------------------------------------------- |
|
|
| `DataWystFaKorygowanej` | Date of **original** invoice |
|
|
| `NrFaKorygowanej` | Number of **original** invoice |
|
|
| `NrKSeF` | Flag: `1` = original was in KSeF |
|
|
| `NrKSeFFaKorygowanej` | KSeF number of original invoice (mandatory if `NrKSeF=1`) |
|
|
|
|
⚠️ **Critical:** The KSeF number must be saved when uploading the original VAT invoice!
|
|
|
|
---
|
|
|
|
## FaWiersz in KOR
|
|
|
|
**Line items show the NEW/CORRECTED values**, not differences:
|
|
|
|
```xml
|
|
<!-- VAT Invoice -->
|
|
<FaWiersz>
|
|
<P_9A>4128.00</P_9A> <!-- Unit price -->
|
|
<P_11>4128.00</P_11> <!-- Net value -->
|
|
</FaWiersz>
|
|
```
|
|
|
|
```xml
|
|
<!-- KOR Invoice -->
|
|
<FaWiersz>
|
|
<P_9A>3500.00</P_9A> <!-- NEW unit price -->
|
|
<P_11>3500.00</P_11> <!-- NEW net value -->
|
|
<P_12>0 KR</P_12> <!-- Tax rate (0% for exempted) -->
|
|
</FaWiersz>
|
|
```
|
|
|
|
---
|
|
|
|
# Testdaten
|
|
|
|
Um Testdaten in die lokale Dev Umgebung zu importieren:
|
|
|
|
1. aus dem Produktiv Archiv System das XML eines Rechnungs-Snapshots unter /docker/transfer speichern
|
|
2. per api Call importieren:
|
|
|
|
http://localhost:8080/api/cargosoft/import?file=/opt/jboss/wildfly/transfer/f28bf914-04de-4843-9809-54c724bdc9bf-1764111735524.xml
|