new impl authManager
This commit is contained in:
parent
6c4e72fe82
commit
1f2d3b4cd5
5 changed files with 216 additions and 76 deletions
|
|
@ -67,6 +67,7 @@ public class KSeFAPIService {
|
||||||
|
|
||||||
// First open an interactive session (reuses existing if valid)
|
// First open an interactive session (reuses existing if valid)
|
||||||
kseFAuthManager.openSession();
|
kseFAuthManager.openSession();
|
||||||
|
|
||||||
logger.info("├── 📤 Upload Invoice...");
|
logger.info("├── 📤 Upload Invoice...");
|
||||||
|
|
||||||
// Validate session
|
// Validate session
|
||||||
|
|
@ -177,8 +178,10 @@ public class KSeFAPIService {
|
||||||
throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
|
throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
|
||||||
"Invoice upload failed: " + e.getMessage());
|
"Invoice upload failed: " + e.getMessage());
|
||||||
} finally {
|
} finally {
|
||||||
kseFAuthManager.closeSession();
|
|
||||||
kseFAuthManager.deleteCurrentSession();
|
// finally we close the session
|
||||||
|
kseFAuthManager.closeInteractiveSession();
|
||||||
|
kseFAuthManager.deleteCurrentAuthSession();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -185,12 +185,15 @@ public class KSeFAuthManager {
|
||||||
public void openSession() throws PluginException {
|
public void openSession() throws PluginException {
|
||||||
logger.info("├── open Session...");
|
logger.info("├── open Session...");
|
||||||
if (!hasValidSession()) {
|
if (!hasValidSession()) {
|
||||||
|
|
||||||
|
// first we make sure that we do not have any old sessions!
|
||||||
|
// this.deleteAllAuthSessions();
|
||||||
|
|
||||||
logger.info("│ ├── open new interactive KSeF Session...");
|
logger.info("│ ├── open new interactive KSeF Session...");
|
||||||
// open new session
|
// open new session
|
||||||
this.loadPublicKeyCertificates();
|
this.loadPublicKeyCertificates();
|
||||||
this.authChallenge();
|
this.authChallenge();
|
||||||
this.authKSeFToken();
|
this.authKSeFToken();
|
||||||
// this.waitSomeTime(3000);
|
|
||||||
|
|
||||||
// Jetzt Status abwarten
|
// Jetzt Status abwarten
|
||||||
this.waitForAuthStatus();
|
this.waitForAuthStatus();
|
||||||
|
|
@ -199,10 +202,8 @@ public class KSeFAuthManager {
|
||||||
this.redeemToken();
|
this.redeemToken();
|
||||||
|
|
||||||
this.openInteractiveSession();
|
this.openInteractiveSession();
|
||||||
// Delete deprecated sessions
|
|
||||||
this.deleteDeprecatedSessions();
|
|
||||||
|
|
||||||
this.checkTokenStatus();
|
this.waitForSessionStatus();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.warning("│ ├── ! Session already exists - reuse existing KSeF Session...");
|
logger.warning("│ ├── ! Session already exists - reuse existing KSeF Session...");
|
||||||
|
|
@ -461,7 +462,8 @@ public class KSeFAuthManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wartet auf den Korrekten Auth Status...
|
* Waits for the auth status code 200 after a new authentication process was
|
||||||
|
* initiated
|
||||||
*
|
*
|
||||||
* @throws PluginException
|
* @throws PluginException
|
||||||
*/
|
*/
|
||||||
|
|
@ -473,11 +475,11 @@ public class KSeFAuthManager {
|
||||||
long timeout = 10_000; // 10 Sekunden
|
long timeout = 10_000; // 10 Sekunden
|
||||||
|
|
||||||
while (System.currentTimeMillis() - start < timeout) {
|
while (System.currentTimeMillis() - start < timeout) {
|
||||||
if (this.checkTokenStatus() == 200) {
|
if (this.checkAuthStatus() >= 200) {
|
||||||
break; // Erfolg
|
break; // ok or borken
|
||||||
}
|
}
|
||||||
// kleine Pause, um CPU zu schonen
|
// kleine Pause, um CPU zu schonen
|
||||||
waitSomeTime(200);
|
waitSomeTime(500);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -488,6 +490,48 @@ public class KSeFAuthManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits for the session status code 200 after a new interactive session was
|
||||||
|
* initiated
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
public void waitForSessionStatus() throws PluginException {
|
||||||
|
logger.info("├── 🔜 Waiting for Session status 200...");
|
||||||
|
|
||||||
|
// Now we need to wait until auth/{AuthRef} will return 200
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
long timeout = 120_000; // 120 Sekunden
|
||||||
|
|
||||||
|
while (System.currentTimeMillis() - start < timeout) {
|
||||||
|
int status = this.checkSessionStatus();
|
||||||
|
|
||||||
|
// Status 100 = Session opened and ready for uploads!
|
||||||
|
if (status == 100 || status == 200) {
|
||||||
|
logger.info("│ └── ✓ Session is ready (status " + status + ")");
|
||||||
|
return; // Session is ready!
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error statuses (400+)
|
||||||
|
if (status >= 400) {
|
||||||
|
throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
|
||||||
|
"API Error - invalid session status: " + status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait and retry
|
||||||
|
waitSomeTime(500);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Optional: prüfen, ob Timeout erreicht wurde
|
||||||
|
if (System.currentTimeMillis() - start >= timeout) {
|
||||||
|
throw new PluginException(KSeFAuthManager.class.getSimpleName(), ERROR_API,
|
||||||
|
"API Error - failed to init new interactive session - ⚠️ Timeout reached after 120 seconds!");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* waits some time..
|
* waits some time..
|
||||||
*/
|
*/
|
||||||
|
|
@ -738,10 +782,10 @@ public class KSeFAuthManager {
|
||||||
*
|
*
|
||||||
* https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Uzyskiwanie-dostepu/paths/~1api~1v2~1auth~1%7BreferenceNumber%7D/get
|
* https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Uzyskiwanie-dostepu/paths/~1api~1v2~1auth~1%7BreferenceNumber%7D/get
|
||||||
*
|
*
|
||||||
* @return HTTP Response Code
|
* @return Auth Status Code
|
||||||
* @throws PluginException
|
* @throws PluginException
|
||||||
*/
|
*/
|
||||||
public int checkTokenStatus() throws PluginException {
|
public int checkAuthStatus() throws PluginException {
|
||||||
logger.info("├── ↩️ KSeF API check auth status...");
|
logger.info("├── ↩️ KSeF API check auth status...");
|
||||||
String uri = baseURI + "/auth/" + authRefNumber;
|
String uri = baseURI + "/auth/" + authRefNumber;
|
||||||
int httpResponse = -1;
|
int httpResponse = -1;
|
||||||
|
|
@ -808,19 +852,77 @@ public class KSeFAuthManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method returns all active sessions
|
* This method verifies the actual status of the status of an interactive
|
||||||
|
* session
|
||||||
|
*
|
||||||
|
* The method returns the aut status code (not the HTTP Response code!)
|
||||||
|
*
|
||||||
|
* https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Status-wysylki-i-UPO/paths/~1api~1v2~1sessions~1%7BreferenceNumber%7D/get
|
||||||
|
*
|
||||||
|
* @return Session Status Code
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
public int checkSessionStatus() throws PluginException {
|
||||||
|
logger.info("├── ↩️ KSeF API check session status...");
|
||||||
|
String uri = baseURI + "/sessions/" + this.sessionRefNumber;
|
||||||
|
int httpResponse = -1;
|
||||||
|
int statusCode = -1;
|
||||||
|
logger.info("│ ├── GET: " + uri);
|
||||||
|
HttpResponse<String> response = null;
|
||||||
|
try {
|
||||||
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(uri))
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.header("Authorization", "Bearer " + this.accessToken)
|
||||||
|
.GET()
|
||||||
|
.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());
|
||||||
|
}
|
||||||
|
|
||||||
|
httpResponse = response.statusCode();
|
||||||
|
logger.info("│ ├── HTTP Response: " + httpResponse);
|
||||||
|
|
||||||
|
logger.info("│ ├── " + response.body());
|
||||||
|
|
||||||
|
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");
|
||||||
|
logger.info("│ ├── Status Code: " + statusCode);
|
||||||
|
logger.info("│ ├── Status Description: " + statusObject.getString("description"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} 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());
|
||||||
|
}
|
||||||
|
|
||||||
|
return statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns all active auth sessions
|
||||||
*
|
*
|
||||||
* https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Aktywne-sesje/paths/~1api~1v2~1auth~1sessions/get
|
* https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Aktywne-sesje/paths/~1api~1v2~1auth~1sessions/get
|
||||||
*
|
*
|
||||||
* @throws PluginException
|
* @throws PluginException
|
||||||
*/
|
*/
|
||||||
public JsonObject getActiveSessions() throws PluginException {
|
public JsonObject getActiveAuthSessions() throws PluginException {
|
||||||
logger.info("├── 🚸 KSeF API active sessions...");
|
logger.info("├── 🚸 KSeF API active sessions...");
|
||||||
String uri = baseURI + "/auth/sessions";
|
String uri = baseURI + "/auth/sessions";
|
||||||
|
|
||||||
if (debug) {
|
|
||||||
logger.info("│ ├── GET: " + uri);
|
logger.info("│ ├── GET: " + uri);
|
||||||
}
|
|
||||||
HttpResponse<String> response = null;
|
HttpResponse<String> response = null;
|
||||||
try {
|
try {
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
|
|
@ -838,7 +940,7 @@ public class KSeFAuthManager {
|
||||||
|
|
||||||
if (true) {
|
if (true) {
|
||||||
logger.info("│ ├── HTTP Response: " + response.statusCode());
|
logger.info("│ ├── HTTP Response: " + response.statusCode());
|
||||||
// logger.info("Response: " + response.body());
|
logger.info("│ ├── Response: " + response.body());
|
||||||
}
|
}
|
||||||
try (Jsonb jsonb = JsonbBuilder.create()) {
|
try (Jsonb jsonb = JsonbBuilder.create()) {
|
||||||
JsonObject jsonObject = jsonb.fromJson(response.body(), JsonObject.class);
|
JsonObject jsonObject = jsonb.fromJson(response.body(), JsonObject.class);
|
||||||
|
|
@ -853,19 +955,52 @@ public class KSeFAuthManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all old sessions
|
* Deletes the current auth session (authRefNumber)
|
||||||
*
|
*
|
||||||
* The method first asks for old sessions and if we have more then 2 sessions we
|
* The method should be called wenn all operations are completed
|
||||||
* delete the deprecated ones.
|
|
||||||
*
|
*
|
||||||
* @param sessionData
|
* @param sessionData
|
||||||
* @throws PluginException
|
* @throws PluginException
|
||||||
*/
|
*/
|
||||||
public void deleteDeprecatedSessions() throws PluginException {
|
public void deleteCurrentAuthSession() throws PluginException {
|
||||||
|
|
||||||
|
// delete old sessions....
|
||||||
|
logger.info("├── 🚮 KSeF API delete current auth sessions...");
|
||||||
|
String uri = baseURI + "/auth/sessions/current";
|
||||||
|
|
||||||
|
HttpResponse<String> response = null;
|
||||||
|
try {
|
||||||
|
HttpRequest request = HttpRequest.newBuilder()
|
||||||
|
.uri(URI.create(uri))
|
||||||
|
.header("Accept", "application/json")
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.header("Authorization", "Bearer " + accessToken)
|
||||||
|
.DELETE()
|
||||||
|
.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());
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("│ ├── HTTP Response: " + response.statusCode());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all auth sessions
|
||||||
|
*
|
||||||
|
* The method should be called before openInteractiveSession() to make sure no
|
||||||
|
* old sessions are still active
|
||||||
|
*
|
||||||
|
* @param sessionData
|
||||||
|
* @throws PluginException
|
||||||
|
*/
|
||||||
|
public void deleteAllAuthSessions() throws PluginException {
|
||||||
int maxIterations = 10; // Sicherheits-Begrenzung
|
int maxIterations = 10; // Sicherheits-Begrenzung
|
||||||
|
|
||||||
for (int iteration = 0; iteration < maxIterations; iteration++) {
|
for (int iteration = 0; iteration < maxIterations; iteration++) {
|
||||||
JsonObject currentSessions = this.getActiveSessions();
|
JsonObject currentSessions = this.getActiveAuthSessions();
|
||||||
|
|
||||||
// Get list of refNumbers
|
// Get list of refNumbers
|
||||||
List<String> referenceNumbers = new ArrayList<>();
|
List<String> referenceNumbers = new ArrayList<>();
|
||||||
|
|
@ -877,21 +1012,15 @@ public class KSeFAuthManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wenn nur noch eine Session da ist, abbrechen
|
// Wenn nur noch eine Session da ist, abbrechen
|
||||||
if (referenceNumbers.size() <= 1) {
|
if (referenceNumbers.size() == 0) {
|
||||||
if (iteration == 0) {
|
logger.info("├── 🎉 No deprecated sessions found");
|
||||||
logger.info("│ ├── Only one session found, no deprecated sessions");
|
|
||||||
} else {
|
|
||||||
logger.info("├── 🎉 All deprecated sessions deleted after " + iteration + " iterations");
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete old sessions....
|
// delete old sessions....
|
||||||
logger.info("├── 🚮 KSeF API delete deprecated sessions (iteration " + (iteration + 1) + ")...");
|
logger.info("├── 🚮 KSeF API delete deprecated sessions...");
|
||||||
String uri = baseURI + "/auth/sessions/";
|
String uri = baseURI + "/auth/sessions/";
|
||||||
|
for (int i = 0; i < referenceNumbers.size(); i++) {
|
||||||
// Alle Einträge ab Index 1 (also ab dem zweiten Eintrag) durchgehen
|
|
||||||
for (int i = 1; i < referenceNumbers.size(); i++) {
|
|
||||||
String referenceNumber = referenceNumbers.get(i);
|
String referenceNumber = referenceNumbers.get(i);
|
||||||
logger.info("│ ├── delete deprecated session: " + referenceNumber);
|
logger.info("│ ├── delete deprecated session: " + referenceNumber);
|
||||||
|
|
||||||
|
|
@ -913,7 +1042,7 @@ public class KSeFAuthManager {
|
||||||
logger.info("│ ├── HTTP Response: " + response.statusCode());
|
logger.info("│ ├── HTTP Response: " + response.statusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info("│ ├── Deleted " + (referenceNumbers.size() - 1) + " sessions in this iteration");
|
logger.info("│ ├── Deleted " + referenceNumbers.size() + " sessions in this iteration");
|
||||||
|
|
||||||
// Kurze Pause vor der nächsten Iteration
|
// Kurze Pause vor der nächsten Iteration
|
||||||
if (referenceNumbers.size() > 1 && iteration < maxIterations - 1) {
|
if (referenceNumbers.size() > 1 && iteration < maxIterations - 1) {
|
||||||
|
|
@ -934,34 +1063,6 @@ public class KSeFAuthManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes the current session
|
|
||||||
*
|
|
||||||
* @throws PluginException
|
|
||||||
*/
|
|
||||||
public void deleteCurrentSession() throws PluginException {
|
|
||||||
|
|
||||||
logger.info("├── 🚮 KSeF API delete current session...");
|
|
||||||
String uri = baseURI + "/auth/sessions/current";
|
|
||||||
|
|
||||||
HttpResponse<String> response = null;
|
|
||||||
try {
|
|
||||||
HttpRequest request = HttpRequest.newBuilder()
|
|
||||||
.uri(URI.create(uri))
|
|
||||||
.header("Accept", "application/json")
|
|
||||||
.header("Content-Type", "application/json")
|
|
||||||
.header("Authorization", "Bearer " + accessToken)
|
|
||||||
.DELETE()
|
|
||||||
.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());
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.info("│ ├── HTTP Response: " + response.statusCode());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method closes the current session
|
* This method closes the current session
|
||||||
*
|
*
|
||||||
|
|
@ -973,7 +1074,7 @@ public class KSeFAuthManager {
|
||||||
*
|
*
|
||||||
* @throws PluginException
|
* @throws PluginException
|
||||||
*/
|
*/
|
||||||
public void closeSession() throws PluginException {
|
public void closeInteractiveSession() throws PluginException {
|
||||||
logger.info("├── 📦 KSeF API close session...");
|
logger.info("├── 📦 KSeF API close session...");
|
||||||
// https://ksef-test.mf.gov.pl/api/v2/sessions/online/{referenceNumber}/close
|
// https://ksef-test.mf.gov.pl/api/v2/sessions/online/{referenceNumber}/close
|
||||||
String uri = baseURI + "/sessions/online/" + sessionRefNumber + "/close";
|
String uri = baseURI + "/sessions/online/" + sessionRefNumber + "/close";
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
package com.alexanderlogistics.ksef.api;
|
package com.alexanderlogistics.ksef.api;
|
||||||
|
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
import javax.crypto.BadPaddingException;
|
import javax.crypto.BadPaddingException;
|
||||||
|
|
@ -12,6 +14,8 @@ import javax.crypto.IllegalBlockSizeException;
|
||||||
import javax.crypto.KeyGenerator;
|
import javax.crypto.KeyGenerator;
|
||||||
import javax.crypto.NoSuchPaddingException;
|
import javax.crypto.NoSuchPaddingException;
|
||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
|
import javax.crypto.spec.OAEPParameterSpec;
|
||||||
|
import javax.crypto.spec.PSource;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -21,7 +25,8 @@ import javax.crypto.spec.SecretKeySpec;
|
||||||
public class KSeFEncryptionHelper {
|
public class KSeFEncryptionHelper {
|
||||||
|
|
||||||
private static final String AES_ALGORITHM = "AES";
|
private static final String AES_ALGORITHM = "AES";
|
||||||
private static final String RSA_TRANSFORMATION = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
|
private static final String xxxRSA_TRANSFORMATION = "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
|
||||||
|
private static final String RSA_TRANSFORMATION = "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
|
||||||
private static final int AES_KEY_SIZE = 256;
|
private static final int AES_KEY_SIZE = 256;
|
||||||
private static final int IV_SIZE = 16;
|
private static final int IV_SIZE = 16;
|
||||||
|
|
||||||
|
|
@ -61,6 +66,26 @@ public class KSeFEncryptionHelper {
|
||||||
* @throws BadPaddingException if padding is incorrect
|
* @throws BadPaddingException if padding is incorrect
|
||||||
*/
|
*/
|
||||||
public static String encryptAesKey(SecretKey aesKey, PublicKey ksefPublicKey)
|
public static String encryptAesKey(SecretKey aesKey, PublicKey ksefPublicKey)
|
||||||
|
throws NoSuchAlgorithmException, NoSuchPaddingException,
|
||||||
|
InvalidKeyException, IllegalBlockSizeException, BadPaddingException,
|
||||||
|
InvalidAlgorithmParameterException { // <- Exception hinzufügen!
|
||||||
|
|
||||||
|
Cipher rsaCipher = Cipher.getInstance(RSA_TRANSFORMATION);
|
||||||
|
|
||||||
|
// WICHTIG: Explizite OAEP-Parameter setzen (wie bei Token-Verschlüsselung!)
|
||||||
|
OAEPParameterSpec oaepParams = new OAEPParameterSpec(
|
||||||
|
"SHA-256",
|
||||||
|
"MGF1",
|
||||||
|
MGF1ParameterSpec.SHA256,
|
||||||
|
PSource.PSpecified.DEFAULT);
|
||||||
|
|
||||||
|
rsaCipher.init(Cipher.ENCRYPT_MODE, ksefPublicKey, oaepParams);
|
||||||
|
|
||||||
|
byte[] encryptedKey = rsaCipher.doFinal(aesKey.getEncoded());
|
||||||
|
return Base64.getEncoder().encodeToString(encryptedKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String OLDencryptAesKey(SecretKey aesKey, PublicKey ksefPublicKey)
|
||||||
throws NoSuchAlgorithmException, NoSuchPaddingException,
|
throws NoSuchAlgorithmException, NoSuchPaddingException,
|
||||||
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
||||||
|
|
||||||
|
|
@ -112,10 +137,11 @@ public class KSeFEncryptionHelper {
|
||||||
* @throws InvalidKeyException if the public key is invalid
|
* @throws InvalidKeyException if the public key is invalid
|
||||||
* @throws IllegalBlockSizeException if the key size is invalid
|
* @throws IllegalBlockSizeException if the key size is invalid
|
||||||
* @throws BadPaddingException if padding is incorrect
|
* @throws BadPaddingException if padding is incorrect
|
||||||
|
* @throws InvalidAlgorithmParameterException
|
||||||
*/
|
*/
|
||||||
public static SessionEncryption createSessionEncryption(PublicKey ksefPublicKey)
|
public static SessionEncryption createSessionEncryption(PublicKey ksefPublicKey)
|
||||||
throws NoSuchAlgorithmException, NoSuchPaddingException,
|
throws NoSuchAlgorithmException, NoSuchPaddingException,
|
||||||
InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
|
InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
|
||||||
|
|
||||||
// Generate AES key and IV
|
// Generate AES key and IV
|
||||||
SecretKey aesKey = generateAesKey();
|
SecretKey aesKey = generateAesKey();
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.alexanderlogistics.ksef.api;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
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.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
@ -12,6 +13,7 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
import org.imixs.workflow.FileData;
|
import org.imixs.workflow.FileData;
|
||||||
import org.imixs.workflow.ItemCollection;
|
import org.imixs.workflow.ItemCollection;
|
||||||
|
import org.imixs.workflow.exceptions.PluginException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.DisplayName;
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
@ -52,15 +54,20 @@ public class KSeFAPIServiceTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Upload Invoice XML (AES-256 + RSA)")
|
@DisplayName("Upload Invoice XML (AES-256 + RSA)")
|
||||||
public void testUploadInvoice() throws Exception {
|
public void testUploadInvoice() {
|
||||||
logger.info("==> Test: Upload Invoice XML");
|
logger.info("==> Test: Upload Invoice XML");
|
||||||
|
|
||||||
ItemCollection workitem = createWorkitem();
|
ItemCollection workitem = null;
|
||||||
|
String referenceNumber = null;
|
||||||
|
try {
|
||||||
|
workitem = createWorkitem();
|
||||||
|
|
||||||
// Execute upload
|
// Execute upload
|
||||||
|
referenceNumber = apiService.uploadInvoice(workitem, "example-invoice-01.xml");
|
||||||
String referenceNumber = apiService.uploadInvoice(workitem, "example-invoice-01.xml");
|
} catch (IOException | PluginException e) {
|
||||||
|
logger.info("⚠️ Upload failed: " + e.getMessage());
|
||||||
|
fail(e);
|
||||||
|
}
|
||||||
// Verify result
|
// Verify result
|
||||||
assertNotNull(referenceNumber, "Reference number should not be null");
|
assertNotNull(referenceNumber, "Reference number should not be null");
|
||||||
assertFalse(referenceNumber.isEmpty(), "Reference number should not be empty");
|
assertFalse(referenceNumber.isEmpty(), "Reference number should not be empty");
|
||||||
|
|
@ -70,6 +77,7 @@ public class KSeFAPIServiceTest {
|
||||||
FileData file = workitem.getFileData("example-invoice-01.xml");
|
FileData file = workitem.getFileData("example-invoice-01.xml");
|
||||||
ItemCollection fileAttributes = new ItemCollection(file.getAttributes());
|
ItemCollection fileAttributes = new ItemCollection(file.getAttributes());
|
||||||
assertEquals(referenceNumber, fileAttributes.getItemValueString("ksef.referenceNumber"));
|
assertEquals(referenceNumber, fileAttributes.getItemValueString("ksef.referenceNumber"));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ItemCollection createWorkitem() throws IOException {
|
private ItemCollection createWorkitem() throws IOException {
|
||||||
|
|
|
||||||
|
|
@ -90,6 +90,8 @@ public class KSeFAuthManagerTest {
|
||||||
|
|
||||||
manager.openInteractiveSession();
|
manager.openInteractiveSession();
|
||||||
|
|
||||||
|
manager.waitForSessionStatus();
|
||||||
|
|
||||||
assertNotNull(manager.getAccessToken(), "AccessToken fehlt");
|
assertNotNull(manager.getAccessToken(), "AccessToken fehlt");
|
||||||
// assertNotNull(manager.getRefNumber(), "ReferenceNumber fehlt");
|
// assertNotNull(manager.getRefNumber(), "ReferenceNumber fehlt");
|
||||||
assertNotNull(manager.getSessionRefNumber(), "SessionReferenceNumber fehlt");
|
assertNotNull(manager.getSessionRefNumber(), "SessionReferenceNumber fehlt");
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue