Kredyt hipoteczny dla początkujących: debugowanie systemu ZUS

W życiu wielu ludzi nadchodzi taki moment, że mają dość mieszkania z rodzicami/teściami/pod mostem i postanawiają wziąć kredyt na mieszkanie. Mnie również się to przydarzyło. Niestety, branie kredytu wiąże się z kontaktem z bardzo zbiurokratyzowanymi instytucjami - bankami, które wymagają dostarczenia różnych dokumentów, potwierdzeń i zaświadczeń. Zazwyczaj jest to łatwe, mi jednak dostarczyło niesamowitych przygód.

To przecież tylko jeden papierek!

Ponieważ jestem biznesmenem i mam firmę, to bank wymaga ode mnie zaświadczenia o niezaleganiu w składkach od Zakładu Usług Społecznych. Nic prostszego! Przecież od dawna już żyjemy w epoce dostępności usług administracyjnych przez Internet (i to akurat nie jest sarkazm), więc uzyskanie takiego dokumentu nie wymaga nawet wyjścia z domu. Wystarczy zalogować się do systemu PUE przy użyciu profilu ePUAP i złożyć stosowny wniosek zgodnie z instrukcją.

Po jakimś czasie dostajemy maila zwrotnego, że zaświadczenie oczekuje już w systemie. Wówczas należy się zalogować w systemie i wejść w Obszar Płatnika -> Dokumenty i wiadomości -> Skrzynka odbiorcza -> wybór z listy -> Szczegóły -> Przeglądaj dokument , a następnie pobrać plik PDF.

Coś tu jednak nie gra…

Po wykonaniu powyżej opisanego klikania zobaczyłem taki efekt:

Czyli nie ma zaświadczenia, jest tylko mroźna zima, halucynacja z niedożywienia i śmierć. Co gorsza - jeszcze jakiś miesiąc temu to działało.

Trop pierwszy - HTML z serwera jest zły

Zacząłem się zastanawiać, co tam się dzieje. Otworzyłem narzędzia deweloperskie przeglądarki i ujrzałem:

Czyli żądanie, które idzie na serwer ZUS, zwraca poprawny HTML zawierający tekst zaświadczenia! Dane są, ale wyświetlają się nieprawidłowo, wniosek - coś nie działa w przeglądarce, a nie na serwerach ZUS. Będzie dobrze.

Jak widać, dokument zaczyna się od . Zajrzałem w konsolę przeglądarki i zobaczyłem błąd opisany: SyntaxError: expected expression, got '&' . Zajrzałem do katalogu Dokumenty wysłane w PUE, bo tam dokumenty wyświetlają sie prawidłowo i zobaczyłem, że HTML, który tam przychodzi z serwera, nie ma spacji na początku, zaczyna się po prostu otwierającym tagiem <html> . Pomyślałem wówczas, że wszystko psuje ta spacja, gdy jej się pozbędę, to będzie ok.

Fiddler na ratunek

A zatem, celem zabawy jest podmiana odpowiedzi na żądanie przeglądarki, zanim w ogóle do niej wróci. Najlepszy specjalista od bezpieczeństwa systemów informatycznych, którego znam, upewnił mnie, że w tym celu trzeba użyć Fiddlera. Z uwagi na to, że ruch do PUE idzie po HTTPS, trzeba w nim wymusić przechwytywanie ruchu tego typu, a następnie skonfigurować przeglądarkę, aby korzystała z Fiddlera jako proxy. Gdy już tego dokonałem i widziałem w Fiddlerze dane przesyłane do/z PUE, we wbudowanym edytorze skryptów rozbudowałem metodę OnBeforeResponse o dodatkowy warunek:

1 if ( oSession . HostnameIs ( "pue.zus.pl" ) 2 && oSession . oResponse . headers . ExistsAndContains ( "Content-Type" , "text/html" )) { 3 oSession . utilDecodeResponse (); 4 oSession . utilReplaceInResponse ( ' & nbsp ;< html ',' < html ' ); 5 }

Proste. Efekt osiągnąłem - przeglądarka dostała oczyszczoną wersję danych. Z tą różnicą, że teraz zobaczyłem błąd: SyntaxError: expected expression, got '<' . No cóż, przynajmniej konsekwentnie.

Trop drugi - a może tak przeczytać stack trace?

Ta, i może jeszcze instrukcję. ;)

Przyjrzałem się dokładnie temu, co widać było w konsoli przeglądarki:

Jakieś Dojo, jakiś JSON, o co chodzi… Dojo to jakaś biblioteka do GUI w JS (tu należałoby wypowiedzieć takie sarkastyczne, angielskie sure it is). No nic, trzeba debugować, postawiłem pułapkę we wskazanej linijce i moim oczom ukazało się takie coś:

Czyli HTML zwrócony z serwera omyłkowo trafia tam, gdzie powinien trafić JSON. Gdyby tylko udało się zmienić sterowanie parsowaniem odpowiedzi tak, żeby odpowiedź z serwera traktowana była jak tekst, a nie JSON, to powinno zadziałać… Pobiegałem trochę w call stacku i znalazłem takie coś:

Przy okazji nastąpnej próby napisałem w konsoli przeglądarki:

1 dfd . ioArgs . handleAs = "text"

I w efekcie otrzymałem:

Sukces!

Czemu tak się dzieje?

Nie chciało mi się debugować tego dalej i dochodzić faktycznej przyczyny. W oczy rzuca mi się jedna rzecz:

To żądanie idzie na serwer metodą POST. W innych miejscach systemu żądania o dokumenty idą GET. Obstawiam, że gdzieś jest magiczna konfiguracja sprawiająca, że wszystkie odpowiedzi na GET mają być traktowane jako HTML, a wszystkie na POST jako JSON. To ma sens, dopóki żądania są wysyłane prawidłowo. Ktoś zapewne niedawno omyłkowo zmienił metodę odwołania pod url: https://pue.zus.pl/portal/obw/dokumentMerytoryczny/pobierzWizualizacje.npi z GET na POST i wyświetlanie dokumentów przestało działać.

Zakończenie

Na zakończenie chciałem podziękować twórcom systemu PUE ZUS za stworzenie prawdziwie developer-friendly systemu. Jestem im wdzięczny za nazywanie metod, handlerów i urli po polsku, przez co ani przez chwilę nie musiałem zastanawiać się, czy dany kod pochodzi z zewnątrz, czy od wykonawcy systemu. Dziękuję im za to, że wstrzymali się od wszechobecnego trendu minifikacji i bundlowania kodu JavaScriptu, dzięki czemu czytanie i debugowanie kodu było przyjemnością. A najbardziej dziękuję za możliwość bycia częścią zespołu testującego na produkcji. Nic tak nie rozwija, jak wyciąganie własnych danych z wartego kilkaset milionów złotych systemu przy użyciu Fiddlera i narzędzi developerskich przeglądarki.