update
This commit is contained in:
parent
f61c7feca5
commit
c232841ed3
8 changed files with 3921 additions and 375 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ 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
|
||||
*
|
||||
|
|
@ -24,17 +25,23 @@ import jakarta.inject.Inject;
|
|||
<ksef name="EXPORT">
|
||||
<debug>true</debug>
|
||||
</ksef>
|
||||
|
||||
|
||||
<ksef name="STATUS">
|
||||
<debug>true</debug>
|
||||
</ksef>
|
||||
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @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<ItemCollection> ksefDefinitions = workflowService.evalWorkflowResultXML(event, "ksef",
|
||||
List<ItemCollection> ksefExportDefinitions = workflowService.evalWorkflowResultXML(event, "ksef",
|
||||
"EXPORT", workitem, false);
|
||||
if (ksefDefinitions != null && ksefDefinitions.size() > 0) {
|
||||
ItemCollection ksefDefinition = ksefDefinitions.get(0);
|
||||
// List<ItemCollection> ksefStatusDefinitions =
|
||||
// workflowService.evalWorkflowResultXML(event, "ksef",
|
||||
// "STATUS", workitem, false);
|
||||
|
||||
// EXPORT
|
||||
if (ksefExportDefinitions != null && ksefExportDefinitions.size() > 0) {
|
||||
ItemCollection ksefDefinition = ksefExportDefinitions.get(0);
|
||||
debug = ksefDefinition.getItemValueBoolean("debug");
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
|
||||
|
|
@ -40,11 +40,12 @@ import jakarta.inject.Inject;
|
|||
*
|
||||
* <pre>
|
||||
* {@code
|
||||
<e-invoice name="ksef">
|
||||
<ksef name="create">
|
||||
<textblock>textblock-ref</textblock>
|
||||
<template>filename</template>
|
||||
<debug>true</debug>
|
||||
</e-invoice>
|
||||
</ksef>
|
||||
|
||||
}
|
||||
* </pre>
|
||||
*
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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<String> 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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
3413
workflow/pl/rechnungsausgang-pl-1.1.0-versuche.bpmn
Normal file
3413
workflow/pl/rechnungsausgang-pl-1.1.0-versuche.bpmn
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue