diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 0468c30..c5212d6 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1951,3 +1951,53 @@ | 🔧 zmienione | 32 | | ➖ usunięte | 0 | + +# Changelog zmian - `## 3.0.20 (2026-03-17)`- `API: 2.2.1` + +## 1. ksef-client + +### 1.1 system +- **FilesUtil.java**: 🔧 dla metody `splitAndEncryptZipStream` zmiana parametru `cryptographyService` na interfejs + +### 1.2 api +- **DefaultKsefClient.java**: 🔧 do response z błędem dodano informacje z url i method, dodanie obsługi mapowań dla kodów http 401 i 403 dla formatu Problem Details `(application/problem+json)` +- **DefaultLighthouseKsefClient.java**: 🔧 do response z błędem dodano informacje z url i method + +### 1.3 client +- **Headers.java**: 🔧 dodanie pola `String APPLICATION_PROBLEM_JSON = "application/problem+json"` + +### 1.4 api.services +- **DefaultCryptographyService.java**: 🔧 dodanie metody `Exception getOfflineModeCause()` dającej informacje o powodzie przejścia w tryb offline + +### 1.5 api.client.interfaces +- **CryptographyService.java**: 🔧 zmiany zgodnie z implementacja w `DefaultCryptographyService.java` + +### 1.6 api.client.model +- **ApiException.java**: 🔧 dodanie pól `String url` i `String method`, zmiana na klasę abstrakcyjną +- **model/session/SchemaVersion.java**: 🔧 dodanie enuma `VERSION_1_1E("1-1E")` +- **UnauthorizedProblemDetails.java**: ➕ dodanie klasy +- **ForbiddenProblemDetails.java**: ➕ dodanie klasy +- **UnauthorizedApiException.java**: ➕ dodanie klasy, rozszerzającej `ApiException` +- **ForbiddenApiException.java**: ➕ dodanie klasy, rozszerzającej `ApiException` +- **KsefApiException.java**: ➕ dodanie klasy, rozszerzającej `ApiException` + +## 2. demo-web-app + +### 2.1 integrationTest +- **QrCodeOnlineIntegrationTest.java.java**: 🔧 drobne zmiany w asercji +- **RrInvoiceIntegrationTest.java.java**: 🔧 użycie nowej wersji schemy RR `SchemaVersion.VERSION_1_1E` +- **KsefTokenIntegrationTest.java.java**: 🔧 zmiany kosmetyczne w assercji +- **ExceptionsApiIntegrationTest.java.java**: ➕ dodanie scenariusza do obsługi kodów http 401 i 403 z API + +### 2.1.1 integrationTest.resources +- **invoice-template-fa-rr-1.xml**: 🔧 aktualizacja pod nową wersję schemy RR + +--- +## 3. Podsumowanie + +| Typ zmiany | Liczba plików | +|-------------|---------------| +| ➕ dodane | 6 | +| 🔧 zmienione | 12 | +| ➖ usunięte | 0 | + diff --git a/demo-web-app/build.gradle.kts b/demo-web-app/build.gradle.kts index 5967a13..3cb8466 100644 --- a/demo-web-app/build.gradle.kts +++ b/demo-web-app/build.gradle.kts @@ -8,7 +8,7 @@ plugins { } group = "pl.akmf.ksef" -version = "3.0.19" +version = "3.0.20" java { toolchain { diff --git a/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/ExceptionsApiIntegrationTest.java b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/ExceptionsApiIntegrationTest.java new file mode 100644 index 0000000..0303b94 --- /dev/null +++ b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/ExceptionsApiIntegrationTest.java @@ -0,0 +1,113 @@ +package pl.akmf.ksef.sdk; + +import jakarta.xml.bind.JAXBException; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import pl.akmf.ksef.sdk.api.builders.permission.entity.GrantEntityPermissionsRequestBuilder; +import pl.akmf.ksef.sdk.client.model.ApiException; +import pl.akmf.ksef.sdk.client.model.ForbiddenApiException; +import pl.akmf.ksef.sdk.client.model.ForbiddenProblemDetails; +import pl.akmf.ksef.sdk.client.model.UnauthorizedApiException; +import pl.akmf.ksef.sdk.client.model.UnauthorizedProblemDetails; +import pl.akmf.ksef.sdk.client.model.permission.OperationResponse; +import pl.akmf.ksef.sdk.client.model.permission.PermissionStatusInfo; +import pl.akmf.ksef.sdk.client.model.permission.entity.EntityPermission; +import pl.akmf.ksef.sdk.client.model.permission.entity.EntityPermissionType; +import pl.akmf.ksef.sdk.client.model.permission.entity.GrantEntityPermissionsRequest; +import pl.akmf.ksef.sdk.client.model.permission.entity.SubjectIdentifier; +import pl.akmf.ksef.sdk.configuration.BaseIntegrationTest; +import pl.akmf.ksef.sdk.util.IdentifierGeneratorUtils; + +import java.io.IOException; +import java.time.Duration; +import java.util.List; +import java.util.Map; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static pl.akmf.ksef.sdk.api.Url.GRANT_INVOICE_SUBJECT_PERMISSION; + +class ExceptionsApiIntegrationTest extends BaseIntegrationTest { + + @Test + void forbiddenTest() throws JAXBException, IOException, ApiException { + String contextNip = IdentifierGeneratorUtils.generateRandomNIP(); + String subjectNip = IdentifierGeneratorUtils.generateRandomNIP(); + String thirdNip = IdentifierGeneratorUtils.generateRandomNIP(); + String accessToken = authWithCustomNip(contextNip, contextNip).accessToken(); + + String grantReferenceNumber = grantPermission(subjectNip, accessToken); + + await().pollDelay(Duration.ZERO) + .atMost(30, SECONDS) + .pollInterval(2, SECONDS) + .until(() -> isOperationFinish(grantReferenceNumber, accessToken)); + + String accessTokenSubject = authWithCustomNip(contextNip, subjectNip).accessToken(); + + ApiException apiException = assertThrows(ApiException.class, () -> + grantPermission(thirdNip, accessTokenSubject)); + Assertions.assertEquals(403, apiException.getCode()); + Assertions.assertEquals("POST", apiException.getMethod()); + Assertions.assertTrue(apiException.getUrl().contains(GRANT_INVOICE_SUBJECT_PERMISSION.getUrl())); + ForbiddenApiException forbiddenApiException = (ForbiddenApiException) apiException; + Assertions.assertNotNull(forbiddenApiException); + ForbiddenProblemDetails forbiddenProblemDetails = forbiddenApiException.getForbiddenProblemDetails(); + Assertions.assertNotNull(forbiddenProblemDetails); + Assertions.assertEquals("Forbidden", forbiddenProblemDetails.getTitle()); + Assertions.assertEquals(403, forbiddenProblemDetails.getStatus()); + Assertions.assertEquals("missing-permissions", forbiddenProblemDetails.getReasonCode()); + Assertions.assertEquals("Brak wymaganych uprawnień do wykonania operacji w bieżącym kontekście.", forbiddenProblemDetails.getDetail()); + Assertions.assertNotNull(forbiddenProblemDetails.getInstance()); + Assertions.assertNotNull(forbiddenProblemDetails.getTraceId()); + Map security = forbiddenProblemDetails.getSecurity(); + Assertions.assertNotNull(security); + Assertions.assertTrue(security.get("requiredAnyOfPermissions").toString().contains("CredentialsManage")); + Assertions.assertTrue(security.get("presentPermissions").toString().contains("InvoiceRead")); + Assertions.assertTrue(security.get("presentPermissions").toString().contains("InvoiceWrite")); + } + + @Test + void unauthorizedTest() { + String subjectNip = IdentifierGeneratorUtils.generateRandomNIP(); + + ApiException apiException = assertThrows(ApiException.class, () -> + grantPermission(subjectNip, "invalidToken")); + Assertions.assertEquals(401, apiException.getCode()); + Assertions.assertEquals("POST", apiException.getMethod()); + Assertions.assertTrue(apiException.getUrl().contains(GRANT_INVOICE_SUBJECT_PERMISSION.getUrl())); + UnauthorizedApiException unauthorizedApiException = (UnauthorizedApiException) apiException; + Assertions.assertNotNull(unauthorizedApiException); + UnauthorizedProblemDetails unauthorizedProblemDetails = unauthorizedApiException.getUnauthorizedProblemDetails(); + Assertions.assertNotNull(unauthorizedProblemDetails); + Assertions.assertEquals("Unauthorized", unauthorizedProblemDetails.getTitle()); + Assertions.assertEquals(401, unauthorizedProblemDetails.getStatus()); + Assertions.assertEquals("Wymagane jest uwierzytelnienie.", unauthorizedProblemDetails.getDetail()); + Assertions.assertNotNull(unauthorizedProblemDetails.getInstance()); + Assertions.assertNotNull(unauthorizedProblemDetails.getTraceId()); + } + + private Boolean isOperationFinish(String referenceNumber, String accessToken) throws ApiException { + PermissionStatusInfo operations = ksefClient.permissionOperationStatus(referenceNumber, accessToken); + return operations != null && operations.getStatus().getCode() == 200; + } + + private String grantPermission(String targetNip, String accessToken) throws ApiException { + GrantEntityPermissionsRequest request = new GrantEntityPermissionsRequestBuilder() + .withPermissions(List.of( + new EntityPermission(EntityPermissionType.INVOICE_READ, true), + new EntityPermission(EntityPermissionType.INVOICE_WRITE, false))) + .withDescription("description") + .withSubjectIdentifier(new SubjectIdentifier(SubjectIdentifier.IdentifierType.NIP, targetNip)) + .withSubjectDetails( + new GrantEntityPermissionsRequest.PermissionsEntitySubjectDetails("Testowo") + ) + .build(); + + OperationResponse response = ksefClient.grantsPermissionEntity(request, accessToken); + Assertions.assertNotNull(response); + + return response.getReferenceNumber(); + } +} \ No newline at end of file diff --git a/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/KsefTokenIntegrationTest.java b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/KsefTokenIntegrationTest.java index d2fa2b8..8602dc4 100644 --- a/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/KsefTokenIntegrationTest.java +++ b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/KsefTokenIntegrationTest.java @@ -65,14 +65,13 @@ void checkGenerateTokenTest() throws IOException, ApiException, JAXBException { Assertions.assertNotNull(token.getToken()); Assertions.assertNotNull(token.getReferenceNumber()); - // step 2: wait for token to become ACTIVE + // step 2: wait for tokens to become ACTIVE Awaitility.await().pollDelay(Duration.ZERO) .atMost(10, SECONDS) .pollInterval(1, SECONDS) - .until(() -> { - AuthenticationToken ksefToken = ksefClient.getKsefToken(token.getReferenceNumber(), accessToken); - return ksefToken != null && ksefToken.getStatus() == AuthenticationTokenStatus.ACTIVE; - }); + .until(() -> isActiveToken(token, accessToken) + && isActiveToken(token2, accessToken) + && isActiveToken(token3, accessToken)); AuthenticationToken ksefToken = ksefClient.getKsefToken(token.getReferenceNumber(), accessToken); Assertions.assertNotNull(ksefToken); @@ -150,4 +149,9 @@ private Boolean isAuthStatusReady(String referenceNumber, String tempToken) thro AuthStatus authStatus = ksefClient.getAuthStatus(referenceNumber, tempToken); return authStatus != null && authStatus.getStatus().getCode() == 200; } + + private Boolean isActiveToken(GenerateTokenResponse token, String accessToken) throws ApiException { + AuthenticationToken ksefToken = ksefClient.getKsefToken(token.getReferenceNumber(), accessToken); + return ksefToken != null && ksefToken.getStatus() == AuthenticationTokenStatus.ACTIVE; + } } diff --git a/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/QrCodeOnlineIntegrationTest.java b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/QrCodeOnlineIntegrationTest.java index cc7a896..bd201ac 100644 --- a/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/QrCodeOnlineIntegrationTest.java +++ b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/QrCodeOnlineIntegrationTest.java @@ -78,7 +78,7 @@ public void qrCodeOnlineE2ETest() throws JAXBException, IOException, ApiExceptio .pollInterval(2, SECONDS) .until(() -> isInvoicesInSessionAdded(sessionReferenceNumber, accessToken)); - checkOnlineSessionStatus(sessionReferenceNumber, 100, accessToken); + Assertions.assertTrue(checkOnlineSessionStatus(sessionReferenceNumber, 100, accessToken)); //Zamknięcie sesji online closeOnlineSession(sessionReferenceNumber, accessToken); @@ -186,8 +186,7 @@ private boolean isInvoicesInSessionAdded(String sessionReferenceNumber, String a private boolean checkOnlineSessionStatus(String sessionReferenceNumber, int expectedSessionStatus, String accessToken) throws ApiException { SessionStatusResponse statusResponse = getSessionStatusResponse(sessionReferenceNumber, accessToken); Assertions.assertNotNull(statusResponse); - Assertions.assertEquals(expectedSessionStatus, (int) statusResponse.getStatus().getCode()); - return true; + return expectedSessionStatus == statusResponse.getStatus().getCode(); } private SessionStatusResponse getSessionStatusResponse(String sessionReferenceNumber, String accessToken) throws ApiException { diff --git a/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/RrInvoiceIntegrationTest.java b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/RrInvoiceIntegrationTest.java index 932287c..f910540 100644 --- a/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/RrInvoiceIntegrationTest.java +++ b/demo-web-app/src/integrationTest/java/pl/akmf/ksef/sdk/RrInvoiceIntegrationTest.java @@ -105,7 +105,7 @@ void sendingFaRrInvoiceWithGrantPermission() throws JAXBException, IOException, encryptionData = defaultCryptographyService.getEncryptionData(); // Otwarcie sesji online z kodem systemu FA_RR - String sessionReferenceNumber = openOnlineSession(encryptionData, SystemCode.FA_RR, SchemaVersion.VERSION_1_0E, SessionValue.RR, authorizedAccessToken); + String sessionReferenceNumber = openOnlineSession(encryptionData, SystemCode.FA_RR, SchemaVersion.VERSION_1_1E, SessionValue.RR, authorizedAccessToken); // Wysłanie faktury FA-RR sendRrInvoice(sessionReferenceNumber, encryptionData, grantorNip, authorizedNip, templateFileName, authorizedAccessToken); diff --git a/demo-web-app/src/integrationTest/resources/xml/invoices/sample/invoice-template-fa-rr-1.xml b/demo-web-app/src/integrationTest/resources/xml/invoices/sample/invoice-template-fa-rr-1.xml index 66b0d30..1a4df22 100644 --- a/demo-web-app/src/integrationTest/resources/xml/invoices/sample/invoice-template-fa-rr-1.xml +++ b/demo-web-app/src/integrationTest/resources/xml/invoices/sample/invoice-template-fa-rr-1.xml @@ -1,8 +1,8 @@ + xmlns="http://crd.gov.pl/wzor/2026/03/06/14189/"> - FA_RR + FA_RR 1 2026-02-23T10:37:00Z SamploFaktur diff --git a/ksef-client/build.gradle.kts b/ksef-client/build.gradle.kts index 9dab125..d3d910b 100644 --- a/ksef-client/build.gradle.kts +++ b/ksef-client/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } -val appVersion = "3.0.19" +val appVersion = "3.0.20" val artifactName = "ksef-client" val githubRepositoryToken = "token" diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultKsefClient.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultKsefClient.java index 036f892..0dbe52f 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultKsefClient.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultKsefClient.java @@ -9,7 +9,12 @@ import pl.akmf.ksef.sdk.client.model.ApiException; import pl.akmf.ksef.sdk.client.model.ApiResponse; import pl.akmf.ksef.sdk.client.model.ExceptionResponse; +import pl.akmf.ksef.sdk.client.model.ForbiddenApiException; +import pl.akmf.ksef.sdk.client.model.ForbiddenProblemDetails; +import pl.akmf.ksef.sdk.client.model.KsefApiException; import pl.akmf.ksef.sdk.client.model.TooManyRequestsResponse; +import pl.akmf.ksef.sdk.client.model.UnauthorizedApiException; +import pl.akmf.ksef.sdk.client.model.UnauthorizedProblemDetails; import pl.akmf.ksef.sdk.client.model.UpoVersion; import pl.akmf.ksef.sdk.client.model.auth.AuthKsefTokenRequest; import pl.akmf.ksef.sdk.client.model.auth.AuthOperationStatusResponse; @@ -114,6 +119,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import static pl.akmf.ksef.sdk.api.HttpStatus.ACCEPTED; import static pl.akmf.ksef.sdk.api.HttpStatus.CREATED; @@ -203,6 +209,7 @@ import static pl.akmf.ksef.sdk.api.Url.TOKEN_STATUS; import static pl.akmf.ksef.sdk.client.Headers.ACCEPT; import static pl.akmf.ksef.sdk.client.Headers.APPLICATION_JSON; +import static pl.akmf.ksef.sdk.client.Headers.APPLICATION_PROBLEM_JSON; import static pl.akmf.ksef.sdk.client.Headers.APPLICATION_XML; import static pl.akmf.ksef.sdk.client.Headers.AUTHORIZATION; import static pl.akmf.ksef.sdk.client.Headers.BEARER; @@ -335,7 +342,7 @@ public OpenBatchSessionResponse openBatchSession(OpenBatchSessionRequest openBat @Override public void closeBatchSession(String referenceNumber, String accessToken) throws ApiException { if (referenceNumber == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling closeBatchSession"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling closeBatchSession"); } String uri = buildUrlWithParams(BATCH_SESSION_CLOSE.getUrl(), new HashMap<>()) @@ -376,7 +383,7 @@ public void sendBatchParts(OpenBatchSessionResponse openBatchSessionResponse, Li } if (!errors.isEmpty()) { - throw new ApiException("Errors when sending parts:\n" + String.join("\n", errors)); + throw new KsefApiException("Errors when sending parts:\n" + String.join("\n", errors)); } } @@ -407,7 +414,7 @@ public void sendBatchPartsWithStream(OpenBatchSessionResponse openBatchSessionRe } if (!errors.isEmpty()) { - throw new ApiException("Errors when sending parts:\n" + String.join("\n", errors)); + throw new KsefApiException("Errors when sending parts:\n" + String.join("\n", errors)); } } @@ -443,7 +450,7 @@ public OpenOnlineSessionResponse openOnlineSession(OpenOnlineSessionRequest open @Override public void closeOnlineSession(String referenceNumber, String accessToken) throws ApiException { if (referenceNumber == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling apiV2SessionsOnlineReferenceNumberClosePost"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling apiV2SessionsOnlineReferenceNumberClosePost"); } String uri = buildUrlWithParams(SESSION_CLOSE.getUrl(), new HashMap<>()) @@ -470,7 +477,7 @@ public void closeOnlineSession(String referenceNumber, String accessToken) throw @Override public SendInvoiceResponse onlineSessionSendInvoice(String referenceNumber, SendInvoiceOnlineSessionRequest sendInvoiceOnlineSessionRequest, String accessToken) throws ApiException { if (referenceNumber == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling apiV2SessionsOnlineReferenceNumberClosePost"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling apiV2SessionsOnlineReferenceNumberClosePost"); } String uri = buildUrlWithParams(SESSION_INVOICE_SEND.getUrl(), new HashMap<>()) @@ -596,7 +603,7 @@ public CertificateListResponse getCertificateList(CertificateListRequest certifi @Override public void revokeCertificate(CertificateRevokeRequest certificateRevokeRequest, String certificateSerialNumber, String accessToken) throws ApiException { if (certificateSerialNumber == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'certificateSerialNumber' when calling revokeCertificate"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'certificateSerialNumber' when calling revokeCertificate"); } String uri = buildUrlWithParams(CERTIFICATE_REVOKE.getUrl(), new HashMap<>()) @@ -680,7 +687,7 @@ public SignatureResponse submitAuthTokenRequest(String signedXml, boolean verify @Override public SignatureResponse submitAuthTokenRequest(String signedXml, boolean verifyCertificateChain, boolean enforceXadesCompliance) throws ApiException { if (signedXml == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'body' when calling apiV2AuthTokenSignaturePost"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'body' when calling apiV2AuthTokenSignaturePost"); } HashMap params = new HashMap<>(); @@ -728,7 +735,7 @@ public SignatureResponse authenticateByKSeFToken(AuthKsefTokenRequest body) thro @Override public AuthStatus getAuthStatus(String referenceNumber, String authenticationToken) throws ApiException { if (referenceNumber == null) { - throw new ApiException(400, "Missing the required parameter 'tokenReferenceNumber' when calling apiV2AuthTokenTokenReferenceNumberGet"); + throw new KsefApiException(400, "Missing the required parameter 'tokenReferenceNumber' when calling apiV2AuthTokenTokenReferenceNumberGet"); } String uri = buildUrlWithParams(AUTH_TOKEN_STATUS.getUrl(), new HashMap<>()) @@ -907,7 +914,7 @@ public QueryEntityRolesResponse searchEntityInvoiceRoles(int pageOffset, int pag /** * Wyszukiwanie uprawnień do obsługi faktur w bieżącym kontekście. * - * @param request EntityPermissionsQueryRequest + * @param request EntityPermissionsQueryRequest * @param pageOffset * @param pageSize * @return QueryEntityPermissionsResponse @@ -1142,7 +1149,7 @@ public InitAsyncInvoicesQueryResponse initAsyncQueryInvoice(InvoiceExportRequest @Override public InvoiceExportStatus checkStatusAsyncQueryInvoice(String referenceNumber, String accessToken) throws ApiException { if (referenceNumber == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'operationReferenceNumber' when calling checkStatusAsyncQueryInvoice"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'operationReferenceNumber' when calling checkStatusAsyncQueryInvoice"); } String uri = buildUrlWithParams(INVOICE_EXPORT_STATUS.getUrl(), new HashMap<>()) @@ -1302,10 +1309,10 @@ public byte[] getSessionUpo(String referenceNumber, String upoReferenceNumber, String accessToken) throws ApiException { if (referenceNumber == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling getSessionUpo"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'referenceNumber' when calling getSessionUpo"); } if (upoReferenceNumber == null) { - throw new ApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'upoReferenceNumber' when calling getSessionUpo"); + throw new KsefApiException(HttpStatus.BAD_REQUEST.getCode(), "Missing the required parameter 'upoReferenceNumber' when calling getSessionUpo"); } String uri = buildUrlWithParams(SESSION_UPO.getUrl(), new HashMap<>()) @@ -2144,7 +2151,7 @@ public List retrievePublicKeyCertificate() throws ApiExcep response.body() == null ? null : objectMapper.readValue(response.body(), new TypeReference>() { })).getData(); } catch (IOException e) { - throw new ApiException(e); + throw new KsefApiException(e); } } @@ -2347,7 +2354,8 @@ protected HttpResponse sendHttpRequest(HttpRequest request, HttpResponse try { return apiClient.send(request, bodyHandler); } catch (IOException | InterruptedException e) { - throw new SystemKSeFSDKException(e.getMessage(), e); + throw new SystemKSeFSDKException(request.method() + " " + request.uri() + " " + + (e.getMessage() != null ? e.getMessage() : ""), e); } } @@ -2363,7 +2371,7 @@ private T getResponse(HttpResponse response, response.body() == null ? null : objectMapper.readValue(response.body(), classType)) .getData(); } catch (IOException e) { - throw new ApiException(e); + throw new KsefApiException(e); } } @@ -2372,30 +2380,50 @@ private void validResponse(HttpResponse response, Url operation) throws ApiException { try { if (!isValidResponse(response, expectedStatus)) { - ExceptionResponse exception = null; - - String contentType = response.headers() - .firstValue(CONTENT_TYPE) - .orElse("") - .toLowerCase(); - - String message = formatExceptionMessage(operation.getOperationId(), response.statusCode(), response.body()); - if (contentType.contains(APPLICATION_JSON)) { - try { - exception = response.body() == null ? null : - objectMapper.readValue(response.body(), ExceptionResponse.class); - if (HttpStatus.TOO_MANY_REQUESTS.getCode() == response.statusCode()) { - setErrorDetailsFor429Status(response.headers(), exception.getStatus()); - } - } catch (com.fasterxml.jackson.databind.DatabindException e) { - throw new ApiException(response.statusCode(), message, response.headers(), exception); - } - } - throw new ApiException(response.statusCode(), message, response.headers(), exception); + handleException(response, operation); } } catch (IOException e) { - throw new ApiException(e); + throw new KsefApiException(e); + } + } + + private void handleException(HttpResponse response, Url operation) throws IOException, ApiException { + ExceptionResponse exception = null; + String uri = response.uri().toString(); + String method = Optional.of(response) + .map(HttpResponse::request) + .map(HttpRequest::method) + .orElse(""); + + String contentType = response.headers() + .firstValue(CONTENT_TYPE) + .orElse("") + .toLowerCase(); + + String message = formatExceptionMessage(operation.getOperationId(), response.statusCode(), response.body()); + if (contentType.contains(APPLICATION_JSON) + || contentType.contains(APPLICATION_PROBLEM_JSON)) { + try { + if (HttpStatus.UNAUTHORIZED.getCode() == response.statusCode()) { + UnauthorizedProblemDetails unauthorizedProblemDetails = response.body() == null ? null : + objectMapper.readValue(response.body(), UnauthorizedProblemDetails.class); + throw new UnauthorizedApiException(response.statusCode(), uri, method, message, response.headers(), unauthorizedProblemDetails); + } + if (HttpStatus.FORBIDDEN.getCode() == response.statusCode()) { + ForbiddenProblemDetails forbiddenProblemDetails = response.body() == null ? null : + objectMapper.readValue(response.body(), ForbiddenProblemDetails.class); + throw new ForbiddenApiException(response.statusCode(), uri, method, message, response.headers(), forbiddenProblemDetails); + } + exception = response.body() == null ? null : + objectMapper.readValue(response.body(), ExceptionResponse.class); + if (HttpStatus.TOO_MANY_REQUESTS.getCode() == response.statusCode()) { + setErrorDetailsFor429Status(response.headers(), exception.getStatus()); + } + } catch (com.fasterxml.jackson.databind.DatabindException e) { + throw new KsefApiException(response.statusCode(), uri, method, message, response.headers(), exception); + } } + throw new KsefApiException(response.statusCode(), uri, method, message, response.headers(), exception); } private void setErrorDetailsFor429Status(HttpHeaders headers, TooManyRequestsResponse status) { diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultLighthouseKsefClient.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultLighthouseKsefClient.java index dd88a0f..05cc0bd 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultLighthouseKsefClient.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/DefaultLighthouseKsefClient.java @@ -5,6 +5,7 @@ import pl.akmf.ksef.sdk.client.model.ApiException; import pl.akmf.ksef.sdk.client.model.ApiResponse; import pl.akmf.ksef.sdk.client.model.ExceptionResponse; +import pl.akmf.ksef.sdk.client.model.KsefApiException; import pl.akmf.ksef.sdk.client.model.lighthouse.KsefMessagesResponse; import pl.akmf.ksef.sdk.client.model.lighthouse.KsefStatusResponse; import pl.akmf.ksef.sdk.system.SystemKSeFSDKException; @@ -17,6 +18,7 @@ import java.time.Duration; import java.util.HashMap; import java.util.Map; +import java.util.Optional; import static pl.akmf.ksef.sdk.api.HttpStatus.OK; import static pl.akmf.ksef.sdk.api.HttpUtils.formatExceptionMessage; @@ -87,7 +89,8 @@ private HttpResponse sendHttpRequest(HttpRequest request, HttpResponse.B try { return httpClient.send(request, bodyHandler); } catch (IOException | InterruptedException e) { - throw new SystemKSeFSDKException(e.getMessage(), e); + throw new SystemKSeFSDKException(request.method() + " " + request.uri() + " " + + (e.getMessage() != null ? e.getMessage() : ""), e); } } @@ -103,7 +106,7 @@ private T getResponse(HttpResponse response, response.body() == null ? null : objectMapper.readValue(response.body(), classType)) .getData(); } catch (IOException e) { - throw new ApiException(e); + throw new KsefApiException(e); } } @@ -113,6 +116,11 @@ private void validResponse(HttpResponse response, try { if (!isValidResponse(response, expectedStatus)) { ExceptionResponse exception = null; + String uri = response.uri().toString(); + String method = Optional.of(response) + .map(HttpResponse::request) + .map(HttpRequest::method) + .orElse(""); String contentType = response.headers() .firstValue(CONTENT_TYPE) @@ -124,10 +132,10 @@ private void validResponse(HttpResponse response, objectMapper.readValue(response.body(), ExceptionResponse.class); } String message = formatExceptionMessage(operation.getOperationId(), response.statusCode(), response.body()); - throw new ApiException(response.statusCode(), message, response.headers(), exception); + throw new KsefApiException(response.statusCode(), uri, method, message, response.headers(), exception); } } catch (IOException e) { - throw new ApiException(e); + throw new KsefApiException(e); } } } diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultCryptographyService.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultCryptographyService.java index b7a8099..0e6b49b 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultCryptographyService.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultCryptographyService.java @@ -103,6 +103,7 @@ public class DefaultCryptographyService implements CryptographyService { private final KSeFClient ksefClient; private String secureRandomAlgorithm = null; private KsefIntegrationMode ksefIntegrationMode = KsefIntegrationMode.OFFLINE; + private Exception offlineModeCause = null; public DefaultCryptographyService(KSeFClient ksefClient) throws SystemKSeFSDKException { this.ksefClient = ksefClient; @@ -465,8 +466,10 @@ public void initCryptographyService() { .map(c -> BEGIN_CERTIFICATE + c + END_CERTIFICATE) .orElse(null); ksefIntegrationMode = KsefIntegrationMode.ONLINE; + offlineModeCause = null; } catch (ApiException | SystemKSeFSDKException e) { ksefIntegrationMode = KsefIntegrationMode.OFFLINE; + offlineModeCause = e; log.error("Error with connection to KseF Api: {}", e.getMessage() + ". Library works in offline mode"); } } @@ -476,6 +479,11 @@ public KsefIntegrationMode getKsefIntegrationMode() { return ksefIntegrationMode; } + @Override + public Exception getOfflineModeCause() { + return offlineModeCause; + } + private byte[] encryptWithRSAUsingPublicKey(byte[] content, PublicKey publicKey) throws SystemKSeFSDKException { try { OAEPParameterSpec oaepParams = new OAEPParameterSpec( diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultQrCodeService.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultQrCodeService.java index b0d3fa2..885b183 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultQrCodeService.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/api/services/DefaultQrCodeService.java @@ -7,6 +7,7 @@ import com.google.zxing.qrcode.QRCodeWriter; import pl.akmf.ksef.sdk.client.interfaces.QrCodeService; import pl.akmf.ksef.sdk.client.model.ApiException; +import pl.akmf.ksef.sdk.client.model.KsefApiException; import javax.imageio.ImageIO; import java.awt.*; @@ -76,7 +77,7 @@ private static BufferedImage getBufferedImage(InputStream is) throws ApiExceptio try { return ImageIO.read(is); } catch (IOException e) { - throw new ApiException(e.getMessage()); + throw new KsefApiException(e.getMessage()); } } @@ -111,7 +112,7 @@ private static BitMatrix createBitMatrix(String payloadUrl, QRCodeWriter qrCodeW try { return qrCodeWriter.encode(payloadUrl, BarcodeFormat.QR_CODE, 0, 0, hints); } catch (WriterException e) { - throw new ApiException(e.getMessage()); + throw new KsefApiException(e.getMessage()); } } @@ -130,7 +131,7 @@ private byte[] toByteArray(BufferedImage image) throws ApiException { ImageIO.write(image, "png", baos); return baos.toByteArray(); } catch (IOException e) { - throw new ApiException(e.getMessage()); + throw new KsefApiException(e.getMessage()); } } } diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/Headers.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/Headers.java index ef97256..b508264 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/Headers.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/Headers.java @@ -13,6 +13,7 @@ private Headers() { public static final String ACCEPT = "Accept"; public static final String OCTET_STREAM = "application/octet-stream"; public static final String APPLICATION_JSON = "application/json"; + public static final String APPLICATION_PROBLEM_JSON = "application/problem+json"; public static final String APPLICATION_XML = "application/xml"; public static final String BEARER = "Bearer "; public static final String X_KSEF_FEATURE = "X-KSeF-Feature"; diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/interfaces/CryptographyService.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/interfaces/CryptographyService.java index c15146e..22eed98 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/interfaces/CryptographyService.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/interfaces/CryptographyService.java @@ -7,14 +7,8 @@ import pl.akmf.ksef.sdk.system.KsefIntegrationMode; import pl.akmf.ksef.sdk.system.SystemKSeFSDKException; -import javax.crypto.BadPaddingException; -import javax.crypto.IllegalBlockSizeException; -import javax.crypto.NoSuchPaddingException; import java.io.InputStream; import java.io.OutputStream; -import java.security.InvalidAlgorithmParameterException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.PublicKey; import java.security.cert.CertificateException; @@ -208,8 +202,11 @@ public interface CryptographyService { * Możliwe jest wtedy ponowne wywyłanie usługi initCryptographyService() w celu próby inicjalizacji serwisu *

* Zwraca status serwisu (w razie nieudanego pobrania certyfikatów podczas inicjowania serwisu jest ustawiony na OFFLINE) - * - * @throws SystemKSeFSDKException */ KsefIntegrationMode getKsefIntegrationMode(); + + /** + * Zwraca powód przejścia w tryb OFFLINE + */ + Exception getOfflineModeCause(); } diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ApiException.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ApiException.java index d743e05..a377640 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ApiException.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ApiException.java @@ -3,14 +3,18 @@ import java.net.http.HttpHeaders; import java.util.stream.Collectors; -public class ApiException extends Exception { +public abstract class ApiException extends Exception { private final int code; + private final String url; + private final String method; private final transient HttpHeaders responseHeaders; private final transient ExceptionResponse exceptionResponse; public ApiException(int code, String message) { super(message); this.code = code; + this.url = ""; + this.method = ""; this.responseHeaders = null; this.exceptionResponse = null; } @@ -18,6 +22,8 @@ public ApiException(int code, String message) { public ApiException(Throwable throwable) { super(throwable); this.code = 0; + this.url = ""; + this.method = ""; this.responseHeaders = null; this.exceptionResponse = null; } @@ -25,6 +31,8 @@ public ApiException(Throwable throwable) { public ApiException(String message) { super(message); this.code = 0; + this.url = ""; + this.method = ""; this.responseHeaders = null; this.exceptionResponse = null; } @@ -32,6 +40,17 @@ public ApiException(String message) { public ApiException(int code, String message, HttpHeaders responseHeaders, ExceptionResponse exceptionResponse) { super(message); this.code = code; + this.url = ""; + this.method = ""; + this.exceptionResponse = exceptionResponse; + this.responseHeaders = responseHeaders; + } + + public ApiException(int code, String url, String method, String message, HttpHeaders responseHeaders, ExceptionResponse exceptionResponse) { + super(message); + this.code = code; + this.url = url; + this.method = method; this.exceptionResponse = exceptionResponse; this.responseHeaders = responseHeaders; } @@ -40,6 +59,14 @@ public int getCode() { return code; } + public String getUrl() { + return url; + } + + public String getMethod() { + return method; + } + public ExceptionResponse getExceptionResponse() { return exceptionResponse; } @@ -50,15 +77,15 @@ public HttpHeaders getResponseHeaders() { @Override public String toString() { - return "ApiException{" + - "\ncode=" + code + + return "code=" + code + + "\nurl=" + url + + "\nmethod=" + method + ",\nresponseHeaders=" + (responseHeaders != null ? responseHeaders.map().entrySet().stream() .flatMap(entry -> entry.getValue().stream() .map(value -> "'" + entry.getKey() + ": " + value + "'")) .collect(Collectors.joining(", ")) : responseHeaders) + ",\n" + exceptionResponse + - ",\nmessage=" + getMessage() + - "\n}"; + ",\nmessage=" + getMessage(); } } diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ForbiddenApiException.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ForbiddenApiException.java new file mode 100644 index 0000000..073bb19 --- /dev/null +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ForbiddenApiException.java @@ -0,0 +1,45 @@ +package pl.akmf.ksef.sdk.client.model; + +import java.net.http.HttpHeaders; + +public class ForbiddenApiException extends ApiException { + + private final ForbiddenProblemDetails forbiddenProblemDetails; + + public ForbiddenApiException(int code, String message, ForbiddenProblemDetails forbiddenProblemDetails) { + super(code, message); + this.forbiddenProblemDetails = forbiddenProblemDetails; + } + + public ForbiddenApiException(Throwable throwable, ForbiddenProblemDetails forbiddenProblemDetails) { + super(throwable); + this.forbiddenProblemDetails = forbiddenProblemDetails; + } + + public ForbiddenApiException(String message, ForbiddenProblemDetails forbiddenProblemDetails) { + super(message); + this.forbiddenProblemDetails = forbiddenProblemDetails; + } + + public ForbiddenApiException(int code, String message, HttpHeaders responseHeaders, ForbiddenProblemDetails forbiddenProblemDetails) { + super(code, message, responseHeaders, null); + this.forbiddenProblemDetails = forbiddenProblemDetails; + } + + public ForbiddenApiException(int code, String url, String method, String message, HttpHeaders responseHeaders, ForbiddenProblemDetails forbiddenProblemDetails) { + super(code, url, method, message, responseHeaders, null); + this.forbiddenProblemDetails = forbiddenProblemDetails; + } + + public ForbiddenProblemDetails getForbiddenProblemDetails() { + return forbiddenProblemDetails; + } + + @Override + public String toString() { + return "ForbiddenApiException{" + + "forbiddenProblemDetails=" + forbiddenProblemDetails + + ", " + super.toString() + + '}'; + } +} diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ForbiddenProblemDetails.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ForbiddenProblemDetails.java new file mode 100644 index 0000000..f69ba01 --- /dev/null +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/ForbiddenProblemDetails.java @@ -0,0 +1,93 @@ +package pl.akmf.ksef.sdk.client.model; + +import java.util.Map; + +public class ForbiddenProblemDetails { + private String title; + private int status; + private String detail; + private String instance; + private String reasonCode; + private Map security; + private String traceId; + + public ForbiddenProblemDetails() { + } + + public ForbiddenProblemDetails(String title, int status, String detail, String instance, String reasonCode, Map security, String traceId) { + this.title = title; + this.status = status; + this.detail = detail; + this.instance = instance; + this.reasonCode = reasonCode; + this.security = security; + this.traceId = traceId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getReasonCode() { + return reasonCode; + } + + public void setReasonCode(String reasonCode) { + this.reasonCode = reasonCode; + } + + public Map getSecurity() { + return security; + } + + public void setSecurity(Map security) { + this.security = security; + } + + public String getTraceId() { + return traceId; + } + + public void setTraceId(String traceId) { + this.traceId = traceId; + } + + @Override + public String toString() { + return "title=" + title + + ", status=" + status + + ", detail=" + detail + + ", instance=" + instance + + ", reasonCode=" + reasonCode + + ", security=" + security + + ", traceId=" + traceId; + } +} diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/KsefApiException.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/KsefApiException.java new file mode 100644 index 0000000..253fd09 --- /dev/null +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/KsefApiException.java @@ -0,0 +1,31 @@ +package pl.akmf.ksef.sdk.client.model; + +import java.net.http.HttpHeaders; + +public class KsefApiException extends ApiException { + + public KsefApiException(int code, String message) { + super(code, message); + } + + public KsefApiException(Throwable throwable) { + super(throwable); + } + + public KsefApiException(String message) { + super(message); + } + + public KsefApiException(int code, String message, HttpHeaders responseHeaders, ExceptionResponse exceptionResponse) { + super(code, message, responseHeaders, exceptionResponse); + } + + public KsefApiException(int code, String url, String method, String message, HttpHeaders responseHeaders, ExceptionResponse exceptionResponse) { + super(code, url, method, message, responseHeaders, exceptionResponse); + } + + @Override + public String toString() { + return "KsefApiException{" + super.toString() + "}"; + } +} diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/UnauthorizedApiException.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/UnauthorizedApiException.java new file mode 100644 index 0000000..477bfc1 --- /dev/null +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/UnauthorizedApiException.java @@ -0,0 +1,45 @@ +package pl.akmf.ksef.sdk.client.model; + +import java.net.http.HttpHeaders; + +public class UnauthorizedApiException extends ApiException { + + private final UnauthorizedProblemDetails unauthorizedProblemDetails; + + public UnauthorizedApiException(int code, String message, UnauthorizedProblemDetails unauthorizedProblemDetails) { + super(code, message); + this.unauthorizedProblemDetails = unauthorizedProblemDetails; + } + + public UnauthorizedApiException(Throwable throwable, UnauthorizedProblemDetails unauthorizedProblemDetails) { + super(throwable); + this.unauthorizedProblemDetails = unauthorizedProblemDetails; + } + + public UnauthorizedApiException(String message, UnauthorizedProblemDetails unauthorizedProblemDetails) { + super(message); + this.unauthorizedProblemDetails = unauthorizedProblemDetails; + } + + public UnauthorizedApiException(int code, String message, HttpHeaders responseHeaders, UnauthorizedProblemDetails unauthorizedProblemDetails) { + super(code, message, responseHeaders, null); + this.unauthorizedProblemDetails = unauthorizedProblemDetails; + } + + public UnauthorizedApiException(int code, String url, String method, String message, HttpHeaders responseHeaders, UnauthorizedProblemDetails unauthorizedProblemDetails) { + super(code, url, method, message, responseHeaders, null); + this.unauthorizedProblemDetails = unauthorizedProblemDetails; + } + + public UnauthorizedProblemDetails getUnauthorizedProblemDetails() { + return unauthorizedProblemDetails; + } + + @Override + public String toString() { + return "UnauthorizedApiException{" + + "unauthorizedProblemDetails=" + unauthorizedProblemDetails + + ", " + super.toString() + + '}'; + } +} diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/UnauthorizedProblemDetails.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/UnauthorizedProblemDetails.java new file mode 100644 index 0000000..c14deba --- /dev/null +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/UnauthorizedProblemDetails.java @@ -0,0 +1,71 @@ +package pl.akmf.ksef.sdk.client.model; + +public class UnauthorizedProblemDetails { + + private String title; + private int status; + private String detail; + private String instance; + private String traceId; + + public UnauthorizedProblemDetails() { + } + + public UnauthorizedProblemDetails(String title, int status, String detail, String instance, String traceId) { + this.title = title; + this.status = status; + this.detail = detail; + this.instance = instance; + this.traceId = traceId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public String getInstance() { + return instance; + } + + public void setInstance(String instance) { + this.instance = instance; + } + + public String getTraceId() { + return traceId; + } + + public void setTraceId(String traceId) { + this.traceId = traceId; + } + + @Override + public String toString() { + return "{title=" + title + + ", status=" + status + + ", detail=" + detail + + ", instance=" + instance + + ", traceId=" + traceId + + "}"; + } +} diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/session/SchemaVersion.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/session/SchemaVersion.java index 287f794..d0daa99 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/session/SchemaVersion.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/client/model/session/SchemaVersion.java @@ -5,6 +5,7 @@ public enum SchemaVersion { VERSION_1_0E("1-0E"), + VERSION_1_1E("1-1E"), VERSION_2_1("2-1"); private final String value; diff --git a/ksef-client/src/main/java/pl/akmf/ksef/sdk/system/FilesUtil.java b/ksef-client/src/main/java/pl/akmf/ksef/sdk/system/FilesUtil.java index 65ca6f1..f24b989 100644 --- a/ksef-client/src/main/java/pl/akmf/ksef/sdk/system/FilesUtil.java +++ b/ksef-client/src/main/java/pl/akmf/ksef/sdk/system/FilesUtil.java @@ -1,7 +1,7 @@ package pl.akmf.ksef.sdk.system; import org.apache.commons.lang3.function.TriFunction; -import pl.akmf.ksef.sdk.api.services.DefaultCryptographyService; +import pl.akmf.ksef.sdk.client.interfaces.CryptographyService; import pl.akmf.ksef.sdk.client.model.invoice.InvoicePackagePart; import pl.akmf.ksef.sdk.client.model.session.EncryptionData; import pl.akmf.ksef.sdk.client.model.session.FileMetadata; @@ -48,7 +48,7 @@ public static List splitAndEncryptZipStream( int zipLength, byte[] cipherKey, byte[] cipherIv, - DefaultCryptographyService cryptographyService) throws IOException { + CryptographyService cryptographyService) throws IOException { List encryptedStreamParts = new ArrayList<>(); // Split ZIP into ${invoicesPartCount} parts