update
This commit is contained in:
parent
278880a6b0
commit
e76a8dc668
2 changed files with 117 additions and 1 deletions
|
|
@ -2,7 +2,6 @@ package com.alexanderlogistics.ksef;
|
||||||
|
|
||||||
public class Params {
|
public class Params {
|
||||||
public static final String TOKEN = "20251113-EC-2751AC3000-5C5466924B-62|nip-9552521552|fc0c95d020dc45d4af491fb0aa755f3f3f674b33ecbf4250a88ea6e36fa8340b";
|
public static final String TOKEN = "20251113-EC-2751AC3000-5C5466924B-62|nip-9552521552|fc0c95d020dc45d4af491fb0aa755f3f3f674b33ecbf4250a88ea6e36fa8340b";
|
||||||
public static final String TOKENx = "20251113-EC-2751AC3000-5C5466924B-62.nip-9552521552.fc0c95d020dc45d4af491fb0aa755f3f3f674b33ecbf4250a88ea6e36fa8340b";
|
|
||||||
public static final String NIP = "9552521552";
|
public static final String NIP = "9552521552";
|
||||||
|
|
||||||
public static String getEncodedToken() {
|
public static String getEncodedToken() {
|
||||||
|
|
@ -10,4 +9,5 @@ public class Params {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,27 @@
|
||||||
package com.alexanderlogistics.ksef;
|
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.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.KeyGenerator;
|
||||||
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
|
||||||
import org.imixs.workflow.exceptions.ModelException;
|
import org.imixs.workflow.exceptions.ModelException;
|
||||||
import org.imixs.workflow.exceptions.PluginException;
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
|
|
@ -44,6 +57,9 @@ public class TestKSeF {
|
||||||
|
|
||||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
private String refNumber = null;
|
||||||
|
private String authToken = null;
|
||||||
|
|
||||||
@BeforeAll
|
@BeforeAll
|
||||||
public static void setupClass() {
|
public static void setupClass() {
|
||||||
logger.info("=== KSeF 2.0 Client Test ===");
|
logger.info("=== KSeF 2.0 Client Test ===");
|
||||||
|
|
@ -119,6 +135,106 @@ public class TestKSeF {
|
||||||
// Prüfen, dass wir eine API-Antwort bekommen
|
// Prüfen, dass wir eine API-Antwort bekommen
|
||||||
assertTrue(response.statusCode() < 500, "API sollte antworten, Status < 500");
|
assertTrue(response.statusCode() < 500, "API sollte antworten, Status < 500");
|
||||||
assertFalse(response.body().contains("<html>"), "Response sollte keine HTML-Seite sein");
|
assertFalse(response.body().contains("<html>"), "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<String> 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");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Order(4)
|
||||||
|
@DisplayName("Rechnung übermitteln an KSeF 2.0 API")
|
||||||
|
public void testSendInvoice() throws Exception {
|
||||||
|
assertNotNull(refNumber, "ReferenceNumber nicht gesetzt");
|
||||||
|
|
||||||
|
// 1. Rechnung laden
|
||||||
|
Path invoicePath = Paths.get("test/resources/test-invoice.xml");
|
||||||
|
byte[] invoiceBytes = Files.readAllBytes(invoicePath);
|
||||||
|
int invoiceSize = invoiceBytes.length;
|
||||||
|
|
||||||
|
// 2. SHA-256 Hash der Originalrechnung
|
||||||
|
MessageDigest sha256 = MessageDigest.getInstance("SHA-256");
|
||||||
|
byte[] invoiceHashBytes = sha256.digest(invoiceBytes);
|
||||||
|
String invoiceHash = Base64.getEncoder().encodeToString(invoiceHashBytes);
|
||||||
|
|
||||||
|
// 3. AES-256 Schlüssel + IV generieren
|
||||||
|
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
|
||||||
|
keyGen.init(256);
|
||||||
|
SecretKey aesKey = keyGen.generateKey();
|
||||||
|
byte[] ivBytes = new byte[16];
|
||||||
|
new SecureRandom().nextBytes(ivBytes);
|
||||||
|
IvParameterSpec iv = new IvParameterSpec(ivBytes);
|
||||||
|
|
||||||
|
// 4. Rechnung verschlüsseln (AES-256-CBC + PKCS7Padding)
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, aesKey, iv);
|
||||||
|
byte[] encryptedInvoiceBytes = cipher.doFinal(invoiceBytes);
|
||||||
|
|
||||||
|
int encryptedInvoiceSize = encryptedInvoiceBytes.length;
|
||||||
|
byte[] encryptedInvoiceHashBytes = sha256.digest(encryptedInvoiceBytes);
|
||||||
|
String encryptedInvoiceHash = Base64.getEncoder().encodeToString(encryptedInvoiceHashBytes);
|
||||||
|
|
||||||
|
// 5. Verschlüsselten Inhalt Base64 codieren
|
||||||
|
String encryptedInvoiceContent = Base64.getEncoder().encodeToString(encryptedInvoiceBytes);
|
||||||
|
|
||||||
|
// 6. JSON-Payload erstellen
|
||||||
|
String jsonPayload = "{"
|
||||||
|
+ "\"invoiceHash\":\"" + invoiceHash + "\","
|
||||||
|
+ "\"invoiceSize\":" + invoiceSize + ","
|
||||||
|
+ "\"encryptedInvoiceHash\":\"" + encryptedInvoiceHash + "\","
|
||||||
|
+ "\"encryptedInvoiceSize\":" + encryptedInvoiceSize + ","
|
||||||
|
+ "\"encryptedInvoiceContent\":\"" + encryptedInvoiceContent + "\","
|
||||||
|
+ "\"offlineMode\":false"
|
||||||
|
+ "}";
|
||||||
|
|
||||||
|
// 7. HTTP POST Request an die API
|
||||||
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(KSEF_TEST_URL + "/sessions/online/" + refNumber + "/invoices"))
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.header("Authorization", "Bearer " + authToken) // Token aus Authentifizierung
|
||||||
|
.POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||||
|
|
||||||
|
System.out.println("Status: " + response.statusCode());
|
||||||
|
System.out.println("Response: " + response.body());
|
||||||
|
|
||||||
|
assertEquals(200, response.statusCode(), "Invoice Upload sollte Status 200 zurückgeben");
|
||||||
|
assertTrue(response.body().contains("invoiceId"), "Antwort sollte field invoiceId enthalten");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue