## Sesja interaktywna
10.07.2025
Sesja interaktywna służy do przesyłania pojedynczych faktur ustrukturyzowanych do API KSeF. Każda faktura musi być przygotowana w formacie XML zgodnie z aktualnym schematem opublikowanym przez Ministerstwo Finansów.
### Wymagania wstępne
Aby skorzystać z wysyłki interaktywnej, należy najpierw przejść proces [uwierzytelnienia](uwierzytelnianie.md) i posiadać aktualny token dostępowy (```accessToken```), który uprawnia do korzystania z chronionych zasobów API KSeF.
Przed otwarciem sesji oraz wysłaniem faktur wymagane jest:
* wygenerowanie klucza symetrycznego o długości 256 bitów i wektora inicjującego o długości 128 bitów (IV),
* zaszyfrowanie dokumentu algorytmem AES-256-CBC z dopełnianiem PKCS#7,
* zaszyfrowanie klucza symetrycznego algorytmem RSAES-OAEP (padding OAEP z funkcją MGF1 opartą na SHA-256 oraz skrótem SHA-256), przy użyciu klucza publicznego KSeF Ministerstwa Finansów.
Operacje te można zrealizować za pomocą komponentu ```CryptographyService```, dostępnego w kliencie KSeF.
Przykład w języku C#:
[KSeF.Client.Tests.Core\E2E\OnlineSession\OnlineSessionE2ETests.cs](https://github.com/CIRFMF/ksef-client-csharp/blob/main/KSeF.Client.Tests.Core/E2E/OnlineSession/OnlineSessionE2ETests.cs)
```csharp
EncryptionData encryptionData = CryptographyService.GetEncryptionData();
```
Przykład w języku Java:
[OnlineSessionIntegrationTest.java](https://github.com/CIRFMF/ksef-client-java/blob/main/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/OnlineSessionIntegrationTest.java)
```java
EncryptionData encryptionData = cryptographyService.getEncryptionData();
```
### 1. Otwarcie sesji
Inicjalizacja nowej sesji interaktywnej z podaniem:
* wersji schematu faktury: [FA(2)](faktury/schemy/FA/schemat_FA(2)_v1-0E.xsd), [FA(3)](faktury/schemy/FA/schemat_FA(3)_v1-0E.xsd)
określa, którą wersję XSD system będzie stosować do walidacji przesyłanych faktur.
* zaszyfrowanego klucza symetrycznego
symetryczny klucz szyfrujący pliki XML, zaszyfrowany kluczem publicznym Ministerstwa Finansów; rekomendowane jest użycie nowo wygenerowanego klucza dla każdej sesji.
Otwarcie sesji jest operacją lekką i synchroniczną – można równocześnie utrzymywać wiele otwartych sesji interaktywnych w ramach jednego uwierzytelnienia.
POST [sessions/online](https://api-test.ksef.mf.gov.pl/docs/v2/index.html#tag/Wysylka-interaktywna/paths/~1sessions~1online/post)
W odpowiedzi zwracany jest obiekt zawierający:
- ```referenceNumber``` – unikalny identyfikator sesji interaktywnej, który należy przekazywać we wszystkich kolejnych wywołaniach API.
- ```validUntil``` – Termin ważności sesji. Po jego upływie sesja zostanie automatycznie zamknięta. Czas życia sesji interaktywnej wynosi 12 godzin od momentu jej utworzenia.
Przykład w języku C#:
[KSeF.Client.Tests.Core\E2E\OnlineSession\OnlineSessionE2ETests.cs](https://github.com/CIRFMF/ksef-client-csharp/blob/main/KSeF.Client.Tests.Core/E2E/OnlineSession/OnlineSessionE2ETests.cs)
```csharp
OpenOnlineSessionRequest openOnlineSessionRequest = OpenOnlineSessionRequestBuilder
.Create()
.WithFormCode(systemCode: SystemCodeHelper.GetValue(systemCode), schemaVersion: DefaultSchemaVersion, value: DefaultFormCodeValue)
.WithEncryption(
encryptedSymmetricKey: encryptionData.EncryptionInfo.EncryptedSymmetricKey,
initializationVector: encryptionData.EncryptionInfo.InitializationVector)
.Build();
OpenOnlineSessionResponse openOnlineSessionResponse = await KsefClient.OpenOnlineSessionAsync(openOnlineSessionRequest, accessToken, CancellationToken);
```
Przykład w języku Java:
[OnlineSessionIntegrationTest.java](https://github.com/CIRFMF/ksef-client-java/blob/main/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/OnlineSessionIntegrationTest.java)
```java
OpenOnlineSessionRequest request = new OpenOnlineSessionRequestBuilder()
.withFormCode(new FormCode(systemCode, schemaVersion, value))
.withEncryptionInfo(encryptionData.encryptionInfo())
.build();
OpenOnlineSessionResponse openOnlineSessionResponse = ksefClient.openOnlineSession(request, accessToken);
```
### 2. Wysłanie faktury
Zaszyfrowaną fakturę należy wysłać na endpoint:
POST [sessions/online/{referenceNumber}/invoices/](https://api-test.ksef.mf.gov.pl/docs/v2/index.html#tag/Wysylka-interaktywna/paths/~1sessions~1online~1%7BreferenceNumber%7D~1invoices/post)
Odpowiedź zawiera ```referenceNumber``` dokumentu – używany do identyfikacji faktury w kolejnych operacjach (np. listy dokumentów).
Po prawidłowym przesłaniu faktury rozpoczyna się asynchroniczna weryfikacja faktury ([szczegóły weryfikacji](faktury/weryfikacja-faktury.md)).
Przykład w języku C#:
[KSeF.Client.Tests.Core\E2E\OnlineSession\OnlineSessionE2ETests.cs](https://github.com/CIRFMF/ksef-client-csharp/blob/main/KSeF.Client.Tests.Core/E2E/OnlineSession/OnlineSessionE2ETests.cs)
```csharp
byte[] encryptedInvoice = cryptographyService.EncryptBytesWithAES256(invoice, encryptionData.CipherKey, encryptionData.CipherIv);
FileMetadata invoiceMetadata = cryptographyService.GetMetaData(invoice);
FileMetadata encryptedInvoiceMetadata = cryptographyService.GetMetaData(encryptedInvoice);
SendInvoiceRequest sendOnlineInvoiceRequest = SendInvoiceOnlineSessionRequestBuilder
.Create()
.WithInvoiceHash(invoiceMetadata.HashSHA, invoiceMetadata.FileSize)
.WithEncryptedDocumentHash(encryptedInvoiceMetadata.HashSHA, encryptedInvoiceMetadata.FileSize)
.WithEncryptedDocumentContent(Convert.ToBase64String(encryptedInvoice))
.Build();
SendInvoiceResponse sendInvoiceResponse = await KsefClient.SendOnlineSessionInvoiceAsync(sendOnlineInvoiceRequest, referenceNumber, accessToken);
```
Przykład w języku Java:
[OnlineSessionIntegrationTest.java](https://github.com/CIRFMF/ksef-client-java/blob/main/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/OnlineSessionIntegrationTest.java)
```java
byte[] invoice = "";
byte[] encryptedInvoice = defaultCryptographyService.encryptBytesWithAES256(invoice,
encryptionData.cipherKey(),
encryptionData.cipherIv());
FileMetadata invoiceMetadata = defaultCryptographyService.getMetaData(invoice);
FileMetadata encryptedInvoiceMetadata = defaultCryptographyService.getMetaData(encryptedInvoice);
SendInvoiceOnlineSessionRequest sendInvoiceOnlineSessionRequest = new SendInvoiceOnlineSessionRequestBuilder()
.withInvoiceHash(invoiceMetadata.getHashSHA())
.withInvoiceSize(invoiceMetadata.getFileSize())
.withEncryptedInvoiceHash(encryptedInvoiceMetadata.getHashSHA())
.withEncryptedInvoiceSize(encryptedInvoiceMetadata.getFileSize())
.withEncryptedInvoiceContent(Base64.getEncoder().encodeToString(encryptedInvoice))
.build();
SendInvoiceResponse sendInvoiceResponse = ksefClient.onlineSessionSendInvoice(sessionReferenceNumber, sendInvoiceOnlineSessionRequest, accessToken);
```
### 3. Zamknięcie sesji
Po wysłaniu wszystkich faktur należy zamknąć sesję, co inicjuje asynchroniczne generowanie zbiorczego UPO.
POST [/sessions/online/\{referenceNumber\}/close](https://api-test.ksef.mf.gov.pl/docs/v2/index.html#tag/Wysylka-interaktywna/paths/~1sessions~1online~1%7BreferenceNumber%7D~1close/post)
Zbiorcze UPO będzie dostępne po sprawdzeniu stanu sesji.
Przykład w języku C#:
[KSeF.Client.Tests.Core\E2E\OnlineSession\OnlineSessionE2ETests.cs](https://github.com/CIRFMF/ksef-client-csharp/blob/main/KSeF.Client.Tests.Core/E2E/OnlineSession/OnlineSessionE2ETests.cs)
```csharp
await KsefClient.CloseOnlineSessionAsync(referenceNumber, accessToken, CancellationToken);
```
Przykład w języku Java:
[OnlineSessionIntegrationTest.java](https://github.com/CIRFMF/ksef-client-java/blob/main/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/OnlineSessionIntegrationTest.java)
```java
ksefClient.closeOnlineSession(sessionReferenceNumber, accessToken);
```
Powiązane dokumenty:
- [Sprawdzenie stanu i pobranie UPO](faktury/sesje/sesja-sprawdzenie-stanu-i-pobranie-upo.md)
- [Weryfikacja faktury](faktury/weryfikacja-faktury.md)
- [Numer KSeF – struktura i walidacja](faktury/numer-ksef.md)