diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAPIService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAPIService.java index 1270b14..abab8ad 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAPIService.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAPIService.java @@ -85,7 +85,7 @@ public class KSeFAPIService { // First open an interactive Session. The KSeFAuthManager automatically reuses // an existing session - // kseFAuthManager.openSession(); + kseFAuthManager.openSession(); if (kseFAuthManager.getAccessToken() == null) { throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API, @@ -219,6 +219,7 @@ public class KSeFAPIService { textlist.add(referenceNumber); fileData.setAttribute("ksef.referenceNumber", textlist); + kseFAuthManager.closeSession(); return referenceNumber; } diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAuthManager.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAuthManager.java index c1623ff..38c2028 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAuthManager.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/KSeFAuthManager.java @@ -204,7 +204,7 @@ public class KSeFAuthManager { this.redeemToken(); this.openInteractiveSession(); } else { - logger.info("│ ├── reuse existing KSeF Session..."); + logger.warning("│ ├── ! Session already exists - reuse existing KSeF Session..."); } } @@ -215,43 +215,41 @@ public class KSeFAuthManager { */ public boolean hasValidSession() { - return false; + // Check if session reference number exists + if (sessionRefNumber == null || sessionRefNumber.isEmpty()) { + return false; + } - // // Check if session reference number exists - // if (sessionRefNumber == null || sessionRefNumber.isEmpty()) { - // return false; - // } + // Check if valid until timestamp exists + if (sessionValidUntil == null || sessionValidUntil.isEmpty()) { + return false; + } - // // Check if valid until timestamp exists - // if (sessionValidUntil == null || sessionValidUntil.isEmpty()) { - // return false; - // } + try { + // Parse the validUntil timestamp (ISO 8601 format with UTC) + DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; + Instant validUntilInstant = Instant.from(formatter.parse(sessionValidUntil)); - // try { - // // Parse the validUntil timestamp (ISO 8601 format with UTC) - // DateTimeFormatter formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME; - // Instant validUntilInstant = Instant.from(formatter.parse(sessionValidUntil)); + // Get current time in UTC + Instant now = Instant.now(); - // // Get current time in UTC - // Instant now = Instant.now(); + // Check if session is still valid + boolean isValid = now.isBefore(validUntilInstant); - // // Check if session is still valid - // boolean isValid = now.isBefore(validUntilInstant); + if (debug && isValid) { + logger.info("├── Session is still valid until: " + sessionValidUntil); + } else if (debug) { + logger.info("├── Session expired at: " + sessionValidUntil); + } - // if (debug && isValid) { - // logger.info("├── Session is still valid until: " + sessionValidUntil); - // } else if (debug) { - // logger.info("├── Session expired at: " + sessionValidUntil); - // } + return isValid; - // return isValid; - - // } catch (Exception e) { - // // If parsing fails, assume session is invalid - // logger.warning("├── ⚠️ Error parsing sessionValidUntil timestamp: " + - // e.getMessage()); - // return false; - // } + } catch (Exception e) { + // If parsing fails, assume session is invalid + logger.warning("├── ⚠️ Error parsing sessionValidUntil timestamp: " + + e.getMessage()); + return false; + } } /** @@ -771,4 +769,51 @@ public class KSeFAuthManager { } } + /** + * This method closes the current session + * + * https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Wysylka-interaktywna/paths/~1api~1v2~1sessions~1online~1%7BreferenceNumber%7D~1invoices/post + * + * + * NOTE: Seems to be not possible to close a session in test - response is + * usually 400 + * + * @throws PluginException + */ + public void closeSession() throws PluginException { + logger.info("├── 📦 KSeF API close session..."); + // https://ksef-test.mf.gov.pl/api/v2/sessions/online/{referenceNumber}/close + String uri = baseURI + "/sessions/online/" + sessionRefNumber + "/close"; + + if (debug) { + logger.info("│ ├── Endpoint: " + uri); + } + + if (sessionRefNumber == null || sessionRefNumber.isEmpty()) { + throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API, + "API Error: Unable to close session - session does not exist!"); + } + + HttpResponse response = null; + try { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(uri)) + .header("Accept", "application/json") + .header("Content-Type", "application/json") + .header("Authorization", "Bearer " + accessToken) + .POST(HttpRequest.BodyPublishers.noBody()) // + .build(); + response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + } catch (IOException | InterruptedException e) { + throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API, + "API Error: Unable to request auth status: " + e.getMessage()); + } + if (true) { + logger.info("│ ├── Response Code = " + response.statusCode()); + logger.info("Response: " + response.body()); + } + + sessionRefNumber = null; + } + } diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAPIServiceTest.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAPIServiceTest.java index b71e099..29dfc26 100644 --- a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAPIServiceTest.java +++ b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAPIServiceTest.java @@ -13,6 +13,7 @@ import java.util.logging.Logger; import org.imixs.workflow.FileData; import org.imixs.workflow.ItemCollection; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; @@ -23,6 +24,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import com.alexanderlogistics.TestLoggerConfig; +@Disabled @ExtendWith(MockitoExtension.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class KSeFAPIServiceTest { @@ -49,9 +51,9 @@ public class KSeFAPIServiceTest { manager.init(); // Open Session - manager.openSession(); + // manager.openSession(); - manager.checkTokenStatus(); + // manager.checkTokenStatus(); // manager.loadPublicKeyCertificates(); // manager.authChallenge(); // manager.authKSeFToken(); diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAuthManagerTest.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAuthManagerTest.java index 6ba6fe7..79e7728 100644 --- a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAuthManagerTest.java +++ b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/KSeFAuthManagerTest.java @@ -18,6 +18,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; @@ -26,6 +27,7 @@ import org.junit.jupiter.api.TestMethodOrder; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; +@Disabled @ExtendWith(MockitoExtension.class) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class KSeFAuthManagerTest { diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/TestKSeF.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/TestKSeF.java deleted file mode 100644 index 31ee2e1..0000000 --- a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/TestKSeF.java +++ /dev/null @@ -1,165 +0,0 @@ -package com.alexanderlogistics.ksef; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.util.logging.Logger; - -import org.imixs.workflow.exceptions.ModelException; -import org.imixs.workflow.exceptions.PluginException; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; - -/** - * Test cases KSeF Interface - * - * - * @author rsoika - */ -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class TestKSeF { - - final static String ENCODING = "UTF-8"; - - private static Logger logger = Logger.getLogger(TestKSeF.class.getName()); - - // Configuration - replace with your actual values - private static final String KSEF_TEST_URL = "https://ksef-test.mf.gov.pl/api/v2"; - // https://ksef-test.mf.gov.pl/api/v2/auth/challenge - - private static HttpClient httpClient; - private static String challenge; // Static variable to share between tests - - private final ObjectMapper objectMapper = new ObjectMapper(); - - private String refNumber = null; - private String authToken = null; - - @BeforeAll - public static void setupClass() { - logger.info("=== KSeF 2.0 Client Test ==="); - logger.info("KSeF URL: " + KSEF_TEST_URL); - logger.info("NIP: " + Params.NIP); - - httpClient = HttpClient.newBuilder() - .version(HttpClient.Version.HTTP_2) - .build(); - } - - @BeforeEach - public void setup() throws PluginException, ModelException { - logger.info("setup test environment ..."); - } - - @Test - @Order(1) - @DisplayName("Einfacher Challenge test 2.0 API") - public void testChallenge() throws Exception { - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(KSEF_TEST_URL + "/auth/challenge")) // nur Endpoint checken - .header("Accept", "application/json") - .POST(HttpRequest.BodyPublishers.noBody()) // - .build(); - - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - - System.out.println("Status: " + response.statusCode()); - System.out.println("Response: " + response.body()); - - // Prüfen, dass wir eine API-Antwort bekommen, kein HTML - assertTrue(response.statusCode() < 500, "API sollte antworten, Status < 500"); - assertFalse(response.body().contains(""), "Response sollte keine HTML-Seite sein"); - - // Challenge aus Response extrahieren und speichern - if (response.statusCode() == 200) { - JsonNode jsonNode = objectMapper.readTree(response.body()); - challenge = jsonNode.get("challenge").asText(); - logger.info("Extracted challenge: " + challenge); - } - } - - @Test - @Order(2) - @DisplayName("KSeF Token Request") - public void testKsefToken() throws Exception { - // JSON Payload erstellen - - String jsonPayload = String.format( - "{" + - "\"challenge\": \"%s\"," + - "\"contextIdentifier\": {" + - " \"type\": \"Nip\"," + - " \"value\": \"%s\"" + - "}," + - "\"encryptedToken\": \"%s\"" + - "}", - challenge, Params.NIP, Params.getEncodedToken()); - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(KSEF_TEST_URL + "/auth/ksef-token")) - .header("Accept", "application/json") - .header("Content-Type", "application/json") - .POST(HttpRequest.BodyPublishers.ofString(jsonPayload)) - .build(); - - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - - System.out.println("Status: " + response.statusCode()); - System.out.println("Response: " + response.body()); - - // Prüfen, dass wir eine API-Antwort bekommen - assertTrue(response.statusCode() < 500, "API sollte antworten, Status < 500"); - assertFalse(response.body().contains(""), "Response sollte keine HTML-Seite sein"); - - // JSON parsen und Werte speichern - if (response.statusCode() == 200 || response.statusCode() == 202) { - JsonNode jsonNode = objectMapper.readTree(response.body()); - - // Reference Number speichern - refNumber = jsonNode.get("referenceNumber").asText(); - logger.info("Extracted referenceNumber: " + refNumber); - - // Authentication Token speichern - authToken = jsonNode.get("authenticationToken").get("token").asText(); - logger.info("Extracted authenticationToken: " + authToken); - } - } - - @Test - @Order(3) - @DisplayName("KSeF Public Key Zertifikate abrufen") - public void testFetchKsefPublicKeys() throws Exception { - assertNotNull(Params.TOKEN, "KSEF_TOKEN environment variable nicht gesetzt"); - - HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create(KSEF_TEST_URL + "/security/public-key-certificates")) - .header("Accept", "application/json") - .header("Authorization", "Bearer " + Params.TOKEN) // Access Token nutzen - .GET() - .build(); - - HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - - System.out.println("Status: " + response.statusCode()); - System.out.println("Response: " + response.body()); - - // Assertions - assertEquals(200, response.statusCode(), "Request sollte 200 OK zurückgeben"); - assertTrue(response.body().contains("certificate"), "Response sollte ein Feld 'certificate' enthalten"); - } - -} diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/sepa/TestSEPATransform.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/sepa/TestSEPATransform.java index 62522a9..a14fc40 100644 --- a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/sepa/TestSEPATransform.java +++ b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/sepa/TestSEPATransform.java @@ -8,6 +8,7 @@ import java.util.logging.Logger; import org.imixs.workflow.exceptions.ModelException; import org.imixs.workflow.exceptions.PluginException; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; /** @@ -16,6 +17,7 @@ import org.junit.jupiter.api.Test; * * @author rsoika */ +@Disabled public class TestSEPATransform { final static String ENCODING = "UTF-8"; diff --git a/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestCargosoftEvents.java b/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestCargosoftEvents.java index 50e563f..6ed86cc 100644 --- a/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestCargosoftEvents.java +++ b/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestCargosoftEvents.java @@ -17,7 +17,7 @@ import org.junit.jupiter.api.Test; * A test to explore a corgosoft invoice event * */ -// @Disabled +@Disabled public class TestCargosoftEvents { private static Logger logger = Logger.getLogger(TestCargosoftEvents.class.getName()); diff --git a/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestSendInvoice.java b/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestSendInvoice.java index 6bf4f13..ee50923 100644 --- a/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestSendInvoice.java +++ b/office-alexander-logistics-testclient/src/test/java/com/alexanderlogistics/rest/TestSendInvoice.java @@ -14,6 +14,7 @@ import org.imixs.workflow.ItemCollection; import org.imixs.workflow.exceptions.PluginException; import org.imixs.workflow.xml.XMLDataCollectionAdapter; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import jakarta.xml.bind.JAXBException; @@ -22,7 +23,7 @@ import jakarta.xml.bind.JAXBException; * A simple example how to send an invoice document remote. * */ -// @Disabled +@Disabled public class TestSendInvoice { private static Logger logger = Logger.getLogger(TestSendInvoice.class.getName());