From 10d08b06e90b4926e01f928f5326821739a08263 Mon Sep 17 00:00:00 2001 From: maciejdybowski Date: Tue, 26 Sep 2023 21:06:57 +0200 Subject: [PATCH 1/2] =?UTF-8?q?Dodanie=20do=20clienta=20obs=C5=82ugi=20end?= =?UTF-8?q?pointu=20do=20pobierania=20faktur=20bez=20uwierzytelniania=20-?= =?UTF-8?q?=20common/Invoice/KSeF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/InterfejsyInteraktywneFakturaApi.java | 12 +++++- .../model/rest/common/InvoiceRequest.java | 21 ++++++++++ .../rest/query/InvoiceQueryResponse.java | 4 ++ .../ksef/client/http/HttpApiClient.java | 19 +++++++++ .../ksef/client/okhttp/OkHttpApiClient.java | 30 ++++++++++++-- .../io/alapierre/ksef/client/ApiClient.java | 1 + .../java/io/alapierre/ksef/sample/Main.java | 39 +++++++++++++++++++ 7 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/common/InvoiceRequest.java diff --git a/ksef-api/src/main/java/io/alapierre/ksef/client/api/InterfejsyInteraktywneFakturaApi.java b/ksef-api/src/main/java/io/alapierre/ksef/client/api/InterfejsyInteraktywneFakturaApi.java index ffbf6f3..d4b9229 100644 --- a/ksef-api/src/main/java/io/alapierre/ksef/client/api/InterfejsyInteraktywneFakturaApi.java +++ b/ksef-api/src/main/java/io/alapierre/ksef/client/api/InterfejsyInteraktywneFakturaApi.java @@ -3,6 +3,7 @@ import io.alapierre.io.IOUtils; import io.alapierre.ksef.client.ApiClient; import io.alapierre.ksef.client.ApiException; +import io.alapierre.ksef.client.model.rest.common.*; import io.alapierre.ksef.client.model.rest.invoice.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -80,13 +81,22 @@ public void getInvoice(@NotNull String referenceNumber, @NotNull String token, @ apiClient.getStream(endpoint, token, os); } + + /** + * Pobranie faktury bez uwierzytelniania na podstawie parametrów podanych przez KSeF zgodnie ze specyfikacją endpoint'u + * common/Invoice/KSeF. Limit w sekwencji 2 użycia, czas odnowy 60 minut + */ + public void getInvoice(@NotNull InvoiceRequest invoiceRequest, @NotNull OutputStream os) throws ApiException { + val endpoint = "common/Invoice/KSeF"; + apiClient.postStream(endpoint, invoiceRequest, os); + } + /** * Pobiera UPO dla podanego numeru referencyjnego sesji interaktywnej lub wsadowej. Przekształca wynik zwracany * z API ze String na ciąg bajtów zakodowany w UTF-8. Jeśli UPO nie jest dostępne, pole UpoDTO.upo będzie miało * wartość null. * * @param referenceNumber numer referencyjny zakończonej sesji interaktywnej lub wsadowej - * * @return Odpowiedź z API z UPO w postaci ciągu bajtów (jeśli UPO jest dostępne) */ public UpoDTO getUpo(@NotNull String referenceNumber) throws ApiException { diff --git a/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/common/InvoiceRequest.java b/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/common/InvoiceRequest.java new file mode 100644 index 0000000..dc82350 --- /dev/null +++ b/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/common/InvoiceRequest.java @@ -0,0 +1,21 @@ +package io.alapierre.ksef.client.model.rest.common; + +import io.alapierre.ksef.client.model.rest.query.InvoiceQueryResponse; +import lombok.*; + +@Data +@Builder +public class InvoiceRequest { + private InvoiceDetails invoiceDetails; + private String ksefReferenceNumber; + + + @Data + @Builder + public static class InvoiceDetails { + private String dueValue; + private String invoiceOryginalNumber; + private InvoiceQueryResponse.SubjectTo subjectTo; + + } +} diff --git a/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java b/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java index 04a3bd8..ce184da 100644 --- a/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java +++ b/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java @@ -1,5 +1,6 @@ package io.alapierre.ksef.client.model.rest.query; +import lombok.AllArgsConstructor; import lombok.Data; import java.util.List; @@ -36,6 +37,7 @@ public static class InvoiceHeaderList{ } @Data + @AllArgsConstructor public static class SubjectTo{ private IssuedToIdentifier issuedToIdentifier; private IssuedToName issuedToName; @@ -43,6 +45,7 @@ public static class SubjectTo{ @Data + @AllArgsConstructor public static class IssuedToName{ private String type; private String tradeName; @@ -50,6 +53,7 @@ public static class IssuedToName{ } @Data + @AllArgsConstructor public static class IssuedToIdentifier{ private String type; private String identifier; diff --git a/ksef-client-jdk11-http-client/src/main/java/io/alapierre/ksef/client/http/HttpApiClient.java b/ksef-client-jdk11-http-client/src/main/java/io/alapierre/ksef/client/http/HttpApiClient.java index 7b822ba..2cff966 100644 --- a/ksef-client-jdk11-http-client/src/main/java/io/alapierre/ksef/client/http/HttpApiClient.java +++ b/ksef-client-jdk11-http-client/src/main/java/io/alapierre/ksef/client/http/HttpApiClient.java @@ -106,6 +106,25 @@ public void getStream(@NotNull String endpoint, @NotNull String token, @NotNull throw new IllegalStateException("Not implemented yet"); } + @Override + public void postStream(@NotNull String endpoint, @NotNull Object body, @NotNull OutputStream os) throws ApiException { + HttpRequest request = preparePostRequest(endpoint, Collections.emptyMap(), HttpRequest.BodyPublishers.ofString(serializer.toJson(body)), true); + + try { + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofInputStream()); + if (response.body() != null) { + try (InputStream is = response.body()) { + IOUtils.copy(is, os); + } + } + } catch (IOException | InterruptedException e) { + throw new ApiException(e); + } + + throw new IllegalStateException("Not implemented yet"); + } + + private HttpRequest prepareGetRequest(@NotNull String endpoint, @NotNull Map headers) throws ApiException { List headersList = prepareHeaders(headers); URI uri = prepareURI(endpoint); diff --git a/ksef-client-okhttp/src/main/java/io/alapierre/ksef/client/okhttp/OkHttpApiClient.java b/ksef-client-okhttp/src/main/java/io/alapierre/ksef/client/okhttp/OkHttpApiClient.java index 6d9696e..75b1dc7 100644 --- a/ksef-client-okhttp/src/main/java/io/alapierre/ksef/client/okhttp/OkHttpApiClient.java +++ b/ksef-client-okhttp/src/main/java/io/alapierre/ksef/client/okhttp/OkHttpApiClient.java @@ -11,7 +11,10 @@ import java.io.IOException; import java.io.OutputStream; -import java.util.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; /** * @author Adrian Lapierre {@literal al@alapierre.io} @@ -123,7 +126,7 @@ public void getStream(@NotNull String endpoint, @NotNull String token, @NotNull throw createException(response); } - if(response.body() != null) { + if (response.body() != null) { try (val is = response.body().byteStream()) { IOUtils.copy(is, os); } @@ -133,7 +136,28 @@ public void getStream(@NotNull String endpoint, @NotNull String token, @NotNull } } - protected Optional doPostJson(@NotNull String endpoint, @NotNull B body, @NotNull Class classOfR, Map headers) throws ApiException { + @Override + public void postStream(@NotNull String endpoint, @NotNull Object body, @NotNull OutputStream os) throws ApiException { + RequestBody requestBody = RequestBody.create(serializer.toJson(body), JSON); + Request request = createRequest(endpoint, requestBody, Collections.emptyMap(), true); + + try (Response response = client.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw createException(response); + } + + if (response.body() != null) { + try (val is = response.body().byteStream()) { + IOUtils.copy(is, os); + } + } + } catch (IOException ex) { + throw new ApiException(ex); + } + } + + + protected Optional doPostJson(@NotNull String endpoint, @NotNull B body, @NotNull Class classOfR, Map headers) throws ApiException { RequestBody requestBody = RequestBody.create(serializer.toJson(body), JSON); Request request = createRequest(endpoint, requestBody, headers, true); diff --git a/ksef-client-spec/src/main/java/io/alapierre/ksef/client/ApiClient.java b/ksef-client-spec/src/main/java/io/alapierre/ksef/client/ApiClient.java index b94dbc4..4aa48dd 100644 --- a/ksef-client-spec/src/main/java/io/alapierre/ksef/client/ApiClient.java +++ b/ksef-client-spec/src/main/java/io/alapierre/ksef/client/ApiClient.java @@ -32,4 +32,5 @@ public interface ApiClient { Optional postXML(@NotNull String endpoint, @NotNull Object body, @NotNull Class classOfR) throws ApiException; void getStream(@NotNull String endpoint, @NotNull String token, @NotNull OutputStream os) throws ApiException; + void postStream(@NotNull String endpoint, @NotNull Object body, @NotNull OutputStream os) throws ApiException; } diff --git a/ksef-sample/src/main/java/io/alapierre/ksef/sample/Main.java b/ksef-sample/src/main/java/io/alapierre/ksef/sample/Main.java index c01726f..cd7bc73 100644 --- a/ksef-sample/src/main/java/io/alapierre/ksef/sample/Main.java +++ b/ksef-sample/src/main/java/io/alapierre/ksef/sample/Main.java @@ -9,13 +9,18 @@ import io.alapierre.ksef.client.iterator.InvoiceQueryResponseAdapter; import io.alapierre.ksef.client.iterator.KsefResultStream; import io.alapierre.ksef.client.model.rest.auth.InitSignedResponse; +import io.alapierre.ksef.client.model.rest.common.InvoiceRequest; import io.alapierre.ksef.client.model.rest.query.InvoiceQueryRequest; +import io.alapierre.ksef.client.model.rest.query.InvoiceQueryResponse; import io.alapierre.ksef.client.okhttp.OkHttpApiClient; import io.alapierre.ksef.client.serializer.gson.GsonJsonSerializer; import io.alapierre.ksef.token.facade.KsefTokenFacade; import lombok.val; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.security.KeyStore; import java.text.ParseException; @@ -66,6 +71,40 @@ public static void main(String[] args) { } } + public static void fetchInvoiceByCommonAPI(){ + try { + val invoiceApi = new InterfejsyInteraktywneFakturaApi(client); + InvoiceQueryResponse.IssuedToIdentifier issued = new InvoiceQueryResponse.IssuedToIdentifier("onip", "9655573052"); + InvoiceQueryResponse.IssuedToName name = new InvoiceQueryResponse.IssuedToName("fn", null, "Firma Janowski"); + InvoiceQueryResponse.SubjectTo subject = new InvoiceQueryResponse.SubjectTo(issued, name); + val invoiceDetails = InvoiceRequest.InvoiceDetails.builder() + .invoiceOryginalNumber("FK2023/09/14") + .subjectTo(subject) + .dueValue("100") + .build(); + + val requestBody = InvoiceRequest.builder() + .ksefReferenceNumber("5282740347-20230914-2979E373175E-25") + .invoiceDetails(invoiceDetails) + .build(); + + + ByteArrayOutputStream out = new ByteArrayOutputStream(0); + invoiceApi.getInvoice(requestBody, out); + + try (FileOutputStream fos = new FileOutputStream(requestBody.getKsefReferenceNumber() + ".xml")) { + fos.write(out.toByteArray()); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + + } catch (ApiException ex) { + System.out.printf("Błąd wywołania API %d (%s) opis błędu %s", ex.getCode(), ex.getMessage(), ex.getResponseBody()); + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + // public static InitSignedResponse loginBySignature() throws IOException, ApiException { // // val signer = new P12Signer(pas, tokenFile); From 2d3b9423381030bccd0283c8af0ccf1770cf8382 Mon Sep 17 00:00:00 2001 From: maciejdybowski Date: Wed, 4 Oct 2023 21:46:33 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Do=C5=82o=C5=BCenie=20@NoArgsConstructor=20?= =?UTF-8?q?w=20celu=20zachowania=20kompatybilno=C5=9Bci=20wstecznej?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ksef/client/model/rest/query/InvoiceQueryResponse.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java b/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java index ce184da..6c99290 100644 --- a/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java +++ b/ksef-api/src/main/java/io/alapierre/ksef/client/model/rest/query/InvoiceQueryResponse.java @@ -2,6 +2,7 @@ import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.util.List; @@ -38,6 +39,7 @@ public static class InvoiceHeaderList{ @Data @AllArgsConstructor + @NoArgsConstructor public static class SubjectTo{ private IssuedToIdentifier issuedToIdentifier; private IssuedToName issuedToName; @@ -46,6 +48,7 @@ public static class SubjectTo{ @Data @AllArgsConstructor + @NoArgsConstructor public static class IssuedToName{ private String type; private String tradeName; @@ -54,6 +57,7 @@ public static class IssuedToName{ @Data @AllArgsConstructor + @NoArgsConstructor public static class IssuedToIdentifier{ private String type; private String identifier;