From c232841ed34889de2dbeb9572c34c44f98e32ebb Mon Sep 17 00:00:00 2001
From: Ralph Soika
Date: Tue, 18 Nov 2025 16:33:58 +0100
Subject: [PATCH] update
---
.../einvoice/EInvoiceAdapter.java | 2 +-
...ExportAdapter.java => KSeFAPIAdapter.java} | 49 +-
.../einvoice/KSeFAdapter.java | 13 +-
.../ksef/api/KSeFAPIService.java | 114 +-
.../ksef/api/KSeFAuthManager.java | 4 +-
.../ksef/api/KSeFAPIServiceTest.java | 2 +-
.../rechnungsausgang-pl-1.1.0-versuche.bpmn | 3413 +++++++++++++++++
workflow/pl/rechnungsausgang-pl-1.1.0.bpmn | 699 ++--
8 files changed, 3921 insertions(+), 375 deletions(-)
rename office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/{KSeFExportAdapter.java => KSeFAPIAdapter.java} (52%)
create mode 100644 workflow/pl/rechnungsausgang-pl-1.1.0-versuche.bpmn
diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/EInvoiceAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/EInvoiceAdapter.java
index 038a921..97ef610 100644
--- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/EInvoiceAdapter.java
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/EInvoiceAdapter.java
@@ -120,7 +120,7 @@ public class EInvoiceAdapter implements SignalAdapter {
throw new PluginException(EInvoiceAdapter.class.getSimpleName(), CONFIG_ERROR,
"missing e-invoice configuration in model event - please check model configuration");
}
- ItemCollection createDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("create"));
+ ItemCollection createDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("CREATE"));
try {
// Load the e-invoice template....
FileData xmlFileData = loadXMLTemplate(workitem, createDefinition);
diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFExportAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFAPIAdapter.java
similarity index 52%
rename from office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFExportAdapter.java
rename to office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFAPIAdapter.java
index 3ae74df..c4e1ccf 100644
--- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFExportAdapter.java
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFAPIAdapter.java
@@ -15,26 +15,33 @@ import com.alexanderlogistics.ksef.api.KSeFAPIService;
import jakarta.inject.Inject;
/**
- * This adapter exports the invoice data to KSeF
+ * This adapter exports the invoice data to KSeF and can poll the current status
+ * of an invoice
*
* To activate debug add the following event definition
*
*
* {@code
-
- true
-
+
+ true
+
+
+
+
+ true
+
+
* }
*
*
* @version 1.0
* @author rsoika
*/
-public class KSeFExportAdapter implements SignalAdapter {
+public class KSeFAPIAdapter implements SignalAdapter {
public static final String CONFIG_ERROR = "CONFIG_ERROR";
- private static Logger logger = Logger.getLogger(KSeFExportAdapter.class.getName());
+ private static Logger logger = Logger.getLogger(KSeFAPIAdapter.class.getName());
private boolean debug = false;
@Inject
@@ -56,25 +63,33 @@ public class KSeFExportAdapter implements SignalAdapter {
throws AdapterException {
// read debug flag
try {
- List ksefDefinitions = workflowService.evalWorkflowResultXML(event, "ksef",
+ List ksefExportDefinitions = workflowService.evalWorkflowResultXML(event, "ksef",
"EXPORT", workitem, false);
- if (ksefDefinitions != null && ksefDefinitions.size() > 0) {
- ItemCollection ksefDefinition = ksefDefinitions.get(0);
+ // List ksefStatusDefinitions =
+ // workflowService.evalWorkflowResultXML(event, "ksef",
+ // "STATUS", workitem, false);
+
+ // EXPORT
+ if (ksefExportDefinitions != null && ksefExportDefinitions.size() > 0) {
+ ItemCollection ksefDefinition = ksefExportDefinitions.get(0);
debug = ksefDefinition.getItemValueBoolean("debug");
+
+ kSeFAPIService.uploadInvoice(workitem, "ksef.xml");
+
}
- } catch (PluginException ee) {
- // no op
- }
- try {
- kSeFAPIService.uploadInvoice(workitem, "ksef.xml");
+ // // STATUS
+ // if (ksefStatusDefinitions != null && ksefStatusDefinitions.size() > 0) {
+ // ItemCollection ksefDefinition = ksefStatusDefinitions.get(0);
+ // debug = ksefDefinition.getItemValueBoolean("debug");
+ // kSeFAPIService.getInvoiceStatus(workitem);
+
+ // }
} catch (PluginException e) {
- // convert PluginException into a AdapterException to handle the error via the
- // model!
- logger.warning("Failed to export data to Zoho: " + e.getMessage());
throw new AdapterException(e);
}
+
return workitem;
}
diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFAdapter.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFAdapter.java
index 20e6cd9..c84d281 100644
--- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFAdapter.java
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/einvoice/KSeFAdapter.java
@@ -40,11 +40,12 @@ import jakarta.inject.Inject;
*
*
* {@code
-
+
textblock-ref
filename
true
-
+
+
}
*
*
@@ -92,18 +93,18 @@ public class KSeFAdapter implements SignalAdapter {
logger.info("├── 🔜 Convert Invoice to KSeF...");
// read configuration....
- ItemCollection eInvoiceConfig = workflowService.evalWorkflowResult(event, "e-invoice",
+ ItemCollection eInvoiceConfig = workflowService.evalWorkflowResult(event, "ksef",
workitem,
false);
- if (eInvoiceConfig == null || !eInvoiceConfig.hasItem("ksef")) {
+ if (eInvoiceConfig == null || !eInvoiceConfig.hasItem("CREATE")) {
throw new PluginException(EInvoiceAdapter.class.getSimpleName(), CONFIG_ERROR,
"missing e-invoice/ksef configuration in model event - please check model configuration");
}
- ItemCollection ksefDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("ksef"));
+ ItemCollection ksefCreateDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("CREATE"));
try {
// Load the e-invoice template....
- FileData xmlFileData = loadXMLTemplate(workitem, ksefDefinition);
+ FileData xmlFileData = loadXMLTemplate(workitem, ksefCreateDefinition);
updateEInvoice(xmlFileData, workitem);
diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAPIService.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAPIService.java
index 27ebd8b..46e20ca 100644
--- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAPIService.java
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAPIService.java
@@ -67,7 +67,7 @@ public class KSeFAPIService {
* @return referenceNumber from KSeF
* @throws PluginException
*/
- public String uploadInvoice(ItemCollection workitem, String fileName) throws PluginException {
+ public void uploadInvoice(ItemCollection workitem, String fileName) throws PluginException {
// First open an interactive session (reuses existing if valid)
kseFAuthManager.openSession();
@@ -182,9 +182,27 @@ public class KSeFAPIService {
textlist.add(referenceNumber);
fileData.setAttribute("ksef.referenceNumber", textlist);
+ workitem.setItemValue("ksef.referenceNumber", referenceNumber);
logger.info("├── ✅ Upload successful - Reference: " + referenceNumber);
- return referenceNumber;
+ // Close Session
+ kseFAuthManager.closeInteractiveSession();
+
+ // Status abfragen
+ // Now we need to wait until auth/{AuthRef} will return 200
+ long start = System.currentTimeMillis();
+ long timeout = 20_000; // 20 Sekunden
+ while (System.currentTimeMillis() - start < timeout) {
+ int code = kseFAuthManager.checkSessionStatus();
+
+ if (code >= 200) {
+ break; // ok or borken
+ }
+
+ // kleine Pause, um CPU zu schonen
+ kseFAuthManager.waitSomeTime(500);
+
+ }
} catch (Exception e) {
logger.severe("├── ⚠️ Invoice upload failed: " + e.getMessage());
@@ -194,11 +212,101 @@ public class KSeFAPIService {
} finally {
// finally we close the session
- kseFAuthManager.closeInteractiveSession();
+
kseFAuthManager.deleteCurrentAuthSession();
}
}
+ /**
+ * Poll Invoice Status
+ *
+ * https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Status-wysylki-i-UPO/paths/~1api~1v2~1sessions~1%7BreferenceNumber%7D/get
+ *
+ * @param workitem
+ * @return
+ * @throws PluginException
+ */
+ private int xxxgetInvoiceStatus(ItemCollection workitem) throws PluginException {
+
+ logger.info("├── 🔎 Get Invoice Status...");
+
+ // Validate session
+ if (kseFAuthManager.getAccessToken() == null) {
+ throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
+ "API Error - missing AccessToken!");
+ }
+ if (kseFAuthManager.getSessionRefNumber() == null) {
+ throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
+ "API Error - missing SessionRefNumber!");
+ }
+ if (kseFAuthManager.getSessionEncryption() == null) {
+ throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
+ "API Error - missing Session Encryption!");
+ }
+
+ try {
+
+ String referenceNumber = workitem.getItemValueString("ksef.referenceNumber");
+ if (referenceNumber.isBlank()) {
+ throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
+ "API Error - missing invoice referenceNumber!");
+ }
+
+ // Calculate hashes
+
+ // Send upload request
+ String uri = kseFAuthManager.getBaseURI() + "/sessions/" + kseFAuthManager.getSessionRefNumber();
+
+ logger.info("│ ├── GET: " + uri);
+
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(uri))
+ .header("Content-Type", "application/json")
+ .header("Authorization", "Bearer " + kseFAuthManager.getAccessToken())
+ .GET()
+ .build();
+
+ HttpResponse response = kseFAuthManager.getHttpClient().send(
+ request, HttpResponse.BodyHandlers.ofString());
+
+ logger.info("│ ├── HTTP Response: " + response.statusCode());
+
+ logger.info("│ ├── Response Body: " + response.body());
+
+ int statusCode = -1;
+ String statusDescription = "";
+ try (Jsonb jsonb = JsonbBuilder.create()) {
+ JsonObject jsonObject = jsonb.fromJson(response.body(), JsonObject.class);
+
+ // Status Code aus dem status-Objekt extrahieren
+ if (jsonObject.containsKey("status")) {
+ JsonObject statusObject = jsonObject.getJsonObject("status");
+ if (statusObject.containsKey("code")) {
+ statusCode = statusObject.getInt("code");
+ statusDescription = statusObject.getString("description");
+ logger.info("│ ├── Status Code: " + statusCode);
+ logger.info("│ ├── Status Description: " + statusDescription);
+ }
+ }
+
+ } catch (Exception e) {
+ logger.severe("├── ⚠️ Error parsing JSON response: " + e.getMessage());
+ throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
+ "Error parsing JSON response: " + e.getMessage());
+ }
+
+ workitem.setItemValue("ksef.status.code", statusCode);
+ workitem.setItemValue("ksef.status.description", statusDescription);
+ return statusCode;
+
+ } catch (Exception e) {
+ logger.severe("├── ⚠️ Get Invoice status failed: " + e.getMessage());
+
+ throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
+ "Invoice upload failed: " + e.getMessage());
+ }
+ }
+
/**
* Encrypt invoice XML with the session encryption keys
*
diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAuthManager.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAuthManager.java
index 2922fd9..5e10a20 100644
--- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAuthManager.java
+++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/ksef/api/KSeFAuthManager.java
@@ -535,7 +535,7 @@ public class KSeFAuthManager {
/**
* waits some time..
*/
- private void waitSomeTime(long millis) {
+ public void waitSomeTime(long millis) {
logger.info("│ ├── waiting " + millis + "ms....");
try {
Thread.sleep(millis);
@@ -1105,7 +1105,7 @@ public class KSeFAuthManager {
logger.info("Response: " + response.body());
}
- sessionRefNumber = null;
+ // sessionRefNumber = null;
}
}
diff --git a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/api/KSeFAPIServiceTest.java b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/api/KSeFAPIServiceTest.java
index 364c801..fabe3e5 100644
--- a/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/api/KSeFAPIServiceTest.java
+++ b/office-alexander-logistics-app/src/test/java/com/alexanderlogistics/ksef/api/KSeFAPIServiceTest.java
@@ -63,7 +63,7 @@ public class KSeFAPIServiceTest {
workitem = createWorkitem();
// Execute upload
- referenceNumber = apiService.uploadInvoice(workitem, "example-invoice-01.xml");
+ apiService.uploadInvoice(workitem, "example-invoice-01.xml");
} catch (IOException | PluginException e) {
logger.info("⚠️ Upload failed: " + e.getMessage());
fail(e);
diff --git a/workflow/pl/rechnungsausgang-pl-1.1.0-versuche.bpmn b/workflow/pl/rechnungsausgang-pl-1.1.0-versuche.bpmn
new file mode 100644
index 0000000..dd45cd9
--- /dev/null
+++ b/workflow/pl/rechnungsausgang-pl-1.1.0-versuche.bpmn
@@ -0,0 +1,3413 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+$workflowstatus
+
+]]>
+
+
+ In case you have already made the payment, please disregard this notice. If you require any information regarding your account, please do not hesitate to contact us.
+Thank you for your cooperation.
+
+Kind regards
Alexander Global Logistics GmbH
+
+