office-alexander-logistics/doc/KSeF
2026-04-27 16:31:42 +02:00
..
FEEDBACK.md Feedback von Taxman 2026-04-27 16:31:42 +02:00
Feld-Mapping Cargo Soft zu KSeF (DE).pdf Feedback von Taxman 2026-04-27 12:47:59 +02:00
openapi.json Berechnung der KSeF Download URLs 2025-11-28 14:01:18 +01:00
README.md docu 2026-03-24 15:12:34 +01:00
schemat.xsd cargosoft export 2025-07-30 10:12:11 +02:00
SECRETS.md ksef export configuration 2025-11-17 21:36:36 +01:00
TEST.md konfiguraition, mailing, 2026-03-09 12:40:55 +01:00
test.xml Berechnung der KSeF Download URLs 2025-11-28 14:01:18 +01:00

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.

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

// 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:

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:

$ sudo apt install libxml2-utils

With the bash script src/test/resources/ksef/validate_xml.sh you can test a xml file:

$ ./validate_xml.sh example-invoice-01.xml

or to manual test a xml run:

$ 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

<!-- 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 -->
<!-- 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>

<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:

<!-- VAT Invoice -->
<FaWiersz>
  <P_9A>4128.00</P_9A>  <!-- Unit price -->
  <P_11>4128.00</P_11>  <!-- Net value -->
</FaWiersz>
<!-- 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