Biała lista podatników i błąd w REST Debugger

0

Cześć,

od kilku dni dostępne jest api MF do sprawdzenia czy podatnik jest na białej liście i na jakie konto należy wykonywać przelew aby nie mieć problemów.

Oczywiście już tam zajrzałem ale okazało się że mam problem.

Informacja i jakaś dokumentacja znajduje się tutaj: https://www.gov.pl/web/kas/api-wykazu-podatnikow-vat

Oto przykładowy adres do sprawdzenia (jest to Orlen): https://wl-api.mf.gov.pl/api/search/nip/7740001454?date=2019-08-01
w przeglądarce czy jakimkolwiek testerze REST-a otrzymacie prawidłowy wynik, niestety REST Debugger z Delphi wyświetla błąd serwera 500 (gdy link będzie zły otrzymacie błąd 400 czyli coś tam działa).

Możecie sprawdzić u siebie czy macie podobnie?

0

Cześć,
potwierdzam problem. Używam delphi wersja 10.3.1. Jeżeli nie podam parametru date - dostaję odpowiedz 400 (zły format zapytania).
Po dodaniu date - odpowiedz 500 (wewnętrzny błąd serwera).
Tak samo wyglądający link wpisany do przeglądarki - dostaję prawidłową odpowiedz w JSON.
Nie mam wielkiego doświadczenia z zewnętrznymi serwerami REST.. W kilku przykładach, które do tej pory testowałem nie miałem takiego problemu.
Pozdrawiam
Paweł

0

Sprawdź jakie nagłówki wysyłasz z przeglądarki i zaaplikuj takie same w swojej apce

4

Nie wiem jak w Delphi 10.3.1 ale w 10.2 u mnie pomaga w RestClient ustawienie Accept na text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8.

3

odpowiedź kolegi @kAzek rozwiązuje problem za co dziękuję. Znalazłem też inne rozwiązanie.

Okazuje się że REST Debugger dokłada do komponentu RESTRequest w Accept jakiś przecinek na końcu stringa?
Tak to wygląda:

application/json, text/plain; q=0.9, text/html;q=0.8,

wystarczy usunąć ostatni przecinek i wszystko działa? Co za cholera?

1

Nawet nie zwróciłem na to uwagi tylko wkleiłem nagłówek jaki wysyła przeglądarka ale podejrzewam, że to błąd Delphi przeciek na końcu powoduje, że serwer nie bardzo wie jaką powinien zwrócić, po prostu tak zakończony przecinkiem nagłówek jest nieprawidłowy. Jeżeli serwer tego nie weryfikuje i robi swoje czyli zwraca zawsze niezależnie od tego nagłówka tą samą zawartość to pół biedy a ten widocznie jest tak ustawiony, że sprawdza ten nagłówek i po prostu się wykrzacza.

0

@axelbest: @kAzek
a tak z czystej ciekawości bo totalna noga jestem w technologiach webowych, jak się sprawdza co przeglądarka wysyła?

3

W najprostszy sposób wystarczy plugin do przeglądarki może to być np. HTTP Header Live
Dla Firefox:
https://addons.mozilla.org/pl/firefox/addon/http-header-live/
Dla Chrome:
https://chrome.google.com/webstore/detail/http-header-live/jljeikaiehipjcfbpedmgikbbhmknpkk
Odpalasz plugin i otwierasz stronę tylko najlepiej wcześniej w opcjach sobie odfiltrować przez dodanie do wykluczeń stron, które masz stale otwarte w zakładkach a które cały czas wysyłają jakieś dane.

0
robertz68 napisał(a):

Oto przykładowy adres do sprawdzenia (jest to Orlen): https://wl-api.mf.gov.pl/api/search/nip/7740001454?date=2019-08-01

Możecie sprawdzić u siebie czy macie podobnie?

Kliknąłem linka i działa.

0

Cześć,
podpowiedzcie proszę jaką wartość wstawić w Params RESTRequest'a.

0

Jak to jaką w tym konkretnym przypadku jest to date.

0

Odświeżam wątek , otóż korzystam z API wykorzystując kod :

Dim reader As StreamReader
     Dim request As HttpWebRequest = DirectCast(WebRequest.Create("https://wl-api.mf.gov.pl/api/search/nip/7740001454?date=2019-10-15"), HttpWebRequest)
    request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0"
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
 Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
    reader = New StreamReader(response.GetResponseStream())

do dnia 2019-10-08 wszystko działało pięknie , niestety po tej dacie wprowadzili jakąś modyfikację i nie mogę przeskoczyć komunikatu :

 {"Odebrano nieoczekiwany znacznik EOF lub 0 bajtw ze strumienia transportowego."} 
2

@crybaby: prawdopodobnie jest jakiś problem z szyfrowaniem. Może używasz starego TLS1.0 lub SSL3, który zostały wyłączone po stronie MF ? Spróbuj wymusić TLS1.2
Akurat 8.10 były zmiany w API po stronie MF.
Zmiany:
• poprawione literówki w opisach błędów: WL-116 i WL-117
• dodany kod błędu: WL-191
• poprawiona wartość w Enum („Niezarejestrowany”) w polu „StatusVat”
• dodana specyfikacja zawartości dla statusu http 400
• połączenie typów Person i EntityPerson jako EntityPerson

WL-191 to błąd, gdy przekroczono ilość 10 zapytań z jednego adresu IP. Może w tym jest problem?
Gdy przekroczysz ilość 10 zapytań, dostajesz kod 429 Too Many Requsts

0

@skrzat: Działa! Wystarczyło włączyć wsparcie dla TLS 1.2 i poszło! Jestem Twoim dłużnikiem.

0
crybaby napisał(a):

@skrzat: Działa! Wystarczyło włączyć wsparcie dla TLS 1.2 i poszło! Jestem Twoim dłużnikiem.

Od pewnego czasu dostaję komunikat: błąd certyfikatu strony. Używałem Indy REST w Delphi. Tam nie ma chyba obsługi szyfrowania SSL. Jak to się tam włącza?

1

Indy REST? Z tego co wiem Indy nie ma dedykowanego klienta REST. Chyba chodzi o TIdHTTP a w nim obsługujesz REST jeżeli tak to w ni9m jako IOHandler ustawiasz TIdSSLIOHandlerSocketOpenSSL a w nim SSLOptions --> SSLVersions na wersję której potrzebujesz. Poza tym w folderze z programem muszą znajdować się potrzebne do obsługi SSL biblioteki DLL np. z https://indy.fulgan.com/SSL/ Oczywiście najlepiej najnowsze wersje.

0
kAzek napisał(a):

Chyba chodzi o TIdHTTP a w nim obsługujesz REST jeżeli tak to w ni9m jako IOHandler ustawiasz TIdSSLIOHandlerSocketOpenSSL a w nim SSLOptions --> SSLVersions na wersję której potrzebujesz.

Dokładnie w ten sposób łączyłem się z poziomu starszego C++ Buildera i nie było problemów. Większość parametrów zostawiłem domyślnie i zadziałało praktycznie od razu. Większym problemem było sparsowanie pozyskanego w ten sposób JSON'a niż jego pobranie. A to tylko dlatego, że miałem do dyspozycji starszą wersję nie posiadającą klienta REST, ani bibliotek do JSON.

0

Tak sorry nie indy tylko Embarcadero : Delphi REST Client Framework - nie widzę w nim obsługi SSL.
Przeszedłem więc na IdHTTP i SSLHandler co działa dla poprawnie zapisanego numeru konta (parametru) przez zwykłe IdHTTP.Get(lRequest);
Jeśli konto ma być zweryfikowane negatywnie tez powinienem dostać w odpowiedzi json a dostaję tylko error 400 (błąd parametru). Tego nie umiem przeskoczyć.

0

@zizu77 my tu z fusów nie wróżymy jakie parametry podajesz itd. wklej kawałek kodu.

0

Z tego co kojarzę to przy poprawnym skonstruowaniu żądania nigdy nie powinno się dostać błędu 400 ani innego. Po prostu dostaje się inny wynik. Dlatego masz coś nie tak w kodzie. PS. czytałeś w ogóle dokumentację? Tam jest opisane co i jak.

0
kAzek napisał(a):

@zizu77 my tu z fusów nie wróżymy jakie parametry podajesz itd. wklej kawałek kodu.

Nie ma co tu wklejać za bardzo ale w sumie:

      IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(fRESTRequest.Owner);
      IdHTTP := TIdHTTP.Create(fRestRequest.Owner);
      try
        with idSSLIOHandlerSocketOpenSSL1 do
        begin
          SSLOptions.Method := sslvSSLv23;
          SSLOptions.Mode := sslmUnassigned;
          SSLOptions.VerifyMode := [];
          SSLOptions.VerifyDepth := 0;
          host := '';
        end;
        IdHTTP.IOHandler := IdSSLIOHandlerSocketOpenSSL1;
        lRequest := 'https://wl-api.mf.gov.pl/api/search/bank-account/6523600018007640000010744?date=2019-12-30'
        fLastResponse := IdHTTP.Get(lRequest);

konto podane w lRequest jest za krótkie o 1 znak i w sumie powinienem dostać taki zwrotny json w fLastResponse:
{"code":"WL-109","message":"Pole 'numer konta' ma nieprawidłową długość. Wymagane 26 znaków (6523600018007640000010744)."}
i tak zwraca przeglądarka Chrome po wklejeniu tego zapytania.
Niestety w delphi w ostatniej linii dostaję HTTP 400.
Jak podam poprawny numer konta to dostaję normalnego json-a.

0

@zizu77 musisz po prostu obsłużyć błędy. W przypadku błędu INDY wali wyjątkiem i nic z tym nie zrobisz. Obsłuż ten wyjątek, a będzie ok. Nie piszę w Delphi, ale w C++ będzie to mniej więcej coś takiego (zakładając IdHTTP oraz IdSSLIOHandlerSocketOpenSSL położone na formatce oraz poprawnie ustawione wartości):

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  TStringStream *ResponseData = new TStringStream();
  try
  {
    IdHTTP->Get("https://wl-test.mf.gov.pl/api/search/nip/32451745046?date=2019-08-01",ResponseData);
  }
  catch (EIdHTTPProtocolException &E)
  {
    ShowMessage(E.ErrorMessage);
  }

  if (IdHTTP->ResponseCode == 200)
  {
    ShowMessage(ResponseData->DataString);
  }
  delete ResponseData;
}
//---------------------------------------------------------------------------
0

To mam oczywiście obsłużone w klasie wyżej łapię wyjątek który brzmi mniej więcej E.Message="HTTP 400". Nie powinien on lecieć tylko powinien zwrócić poprawnego jsona z kodem błędu oraz wyjaśnieniem przyczyny, tymczasem wali exception.
Może to kwestia wpisania czegoś magicznego np:

IdHTTP.Request.Accept := 'application/json,text/plain;q=0.9,text/html;q=0.8';
IdHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:12.0) Gecko/20100101 Firefox/12.0';

Wpisuję też tak ale nie pomaga.

1

Masz błędne zapytanie tak jak dostajesz odpowiedź numer konta powinien mieć 26 znaków a u Ciebie ma 25 tak samo NIP powinien mieć 10 znaków a w przykładzie wyżej ma 11.

1

Tak mam błędnie napisany numer konta (świadomie) ma mieć 26 znaków a ma 25. I oczekuję że dostanę json z wyjaśnieniem przyczyny błędu a nie error 400. Wklej to zapytanie na stronę internetową i dostaniesz piękną odpowiedź:

{"code":"WL-109","message":"Pole 'numer konta' ma nieprawidłową długość. Wymagane 26 znaków (6523600018007640000010744)."}

Niestety zamiast tego co zwraca przeglądarka ja dostaję tylko HTTP 400.

3

Musisz obsłużyć wyjątek coś w stylu:

  try
    Memo1.Text:= IdHTTP1.Get(lRequest);
  except
    on E: EIdHTTPProtocolException do begin
      if E.ErrorCode = 400 then
        Memo1.Text:= E.ErrorMessage;
    end;
  end;
0
zizu77 napisał(a):

To mam oczywiście obsłużone w klasie wyżej łapię wyjątek który brzmi mniej więcej E.Message="HTTP 400". Nie powinien on lecieć tylko powinien zwrócić poprawnego jsona z kodem błędu oraz wyjaśnieniem przyczyny, tymczasem wali exception.

I właśnie mój kod tak działa. ShowMessage w catchu wypisuje tego JSONa o którego Ci chodzi. Co do wywalania wyjątku to po prostu INDY tak jest napisane. Nie znam innych bibliotek tam to może jest zorganizowane inaczej. Jednak tu jest tak i należy wyłapać odpowiedni wyjątek, wszystko jest w dokumentacji ładnie opisane :)

0

Czy dalej jest to ograniczenie do 10 wyszukań, czy pomaga odpowiedni nagłówek, useragent itp?
A jeśli są ograniczenia, to czy może ktoś korzystał z tzw. pliku płaskiego, który codziennie można ściągnąć:
https://www.podatki.gov.pl/vat/bezpieczna-transakcja/wykaz-podatnikow-vat/plik-plaski/
W środku są zahaszowane SHA512 dane podatników w postaci
RRRRMMDDNIP0000000NRKONTA0000000000000000000
Testowałem wyliczanie hasha choćby online dla konkretnego podatnika, podajac date, nip i nr konta, ale nie udalo mi sie znaleźć potem tego hasza w pliku, może ktoś próbował?

0
Kristof napisał(a):

Czy dalej jest to ograniczenie do 10 wyszukań, czy pomaga odpowiedni nagłówek, useragent itp?

Nie, nic nie pomaga. Ponieważ limit jest na IP. Więc w dużych firmach gdzie systemy finansowo-księgowe są zainstalowane na wielu komputerach te API z takim limitem jest zupełnie bez sensu.

Kristof napisał(a):

W środku są zahaszowane SHA512 dane podatników w postaci
RRRRMMDDNIP0000000NRKONTA0000000000000000000
Testowałem wyliczanie hasha choćby online dla konkretnego podatnika, podajac date, nip i nr konta, ale nie udalo mi sie znaleźć potem tego hasza w pliku, może ktoś próbował?

Popatrz, że tam jest liczba iteracji jaką należy wykonać podczas liczenia hasha i dopiero wtedy wyszukujemy w pliku żądaną wartość SHA512 Liczenie skrótu od skrótu

Ogólnie całe te API oraz plik bardziej przypomina zabawkę niż cokolwiek użytecznego.

0

Hah 5000 iteracji! Jutro to sprawdzę i zobaczymy:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1