Krajowy system e-Faktur

Marcin Konopka
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Siedlce
  • Postów: 15
1

Sprawdzam działanie testowej aplikacji KSeF.
Wygenerowałem swoją aplikacją XML faktury wczoraj, czyli np. 07.11.2025, a dzisiaj czyli 08.11.2025 wciągam do do aplikacji KSeF poprzez "Faktury / Wczytaj fakturę" i otrzymuję komunikat błędu:
Data wystawienia, z zastrzeżeniem art. 106na ust. 1 ustawy - "Wprowadź dzisiejszą datę".
Skoro przewidziano faktury offline 24 to dlaczego nie można wysłać ich w dniu następnym??? Klient otrzymał wydrukowaną fakturę z datą 7.11 więc chyba nie należy zmieniać tej daty na 8.11.
Zgłupiałem...

Marcin IksIks
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1
0

Serdeczne Dzień Dobry!

Zrobiłem wysyłkę XML, niestety miałem problem z XML generowanymi z mojego systemu.
Te XML z aplikacji demo dołączanej do "KSeF Clienta" (invoice-template.xml) udało się wysłać, a moich nie.

Wyklikałem więc fakturę w Systemie e-faktur, pobrałem XML i się okazuje, że jego też nie można za pomocą api wysłać do KSeF - za każdym razem dostaję błąd walidacji:

Błąd weryfikacji semantyki dokumentu faktury
Could not find schema information for the element 'http://crd.gov.pl/wzor/2025/06/25/13775/:Faktura'.

Czy wczytywanie przez API obsługuje FA(3) ?

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

Jak w praktyce widzicie wykorzystanie 50 certyfikatów w przypadku podmiotów uwierzytelniających się NIP?

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 56
0

Zastanawiam się czy to zgłaszać/proponować ale najpierw zapytam, bo może już to ktoś rozkminiał. Pobranie statusu uwierzytelniania: kody 450, 460. W obu przypadkach ten sam kod jest dla kilku, powiedzmy sobie szczerze różnych przypadków. Obstawiam, że rozróżniacie w komunikatach błędów dla użytkownika między "Nieważny certyfikat" a " Certyfikat odwołany". Myślę, że zamiast porównywania stringów details z otrzymanego przez api błędu lepiej byłoby mieć oddzielne kody:
460 - Nieważny certyfikat
461 - Błąd weryfikacji łańcucha certyfikatów
itd...

Btw - jak bez narażania się na dożywocie przetestować kod 470 :P?

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

Nie mogę już edytować oryginalnego posta z kodem mojej propozycji ładowania certyfikatu z MUC do klasy X509Certificate2. W jego komentarzach @Waldek1987 zwrócił mi uwagę, że mógłbym użyć metody CreateFromEncryptedPem (dziękuję!). Istotnie, to o wiele lepszy pomysł, redukujący kilkadziesiąt linii mojego kodu z pierwszej propozycji do trzech eleganckich linii:

Kopiuj
//Wszystko typu string: certText = zawartość pliku *.crt, pkeyText = zawartość pliku *.key, pwd = hasło
if (pwd.Length == 0)
	result = X509Certificate2.CreateFromPem(certText, pkeyText);
else
	result = X509Certificate2.CreateFromEncryptedPem(certText, pkeyText, pwd); //Zgłosi wyjątek, gdy hasło się nie zgadza

Co więcej, moja pierwsza propozycja "umiała" przetwarzać tylko klucza zakodowane w PKCS#8, a metody CreateFrom*Pem wczytują także klucze kodowane w PKCS#1 (takie, które zaczynają się od napisu "----BEGIN RSA PRIVATE KEY-----", "-----BEGIN ECD PRIVATE KEY-----").

@gbbsoft, @TymOnX, @kzolnierz : potraktujcie tę wiadomość jako "erratę" tej poprzedniej.

Autoanaliza :): dlaczego od razu nie wpadłem na to lepsze rozwiązanie? No cóż, szukając go tydzień temu, "sfokusowałem" się na czymś, co potrafi odczytywać klucze zapisane w PKCS#8, bo taki format stosuje MUC. Przypominam sobie, że czytałem opis metody CreateFromEncryptedPem: Creates a new X509 certificate from the contents of an RFC 7468 PEM-encoded certificate and password protected private key. Wtedy nie wiedziałem, czym jest format "RFC 7468", a nie chciało mi się tego dociekać, bo z tego zdania wynikało, że dotyczy sposobu zapisu certyfikatu, a nie klucza. I szukałem dalej jakiejś metody, która w nazwie miałaby jawnie "Pkcs8". Jak widać, nieuctwo prowadzi do brzydkiego kodu. Czasami jednak musimy decydować "w ciemno", czy opłaca się nam sprawdzić jakiś wątek, czy też to wygląda na ślepą uliczkę i należy szukać gdzie indziej. (Bo nie ma czasu sprawdzić wszystkich możliwości, a AI też potrafi w takich niszowych tematach bzdury gadać).

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 56
0

Czytam sobie ichniejszego klienta javowego (nie wiem czy analogicznie jest w .necie). Czy dobrze widzę, że pobieranie statusu uwierzytelnienia zakłada, że w końcu wpadniemy w status 200?

Test:

Kopiuj
     await().atMost(30, SECONDS)
                .pollInterval(2, SECONDS)
                .until(() -> isAuthStatusReady(response.getReferenceNumber(), response.getAuthenticationToken().getToken()));

gdzie:

Kopiuj
    private Boolean isAuthStatusReady(String referenceNumber, String tempToken) throws ApiException {
        AuthStatus authStatus = ksefClient.getAuthStatus(referenceNumber, tempToken);
        return authStatus != null && authStatus.getStatus().getCode() == 200;
    }

Albo, w aplikacji webowej, zawsze ten sam exception:

Kopiuj
 private void isAuthStatusReady(String referenceNumber, String tempToken) throws ApiException {

        AuthStatus authStatus = ksefClient.getAuthStatus(referenceNumber, tempToken);

        if (authStatus.getStatus().getCode() != 200) {
            throw new StatusWaitingException("Authentication process has not been finished yet");
        }
    }

Wydaje mi się, że jeśli te statusy są powyżej 200 (czyli zakończone niepowodzeniem) to można w teście przestać czekać a w kontrolerze rzucić jakiś inny wyjątek.

JK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 37
0

Czy pokazujecie userom dane z exceptionDetailList.details? Np. przy autoryzacji, w details mogą się znaleźć takie przykładowe rzeczy:

  • Brak przypisanych uprawnień
  • Certyfikat KSeF typu 'Offline' nie może zostać użyty do uwierzytelnienia
  • Element wskazywany przez referencę 'null' nie został odnaleziony

itp. Z podanych przykładów pierwsze 2 zdecydowanie nadają się do pokazania, natomiast ten trzeci najprawdopodobniej nie zostanie zrozumiany i nie jest dla usera wartościowy bo nie jest to jego błąd po jego stronie tylko po stronie integratora

Zawsze pokazujecie? Nigdy nie pokazujecie (i wyświetlacie np. tylko exceptionDescription)? A może decydujecie czy pokazać details w zależności od exceptionCode?

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

Jako, że weekend i odpoczywam, jednak pojechałem zobaczy pomnik upamiętniający KSeF :)
Wybaczcie totalny off topic, ale chwila wytchnienia się należy 😀
20251110_092111.jpg

Monumentalny, choć goły
Otoczony, choć samotny
Widoczny, choć we mgle
Tak cię widzę o KSeF! :)

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

Czy kontekście tego endpointa https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Pobieranie-faktur/paths/~1api~1v2~1invoices~1query~1metadata/post da się pobrać total, całkowitą ilość pozycji wyszukiwania niezależną od offsettu i limitu? Wydaje mi się że w pierwszej wersji można było.

V2
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 28
0

Co dostaje się pobierając dane z adresów podanych w "downloadUrl" elementów tablicy "pages" w obiekcie "upo" zwracanym przez endpoint /api/v2/sessions/{referenceNumber}? Czy to jest UPO w postaci XML podzielone na tyle części ile jest elementów w tablicy "pages" (które to części trzeba skleić żeby dostać jeden XML), czy może tyle odrębnych UPO XML ile jest elementów w tablicy "pages" (a w kaźdym z tych UPO są inne faktury z danej sesji)?
Czy ma ktoś i może udostępnić przykład takiej odpowiedzi, w której jest więcej niż 1 strona z "downloadUrl", i (najlepiej) adresy URL jeszcze działają?

JK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 37
0

Czy miał ktoś z Was taki efekt w ksef 1.0, że przy logowaniu tokenem wyskakiwał błąd "Nieprawidłowe wywołanie"? Dzisiaj pomiędzy 00:08 a 09:31.
Straciłem chwilę na próbę zdebugowania o co chodzi, po czym zaczęło działać ponownie.
Czyżby coś grzebali w jedynce?

SK
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 12
0

Zapytanie odnośnie Aplikacji Podatnika - TEST:

  1. Uruchamiam https://web2te-ksef.mf.gov.pl/web/login
  2. Wynieram opcję "Zaloguj się uwierzytelnianiem testowym"
  3. Na następnej stronie mam:
    Testowy certyfikat
    Generowanie testowego certyfikatu na potrzeby autoryzacji. Po kliknięciu przycisku "Generuj certyfikat" uzyskasz SHA256 certyfikatu (do nadania uprawnienia) oraz ID (do wykorzystania certyfikatu podczas autoryzacji)

Czy ktoś może mi wyjaśnić, o co chodzi co z tym de-facto można zrobić? Bo jakoś nie kumam 😦

Potem można w tej aplikacji wygenerować certyfikat dostępowy. Ale żeby go móc użyć w wywołaniu HTTP, to trzeba jeszcze podać klucz prywatny. Jeśli sam sobie generuję certyfikat dostępowy przez API, to ten klucz mam, ale w tym przypadku, to skąd mam go wziąć?

Wdzięczny z góry za wszelkie podpowiedzi.

xoree
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0

W dokumentacji: https://ksef-demo.mf.gov.pl/docs/v2/index.html opisane są metody uwierzytelniania z wykorzystaniem podpisu XAdES oraz tokena KSeF, ale gdzie znajduje się opis uwierzytelniania przy użyciu certyfikatu KSeF?

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

Cześć) Ja coś nie bardzo rozumiem jak zrobić podpis w formacie XADES certyfikatem KSeF na PHP. Czytam, szukam i chyba nie bardzo coś znalazłem. Czy może ktoś coś powiedzieć w tym temacie ?

J0
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 82
0

Cześć. Używając TMS CP podpisałem XML'a swoim certyfikatem KSeF, ale niestety podpis został odrzucony. {"exceptionCode":9105,"exceptionDescription":"Nieprawidłowy podpis.","details":["Nieprawidłowa wartość skrótu dla referencji wskazującej na element '#xades-id-F43CED3EA3BA08A03D756B4509623475'."]}

Z wcześniejszych postów TUTAJ i TUTAJ okazuje się, że TMS nie wspiera ECDSA w starszych wersjach (moja to 4.3.2.5).

Sprawdziłem ostatnio TMS i pojawiła się wersja 5.0.9.9

v5.0.9.9
: Improved: X509Certificate.Decode (addition of many OIDs, certificate signature verification - partial
: Improved: ECDSA curves added back in PEM certificates and private keys)
: Fixed: RSA-PSS (incorrect verification)
: Fixed: Issue in TMSEncryptedIniFile
5.0.9.9: Fixed: AES-CTR (use of random IV/CTR), fix for Argon2d (missing ''var'' for a method parameter and an incorrect parameter name within a procedure)

Zastanawiam się nad wykupieniem aktualizacji.
Czy ktoś może testował już tą wersję i czy działa ona już z certyfikatami KSeF?

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

Czy udało się komuś wygenerować link weryfikacyjny KOD II przy użyciu klucza EC wygenerowanego z aplikacji podatnika? Za każdym razem mam błąd: "Podpis wystawcy nie jest prawidłowy" i "
Wystawca nie posiada uprawnienia do wystawienia faktury". Sprawdziłem tysiąc razy implementację moją i SDK i różnic nie widzę. Udało się komuś?

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

Certyfikaty KSeF (JDG) i logowanie
https://web2te-ksef.mf.gov.pl/web/ i https://mcu.mf.gov.pl/web/login

który z nich jest do testów ?

wygenerowałem za ich pomocą certyfikat do logowania
teraz przez api loguję się na nip (test) i widzę tylko ten wygenerowany w web2te, gdzie jest ten drugi (z mcu) ?

finalnie i tak nie mogę się zalogować z ich certyfikatem przez api do test:
exceptionCode=9105, exceptionDescription=Nieprawidłowy podpis.

jak wygeneruję swój certyfikat (rsa) to logowanie przechodzi, jak użyję ich to kicha, róźnica w podpisanym xmlu sprowadza się do jednego kawałka no i oczywiście samej zawartości skrótu (rsa vs ec):
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>

macie może jakąś wskazówkę - co robię nie tak ?

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

Cześć

Męczę się z kodem QR OFFLINE - w specyfikacji nie ma nic jak ma wyglądać HASH

ja mam tak:

Kopiuj
$nip = '1111111111';
$date = '01-02-2026';

$dataToHash = "{$nip}|{$date}";
$digest = hash('sha256', $dataToHash, true);
$hash = rtrim(strtr(base64_encode($digest), '+/', '-_'), '=');

$link = "https://ksef-test.mf.gov.pl/client-app/invoice/{$nip}/{$date}/{$hash}";

Niby strona się otwiera i jest napisane: Faktura nie została znaleziona w KSeF!

czy tak ma być czy cos jest złe ?
I generuje się zupełnie inny HASH niż w dokumentacji.

xoree
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0
Kopiuj
skrypt :# === KONFIG ===
NIP="1111111111"
CRT="Magnet_Ksef_Certyfikat.crt"
KEY="Magnet_Ksef_Certyfikat.key"
PASSFILE="pass.txt"


curl -s -X POST "https://ksef-demo.mf.gov.pl/api/v2/auth/challenge" \
  -H "Content-Type: application/json" \
  -d "{\"contextIdentifier\":{\"nip\":\"$NIP\"}}" > challenge.json
CHALLENGE=$(grep -o '"challenge":"[^"]*' challenge.json | cut -d'"' -f4)
echo "CHALLENGE=$CHALLENGE"


CERT_DIGEST_B64=$(openssl x509 -in "$CRT" -outform der | openssl dgst -sha256 -binary | base64 -w0)
ISSUER=$(openssl x509 -in "$CRT" -noout -issuer | sed 's/^issuer=//')
SER_HEX=$(openssl x509 -in "$CRT" -noout -serial | sed 's/^serial=//; s/://g')
SER_DEC=$((16#$SER_HEX))
SIGNING_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
CERT_BASE64=$(awk 'BEGIN{p=0} /BEGIN CERTIFICATE/{p=1;next} /END CERTIFICATE/{p=0} p' "$CRT")


cat > AuthTokenRequest.withsig.xml <<EOF
<?xml version="1.0" encoding="utf-8"?>
<AuthTokenRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns="http://ksef.mf.gov.pl/auth/token/2.0"
                  xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
                  xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">
  <Challenge>${CHALLENGE}</Challenge>
  <ContextIdentifier><Nip>${NIP}</Nip></ContextIdentifier>
  <SubjectIdentifierType>certificateSubject</SubjectIdentifierType>

  <ds:Signature Id="Sig-1">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
      <ds:Reference URI="">
        <ds:Transforms>
          <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
          <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue></ds:DigestValue>
      </ds:Reference>
      <ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#SignedProperties-1">
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue></ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue></ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>
${CERT_BASE64}
        </ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>

    <ds:Object>
      <xades:QualifyingProperties Target="#Sig-1">
        <xades:SignedProperties Id="SignedProperties-1">
          <xades:SignedSignatureProperties>
            <xades:SigningTime>${SIGNING_TIME}</xades:SigningTime>
            <xades:SigningCertificate>
              <xades:Cert>
                <xades:CertDigest>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                  <ds:DigestValue>${CERT_DIGEST_B64}</ds:DigestValue>
                </xades:CertDigest>
                <xades:IssuerSerial>
                  <ds:X509IssuerName>${ISSUER}</ds:X509IssuerName>
                  <ds:X509SerialNumber>${SER_DEC}</ds:X509SerialNumber>
                </xades:IssuerSerial>
              </xades:Cert>
            </xades:SigningCertificate>
          </xades:SignedSignatureProperties>
        </xades:SignedProperties>
      </xades:QualifyingProperties>
    </ds:Object>
  </ds:Signature>
</AuthTokenRequest>
EOF


xmlsec1 --sign \
  --privkey-pem "$KEY","$CRT" \
  --pwd "$(cat "$PASSFILE")" \
  --X509-skip-strict-checks \
  --id-attr:Id ds:Signature \
  --output AuthTokenRequest-signed.xml \
  AuthTokenRequest.withsig.xml

grep -q "<ds:Signature" AuthTokenRequest-signed.xml && echo "OK: ds:Signature jest"


curl -s -X POST "https://ksef-demo.mf.gov.pl/api/v2/auth/xades-signature?verifyCertificateChain=false" \
  -H "Content-Type: application/xml" \
  --data-binary "@AuthTokenRequest-signed.xml" | tee login-response.json


TOKEN=$(grep -o '"token":"[^"]*' login-response.json | cut -d'"' -f4 || true)
echo "TOKEN=${TOKEN}"

i dostaje
{"exception":{"exceptionDetailList":[{"exceptionCode":21115,"exceptionDescription":"Nieprawidłowy certyfikat."}],"serviceCode":"00-37d9c059ebfae4e72658b4c35cc2bce6-cde7d625d08168c0-00","timestamp":"2025-11-11T06:19:09.9788346Z"}}TOKEN=

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

Środki transportu - ktoś to wdraża u siebie? są jakieś przepisy i wymogi, może dla branży spedycyjnej, czy to zwykła nadgorliwość biurokratyczna w ramach KSeF.

Wagie-droid
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4
0

Witam,

Mam problem z wygenerowaniem offline kodów QR dla https://ksef-test.mf.gov.pl/client-app .
Mimo że postępuję zgodnie z instrukcją zawartą w przykładowym kliencie java:

Kopiuj
//Utworzenie odnośnika (Url) do weryfikacji certyfikatu (KOD II)
        String url = verificationLinkService.buildCertificateVerificationUrl(
                contextNip,
                ContextIdentifierType.NIP,
                contextNip,
                certificate.getCertificateSerialNumber(),
                invoiceHash,
                cryptographyService.parsePrivateKeyFromPem(privateKey));

zawsze otrzymuję komunikat http 404.

Czy ktoś może podać działający adres URL do weryfikacji offline, abym mógł zobaczyć, jak powinien wyglądać?

xoree
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 45
0
Kopiuj
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

########################################
# === KONFIG ===
########################################
NIP="111111111111"
CRT="main_nip.crt"
KEY="main_nip.key"
PASSFILE="pass.txt"

# Endpoints TEST
KSEF_BASE="https://ksef-test.mf.gov.pl"
URL_CHALLENGE="${KSEF_BASE}/api/v2/auth/challenge"
URL_XADES="${KSEF_BASE}/api/v2/auth/xades-signature?verifyCertificateChain=false"

# Pliki robocze
OUT_DIR="$(pwd)"
CHALLENGE_JSON="${OUT_DIR}/challenge.json"
AUTH_XML_TMPL="${OUT_DIR}/AuthTokenRequest.withsig.xml"
AUTH_XML_SIGNED="${OUT_DIR}/AuthTokenRequest-signed.xml"
LOGIN_JSON="${OUT_DIR}/login-response.json"

########################################
# === PRE-CHECKS ===
########################################
need() { command -v "$1" >/dev/null 2>&1 || { echo "Brak programu: $1" >&2; exit 1; }; }
need curl
need jq
need openssl
need xmlsec1
need bc

[[ -f "$CRT" ]] || { echo "Brak pliku certyfikatu: $CRT" >&2; exit 1; }
[[ -f "$KEY" ]] || { echo "Brak pliku klucza: $KEY" >&2; exit 1; }
[[ -f "$PASSFILE" ]] || { echo "Brak pliku hasła: $PASSFILE" >&2; exit 1; }

# Sprawdź typ klucza – oczekujemy EC
PUBALG="$(openssl x509 -in "$CRT" -noout -text | grep -Eo 'Public Key Algorithm: .*' | sed 's/^Public Key Algorithm: //')"
if [[ "$PUBALG" != "id-ecPublicKey" ]]; then
  echo "UWAGA: Certyfikat nie jest EC (wykryto: $PUBALG). Ten skrypt zakłada ECDSA-SHA256." >&2
  echo "Jeśli masz RSA, zmień SignatureMethod na rsa-sha256 i zweryfikuj całość." >&2
fi

# Weryfikacja pary klucz<->cert (fingerprint publicznych)
FPR_CERT="$(openssl x509 -in "$CRT" -pubkey -noout \
  | openssl pkey -pubin -outform der \
  | openssl dgst -sha256 | awk '{print $2}')"

FPR_KEY="$(openssl pkey -in "$KEY" -passin file:"$PASSFILE" -pubout \
  | openssl pkey -pubin -outform der \
  | openssl dgst -sha256 | awk '{print $2}')"

if [[ "$FPR_CERT" != "$FPR_KEY" ]]; then
  echo "BŁĄD: Klucz prywatny nie pasuje do certyfikatu (fingerprinty różne)." >&2
  exit 1
fi

########################################
# === POBRANIE CHALLENGE ===
########################################
echo "[1/4] Pobieram challenge..."
curl -s -X POST "$URL_CHALLENGE" \
  -H "Content-Type: application/json" \
  -d "{\"contextIdentifier\":{\"nip\":\"$NIP\"}}" > "$CHALLENGE_JSON"

CHALLENGE="$(jq -r '.challenge' "$CHALLENGE_JSON")"
if [[ -z "${CHALLENGE:-}" || "$CHALLENGE" == "null" ]]; then
  echo "BŁĄD: Nie udało się pobrać challenge. Odpowiedź:" >&2
  jq -c . "$CHALLENGE_JSON" >&2 || true
  exit 1
fi
echo "CHALLENGE=${CHALLENGE}"

########################################
# === DANE DO XAdES ===
########################################
echo "[2/4] Przygotowuję dane do XAdES..."

# Digest certyfikatu (DER → SHA256 → base64)
CERT_DIGEST_B64="$(openssl x509 -in "$CRT" -outform der | openssl dgst -sha256 -binary | base64 -w0)"

# Issuer (dokładnie tak jak z certu, bez 'issuer=')
ISSUER="$(openssl x509 -in "$CRT" -noout -issuer | sed 's/^issuer=//')"

# Serial HEX → DEC
SER_HEX="$(openssl x509 -in "$CRT" -noout -serial | sed 's/^serial=//; s/://g')"
SER_HEX_UP="$(echo "$SER_HEX" | tr '[:lower:]' '[:upper:]')"
SER_DEC="$(echo "ibase=16; $SER_HEX_UP" | bc)"

# Czas podpisu (UTC, ISO8601)
SIGNING_TIME="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"

# Zawartość certyfikatu Base64 (bez nagłówków/stopki)
CERT_BASE64="$(awk 'BEGIN{p=0} /BEGIN CERTIFICATE/{p=1;next} /END CERTIFICATE/{p=0} p' "$CRT")"

########################################
# === SZABLON XML (ECDSA-SHA256) ===
########################################
cat > "$AUTH_XML_TMPL" <<EOF
<?xml version="1.0" encoding="utf-8"?>
<AuthTokenRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns="http://ksef.mf.gov.pl/auth/token/2.0"
                  xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
                  xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">
  <Challenge>${CHALLENGE}</Challenge>
  <ContextIdentifier><Nip>${NIP}</Nip></ContextIdentifier>
  <SubjectIdentifierType>certificateSubject</SubjectIdentifierType>

  <ds:Signature Id="Sig-1">
    <ds:SignedInfo>
      <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
      <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"/>
      <ds:Reference URI="">
        <ds:Transforms>
          <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
          <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
        </ds:Transforms>
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue></ds:DigestValue>
      </ds:Reference>
      <ds:Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#SignedProperties-1">
        <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
        <ds:DigestValue></ds:DigestValue>
      </ds:Reference>
    </ds:SignedInfo>
    <ds:SignatureValue></ds:SignatureValue>
    <ds:KeyInfo>
      <ds:X509Data>
        <ds:X509Certificate>
${CERT_BASE64}
        </ds:X509Certificate>
      </ds:X509Data>
    </ds:KeyInfo>

    <ds:Object>
      <xades:QualifyingProperties Target="#Sig-1">
        <xades:SignedProperties Id="SignedProperties-1">
          <xades:SignedSignatureProperties>
            <xades:SigningTime>${SIGNING_TIME}</xades:SigningTime>
            <xades:SigningCertificate>
              <xades:Cert>
                <xades:CertDigest>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                  <ds:DigestValue>${CERT_DIGEST_B64}</ds:DigestValue>
                </xades:CertDigest>
                <xades:IssuerSerial>
                  <ds:X509IssuerName>${ISSUER}</ds:X509IssuerName>
                  <ds:X509SerialNumber>${SER_DEC}</ds:X509SerialNumber>
                </xades:IssuerSerial>
              </xades:Cert>
            </xades:SigningCertificate>
          </xades:SignedSignatureProperties>
        </xades:SignedProperties>
      </xades:QualifyingProperties>
    </ds:Object>
  </ds:Signature>
</AuthTokenRequest>
EOF

########################################
# === PODPISANIE XML ===
########################################
echo "[3/4] Podpisuję XML (xmlsec1)..."
xmlsec1 --sign \
  --privkey-pem "$KEY","$CRT" \
  --pwd "$(cat "$PASSFILE")" \
  --X509-skip-strict-checks \
  --id-attr:Id ds:Signature \
  --output "$AUTH_XML_SIGNED" \
  "$AUTH_XML_TMPL"

# Lokalna weryfikacja integralności (ostrzeżenie o CA można zignorować)
xmlsec1 --verify --pubkey-cert-pem "$CRT" --id-attr:Id ds:Signature "$AUTH_XML_SIGNED" || true

########################################
# === WYŚLIJ PODPIS I ODBIERZ TOKEN ===
########################################
echo "[4/4] Wysyłam podpis do KSeF (TEST)..."
curl -s -X POST "$URL_XADES" \
  -H "Content-Type: application/xml" \
  --data-binary "@${AUTH_XML_SIGNED}" > "$LOGIN_JSON"

# Token / błąd
TOKEN="$(jq -r '.authenticationToken.token // empty' "$LOGIN_JSON")"
VALID_UNTIL="$(jq -r '.authenticationToken.validUntil // empty' "$LOGIN_JSON")"

if [[ -n "$TOKEN" ]]; then
  echo "OK: Otrzymano authenticationToken."
  echo "TOKEN=${TOKEN}"
  [[ -n "$VALID_UNTIL" && "$VALID_UNTIL" != "null" ]] && echo "VALID_UNTIL=${VALID_UNTIL}"
  exit 0
else
  echo "BŁĄD: Brak tokenu. Odpowiedź serwera:" >&2
  jq -c . "$LOGIN_JSON" >&2 || cat "$LOGIN_JSON" >&2
  exit 1
fi

Ok działa jak się zrobi to: "Stl86 dziś, 09:12
a skąd masz ten certyfikat? z MCU ? Jak chcesz przetestować certyfikaty KSeF to wejdź na https://web2te-ksef.mf.gov.pl/ na dowolny nip/pesel , tam zrób sobie certyfikat i spróbuj z nim ale na środowisko test a nie demo." - Dla potomnych. skrypt zwraca token jak już token jest to sprawa prosta ;)

tmg
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 11
0

Utknąłem w jednym punkcie. Testuję wysyłkę sesją interaktywną do instancji TEST i ciągle mam błąd "Błąd weryfikacji pliku faktury". Sam plik faktury przechodzi mi weryfikację XSD (schema v3) bezbłędnie. Co więcej w apce testowej mogę go załadować jako fakturę też bez błędu. Wydaje mi się że błęd wskazuje na problem z danymi na fakturze a nie procesem jej odszyfrowania (czy się mylę?). A może instancja testowa ma jakieś ograniczenie o kótrym nie wiem. Szukałem w starszych wątkach ale bez rezultatu. Poproszę o jakąś podpowiedź :)

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 56
0

Hej
Po udanym uwierzytelnieniu dostajemy refNumber uwierzytenienia i tmpAuthToken. Później redeemujemy tmpAuthToken i dostajemy accessToken + refreshToken.
Teraz tak - tmpAuthToken jest ważny 45min a refreshtoken jest ważny tydzień.
Którego tokena można użyć na następny dzień (i resztę 7 dni ważności konkretnego uwierzytelnienia), żeby wyciągnąć status "/api/v2/auth/{referenceNumber}".
Po co? - a tak bym chciał sobie sprawdzić pole lastTokenRefreshDate z odpowiedzi.
Użycie czegokolwiek poza tmpAuthToken rzuca 403.

DR
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 4
0
tmg napisał(a):

[ ..] Sam plik faktury przechodzi mi weryfikację XSD (schema v3) bezbłędnie.
a jak to robisz

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

Ktoś robił walidacje faktur z wykorzystaniem schemat (FA3).xsd w c# ?
w przypadku KSeF 1.0 walidacja działała, a teraz wywala błąd nawet dla przykładowych faktur z MF:
Type 'http://crd.gov.pl/xml/schematy/dziedzinowe/mf/2022/01/05/eD/DefinicjeTypy/:TNaturalny' is not declared, or is not a simple type.”

            xml.Load(sXMLPath);
            xml.Schemas.Add(null, _sXSDPath);                              
            try
            {
                xml.Validate(null);
            }
            ..

Znalazłem tylko jeden wątek w tym temacie ale walidacja odbywała się przy pomocy pliku zewnętrzengo exe ...

JO
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 8
0

Cześć wszystkim, mam pytanie dotyczące znaczenia "ContextIdentifier” w kontekście uwierzytelniania i kodów QR offline. Jeśli jestem podmiotem z NIP upoważnionym do wystawiania faktur w imieniu sprzedawcy, wyobrażam sobie, że podczas uwierzytelniania „ContextIdentifier” powinien być identyfikatorem sprzedawcy, który mnie autoryzował, a podpis "AuthTokenRequest” powinien wykorzystywać mój certyfikat.

Z drugiej strony, podczas generowania kodu QR do przesłania offline, KSEF informuje, że link musi zawierać:

  • wartości identyfikatora kontekstu
  • NIP sprzedawcy

Który NIP powinien zostać użyty w każdym polu? (W tym scenariuszu mamy NIP sprzedawcy, który mnie autoryzował, oraz mój NIP, dla którego posiadam certyfikat).

PK_64
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
  • Postów: 30
0

Czy ktoś mi może powiedzieć dlaczego ten XML jest niepoprawny ?

<?xml version="1.0" encoding="utf-8"?> <faktura xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/"> <naglowek> <kodformularza kodsystemowy="FA(3)" wersjaschemy="1-0E">FA</kodformularza> <wariantformularza>3</wariantformularza> <datawytworzeniafa>2025-11-11T20:13:11.027Z</datawytworzeniafa> <systeminfo>IKOR-FK System INFO-KOR</systeminfo> </naglowek> <podmiot1> <prefikspodatnika>PL</prefikspodatnika> <daneidentyfikacyjne> <nip>5730010551</nip> <nazwa> Sp. z o.o.</nazwa> </daneidentyfikacyjne> <adres> <kodkraju>PL</kodkraju> <adresl1>Kalinowa 29</adresl1> <adresl2>42-221 Częstochowa</adresl2> </adres> </podmiot1> <podmiot2> <daneidentyfikacyjne> <nip>1132809791</nip> <nazwa>7777</nazwa> </daneidentyfikacyjne> <adres> <kodkraju>PL</kodkraju> <adresl1>777</adresl1> <adresl2>05-800 Pruszków</adresl2> </adres> <jst>2</jst><gv>2</gv> </podmiot2> <fa> <kodwaluty>PLN</kodwaluty> <p_1>2025-11-11</p_1> <p_1m>Warszawa</p_1m> <p_2>75/25/FWA</p_2> <p_6>2025-11-11</p_6> <p_13_1>5080.00</p_13_1> <p_14_1>1168.40</p_14_1> <p_15>6248.40</p_15> <adnotacje> <p_16>2</p_16> <p_17>2</p_17> <p_18>2</p_18> <p_18a>2</p_18a> <zwolnienie> <p_19n>1</p_19n> </zwolnienie> <nowesrodkitransportu><p_22n>1</p_22n></nowesrodkitransportu> <p_23>2</p_23> <pmarzy><p_pmarzyn>1</p_pmarzyn></pmarzy> </adnotacje> <rodzajfaktury>VAT</rodzajfaktury> <dodatkowyopis> <nrwiersza>1</nrwiersza> <klucz>Opis</klucz> <wartosc>za okres 07.2025</wartosc> </dodatkowyopis> <dodatkowyopis> <nrwiersza>2</nrwiersza> <klucz>Opis</klucz> <wartosc>za okres 07.2025</wartosc> </dodatkowyopis> <dodatkowyopis> <nrwiersza>3</nrwiersza> <klucz>Opis</klucz> <wartosc>Archiwizacja, konserwacja za okres 07.2025</wartosc> </dodatkowyopis> <fawiersz> <nrwierszafa>1</nrwierszafa> <p_7>Usługi informatyczne</p_7> <p_8a>Szt</p_8a> <p_8b>1.00</p_8b> <p_9a>1800.00</p_9a> <p_11>1800.00</p_11> <p_12>Podatek</p_12> </fawiersz> <fawiersz> <nrwierszafa>2</nrwierszafa> <p_7>Wypożyczenie oprogramowania i bazy danych</p_7> <p_8a>Szt</p_8a> <p_8b>26.00</p_8b> <p_9a>80.00</p_9a> <p_11>2080.00</p_11> <p_12>Podatek</p_12> </fawiersz> <fawiersz> <nrwierszafa>3</nrwierszafa> <p_7>Usługi naSzt.u serwera</p_7> <p_8a>Szt</p_8a> <p_8b>1.00</p_8b> <p_9a>1200.00</p_9a> <p_11>1200.00</p_11> <p_12>Podatek</p_12> </fawiersz> <platnosc> <formaplatnosci>6</formaplatnosci> </platnosc> </fa> </faktura>
RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 56
0

Taka ciekawostka (jeśli komuś randomowo testy failują): Jeśli po uwierzytelnieniu za szybko odświeży się accessToken to dostaje się nową datę validUntil ale token zostaje ten sam. W scenariuszu uwierzytelnienie, otwarcie sesji, refreshToken (wykonywane bez przerw) dostaję ten sam accessToken raz na trzy/cztery razy.

PK_64
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Warszawa
  • Postów: 30
0
PK_64 napisał(a):

Czy ktoś mi może powiedzieć dlaczego ten XML jest niepoprawny ?

<?xml version="1.0" encoding="utf-8"?> <faktura xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://crd.gov.pl/wzor/2025/06/25/13775/"> <naglowek> <kodformularza kodsystemowy="FA (3)" wersjaschemy="1-0E">FA</kodformularza> <wariantformularza>3</wariantformularza> <datawytworzeniafa>2025-11-11T20:13:11.027Z</datawytworzeniafa> <systeminfo>IKOR-FK System INFO-KOR</systeminfo> </naglowek> <podmiot1> <prefikspodatnika>PL</prefikspodatnika> <daneidentyfikacyjne> <nip>5730010551</nip> <nazwa> Sp. z o.o.</nazwa> </daneidentyfikacyjne> <adres> <kodkraju>PL</kodkraju> <adresl1>Kalinowa 29</adresl1> <adresl2>42-221 Częstochowa</adresl2> </adres> </podmiot1> <podmiot2> <daneidentyfikacyjne> <nip>1132809791</nip> <nazwa>7777</nazwa> </daneidentyfikacyjne> <adres> <kodkraju>PL</kodkraju> <adresl1>777</adresl1> <adresl2>05-800 Pruszków</adresl2> </adres> <jst>2</jst><gv>2</gv> </podmiot2> <fa> <kodwaluty>PLN</kodwaluty> <p_1>2025-11-11</p_1> <p_1m>Warszawa</p_1m> <p_2>75/25/FWA</p_2> <p_6>2025-11-11</p_6> <p_13_1>5080.00</p_13_1> <p_14_1>1168.40</p_14_1> <p_15>6248.40</p_15> <adnotacje> <p_16>2</p_16> <p_17>2</p_17> <p_18>2</p_18> <p_18a>2</p_18a> <zwolnienie> <p_19n>1</p_19n> </zwolnienie> <nowesrodkitransportu><p_22n>1</p_22n></nowesrodkitransportu> <p_23>2</p_23> <pmarzy><p_pmarzyn>1</p_pmarzyn></pmarzy> </adnotacje> <rodzajfaktury>VAT</rodzajfaktury> <dodatkowyopis> <nrwiersza>1</nrwiersza> <klucz>Opis</klucz> <wartosc>za okres 07.2025</wartosc> </dodatkowyopis> <dodatkowyopis> <nrwiersza>2</nrwiersza> <klucz>Opis</klucz> <wartosc>za okres 07.2025</wartosc> </dodatkowyopis> <dodatkowyopis> <nrwiersza>3</nrwiersza> <klucz>Opis</klucz> <wartosc>Archiwizacja, konserwacja za okres 07.2025</wartosc> </dodatkowyopis> <fawiersz> <nrwierszafa>1</nrwierszafa> <p_7>Usługi informatyczne</p_7> <p_8a>Szt</p_8a> <p_8b>1.00</p_8b> <p_9a>1800.00</p_9a> <p_11>1800.00</p_11> <p_12>23</p_12> </fawiersz> <fawiersz> <nrwierszafa>2</nrwierszafa> <p_7>Wypożyczenie oprogramowania i bazy danych</p_7> <p_8a>Szt</p_8a> <p_8b>26.00</p_8b> <p_9a>80.00</p_9a> <p_11>2080.00</p_11> <p_12>23</p_12> </fawiersz> <fawiersz> <nrwierszafa>3</nrwierszafa> <p_7>Usługi naSzt.u serwera</p_7> <p_8a>Szt</p_8a> <p_8b>1.00</p_8b> <p_9a>1200.00</p_9a> <p_11>1200.00</p_11> <p_12>23</p_12> </fawiersz> <platnosc> <formaplatnosci>6</formaplatnosci> </platnosc> </fa> </faktura>

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.