Krajowy system e-Faktur

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

Tego ma nie być

public function encryptToken($token, $challengeTimeMillis) {
    $dataToEncrypt = "$token|$challengeTimeMillis";
    $publicKey = file_get_contents($this->publicKeyPath);
    if (!$publicKey) {
        echo "Nie można odczytać klucza publicznego.\n";
        return false;
    }

    if (openssl_public_encrypt($dataToEncrypt, $encrypted, $publicKey, OPENSSL_PKCS1_PADDING)) {
        return base64_encode($encrypted);
    } else {
        echo "Nie udało się zaszyfrować tokenu.\n";
        return false;
    }

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

Teraz mam
Błąd w uzyskiwaniu tokenu sesji. {"exception":{"serviceCtx":"srvTEMFD","serviceCode":"20250721-EX-05CF6133B5-2A5B60B197-37","serviceName":"online.session.session.token.init","timestamp":"2025-07-21T11:00:35.546Z","referenceNumber":"20250721-SE-46BA42C035-6522003106-3B","exceptionDetailList":[{"exceptionCode":21401,"exceptionDescription":"Dokument nie jest zgodny ze schemą (xsd)."}]}}

skąd moge pobrać cheme ?

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

Mam pytanie wysyłam fakturę i mam w odpowiedzi
"response" => "{"timestamp":"2025-07-22T06:47:42.333Z","referenceNumber":"20250722-SE-8DEF7ABAA2-2583E4BD12-EE","processingCode":100,"processingDescription":"Proces został zarejestrowany.","elementReferenceNumber":"20250722-EE-BD5FC8AC9A-20A5F19BDF-F5"} ◀"
"httpCode" => 202
czy to znaczy że faktura jest wysłana, mogę ja pobrać, poniżej jest kod do wysyłki faktury
public function sendInvoice2($invoiceFile, $session)
{
if (!file_exists($invoiceFile) || !is_readable($invoiceFile)) {
die("Plik faktury nie istnieje lub nie można go odczytać: $invoiceFile\n");
}

    $invoiceData = file_get_contents($invoiceFile);
    $hashSHA = base64_encode(hash('sha256', $invoiceData, true));
    $invoiceBody = base64_encode($invoiceData);
    $fSize = filesize($invoiceFile);

    $body = json_encode([
        "invoiceHash" => [
            "fileSize" => $fSize,
            "hashSHA" => [
                "algorithm" => "SHA-256",
                "encoding" => "Base64",
                "value" => $hashSHA
            ]
        ],
        "invoicePayload" => [
            "type" => "plain",
            "invoiceBody" => $invoiceBody
        ]
    ]);

    $headers = [
        'Accept: application/json',
        'Content-Type: application/json', // ✅ poprawione
        'SessionToken: ' . $session // ✅ wymagane
    ];


    $response = $this->sendRequest("{$this->apiUrl}/online/Invoice/Send", $body, $headers, 'PUT');

    $httpCode = $response['httpCode'];

    if (in_array($httpCode, [200, 201, 202])) {
        return json_decode($response['response'], true);
    } else {
        echo "Błąd w wysyłaniu faktury. HTTP $httpCode\n";
        echo $response['response'] . "\n";
        return false;
    }
}

W dokumentacji widziałem że endpoint to https://ksef-test.mf.gov.pl/api/v2/sessions/online/{referenceNumber}/invoices
M4
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 58
0
mores4 napisał(a):

Mam pytanie wysyłam fakturę i mam w odpowiedzi
"response" => "{"timestamp":"2025-07-22T06:47:42.333Z","referenceNumber":"20250722-SE-8DEF7ABAA2-2583E4BD12-EE","processingCode":100,"processingDescription":"Proces został zarejestrowany.","elementReferenceNumber":"20250722-EE-BD5FC8AC9A-20A5F19BDF-F5"} ◀"
"httpCode" => 202
czy to znaczy że faktura jest wysłana, mogę ja pobrać, poniżej jest kod do wysyłki faktury
public function sendInvoice2($invoiceFile, $session)
{
if (!file_exists($invoiceFile) || !is_readable($invoiceFile)) {
die("Plik faktury nie istnieje lub nie można go odczytać: $invoiceFile\n");
}

    $invoiceData = file_get_contents($invoiceFile);
    $hashSHA = base64_encode(hash('sha256', $invoiceData, true));
    $invoiceBody = base64_encode($invoiceData);
    $fSize = filesize($invoiceFile);

    $body = json_encode([
        "invoiceHash" => [
            "fileSize" => $fSize,
            "hashSHA" => [
                "algorithm" => "SHA-256",
                "encoding" => "Base64",
                "value" => $hashSHA
            ]
        ],
        "invoicePayload" => [
            "type" => "plain",
            "invoiceBody" => $invoiceBody
        ]
    ]);

    $headers = [
        'Accept: application/json',
        'Content-Type: application/json', // ✅ poprawione
        'SessionToken: ' . $session // ✅ wymagane
    ];


    $response = $this->sendRequest("{$this->apiUrl}/online/Invoice/Send", $body, $headers, 'PUT');

    $httpCode = $response['httpCode'];

    if (in_array($httpCode, [200, 201, 202])) {
        return json_decode($response['response'], true);
    } else {
        echo "Błąd w wysyłaniu faktury. HTTP $httpCode\n";
        echo $response['response'] . "\n";
        return false;
    }
}

W dokumentacji widziałem że endpoint to https://ksef-test.mf.gov.pl/api/v2/sessions/online/{referenceNumber}/invoices

Rozumie że powinienem używać api v2 ?

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

Czy dobrze rozumie że środowisko testowe obsługujące api v2 będzie dostępne od 30 września ?

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

Witam,
Ostatnio miałem wiele skarg, że portal/API KSeF nie dostarcza przydatnych informacji, gdy dokument zostanie odrzucony.

Wiązałem duże nadzieje z KSeF 2.0, ale tam też nie ma wzmianki o weryfikacji.

Jak sobie z tym radzicie?
screenshot-20250722164327.png

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

Wysłałem wczoraj fakturę na serwer testowy jednak do dziś nie widzę jej w aplikacji testowe MF, co może być nie tak ?

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

Sprawdziłem status faktury po wysyłce i mam błąd
"timestamp": "2025-07-23T07:39:17.301Z",
"referenceNumber": "20250723-SE-8E28161BEB-1CE5F13404-1C",
"processingCode": 425,
"processingDescription": "21417:Nieobsługiwana wersja dokumentu",
"elementReferenceNumber": "20250723-EE-487469D5B8-BD60718898-68",
"invoiceStatus": {}
Poniżej faktura, co jest nie tak
<?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:etd="http://crd.gov.pl/xml/schematy/2020/10/08/eDokumenty" xmlns="http://crd.gov.pl/wzor/2023/06/29/12648/">
<Naglowek>
<KodFormularza kodSystemowy="FA (2)" wersjaSchemy="1-0E">FA</KodFormularza>
<WariantFormularza>2</WariantFormularza>
<DataWytworzeniaFa>2025-05-20T00:02:31.7293142Z</DataWytworzeniaFa>
<SystemInfo>Generator danych</SystemInfo>
</Naglowek>
<Podmiot1>
<DaneIdentyfikacyjne>
<NIP>7343170998</NIP>
<Nazwa>Twardowski, Januszewski and Żyła</Nazwa>
</DaneIdentyfikacyjne>
<Adres>
<KodKraju>PL</KodKraju>
<AdresL1>al. Bochenek 4828</AdresL1>
<AdresL2>01-179 Zagórz</AdresL2>
</Adres>
<DaneKontaktowe>
<Email>Ksawera.Kubacki@example.com</Email>
<Telefon>17-683-41-36</Telefon>
</DaneKontaktowe>
</Podmiot1>
<Podmiot2>
<DaneIdentyfikacyjne>
<NIP>6888785549</NIP>
<Nazwa>Adamus and Sons</Nazwa>
</DaneIdentyfikacyjne>
<Adres>
<KodKraju>PL</KodKraju>
<AdresL1>al. Jędrzejczak 95518</AdresL1>
<AdresL2>76-424 Lubawa</AdresL2>
</Adres>
<DaneKontaktowe>
<Email>Sergiusz.Piasecki@yahoo.com</Email>
<Telefon>41-825-77-29</Telefon>
</DaneKontaktowe>
<NrKlienta>KL-7922</NrKlienta>
</Podmiot2>
<Fa>
<KodWaluty>PLN</KodWaluty>
<P_1>2025-06-15</P_1>
<P_1M>Polanica-Zdrój</P_1M>
<P_2>FA/GRQMB-#invoice_number#/05/2025</P_2>
<P_6>2025-05-18</P_6>
<P_13_1>28457.88</P_13_1>
<P_14_1>6545.31</P_14_1>
<P_15>35003.19</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>
<FaWiersz>
<NrWierszaFa>1</NrWierszaFa>
<UU_ID>50114615-1a94-06fd-4b58-7e6cd042abcd</UU_ID>
<P_7>Gorgeous Metal Shirt</P_7>
<P_8A>szt.</P_8A>
<P_8B>3</P_8B>
<P_9A>59.38</P_9A>
<P_11>178.14</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>2</NrWierszaFa>
<UU_ID>a4ce7b32-da15-da19-f357-984e2946d1e7</UU_ID>
<P_7>Handmade Concrete Chicken</P_7>
<P_8A>szt.</P_8A>
<P_8B>6</P_8B>
<P_9A>437.30</P_9A>
<P_11>2623.80</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>3</NrWierszaFa>
<UU_ID>6276dee1-8420-1603-c4fa-76fa661a7101</UU_ID>
<P_7>Awesome Plastic Soap</P_7>
<P_8A>szt.</P_8A>
<P_8B>4</P_8B>
<P_9A>509.70</P_9A>
<P_11>2038.80</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>4</NrWierszaFa>
<UU_ID>b8735d0f-a255-bf76-cd64-921a28807e17</UU_ID>
<P_7>Handcrafted Plastic Chicken</P_7>
<P_8A>szt.</P_8A>
<P_8B>4</P_8B>
<P_9A>824.13</P_9A>
<P_11>3296.52</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>5</NrWierszaFa>
<UU_ID>b60d756e-7a97-a51f-f3e4-fc51bb756c6d</UU_ID>
<P_7>Intelligent Granite Ball</P_7>
<P_8A>szt.</P_8A>
<P_8B>10</P_8B>
<P_9A>146.72</P_9A>
<P_11>1467.20</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>6</NrWierszaFa>
<UU_ID>f7b537dc-c749-bc97-61dc-f44f7ba19b54</UU_ID>
<P_7>Unbranded Plastic Bacon</P_7>
<P_8A>szt.</P_8A>
<P_8B>6</P_8B>
<P_9A>944.35</P_9A>
<P_11>5666.10</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>7</NrWierszaFa>
<UU_ID>ae9e8505-323f-9e1f-b300-691f537ab332</UU_ID>
<P_7>Handmade Metal Chicken</P_7>
<P_8A>szt.</P_8A>
<P_8B>3</P_8B>
<P_9A>130.78</P_9A>
<P_11>392.34</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>8</NrWierszaFa>
<UU_ID>4bbc175d-c8de-75b5-88a5-a7c273403730</UU_ID>
<P_7>Refined Granite Mouse</P_7>
<P_8A>szt.</P_8A>
<P_8B>10</P_8B>
<P_9A>622.27</P_9A>
<P_11>6222.70</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>9</NrWierszaFa>
<UU_ID>a09eac2f-e8c1-3c7a-bcd9-62a5cb4f1068</UU_ID>
<P_7>Handcrafted Granite Hat</P_7>
<P_8A>szt.</P_8A>
<P_8B>8</P_8B>
<P_9A>173.12</P_9A>
<P_11>1384.96</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>10</NrWierszaFa>
<UU_ID>1324529f-e29c-b009-126c-ebf2c091c2da</UU_ID>
<P_7>Incredible Metal Mouse</P_7>
<P_8A>szt.</P_8A>
<P_8B>9</P_8B>
<P_9A>419.46</P_9A>
<P_11>3775.14</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>11</NrWierszaFa>
<UU_ID>b9f53150-e024-2c98-dc7c-7cea995a3d92</UU_ID>
<P_7>Rustic Metal Table</P_7>
<P_8A>szt.</P_8A>
<P_8B>6</P_8B>
<P_9A>109.27</P_9A>
<P_11>655.62</P_11>
<P_12>23</P_12>
</FaWiersz>
<FaWiersz>
<NrWierszaFa>12</NrWierszaFa>
<UU_ID>fa465ac5-bc71-30b4-c7ee-368d37a4ab53</UU_ID>
<P_7>Unbranded Wooden Gloves</P_7>
<P_8A>szt.</P_8A>
<P_8B>4</P_8B>
<P_9A>189.14</P_9A>
<P_11>756.56</P_11>
<P_12>23</P_12>
</FaWiersz>
<Platnosc>
<Zaplacono>1</Zaplacono>
<DataZaplaty>2025-06-02</DataZaplaty>
<FormaPlatnosci>7</FormaPlatnosci>
</Platnosc>
</Fa>
</Faktura>

M4
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 58
0
Kopiuj
public function getKSeFSessionToken(string $encryptedToken, string $challenge): ?array
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->preserveWhiteSpace = false;
        $dom->formatOutput = true;
        $dom->xmlStandalone = true;

        $root = $dom->createElementNS(
            'http://ksef.mf.gov.pl/schema/gtw/svc/online/auth/request/2021/10/01/0001',
            'ns3:InitSessionTokenRequest'
        );

        $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://ksef.mf.gov.pl/schema/gtw/svc/online/types/2021/10/01/0001');
        $root->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:ns2', 'http://ksef.mf.gov.pl/schema/gtw/svc/types/2021/10/01/0001');
        $dom->appendChild($root);

        // Context
        $context = $dom->createElement('ns3:Context');
        $root->appendChild($context);

        // Challenge
        $challengeElement = $dom->createElement('Challenge', $challenge);
        $context->appendChild($challengeElement);

        // Identifier
        $identifier = $dom->createElement('Identifier');
        $identifier->setAttributeNS(
            'http://www.w3.org/2001/XMLSchema-instance',
            'xsi:type',
            'ns2:SubjectIdentifierByCompanyType'
        );
        $ns2Identifier = $dom->createElement('ns2:Identifier', $this->nip);
        $identifier->appendChild($ns2Identifier);
        $context->appendChild($identifier);

        // DocumentType
        $documentType = $dom->createElement('DocumentType');
        $service = $dom->createElement('ns2:Service', 'KSeF');
        $documentType->appendChild($service);

        $formCode = $dom->createElement('ns2:FormCode');
        $formCode->appendChild($dom->createElement('ns2:SystemCode', 'FA (1)'));
        $formCode->appendChild($dom->createElement('ns2:SchemaVersion', '1-0E'));
        $formCode->appendChild($dom->createElement('ns2:TargetNamespace', 'http://crd.gov.pl/wzor/2021/11/29/11089/'));
        $formCode->appendChild($dom->createElement('ns2:Value', 'FA'));
        $documentType->appendChild($formCode);
        $context->appendChild($documentType);

        // Token
        $tokenElement = $dom->createElement('Token', trim($encryptedToken));
        $context->appendChild($tokenElement);

        // Przygotowanie i wysyłka
        $url = "{$this->apiUrl}/online/Session/InitToken";
        $headers = [
            "Content-Type: application/octet-stream",
            "Accept: application/json"
        ];

        $xmlPayload = $dom->saveXML();
        $response = $this->sendRequest($url, $xmlPayload, $headers);

        if ($response['httpCode'] === 200 || $response['httpCode'] === 201) {
            $data = json_decode($response['response'], true);

            return [
                'referenceNumber' => $data['referenceNumber'] ?? null,
                'token' => $data['sessionToken']['token'] ?? null,
            ];
        } else {
            echo "Błąd w uzyskiwaniu tokenu sesji.\n";
            echo $response['response'] . "\n";
            return null;
        }
    }

   public function sendInvoice2($invoiceFile, $session)
    {
        if (!file_exists($invoiceFile) || !is_readable($invoiceFile)) {
            die("Plik faktury nie istnieje lub nie można go odczytać: $invoiceFile\n");
        }

        $invoiceData = file_get_contents($invoiceFile);
        $hashSHA = base64_encode(hash('sha256', $invoiceData, true));
        $invoiceBody = base64_encode($invoiceData);
        $fSize = filesize($invoiceFile);

        $body = json_encode([
            "invoiceHash" => [
                "fileSize" => $fSize,
                "hashSHA" => [
                    "algorithm" => "SHA-256",
                    "encoding" => "Base64",
                    "value" => $hashSHA
                ]
            ],
            "invoicePayload" => [
                "type" => "plain",
                "invoiceBody" => $invoiceBody
            ]
        ]);

        $headers = [
            'Accept: application/json',
            'Content-Type: application/json',
            'SessionToken: ' . $session
        ];

        $response = $this->sendRequest("{$this->apiUrl}/online/Invoice/Send", $body, $headers, 'PUT');
        //dump($response);

        $httpCode = $response['httpCode'];

        if (in_array($httpCode, [200, 201, 202])) {
            $responseData = json_decode($response['response'], true);
            if (isset($responseData['elementReferenceNumber'])) {
                // Zwróć pełną odpowiedź oraz elementReferenceNumber dla łatwego dostępu
                return [
                    'response' => $responseData,
                    'elementReferenceNumber' => $responseData['elementReferenceNumber']
                ];
            }
            return ['response' => $responseData];
        } else {
            echo "Błąd w wysyłaniu faktury. HTTP $httpCode\n";
            echo $response['response'] . "\n";
            return false;
        }
    }


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

zadeklarowałem FA(1) i wysyłam FA(1) i też ten błąd nieobsługiwana wersja dokumentu

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

Dotyczy API 2.0. Mam kolejny feedback do zgłoszenia z 30 czerwca (o tym, że funkcja AuthCoordinator.AuthAsync() z biblioteki .NET nie będzie działać, bo zostawiono w niej kod przykładowy stworzony na potrzeby pewnej ilustracji w dokumentacji uwierzytelnień):

Szanowny Panie,

dziękujemy za zgłoszenie - wskazany błąd zostanie poprawiony.

No no, 25 dni od zgłoszenia... I nawet terminu nie podali...

Postaram się sprawdzić, a potem zgłosić jeszcze parę możliwych błędów, które zauważyłem w bibliotece .NET. Optymistycznie zakładam, że za kolejnych 25 dni poprawią ten zgłoszony 30 czerwca (tzn. całkowity czas rozwiązania problemu to 2 miesiące). Jest więc szansa, że do 30 września zdążą skorygować błędy, które zgłoszę w lipcu...

No cóż, to tempo nie napawa optymizmem, a szczegółów technicznych tworzenia faktur offline (przypuszczam, że to będzie jedyne wyjście) jak nie było, tak nie ma. Dokładniej, to mi brakuje:

  • adresów url, które mają być w tych kodach QR,
  • potwierdzenia szczegółów algorytmu szyfrowania skrótu pliku faktury.

W przypadku szyfrowania można przypuszczać, że będzie taki sam jak przy szyfrowaniu innych elementów w tym API, ale pewności nie ma. Oczywiście, wysłałem do KSeF przypomnienie także o tym (tydzień temu).

M4
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 58
0
mores4 napisał(a):

zadeklarowałem FA(1) i wysyłam FA(1) i też ten błąd nieobsługiwana wersja dokumentu

Słabo że nigdzie nie można tego nowego Api potestować

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

Ten projekt wygląda jakby miał po prostu nie wypalić. Te terminy w tym momencie to jakiś absurd, brak możliwości testowania itd. Zostaną 3 miesiące teoretycznie. Patrząc na to, ze w tym github poza nami to tam nikt nic nie pisze więc zakładam, ze nie ma jakiegoś poruszenia w tym temacie. A to właściwie jest nowe API, stara robota poza budowaniem XMLa z fakturą, ew to szyfrowanie jeszcze, to resztę można zapomnieć.
Dodatkowo nie wiem, czy tam w dyskusjach odpowiadają CI co to robią czy przypadkowi ludzie ?

Ja nie rozumiem, czemu tego nie zrobić tak, że ok wprowadzamy wysyłkę tych faktur, nawet przez to nieszczęsne API , ale działają nadal i mają podstawę prawną takie faktury jak dotychczas. Dopiero jak się uzna, że jest pokrycie w wysyłce na jakimś sensownym poziomie procentowym dla gospodarki to olewamy te papierowe i przechodzimy na to tą cyfrową formę. W takiej formie mieliby szanse sprawdzić czy ta ich infrastruktura itd to wytrzyma..

RA
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 58
1

Czy ktoś już rozkminiał załączniki z FA3 a konkretnie element Tabela? Na logikę ilość elementów Wiersz.WKom powinna być równa ilości elementów TNaglowek.Kol żeby element Tabela był tabelą ale czy jest to gdzieś oficjalnie napisane?

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

Po kilku godzinach rozkminy jak prezentować załączniki nasunęło mi się kilka myśli i pytań. W obecnej wersji załącznik jest niby generyczny: listy tekstów i tabel ale próba sensownego wyświetlenia tego dla odbiorcy, żeby nie wyglądało jak html pozbawiony stylów, graniczy z cudem. W elemencie Tabela jest TNaglowek.Kol.Typ który daje jakiś pogląd na zawartość, ale do czego są struktury MetaDane i TMetaDane dla odpowiednio BlokDanych i Tabela? W sensie jaki jest cel ich istnienia w kontekście załącznika? Klucze w tych strukturach nie są enumami (jak w przypadku TNaglowek.Kol.Typ) o szczególnym znaczeniu, więc jak dla mnie metadane to kolejne tabele danych do wyświetlenia. Równie dobrze można w xsd zmienić Tabela minOccurs="0" maxOccurs="1001" A może jakiś branżowy standard comarch z infaktem i fakturownią szykują, że w metadanych będą pod kluczem "A" trzymać wartość typu "B"?

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

W API 1.0 był endpoint /online/Payment/Identifier/Request do generowania zbiorczego indentyfikatora płatności.
Nie widzę odpowiedniak w API 2.0. Na stronie KSeF znalazłem informacje "Generowanie identyfikatora zbiorczego będzie możliwe zarówno w Aplikacji Podatnika KSeF jak i komercyjnych systemach finansowo-księgowych, które będą połączone z API KSeF."

Czy to znaczy, że jedynie duzi gracze będą mogli się generować indentyfikator zbiorczy, a pozostałym dostęp poprzez API KSeF został zabrany?

DVI Kesatuan
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 13
0

Czy ktoś wie co ile można odpytywać dany endpoint? Aktualnie przy pobraniu większej ilości faktur dostaje blokadę
obraz (2).png

Moje flow zapytań wygląda następująco:

  1. online/Session/AuthorisationChallenge
  2. online/Session/InitToken
  3. online/Session/Status/{sessionToken.ReferenceNumber} -> odpytane co 5 sekund do czasu otworzenia sesji
  4. online/Query/Invoice/Sync -> odpytany tylokrotnie ile faktur znajduje się w danym przedziale czasowym podzielone przez 10 (stronicowanie ustawione na 10 faktur i po prostu odpytanie wszystkich stron)
  5. online/Invoice/Get/{ksefReferenceNumber} -> każda faktura pobierana osobno asynchronicznie (wiele tasków jednocześnie)

Czy jestem w stanie w jednej sesji pobrać np. 100 faktur, czy musiałbym nawiązywać kolejną? Co jaki czas mogę wywoływać te zapytania żeby nie dostać bloka? 😄

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

Dzisiaj zauważyłem w dokumentacji online API 2.0 NOWĄ grupę 3 endpointów do sprawdzenia/zarządzania aktualnymi sesjami uwierzytelnienia:
https://ksef-test.mf.gov.pl/docs/v2/index.html#tag/Aktywne-sesje
Szybki rzut oka na początek specyfikacji online potwierdził moje spostrzeżenie: ostatnia zmiana 25 lipca.
Niby poniżej jest link do "Changelog", ale niestety, prowadzi do nikąd. (Chciałem sprawdzić, czy nie wprowadzono zmian w innych miejscach).
Przeglądając inne grupy dokumentacji online, zauważyłem kolejny nowy endpoint:
/api/v2/sessions : zwraca listę sesji (także tych zamkniętych).
a w metadanych listy faktur sesji opisujących fakturę, jest z powrotem jej skrót (pole "invoiceHash") - tak jak w API 1.0. Na razie w tej jednej metodzie, ale mam nadzieję, że dodadzą tę informację także w /api/v2/invoices/query, bo mały napis "[mock]" przy nazwie zdaje się sugerować, że jeszcze się nie zabrali za jej implementację...

Wydaje mi się, że w ten sposób zrealizowano część zgłoszeń z sekcji Issues dokumentacji API na GitHub (tych oznaczonych jako "Closed").

EDIT:
Link w dokumentacji online był pusty, ale znalazłem dziennik zmian wśród innych ksef-docs: https://github.com/CIRFMF/ksef-docs/blob/main/api-changelog.md.
Jak widać, nie miałem racji z tym skrótem pliku: był tam od początku...

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

Dzisiaj opublikowano specyfikację techniczną trybu offline: https://github.com/CIRFMF/ksef-docs/blob/main/kody-qr.md.

Podane w niej przykłady wydają się sugerować, że do bibliotek klienta .NET i Java dojdą pomocnicze serwisy do generowania url tych linków oraz obrazków z odpowiadającym im kodem QR.

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

Zapytanie dotyczy bardziej FA, ale może ktoś wie - czy pobrania powinny być wyszczególnione jako inna forma płatności? Raczej ona jest dość charakterystyczna, ale nie ma wyszczególnionej takiej.
A druga rzecz - jak rozumieć płatność "Mobilna"?

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

Aby "zalogować" się do API KSeF za pomoca certyfikatu, trzeba podpisać XML z żądaniem autoryzacji podpisem XAdES.

Kilka razy widziałem w tym wątku pytania i spekulacje na temat "podpisywania kartą", więc chciałbym pokazać jeden ze sposobów wykonania takiego podpisu.

W bibliotece .NET dostarczonej przez MF do obsługi API 2.0 przygotowano do tego pomocniczy serwis ISignatureService, który implementuje jedną metodę: Sign(string xml, X509Certificate2 certyficate) (por. przykład C# w Uwierzytelnienie, sekcja 2.1, p. 2).

Tak się składa, że klasa implementująca ISignatureService (KSeF.Client.Api.Services.SignatureService) nie wymaga żadnego połączenia z serwerem KSeF. W związku z tym można ją wypróbować już teraz.

Przygotowuję na potrzeby mojej firmy "wrapper" wokół bilblioteki .NET MF. Poniżej zamieszczam jego fragment, który wykorzystuje ISignatureService do podpisania dokumentu XML:

  • za pomocą mojego podpisu kwalifikowanego na karcie;
  • za pomocą testowych plików z certyfikatem i kluczem prywatnym. (Zrobiłem szybko w OpenSSl taki certyfikat "self-signed", aby zasymulować obsługę certyfikatu KSeF).

Struktury danych

Dane we/wy w prezentowanych dalej metodach są przekazywane w stringach JSON (przyczyny pominę). Poniżej odpowiadające im struktury, wraz z opisem:

Kopiuj
//Struktura danych wejściowych (w JSON pierwsze litery nazw pól mają być małe):
protected class InputData
{
	public required string SrcFile { get; set; } //ścieżka do pliku XML do podpisania (może być względna)
	public string? CertificateFile { get; set; } //ścieżka do pliku certyfikatu (*.pem)
	public string? PrivateKeyFile { get; set; } //ścieżka do pliku z kluczem prywatnym (*.pem)
	public string? CertificateName { get; set; } //nazwa ("Friendly Name") certyfikatu
													//w domyślnym magazynie lokalnym Windows
													//aktualnie zalogowanego użytkownika
	public string? DstFile { get; set; }	//ścieżka, w której ma być zapisany podpisany plik XML
}
/* Uwagi:
	1.	Jeżeli "privateKeyFile" jest pominięty, program zakłada, że klucz prywatny znajduje się także w "certificateFile"
	2.	Należy podać wartość "certificateFile"[+"privateKeyFile"] LUB "certificateName". To alternatywa. 
		Brak jakiejkolwiek informacji o certyfikacie wywoła wyjątek. 
	3.	Jeżeli nie podano DstFile, to podpisany XML zostanie zapisany w pliku "srcFile" (plik ulegnie zmianie).
*/

//Struktura danych wyjściowych:
protected class Results
{
	public string SignedFile { get; set; } = string.Empty; //ścieżka do podpisanego pliku (tak - dla potwierdzenia)
}

//Struktura wewnętrzna, na przetworzone dane wejściowe: 
protected class Params 
{ 
	public string xml = ""; //XML do podpisania (zawartość srcFile)
	public X509Certificate2? certificate; //certyfikat, którym mamy podpisać plik
}

Prywatne dane klasy

Podpisywanie w moim programie jest realizowane przez trzy metody pewnej klasy, które wykorzystują poniższe pola:

Kopiuj
	protected Params _input = new ();
	protected Results _output = new();

Załadowanie certyfikatów (i pliku XML)

Pierwsza metoda wypełnia pola _input oraz, trochę paradoksalnie - _output,
(bo _output zawiera tylko nazwę pliku, który ma powstać):

Kopiuj
public override Task PrepareInputAsync(string data, CancellationToken stopToken)
{
	var inp = JsonUtil.Deserialize<InputData>(data);
	if (inp == null) throw new ArgumentException($"Cannot parse expression '{data}'", nameof(data));
	_input.xml = File.ReadAllText(Program.FullPath(inp.SrcFile));
	if (inp.CertificateName != null) //Certyfikat z lokalnego magazynu?
	{
		_input.certificate = RetrieveFromStore(inp.CertificateName); //w tym momencie może się wyświetlić okno dialogowe z PIN-em
		if (_input.certificate == null) 
			throw new KeyNotFoundException(	$"Did not found any valid certificate with Friendly Name = '{inp.CertificateName}' " +
																$"in the local store of the current user ({Environment.UserName})");
	}
	else //Certyfikat z pliku
	{
		if (inp.CertificateFile == null) throw new ArgumentException($"Missing certificate reference in '{data}'", 
																										"certificateFile");
		if (inp.PrivateKeyFile == null) //w takim przypadku klucz prywatny powinien być w pliku certyfikatu
			_input.certificate = X509Certificate2.CreateFromPemFile(Program.FullPath(inp.CertificateFile));
		else //OK, wskazano oddzielne pliki certyfikatu i klucza prywatnego:
			_input.certificate = X509Certificate2.CreateFromPemFile(Program.FullPath(inp.CertificateFile), 
																					Program.FullPath(inp.PrivateKeyFile));
	}
	_output.SignedFile = Program.FullPath(inp.DstFile??inp.SrcFile);
	return Task.CompletedTask;
}

Nie zwracajcie uwagi na zwracany Task i "Async" w nazwie tej metody: to wymogi interfejsu, któy implementuje.

Przy okazji używam pomocniczą klasę z biblioteki MF: JsonUtil. (To taki wrapper wokół standardowego JsonSerilizer .NET, z poustawianymi różnymi opcjami).

Statyczna metoda Program.FullPath() to drobiazg, który zamienia ewentualne ścieżki względne na bezwzględne (katalogiem "root" jest położenie programu, stąd klasa Program)

Przykładowe dane, przekazywane tej metodzie:

  • gdy certyfikat i klucz są w plikach .pem:
Kopiuj
{	
	"srcFile"  : "../Request.xml", 
	"certificateFile" : "../certificate.pem",  
	"privateKeyFile" : "../privatekey.pem",  
	"dstFile" : "../RequestSigned.xml" 
}
  • gdy podpisuję za pomoca mojego certyfikatu kwalifikowanego (z karty), podaję "Friendly Name" certyfikatu umieszczonego w Windows Store:
Kopiuj
{	
	"srcFile"  : "../Request.xml", 
	"certificateName" : "Witold Jaworski",  
	"dstFile" : "../RequestSigned.xml" 
}

Pomocnicza funkcja, pobierająca certyfikat o podanej nazwie z Windows Store (aktualnego użytkownika) wygląda tak:

Kopiuj
//Pomocnicza funkcja, odczytująca certyfikat z lokalnego magazynu Windows (aktualnego użytkownika)
//Argumenty:
//	friendlyName: "nazwa potoczna", pod którą certyfikat figuruje na liście magazynu
//UWAGA: sprawdza także terminy ważności certyfikatów, i wybiera tylko spośród aktualnie obowiązujących.
private static X509Certificate2? RetrieveFromStore(string friendlyName)
{
	var store = new X509Store(StoreLocation.CurrentUser);
	store.Open(OpenFlags.ReadOnly);
	var certificates = store.Certificates;
	foreach (var certificate in certificates)
	{
		if (certificate.FriendlyName == friendlyName 
				&& certificate.NotAfter > DateTime.Now && certificate.NotBefore < DateTime.Now)
		{
			return certificate;
		}
	}
	return null;
}

W momencie pobrania certyfikatu z karty system wyświetla okno dialogowe sterownika karty i prosi o wpisanie PIN. (U każdego dostawcy podpisów jest to inne okno).

Podpisanie XML

Poniższa procedura podpisuje XML podpisem XAdES:

Kopiuj
//Podpisanie pliku za pomocą pobranego certyfikatu
public async override Task ProcessAsync(CancellationToken stopToken)
{
	var signatureService = _services?.GetRequiredService(typeof(ISignatureService)) as ISignatureService;
	Debug.Assert(signatureService != null, $"Missing service: {typeof(ISignatureService)}");
	string signedXML = await signatureService.Sign(_input.xml, _input.certificate);
	if (signedXML != null) File.WriteAllText(_output.SignedFile, signedXML);
	return;
}

Mój program wykorzystuje (zgodnie z sugestią twórców biblioteki) .NET Generic Host. Pole _services to przekazany (w konstruktorze klasy) interfejs IServiceCollection związany z zakresem (scope) utworzonym do obsługi żądania podpisania dokumentu XML. Stąd dwie pierwsze linie są tak złożone.

W bardziej klasycznym programie wystarczyłoby zastąpić dwie górne linie tej metody prostym stworzeniem nowego obiektu klasy SignatureService:

Kopiuj
var signatureService = new SignatureService();

(Tak te "serwisy" wykorzystuje np. towarzyszący bibliotece KSeF.Client projekt KSeF.Client.Tests)

Weryfikacja i zwrócenie rezultatu

Dla porządku, zanim zwrócę rezultat, staram się ten podpis zweryfikować:

Kopiuj
public override string SerializeResults()
{
	//Na wszelki wypadek, sprawdźmy to, co powstało:
	if (Verify(_output.SignedFile)) //niezależna weryfikacja podpisu, m.in. liczy ponownie hash (digest) podpisanego XML-a
		return JsonUtil.Serialize<Results>(_output);
	else throw new InvalidDataException($"Invalid signature in '{_output.SignedFile}'"); //umieszczam te throw dla porządku,
																							//bo Verify zgłasza wyjątki gdy coś jest nie tak.
}

Funkcja Verify() jest przepisana z przykładu Microsoft:

Kopiuj
//Na wszelki wypadek: niezależnie sprawdzenie poprawności podpisu
//Argument:
//	filePath: nazwa pliku XML do sprawdzenia
public static bool Verify(string filePath)
{
	try
	{
		XmlDocument xmlDocument = new()
		{
			PreserveWhitespace = true   //bez tego ustawienia programowi wyjdzie inny hash pliku (digest)
		};

		xmlDocument.Load(filePath);
		if (xmlDocument.DocumentElement == null) throw new InvalidOperationException($"Cannot load XML data from the source file");

		SignedXml signedXml = new(xmlDocument);

		XmlNodeList nodeList = xmlDocument.GetElementsByTagName("Signature"); //Spróbuj znaleźć element <Signature>

		if (nodeList.Count <= 0) throw new CryptographicException("Cannot find 'Signature' element in this XML file.");
		//Wątpię, by kiedykolwiek to się zdarzyło, ale na wszelki wypadek:
		if (nodeList[0] is not XmlElement signature) throw new CryptographicException($"'Signature' element is empty");

		signedXml.LoadXml(signature); // informacja towarzysząca: zawartość węzła <Signature>
				
		// Sprawdź poprawność (może zgłosić wyjątek)
		return signedXml.CheckSignature(); //Sprawdza, m.in liczy ponownie hash (digest) badanego pliku XML
	}
	catch (Exception exc)
	{
		throw new Exception($"Signature applied to '{filePath}' is invalid", exc);
	}
}

Nazwę pliku wynikowego określiłem w parametrach wejściowych, więc ta procedura zwraca ją dla potwierdzenia, że nie wystąpił żaden wyjątek (równie dobrze mogłaby zwracać jakiś kod "OK"):

Kopiuj
{"signedFile":"C:\\Users\\Hyperbook\\source\\repos\\KSeF-API\\KSeF.Services\\bin\\Debug\\RequestSigned.xml"}

Uwagi końcowe

Używam podpisu kwalifikowanego Certum, ale sądzę, że przedstawiona metoda pobierania certyfikatu z magazynu (RetrieveFromStore()) jest uniwersalna.

Załączam zip z plikiem XML Request: przed i po podpisie, oraz skrypt generate.bat, którego użyłem do stworzenia pliku certyfikatu i jego klucza prywatnego. XadesSignExample.zip

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

Obiecali przemyśleć kwestię wizualizacji - https://github.com/CIRFMF/ksef-docs/issues/12#issuecomment-3142617090
Moja sugestia - może podłapkujcie temat, to uda się wpłynąć na to?

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

Widzę, że kolejny przełom będzie w API - identyfikacja i blokowanie duplikatów na podstawie NIPu sprzedawcy, rodzaju faktury i numeru.
I ma być też publiczny endpoint do listy sesji, więc będzie możliwość przywracania danych po utracie.

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

Uaktualniono także kod bibliotek. Z biblioteki .NET zniknął dziwaczny "serwis" XadesDummy, a pojawiły się (w Api\Services) serwisy tworzące url dla linków i odpowiadające im kody QR (w formacie *.png). Poprawiono także parę rzeczy, które zgłosiłem na początku lipca 😀

Tylko w tej nowej wersji jeden z programistów zapomniał poprawić odwołań do konstruktora klasy CryptographyServices - nie usunął z nich niepotrzebnego już argumentu "restClient" - trzeba ręcznie zmienić w pięciu miejscach (por. zgłoszenie #12). Chodzi o ten commit - usunęli w definicji, sprawdzili, że biblioteka się kompiluje, ale nie sprawdzili potem pomocniczego projektu KSeF.Client.Tests, w którym ten konstruktor jest wywoływany.

Oj, teraz widzę, że zmieniono wymaganą wersję .NET core z 8 na 9. Ech, ja robię w 8 (bo jest LTS...)

Serwisy do obsługi linków offline / kodów QR są lokalne. Po 15 sierpnia zabiorę się za przygotowanie nanoszenia kodów QR na PDF-y faktur.
Aha, ze zmian w kodzie wynika, że wprowadzają alternatywną metodę szyfrowania z użyciem klucza publicznego. Opis brzmi tak:
"Szyfruje dane przy pomocy klucza publicznego ECDSA (ECC P-256) wzorując się na ECIES"
Wydaje mi się, że można stosować tę podana 30 czerwca, i tę nową, do wyboru.
Ta druga ma być szybsza i generować krótsze ciągi zaszyfrowanych danych.

EDIT: znalazłem szczegółowy dziennik zmian wykonywanych w bibliotece .NET.
Jest w: https://github.com/CIRFMF/ksef-client-csharp/blob/main/.github/RELEASE_NOTES.md
Możecie tam zobaczyć wszystkie szczegóły.

Swoją drogą - w zaproponowanym przez Billenium (przypuszczam, ze to oni stworzyli to API 2.0 na zlecenie MF) modelu "Dependecy Injection" można dość łatwo naprawić jakiś zauważony "babol", zachowując binarna zgodność z plikiem oryginalnym *.dll biblioteki. Wystarczy stworzyć klasę pochodną tej błędnej, implementującą ten sam interfejs. Stworzyć w niej "wrappera" pojedynczej metody, która ma błąd, a potem zarejestrować w sekwencji startowej jako serwis (w miejsce oryginalnego).

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

Cześć
Błahy temat jako przerywnik poważnych rozmów. Chodzi o element Fa/Rozliczenie/DoZaplaty w xmlu. Obecnie w przypadku faktur opłaconych częściowo częstą praktyką jest explicite podawanie kwoty pozostałej do zapłaty. Dla przykładu: sprzedaż na 1500 pln, klient przy zakupie płaci 400 pln i 1100 w terminie 2 tygodni. Na fakturach regularnie widuję dane: Sprzedaż 1500, Zapłacono 400, Pozostaje do zapłaty: 1100.
Dla pola Fa/Rozliczenie/DoZaplaty dokumentacja brzmi "Kwota należności do zapłaty równa polu P_15 powiększonemu o Obciazenia i pomniejszonemu o Odliczenia" a jako przykłady użycia podawane są:

  • zwrot udokumentowanych wydatków poniesionych w imieniu i na rzecz usługobiorcy (opłata
    urzędowa uiszczona przez pełnomocnika w imieniu i na rzecz klienta),
  • rozliczenie salda klienta (np. w związku z wpłatami klienta w zbyt wysokiej wartości),
  • rozliczenie kwot (różnicy) wynikających z wystawionych wcześniej faktur korygujących in
    minus/in plus

W niedawnej dyskusji zasugerowano mi, że można sumę elementów Fa/Platnosc/ZaplataCzesciowa/KwotaZaplatyCzesciowej podać jako wartość Rozliczenie/Odliczenia->Kwota a jako Rozliczenie/Odliczenia->Powod wpisać "Zapłata częściowa".
Jak dawno temu rozkminiałem strukturę faktury może za szybko stwierdziłem, że nie mogę użyć Fa/Rozliczenie/DoZaplaty w tym celu, bo przecież na zdrowy chłopski rozum wydaje mi się, że powinien być to pierwszy przykład użycia elementu Rozliczenie. Dodatkowo: o ile aplikacja WWW ksef nie jest jakoś super rozbudowana wydawałoby się, że powinna takie podstawowe rzeczy robić z automatu a w tym momencie nie robi.
Stąd moje wątpliwości i pytanie: czy wasze systemy używają w ten sposób elementu Rozliczenie? Ewentualnie czy jest jakiś konkretny powód, że nie używają Rozliczenia w tym właśnie celu?

JS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Cześć
Czy KSeF będzie zwracał FV w formacie w jakim zostały wgrane tj FA(1), FA(2)... czy w obecnie obowiązującym?

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

Aby ułatwić przemyślenia nad przykładowymi fakturami KSeF,
załączam w pliku *.zip w ich możliwe wizualizacje "a la Aplikacja Podatnika" w PDF.
To ekstrapolacja obecnego stylu wizualizacji FA(2), tylko musiałem użyć innej czcionki, aby zachować te PDF w sensownym rozmiarze.Nie dziwcie się pustej przestrzeni w nagłówku - to miejsce na kody QR.
Zwróćcie uwagę na załączniki - robienie "quasi-nagłówka" z wiersza z pojedynczą komórką wydaje mi się trochę naciągane (jak cały pomysł z tą "tabelyzacją" zawartości).

Edit: przy okazji - ogłaszam mały quiz: skąd się wzięły takie, a nie inne kwoty netto w "Podsumowanie podatku" w przykładzie 11? (por. plik FA_3_Przyklad_11.pdf).
Edit/Edit: 🙂 dodatkowa podpowiedź: faktura z przykładu 11 koryguje fakturę z przykładu 10. Dla ułatwinenia załączam Opisy przykładów dla struktury logicznej FA(3).pdf z oryginalnego zipa MF.

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

UPO

Nie jestem pewien, więc podpytam o UPO. W dokumentacji są wymienione dwa dokumenty UPO: UPO-sesja i UPO-faktura. Czy dla faktur przesłanych w ramach jednej sesji UPO-sesja i UPO-faktura będą miały osobne numery UPO? Inaczej konstruując pytanie: czy w KSeF 2.0 każda faktura będzie mieć przypisane dwa UPO?

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

Witam
Mam problem z właściwym odpaleniem "https://ksef-demo.mf.gov.pl/api/online/Session/InitToken". Mam token wygenerowany w apce ( nie wiem czy i jakie ma znaczenie wielkośc liter w tokenie bo wszystkie sa upper case) . AuthorisationChallenge zwraca mi challenge i timestamp, którego konwertuje do ms.Szyfruje token|timestamp(ms) za pomoca klucza publicznego dla test i w odpowiedzi zawsze dostaje
"exceptionCode": 21111,
"exceptionDescription": "Nieprawidłowe wyzwanie autoryzacyjne."
Zakładam że problemem jest nieszczęsny zaszyfrowany token - probowalem juz nawet onlinowo go sobie przegenerowac (np przez https://emn178.github.io/online-tools/rsa/encrypt/) , zmieniałęm wielkość liter w tokenie i zawsze to samo.Czy ktoś miał coś podobnego albo jakąś recepte na to ?

JS
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 22
0

Przepraszam, że tutaj ale działa Wam połączenie z https://bramka.edeklaracje.gov.pl/uslugi/dokumenty do obsługi deklaracji np vat8 ?

od wczoraj

A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 145.237.235.227:443

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.