Krajowy system e-Faktur

Dzyszla
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 185
2

Jakby ktoś był ciekawy implementacji wniosku o podpis i utworzenie certyfikatu w Delphi w oparciu o SecureBlackBox (nigdzie w necie nie znalazłem w ogóle przykładu kompleksowego):

Kopiuj
CertRequest := TElCertificateRequest.Create(nil);
  with CertRequest.Subject do
  begin
      Add(SB_CERT_OID_COMMON_NAME, BytesOfString(KSeFClient.JSONResponse.GetValue<String>('commonName', '')));
      Add(SB_CERT_OID_COUNTRY, BytesOfString(KSeFClient.JSONResponse.GetValue<String>('countryName', 'PL')));
     ...
  end;

  if rbAlgorytm_RSA.Checked then
  begin
      Algorithm := SB_CERT_ALGORITHM_ID_RSA_ENCRYPTION;
      if rbHash_SHA1.Checked then
          Hash := SB_CERT_ALGORITHM_SHA1_RSA_ENCRYPTION
      else if rbHash_SHA256.Checked then
          Hash := SB_CERT_ALGORITHM_SHA256_RSA_ENCRYPTION
      else if rbHash_SHA364.Checked then
          Hash := SB_CERT_ALGORITHM_SHA384_RSA_ENCRYPTION
      else
          Hash := SB_CERT_ALGORITHM_SHA512_RSA_ENCRYPTION;
      KeySize := 2048;
  end
  else
  begin
      Algorithm := SB_CERT_ALGORITHM_EC;
      if rbHash_SHA1.Checked then
      begin
          Hash := SB_CERT_ALGORITHM_SHA1_ECDSA;
          KeySize := 160;
      end
      else if rbHash_SHA256.Checked then
      begin
          Hash := SB_CERT_ALGORITHM_SHA256_ECDSA;
          KeySize := 256;
      end
      else if rbHash_SHA364.Checked then
      begin
          Hash := SB_CERT_ALGORITHM_SHA384_ECDSA;
          KeySize := 256;
      end
      else
      begin
          Hash := SB_CERT_ALGORITHM_SHA512_ECDSA;
          KeySize := 256;
      end;
  end;

  CertRequest.Generate(Algorithm, KeySize, Hash);
  CertRequest.SaveKeyToStream(crtKey);

  // REQUEST, pobranie wyniku;

  Cert := TElX509Certificate.Create(nil);
  crtStream := TMemoryStream.Create;
  try
      crtStream.Write(crtBytes, Length(crtBytes));
      crtStream.Position := 0;
      Cert.LoadFromStream(crtStream);

      crtKey.Position := 0;
      Cert.LoadKeyFromStream(crtKey);

      crtStream.Clear;
      Cert.SaveToStreamPFX(crtStream, '');

     //zapis crtStream do pliku/bazy
  finally
      crtStream.Free;
      Cert.Free;
  end;

Może te fragmenty pomogą komuś. W sumie zadziałało od strzała, choć po tylu postach z problemami też się ich bałem. A tu nawet SBB nie muszę jednak aktualizować.

GS
  • Rejestracja: dni
  • Ostatnio: dni
0

Inicjuję sesję wsadową.
Przygotowałem plik FA3..zip o rozmiarze 2087 oraz plik zaszyfrowany FA3..zip.aes o rozmiarze 2096.
Poniżej metadane

Kopiuj
{ 
 "formCode":  {
              "systemCode": "FA (3)", 
              "schemaVersion": "1-0E", 
              "value": "FA" 
              }, 
 "batchFile": {
              "fileSize": 2087,     <- tutaj rozmiar pliku ZIP
              "fileHash": "gjPM6Y2P/vdV5AVvIuzPXEpMvlvBY7w8BM9hNMt1eL8=", 
              "fileParts": [
                             {
                               "ordinalNumber": 1,
                               "fileName": "FA3.zip.aes",
                               "fileSize": 2096,    <- tutaj rozmiar pliku ZIP po zaszyfrowaniu
                               "fileHash": "gjPM6Y2P/vdV5AVvIuzPXEpMvlvBY7w8BM9hNMt1eL8="
                             }
                           ] 
              },
 "encryption":{ 
              "encryptedSymmetricKey":  "lyGzGwugEnEQa3zCAwYXHSC86Z4YPGFF/6x9rhxR38Q743uibzgxqLZuJW1uQ6vFVTdf6vXP5hb4hLRGTHcROJuV+0ozIBE/HZ3yJ97aJkJ23KUvCRaj8b6/bIjOj/XjVOJUfb/ozt9QRaKMuPMix50XZLYyYCzrY0tAAGNpuTV2Nsht5+Shen7VQ9Io6RNmonTTqSFqIDiitaq+xkyU56WaCoRfKkAwqWlGsev8gxz9pthJZRal4pErjA1Rffsp29r9ePXOGWSWMm0L2MNAgb6bSWbHUEM0YIllo10o1rT8SGHpuxw9ZI/jg/J0Wjsxz345R7Amnk3g6nW14CYYhA==", 
              "initializationVector": "MTIzNDU2Nzg5MDEyMzQ1Ng==" 
             }, 
 "offlineMode": false 
}

Po wysłaniu pliku FA3.zip.aes i zamknięcciu sesji otrzymuję rezultat:

Kopiuj
{
  "exception":
  {
   "exceptionDetailList":
    [
     {
       "exceptionCode":21157,
       "exceptionDescription":"Nieprawidłowy rozmiar części pakietu.",
       "details":  ["Zadeklarowany rozmiar części '1' nie zgadza się z rzeczywistym."]
     }
    ],
   "serviceCode":"00-7c414fa422382c00587a3cc3ca2b22e0-ad75d59b10b85fa2-00",
   "timestamp":"2025-10-13T14:21:34.6063784Z"
   }
}

Czy w metadanych prawidłowo zdeklarowałem rozmiar łączny oraz rozmiar elementu ?

Po odszyfrowaniu FA3.zip.aes dostaję plik identyczny z FA3.zip więc samo szyfrowanie powinno być OK

tak wygląda upload:

Kopiuj
function uploadZipAesFile(aToken, aFileName, aUrl, aMethod, aHeaderParamName, aHeaderParamValue: string): TrestResponseRec;
var
  restx: TmREST;
  fs: tfilestream;
begin
  restx := TmREST.Create;
  fs := tfilestream.Create(aFileName, fmOpenRead);
  fs.Seek(0, 0);
  try
    restx.RRequest.Resource := '';
    restx.RRequest.Client.baseUrl := aUrl;
    if Uppercase(aMethod) = 'PUT' then
      restx.RRequest.Method := rmPut;
    if Uppercase(aMethod) = 'GET' then
      restx.RRequest.Method := rmGet;
    if Uppercase(aMethod) = 'POST' then
      restx.RRequest.Method := rmPost;
    restx.RRequest.Params.clear;
    restx.RRequest.Params.Addheader(aHeaderParamName, aHeaderParamValue);
    restx.RRequest.body.Add(fs,trestcontenttype.ctNone);  
    restx.RRequest.Execute;
    result.content := restx.RResponse.content;
    result.statusCode := restx.RResponse.statusCode;
  finally
    restx.Free;
    fs.Free;
  end;
end;

poprawiony i działający kod

Kopiuj
function uploadZipAesFile(aToken, aFileName, aUrl, aMethod, aHeaderParamName, aHeaderParamValue: string): TrestResponseRec;
var
  restx: TmREST;
  fs: tfilestream;
begin
  restx := TmREST.Create;
  fs := tfilestream.Create(aFileName, fmOpenRead);
  fs.Seek(0, 0);
  try
    restx.RRequest.Resource := '';
    restx.RRequest.Client.baseUrl := aUrl;
    if Uppercase(aMethod) = 'PUT' then
      restx.RRequest.Method := rmPut;
    if Uppercase(aMethod) = 'GET' then
      restx.RRequest.Method := rmGet;
    if Uppercase(aMethod) = 'POST' then
      restx.RRequest.Method := rmPost;
    restx.RRequest.Params.clear;
    restx.RRequest.Params.Addheader(aHeaderParamName, aHeaderParamValue);
    //  restx.RRequest.body.Add(fs,trestcontenttype.ctNone);  <- ŹLE  !!!!!
    restx.RRequest.AddBody(fs, ctAPPLICATION_OCTET_STREAM); <- DOBRZE  !!! :) 
    restx.RRequest.Execute;
    result.content := restx.RResponse.content;
    result.statusCode := restx.RResponse.statusCode;
  finally
    restx.Free;
    fs.Free;
  end;
end;
Dzyszla
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 185
0

Pytanie biznesowe - czy widzi ktoś jakiś sens ściągania certyfikatów z KSeFu? Chodzi mi o ściągnięcie tych wygenerowanych samemu. Co można by tym uzyskać?

GS
  • Rejestracja: dni
  • Ostatnio: dni
0

Jaka dokładnie treść ma być zawarta w kodach QR na fakturze zarejestrowanej w Ksef oraz w kodach "OFFLINE" i "CERTYFIKAT" ?
Nie wiem gdzie szukać szczegółowej informacji na ten temat

M4
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 58
0

Mam pytani o wystawienie certyfikatu dla firmy podmiotu, składamy w Module Certyfikatów i Uprawnień czy przez api ?

BS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 34
0

czy może ktoś miał taki problem, że nie może się doczekać na potwierdzenie? sprawdzam za pomocą '/v2/sessions/' + sReferenceNumber + '/invoices'. wysłałem fv wsadowo to dla podanego sReferenceNumber mam pusto. wysłałem sesyjnie to mam 150 i trwa przetwarzanie. faktury wysłałem 9go. nie mam już pomysłu co jest nie tak. :(

LI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3
0

Dobry, czy działa komuś uwierzytelnianie za pomocą InternalId? Czy na chwilę obecną nie ma takiej możliwości by to zadziałało?
Bo w sumie nie mam jak nadać uprawnień dla niego. Przykładowy: 7592891627-12345.
Dla zwykłego NIP działa poprawnie.

P2
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10
0

Byłby w stanie ktoś mi wytłumaczyć kroki biznesowe w aplikacji która ma wystawiać i pobierać faktury? Chodzi mi o kroki autoryzacji, w systemie w firmie może wiele osób obsługiwać integracje ksef więc jak ma wygladać po kolei proces autoryzacji?
Teraz robię tak że podpisuje xml z challenge prywatnym profilem zaufanyn (jedyne co mi działa), zwraca mi token ale po sprawdzeniu jego statusu mam brak uprawnień.
Jak to powininen krok po kroku dobrze robić bo nie rozumiem za bardzo tej dokumentacji. Kilka metod autoryzacji z czego jedna będzie niby wyłączona.

S8
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 81
0

Jak wg Was będzie wyglądało generowanie certyfikatu w tej ich apce? będzie można pobrać zarówno klucz prywatny jak i certyfikat?

ZB
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 66
0

W KSeF 1 były metody na sprawdzanie stanu konkretnej sesji bez uprawnień (tzw. common) oraz w kontekście uwierzytelnionym (tokenem). Czy teraz też jest jakaś metoda dla sprawdzenia sesji (online lub wsadowej) nie wymagająca access tokena czy to se ne vrati?

SU
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 3
0

Czy dla UPO z KSeF 2 jest udostępniony przez MF jakiś szablon .xsl , czy trzeba go sobie samemu wybudować? Dla faktury znalazłem, ale dla UPO jakoś nie.
Pozdrawiam.

Dzyszla
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 185
1

Na prośbę @Siewek kod Delphi z SBB do podpisywania XMLi XAdESem (nie mogę już edytować tamtego):

Kopiuj
procedure TEncryptor.SignXML(const aXMLStream: TStringStream);
var
	Signer: TElXMLSigner;
	ElXMLDoc: TElXMLDOMDocument;
	Ref: TElXMLReference;
	X509KeyData: TElXMLKeyInfoX509Data;
	XAdESSigner: TElXAdESSigner;
	XMLEncoder: TElXMLUTF8Codec;
begin
	ElXMLDoc := TElXMLDOMDocument.Create;
	try
		aXMLStream.Seek(0, soFromBeginning);
		ElXMLDoc.LoadFromStream(aXMLStream);

		Signer := TElXMLSigner.Create(nil);
		XAdESSigner := TElXAdESSigner.Create(nil);
		X509KeyData := TElXMLKeyInfoX509Data.Create(False);
		try
			Signer.XAdESProcessor := XAdESSigner;
			Signer.SignatureType := xstEnveloped;
			Signer.SignatureMethodType := xmtSig;
			Signer.SignatureCompliance := xscDSIG;
			case fCert.PublicKeyAlgorithm of
				SB_CERT_ALGORITHM_ID_RSA_ENCRYPTION:
					case fCert.KeyMaterial.Bits of
						160: Signer.SignatureMethod  := xsmRSA_SHA1;
						224: Signer.SignatureMethod  := xsmRSA_SHA224;
						384: Signer.SignatureMethod  := xsmRSA_SHA384;
						512: Signer.SignatureMethod  := xsmRSA_SHA512;
					else
						Signer.SignatureMethod  := xsmRSA_SHA256;
					end;
				SB_CERT_ALGORITHM_EC:
					case fCert.KeyMaterial.Bits of
						160: Signer.SignatureMethod  := xsmECDSA_SHA1;
						224: Signer.SignatureMethod  := xsmECDSA_SHA224;
						384: Signer.SignatureMethod  := xsmECDSA_SHA384;
						512: Signer.SignatureMethod  := xsmECDSA_SHA512;
					else
						Signer.SignatureMethod  := xsmECDSA_SHA256;
					end;
			end;
			Signer.CanonicalizationMethod := xcmExclCanon;
			Signer.IncludeKey := True;

			Ref := Signer.References[Signer.References.Add];
			Ref.URINode := ElXMLDoc.DocumentElement;
			Ref.URI := '';
			Ref.DigestMethod := xdmSHA256;
			Ref.TransformChain.AddEnvelopedSignatureTransform;

			X509KeyData.Certificate := fCert;
			X509KeyData.IncludeKeyValue := False;

			Signer.KeyData := X509KeyData;
			Signer.UpdateReferencesDigest;

			XAdESSigner.XAdESVersion := XAdES_v1_3_2;
			XAdESSigner.SigningCertificates := TElMemoryCertStorage.Create(nil);
			XAdESSigner.OwnSigningCertificates := True;
			XAdESSigner.SigningCertificates.Add(fCert, False);
			XAdESSigner.SignedPropertiesReferenceDigestMethod := xdmSHA256;

			XAdESSigner.Generate(XAdES_BES);
			XAdESSigner.QualifyingProperties.SignedProperties.SignedSignatureProperties.SignaturePolicyIdentifier.SignaturePolicyImplied := False;

			XAdESSigner.QualifyingProperties.XAdESPrefix := 'xades';
			XAdESSigner.QualifyingProperties.Target := '#Signature-0';
			XAdESSigner.SigningTime := TTimeZone.Local.ToUniversalTime(Now);

			Signer.GenerateSignature;

			Signer.SaveEnveloped(ElXMLDoc.DocumentElement);
		finally
			X509KeyData.Free;
			Signer.Free;
			XAdESSigner.Free;
		end;

		aXMLStream.Clear;

		XMLEncoder := TElXMLUTF8Codec.Create;
		try
			XMLEncoder.WriteBOM := False;

			ElXMLDoc.SaveToStream(aXMLStream, xcmNone, XMLEncoder);
		finally
			XMLEncoder.Free;
		end;
	finally
		ElXMLDoc.Free;
	end;
end;
GB
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 27
0

Czy wy też tak myślicie, że po 1 lutego jak przyjdę na stację benzynową (lub np: do restauracji) i poproszę o fakturę, to Pan/Pani spyta mnie się o Imię, Nazwisko i NUMER KLIENTA?

SI
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 24
0

Mam już certyfikat ksef, zakodowany w base64 ciąg znaków, który muszę odkodować z powrotem do pliku .Der by móc używać jako certyfikat. Ale czy mogę takim plikiem Der po prostu podpisać swojego xml? Czy muszę jeszcze dodeklarowywać swój klucz RSA albo EC i przerabiać z Der do p12 i tym dopiero podpisywać? Mam wrażenie że już się bardzo pogubiłem w całym procesie i już zaczynam plątać który ciąg znaków jest czym.

S1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 15
0

czy dziś nie miał wystartować ksed-demo (wersja przedprodukcyjna - https://ksef.podatki.gov.pl/)?? - ruszyło to gdzieś, jakiś nowy adres czy ma być nadal
ksef-demo.podatki.gov.pl ?

Dzyszla
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 185
0

Potrzebuję chyba małą agregację danych i żeby czegoś nie pominąć. Główne zagadnienie: czym w zasadzie różni się obecnie sesja interaktywna od wsadowej?

Interaktywna - trwa 12h, można dosyłać faktury na bieżąco (byle nie więcej niż 10 000). Czas wysłania, to czas dosłania.
Wsadowa - Wysyła się na raz. Czas wysłania to czas rozpoczęcia sesji.

To jedyne różnice (oczywiście pomijam przygotowywanie paczek dla wsadu)?

PK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7
0

Po długiej przerwie wznawiam przygodę z KSeF z API2.
Ćwiczę uwierzytelnienie z wykorzystaniem tokena KSeF i nie udaje sie mi wykonać tego poprawnie z Delphi 10.2 Tokyo.

Wykonuję inicjalizację uwierzytelnienia i otrzymuję prawidłową odpowiedź (challenge i timestamp).
Przystępuję do uwierzytelnienie z wykorzystaniem tokena KSeF. Biorę token KSeF wraz z timestampem ze wcześniej wygenerowanego challenge'a
(w formacie token|timestamp) i szyfruję dedykowanym do tego celu kluczem publicznym. Wykonuję request POSTMANem i otrzymuję prawidłową odpowiedź
zawierającą kod 202, referenceNumber, authenticationToken.token oraz authenticationToken.validUntil.

Próbuję wykonać to w Delphi 10.2 i nie udaje mi się:
myREST.RRequest.Resource := 'https://ksef-test.mf.gov.pl/api/v2/auth/ksef-token';
myREST.RRequest.Method := rmPost;
myREST.RRequest.Params.AddItem('Content-Type', 'application/json', pkHTTPHEADER, [poDoNotEncode]);
//myREST.RRequest.Params.AddHeader('Content-Type', 'application/json');
myREST.RRequest.Accept := 'application/json';
myREST.RRequest.AddBody(content_body.Text, TRESTContentType.ctAPPLICATION_JSON);
myREST.RRequest.Execute;
gdzie body :={ "challenge": "", "contextIdentifier": { "type": "Nip", "value": "7991880938" },
"encryptedToken": "qKatKWbgb8gU8SefGQi7h4UKeNR+HwXlBGgDGLZ92xM1I0bEwUBPAbjJD7YTyJlsqGMH93IySc270TwEzTxAHbXjh2iWM89swvUKof0KyLDDq9aAgTqEQCNEvtjytmuajvJ7w5NNGoqzea5w87BXNSOwP2kjMqq2M31Cl2zagmfr3D639ZgDwdv8eMyHbY23IbnYSMdThajHaZ6CxINZ31CjnwxamWaM8T/XHorXPTEJLpmA7XNxW3NEeOqTNgeCASsSsAQvoVLXaRN8xurGqL2YJmMVAWM/aEFOTXP5uSJRYHfaIW7KxuDim5d3xtytX+0mXAOkUV3qulOuskPdZQ==" }
Obiekt myREST.RRequest jest tworzony z klasy.

Dostaję odpowiedź:
https://ksef-test.mf.gov.pl/api/v2/auth/ksef-token response: 400 Bad Requesthttps://ksef-test.mf.gov.pl/api/v2/auth/ksef-token
response: {"exception":{"serviceCtx":"srvTEMFE","serviceCode":"5B32CCFB-1FEF-4349-8E68-2C8FC3805D95","serviceName":"exception.handler"
,"timestamp":"2025-10-15T10:45:50.002Z","exceptionDetailList":[{"exceptionCode":21180,"exceptionDescription":"Nieprawidłowe żądanie."}]}}

Body jest takie samo jak w request w POSTMAN więc zakładam, że jest prawidłowe, bo z POSTMANa otrzymuje prawidłową odpowiedź.

Mam prośbę, czy ktoś mógłby sprawdzić w czym problem? Z góry dziękuję za pomoc.

ZB
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 66
0

Pytania o endpoint odczytu faktur z sesji:

/api/v2/sessions/{referenceNumber}/invoices

czyli:

https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Status-wysylki-i-UPO/paths/~1api~1v2~1sessions~1%7BreferenceNumber%7D/get

  1. Czy to służy do pobierania danych obu typów sesji, interaktywnych i wsadowych?
  2. Czy referenceNumber może dotyczyć aktywnej i nie zamkniętej sesji?
  3. Jak się mają do siebie pola z odpowiedzi: acquisitionDate, invoicingDate i permanentStorageDate? Czy któraś z tych dat jest uznawana za FAKTYCZNĄ datę wystawienia faktury?
PK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7
0

@pkscargo: W skopiowanym kodzie brakuje wartości challenge (to mój błąd) ale w request jest i to z dzisiaj. Tymi samymi danymi posługuje siw w POSTMAN-ie i otrzymuję poprawną odpowiedź. W POSTMAN nie mam nagłówka autoryzacyjnego, podaję challange, NIP i encryptedToken i otrzymuję poprawną odpowiedź:

Kopiuj
{
    "referenceNumber": "20251015-AU-1E527E9000-FCD848EE53-69",
    "authenticationToken": {
        "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJBdXRoZW50aWNhdGlvblRva2VuIiwiYXJuIjoiMjAyNTEwMTUtQVUtMUU1MjdFOTAwMC1GQ0Q4NDhFRTUzLTY5IiwiZXhwIjoxNzYwNTIwODk1LCJpYXQiOjE3NjA1MTgxOTUsImlzcyI6ImtzZWYtYXBpLXRlIiwiYXVkIjoia3NlZi1hcGktdGUifQ.VpnLwd9rsUS9sgFE9CnVepWyhsjSxB_ecZA1IP0eEfk",
        "validUntil": "2025-10-15T09:34:55.1918413+00:00"
    }
}

Macie jakiś pomysł?

PK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 7
0
pkscargo napisał(a):

Po długiej przerwie wznawiam przygodę z KSeF z API2.
Ćwiczę uwierzytelnienie z wykorzystaniem tokena KSeF i nie udaje sie mi wykonać tego poprawnie z Delphi 10.2 Tokyo.

Wykonuję inicjalizację uwierzytelnienia i otrzymuję prawidłową odpowiedź (challenge i timestamp).
Przystępuję do uwierzytelnienie z wykorzystaniem tokena KSeF. Biorę token KSeF wraz z timestampem ze wcześniej wygenerowanego challenge'a
(w formacie token|timestamp) i szyfruję dedykowanym do tego celu kluczem publicznym. Wykonuję request POSTMANem i otrzymuję prawidłową odpowiedź
zawierającą kod 202, referenceNumber, authenticationToken.token oraz authenticationToken.validUntil.

Próbuję wykonać to w Delphi 10.2 i nie udaje mi się:
myREST.RRequest.Resource := 'https://ksef-test.mf.gov.pl/api/v2/auth/ksef-token';
myREST.RRequest.Method := rmPost;
myREST.RRequest.Params.AddItem('Content-Type', 'application/json', pkHTTPHEADER, [poDoNotEncode]);
//myREST.RRequest.Params.AddHeader('Content-Type', 'application/json');
myREST.RRequest.Accept := 'application/json';
myREST.RRequest.AddBody(content_body.Text, TRESTContentType.ctAPPLICATION_JSON);
myREST.RRequest.Execute;
gdzie body :={ "challenge": "", "contextIdentifier": { "type": "Nip", "value": "7991880938" },
"encryptedToken": "qKatKWbgb8gU8SefGQi7h4UKeNR+HwXlBGgDGLZ92xM1I0bEwUBPAbjJD7YTyJlsqGMH93IySc270TwEzTxAHbXjh2iWM89swvUKof0KyLDDq9aAgTqEQCNEvtjytmuajvJ7w5NNGoqzea5w87BXNSOwP2kjMqq2M31Cl2zagmfr3D639ZgDwdv8eMyHbY23IbnYSMdThajHaZ6CxINZ31CjnwxamWaM8T/XHorXPTEJLpmA7XNxW3NEeOqTNgeCASsSsAQvoVLXaRN8xurGqL2YJmMVAWM/aEFOTXP5uSJRYHfaIW7KxuDim5d3xtytX+0mXAOkUV3qulOuskPdZQ==" }
Obiekt myREST.RRequest jest tworzony z klasy.

Dostaję odpowiedź:
https://ksef-test.mf.gov.pl/api/v2/auth/ksef-token response: 400 Bad Requesthttps://ksef-test.mf.gov.pl/api/v2/auth/ksef-token
response: {"exception":{"serviceCtx":"srvTEMFE","serviceCode":"5B32CCFB-1FEF-4349-8E68-2C8FC3805D95","serviceName":"exception.handler"
,"timestamp":"2025-10-15T10:45:50.002Z","exceptionDetailList":[{"exceptionCode":21180,"exceptionDescription":"Nieprawidłowe żądanie."}]}}

Body jest takie samo jak w request w POSTMAN więc zakładam, że jest prawidłowe, bo z POSTMANa otrzymuje prawidłową odpowiedź.

Mam prośbę, czy ktoś mógłby sprawdzić w czym problem? Z góry dziękuję za pomoc.

W skopiowanym kodzie brakuje wartości challenge (to mój błąd) ale w request jest i to z dzisiaj. Tymi samymi danymi posługuje siw w POSTMAN-ie i otrzymuję poprawną odpowiedź. W POSTMAN nie mam nagłówka autoryzacyjnego, podaję challange, NIP i encryptedToken i otrzymuję poprawną odpowiedź:
Kopiuj

{
"referenceNumber": "20251015-AU-1E527E9000-FCD848EE53-69",
"authenticationToken": {
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0eXAiOiJBdXRoZW50aWNhdGlvblRva2VuIiwiYXJuIjoiMjAyNTEwMTUtQVUtMUU1MjdFOTAwMC1GQ0Q4NDhFRTUzLTY5IiwiZXhwIjoxNzYwNTIwODk1LCJpYXQiOjE3NjA1MTgxOTUsImlzcyI6ImtzZWYtYXBpLXRlIiwiYXVkIjoia3NlZi1hcGktdGUifQ.VpnLwd9rsUS9sgFE9CnVepWyhsjSxB_ecZA1IP0eEfk",
"validUntil": "2025-10-15T09:34:55.1918413+00:00"
}
}

T2
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 13
0

Cześć

Pytanie czy struktura logiczna FA(3) będzie obsługiwana w KSeF 1.0 ?

M1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4
0

Pytanie architektoniczne:
W przypadku aplikacji webowych — czy przechowujecie certyfikaty KSeF po stronie backendu, np. w bazie danych?

Pytanie dotyczące certyfikatów:
Mam spółki z o.o., które nie posiadają pieczęci kwalifikowanej. Jedynie pracownicy dysponują certyfikatami kwalifikowanymi powiązanymi z numerem PESEL.
Chciałbym umożliwić utworzenie wielu certyfikatów KSeF (w ramach limitu 100) i przypisanie ich do poszczególnych pracowników.

Najlepszym rozwiązaniem byłaby pieczęć kwalifikowana, dzięki której firma mogłaby samodzielnie generować certyfikaty, jednak ta opcja w naszym przypadku odpada.
Wydaje mi się niedopuszczalne również rozwiązanie, w którym pracownicy musieliby sami generować certyfikaty KSeF (po nadaniu im uprawnień), ponieważ planuję umieszczać te certyfikaty bezpośrednio w systemie.
Rozumiem, że są to ich prywatne certyfikaty — więc trudno oczekiwać, by udostępniali je w systemie firmowym.

Podsumowując — czy istnieje jakiekolwiek rozwiązanie, które pozwala firmie bez pieczęci kwalifikowanej generować certyfikaty KSeF (w ramach limitu 100)?
I drugie pytanie — czy w ogóle ma sens korzystanie z wielu certyfikatów KSeF, czy lepiej ograniczyć się do jednego zestawu w ramach danej firmy?

Dzyszla
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 185
0

Kolejna aktualizacja wjeźdża! no to już nawet nie co tydzień coś! :)\

Wersja 2.0.0 RC5.4

Pobranie listy metadanych certyfikatów (POST /invoices/query/metadata)
Dodano parametr sortOrder, umożliwiający określenie kierunku sortowania wyników.

Status sesji
Usunięto błąd uniemożliwiający uzupełnianie tej właściwości w odpowiedziach API dotyczących faktur (pole nie było wcześniej zwracane). Wartość jest uzupełniana asynchronicznie w momencie trwałego zapisu i może być tymczasowo null.

OpenAPI
Doprecyzowano definicje parametrów tablicowych w query; zastosowano style: form. Wiele wartości należy przekazywać przez powtórzenie parametru, np. ?statuses=InProgress&statuses=Succeeded. Zmiana dokumentacyjna, bez wpływu na działanie API.
Zaktualizowano opisy właściwości (partUploadRequests, encryptedSymmetricKey, initializationVector).

AP
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2
0

Witam,

może to głupie pytanie, ale już się dość mocno pogubiłem.
Udało mi się wygenerować certyfikat (/certificates/enrollments), następnie wniosek ten został poprawnie przetworzony i finalnie udało mi się go pobrać (/certificates/retrieve). W jaki sposób mam się teraz uwierzytelnić tym certyfikatem?

W dokumentacji stoi coś takiego:

Certyfikat KSeF to cyfrowe poświadczenie tożsamości podmiotu, wydawane przez system KSeF na wniosek uwierzytelnionego podmiotu. Certyfikat ten może być wykorzystywany do:
uwierzytelniania się w systemie KSeF,

Co ja mam teraz z tym certyfikatem zrobić, aby korzystać już z niego?

WJ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 47
0

Uruchomiono środowisko DEMO.
(w nocy z 15 na 16 października, zapewne o 23:55 :))

Obydwa serwery, gdy wywoła się ich "bazę" API (https://ksef-test.mf.gov.pl/api/v2, https://ksef-demo.mf.gov.pl/api/v2), zwracają swój stan:

Kopiuj
https://ksef-test.mf.gov.pl/api/v2:
{
"status":"Healthy",
"product":"KSeF API (TE)",
"version":"2.0.0",
"build":"2.0.0-rc5.4-te-20251015.1\u002Bf7f90703afae4444ee8aeec007773c68dad2b2a8"
}

https://ksef-demo.mf.gov.pl/api/v2:
{
"status":"Healthy",
"product":"KSeF API (TR)",
"version":"2.0.0",
"build":"2.0.0-rc5.4-tr-20251015.4\u002B8acd97600a19f8ffde92e22c6a7b401787af5b91"
}

W wyniku jakiegoś drobnego niedopatrzenia, gdy na stronie https://ksef-demo.mf.gov.pl kliknięcie w przycisk
[Przejdź do środowiska przedprodukcyjnego (Demo) API KSeF 2.0]
to w przeglądarce pojawi się ten JSON ze tym statusem, ale w pasku adresu powyżej - niezamaskowana nazwa bazowego serwera Azure: https://ksef-tr-api-huazctbsfvduh5gg.a01.azurefd.net/api/v2

VD
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 5
0

Nie widziałem nigdzie (może pominęło mi). Czy gdzieś jest info o czasie oczekiwanym w produkcyjnym środowisku ile trzeba będzie oczekiwać na wyniki żądań ? Np. uwierzytelnienie, albo pobranie wyniku przetwarzania wniosku certyfikacyjnego ?

Jacek Kruszniewski (JUPIT Jacek K.)
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Gliwice
  • Postów: 2
0

Witam
Jestem nowicjuszem tutaj.
Tworzę klienta KSeF 2.0, ale tylko do odbioru faktur (na razie w środowisku testowym) /system do pobierania faktur .../.
Mam projekt w python, już się loguję pieczęcią firmową wygenerowaną w python, i chcę na "testowym" nip (losowo wygenerowany) wygenerować token dostępowy lub pobrać listę faktur. I otrzymuję błąd HTTP: 403.
Czy w środowisku testowym są jakieś faktury do pobrania?

P2
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 10
0

Przy próbie wysyłki faktury z użyciem sesji interaktywnej mam Status sesji (415) uniemożliwia wysyłkę faktur. Miał ktoś taki błąd i wie co on oznacza? Otworzyłem sesję interaktywna i otrzymałem referenceNumber ale próba wysyłki skuktuje tym co napisałem. Czy możliwe że źle przygotowałem fakturę do wysyłki?

JA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1
0

Witam, testuję pobieranie faktur. Prośba w wolnej chwili o zarejestrowanie kilku na nip: 5421025750.
Pozdrawiam

SM
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2
0

Cześć, czy działa Wam może wysyłka wsadowa, co bym nie zrobił dostaję błąd: 21157 Nieprawidłowy rozmiar części pakietu. Zadeklarowany rozmiar części '1' nie zgadza się z rzeczywistym.

Co zrobiłem:

  1. Użyłem przykładowe request z dokumentacji online (Request sample) dostępny pod https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Wysylka-wsadowa/paths/~1api~1v2~1sessions~1batch/post

i wstawiłem do postmana, użyte endpointy:
a) https://ksef-test.mf.gov.pl/api/v2/sessions/batch
b) enpoint zwrócony z odpowiedzi z pkt. a
c) https://ksef-test.mf.gov.pl/api/v2/sessions/batch/{referenceNumber}/close

pkt. c zwraca błąd 21157

  1. Wyłuskałem kod z opasłej apki MF do jednej metody konsolowej w C# .net Core 5 i dalej ten sam błąd (nie oceniajcie proszę, kod jest mocno roboczy na potrzeby analizy na forum :))

< static void Main(string[] args)
{
string filePathName1 = @"C:...\FA_2_Example_1.xml";
string filePathName2 = @"C:...\FA_2_Example_2.xml";

        var invoices = new List<string>();

        invoices.Add(filePathName1);
        invoices.Add(filePathName2);

        // 1. Wczytaj pliki do pamięci
        var files = invoices.Select(f => new { FileName = Path.GetFileName(f), Content = System.IO.File.ReadAllBytes(f) }).ToList();
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // 2. Stwórz ZIP w pamięci
        byte[] zipBytes;
        using var zipStream = new MemoryStream();
        using var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, leaveOpen: true);

        foreach (var file in files)
        {
            var entry = archive.CreateEntry(file.FileName, CompressionLevel.Optimal);
            using var entryStream = entry.Open();
            entryStream.Write(file.Content);
        }

        archive.Dispose();
        zipBytes = zipStream.ToArray();
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // 3. Zrób skrót SHA256 pliku paczki, zakodowany w formacie Base64.
        int zipLength = zipBytes.Length;
        string zipHash   = "";
        using (var sha256 = SHA256.Create())
        {
            byte[] hash = sha256.ComputeHash(zipBytes);
            zipHash = Convert.ToBase64String(hash);
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // 4. Wygeneruj Klucz symetryczny o długości 32 bajtów i wektor inicjalizujący (IV) o długości 16 bajtów
        byte[] key = new byte[256 / 8];
        RandomNumberGenerator rng1 = RandomNumberGenerator.Create();
        rng1.GetBytes(key);

        byte[] iv = new byte[16];
        RandomNumberGenerator rng2 = RandomNumberGenerator.Create();
        rng2.GetBytes(iv);
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // 5. Szyfruj 1 część (na ten moment bez dzielenia na kilka części)
        int zipPartLength = 0;
        string zipPartHash   = "";
        
        Aes aes = Aes.Create();
        aes.KeySize = 256;
        aes.Mode = CipherMode.CBC;
        aes.Padding = PaddingMode.PKCS7;
        aes.BlockSize = 16 * 8;
        aes.Key = key;
        aes.IV = iv;

        ICryptoTransform encryptor = aes.CreateEncryptor();

        using Stream input = BinaryData.FromBytes(zipBytes).ToStream();
        using MemoryStream output = new();
        using CryptoStream cryptoWriter = new(output, encryptor, CryptoStreamMode.Write);
        input.CopyTo(cryptoWriter);
        cryptoWriter.FlushFinalBlock();

        output.Position = 0;
        var encrypted = BinaryData.FromStream(output).ToArray();

        zipPartLength = encrypted.Length;

        using (var sha256 = SHA256.Create())
        {
            byte[] hash = sha256.ComputeHash(encrypted);
            zipPartHash = Convert.ToBase64String(hash);
        }
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // 6. Szyfruj kluczem publicznym Ministerstwa Finansów klucz symetryczny
        // wartość z WS KSEF
        string certificateDer = "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";

        X509Certificate2 sym = new X509Certificate2(Convert.FromBase64String(certificateDer));

        RSA rsa = sym.GetRSAPublicKey();

        byte[] encryptedKey = rsa.Encrypt(key, RSAEncryptionPadding.OaepSHA256);

        string EncryptedSymmetricKey = Convert.ToBase64String(encryptedKey);
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // 7. Koduj w Base64 wektor inicjalizujący
        string InitializationVector = Convert.ToBase64String(iv);
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // 7. Buduj json do otwarcia sesji wsadowej
        string jsonBatchFileName = @"C:\...\Examples\Json_Batch.txt";
        string json = File.ReadAllText(jsonBatchFileName);

        json = json.Replace("{0}", zipLength.ToString());
        json = json.Replace("{1}", zipHash);
        json = json.Replace("{2}", zipPartLength.ToString());
        json = json.Replace("{3}", zipPartHash);
        json = json.Replace("{4}", EncryptedSymmetricKey);
        json = json.Replace("{5}", InitializationVector);
                                 
        string stop = "END"; // :)
    }/>

Zawartość pliku Json_Batch.txt

<{
"formCode": {
"systemCode": "FA (2)",
"schemaVersion": "1-0E",
"value": "FA"
},
"batchFile": {
"fileSize": {0},
"fileHash": "{1}",
"fileParts": [
{
"ordinalNumber": 1,
"fileName": "FA_Part_1.zip.aes",
"fileSize": {2},
"fileHash": "{3}"
}
]
},
"encryption": {
"encryptedSymmetricKey": "{4}",
"initializationVector": "{5}"
},
"offlineMode": false
}/>

Będę bardzo wdzięczny o pomoc / porady

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.