Wystawienie faktury ustrukturyzowanej z wykorzystaniem Open API Krajowego Systemu e-Faktur (KSeF)
Proces wystawienia e-Faktury z wykorzystaniem API KSeF wcale nie jest trywialny, dlatego przygotowaliśmy poniższą instrukcję, żeby każdy kto się nie boi mógł spróbować swoich sił w tej „konkurencji”. Zresztą nie ma co przedłużać wstępu – zobaczcie sami:
1. Wyzwanie autoryzacyjne
Aby wystartować komunikację z API KSeF w pierwszej kolejności musimy wywołać AutrhorisationChallenge
, czyli tzw. wyzwanie autoryzacyjne, na podstawie którego będziemy mogli ustanowić sesję. A zatem wywołujemy:
POST /online/Session/AuthorisationChallenge
Gdzie podajemy czas w formacie timestamp (np.: "timestamp": "2023-10-10T13:00:00Z"
) oraz typ identyfikatora ("identifierType": "onip"
) i jego wartość ("identifier": "<nip wystawcy faktury>"
)
Zwrócony zostanie znacznik czasowy oraz wartość samego wyzwania autoryzacyjnego
2. Sesja podpisana
Następnie wywołujemy nawiązanie sesji podpisanej:
POST /online/Sesision/InitSigned
InitSessionSignedRequest
– zawiera opcjonalną sekcję Encryption
– każda faktura wysłana w ramach utworzonej sesji interaktywnej będzie zaszyfrowana kluczem symetrycznym wskazanym w sesji Encryption
.
Uzupełniamy:
- kontekst w którym pracujemy, czyli atrybut
<Context><Identifier>
– wpisując NIP wystawcy faktury - wyzwanie autoryzacyjne, czyli atrybut
<Context><Challenge>
– wpisujemy <wartość wyzwania zwrócona z poprzedniej operacji> - znacznik czasowy, czyli atrybut
<Context><Timestamp>
– wpisujemy <wartość timestamp zwrócona z poprzedniej operacji> – Uwaga! znacznik ważny jest 5 minut - Tak przygotowane żądanie uwierzytelniające należy podpisać korzystając z podpisu kwalifikowanego lub pieczęci elektronicznej która zawiera numer PESEL podany w kontekście
- Po wykonaniu podpisu do żądania dodawany jest element
<ds:Signature>
zawierający m.in. podpis (wartość z funkcji skrótu) oraz certyfikat X.509 który służy do weryfikacji poprawności podpisu XAdES. - Tak przygotowane żądanie uwierzytelniające wysyłamy korzystając z metody
POST /online/Sesision/InitSigned
- Brak autoryzacji, ponieważ nie możemy powiązać PESEL z tą konkretną firmą (numerem NIP firmy) z kontekstu.
- Żądanie uwierzytelniające musi być podpisane podpisem lub pieczęcią elektroniczną z numerem NIP – po to aby możliwe było powiązanie (potwierdzenie) podanego numeru NIP w kontekście.
- Jeśli wykorzystamy podpis/pieczęć z NIP to wtedy w odpowiedzi dostaniemy:
- Numer referencyjny sesji
referenceNumber
„- bardzo ważny atrybut służy do sprawdzenia statusu sesji oraz pobrania UPO. - Token sesji – atrybut
sessionToken : { "token", "context" …. }
- Numer referencyjny sesji
Uwaga! Mając token sesji – każde kolejne zapytanie powinno być autoryzowane tym tokenem
3. Nadanie uprawnień do wysyłania żądań do KSeF
Nadanie uprawnień (czyli komu i co nadajemy) dla konkretnego numeru PESEL, czyli osobie która w ramach firmy będzie mogła np. wystawiać i odczytywać faktury:
POST /online/Credentials/Grant
Proces nadawania uprawnień jest asynchroniczny i może chwilę potrwać. Ale za pomocą wartości zwróconego atrybutu elementReferenceNumber
możemy dowiedzieć się jaki jest status – w tym przypadku – nadania uprawnień.
3a. Sprawdzenie statusu nadania uprawnień
GET /online/Credentials/Status/{CredentialsElementReferenceNumber}
- Status
Proces został zarejestrowany
(processingCode:100) oznacza że dopiero rozpoczęło się procesowanie nadania uprawnień. - Status
Proces uprawnień zakończony
(processingCode:200) oznacza że uprawnienia zostały nadane
4. Żądanie uwierzytelniające
Teraz mając nadane uprawnienia dla PESEL możemy jeszcze raz wysłać podpisane żądanie uwierzytelniające podpisane kwalifikowanym (z PESEL):
POST /online/Sesision/InitSigned
W odpowiedzi powinniśmy otrzymać:
Ważny jest token sesyjny (token), który umożliwia wykonywanie takich operacji jak wystawianie i odbiór faktur. Oczywiście jest o też zupełnie inna sesja (inna wartość dla referenceNumber
).
5. Wygenerowanie tokena autoryzacyjnego
Poniżej przykłada żądania, które należy wysłać do metody GenerateToken
.
POST /online/Credentials/GenerateToken
Wywołanie i odpowiedź:
Uwaga! Token autoryzacyjny (authorisationToken
) jest zwracany i możliwy do pobrania tylko raz po wywołaniu metody GenerateToken
, później nie jest już możliwy do uzyskania.
Ten token autoryzacyjny można już wpisać w aplikacji.
Z uwagi na processingCode:100
musimy sprawdzić kiedy zakończy się proces generowania tokenu…. I dopiero wtedy (jak będzie processingCode:200
) token będzie gotowy do użycia.
5a. Sprawdzenie statusu generowania tokenu
W celu sprawdzenia statusu generowania tokenu, musimy wysłać wartość atrybutu elementReferenceNumber
z odpowiedzi uzyskanej w kroku 5 wysłać na adres metody:
GET /online/Credentials/Status/{CredentialsElementReferenceNumber}
6. Nawiązanie sesji umożliwiającej wysłanie e-Faktury
Jeśli mamy token autoryzacyjny to teraz należy nawiązać nim sesję w celu wykonania czynności takich jak wysłanie lub odbieranie faktur.
- Generujemy wyzwanie autoryzacyjne w tym samym kontekście:
POST /online/Session/AuthorisationChallenge
- Przygotowujemy żądanie
InitSessionTokenRequest
, gdzie wypełniamy atrybuty:timestamp
(z wyzwania autoryzacyjnego),challenge
(również z wyzwania autoryzacyjnego),identifier
(zgodny z kontekstem) oraztoken
– zgodnie z dokumentacją jest toBase64()
:
Uwaga! Taka przygotowanego żądania nie musimy już podpisywać – to jest różnica między nawiązaniem sesji z wykorzystaniem podpisu, a sesją z wykorzystaniem tokenu autoryzacyjnego.
W odpowiedzi dostajemy token sesyjny: w atrybucie sessionToken > token
Uwaga! Z tym tokenem możemy dopiero wystawiać/odbierać faktury!!!
7. Wysłanie e-Faktury do KSeF
PUT /online/Invoice/Send
Wartość w atrybucie faktury <Podmiot1><DaneIdentyfikacyjne><NIP>
musi być taka sama jak w wartość z kontekstu zadeklarowana w wyzwaniu autoryzacyjnym. Wyjątkiem jest np. samofakturowanie, wtedy w tym polu może pojawić się inny NIP, ale trzeba mieć uprawnienia nadane do samofakturowania (a w danych odbiorcy musi być NIP zgodny z zadeklarowanym w wyzwaniu autoryzacyjnym).
Przykład żądania:
- Autoryzujemy sesję z wykorzystaniem tokena sesyjnego
- Jeśli jest aktywna sesja to wywołujemy
PUT /online/Invoice/Send
i przekazujemy żądnie zawierające: skrót z faktury (hashSHA
), rozmiar (fileSize
) oraz samą fakturę (invoiceBody
) - W odpowiedzi otrzymujemy informację, że proces odebrania przesłanej faktury wystartował:
Uwaga! Atrybut referenceNumber
, czyli numer referencyjny sesji należy odłożyć ponieważ po nim będziemy mogli sprawdzić i pobrać UPO.
7a. Sprawdzenie statusu odebrania przez KSeF wysłanej przez nas faktury
GET /online/Credentials/Status/{CredentialsElementReferenceNumber}
Jeśli faktura została zaakceptowana (status 200), to ważny jest atrybut ksefReferenceNumber
, który jednoznacznie identyfikuje fakturę. Atrybut acquisitionTimestamp
określi datę i czas kiedy dokładnie faktura została przyjęta do systemu KSeF.
Tak to już wszystko i możemy cieszyć się z wystawienia pierwszej e-faktury w KSeF.
Niniejszy wpis powstał na podstawie Webinarium przeprowadzonego w dniu 25.11.2022r. przez przedstawicieli Ministerstwa Finansów.