VIES SOAP API — dokumentacja integracji
Dokumentacja techniczna dla programistów integrujących VIES SOAP API z systemami ERP, e-commerce i księgowymi. Pełne przykłady kodu w PHP, Python, Node.js i .NET.
Endpoint i WSDL
Oficjalny endpoint: https://ec.europa.eu/taxation_customs/vies/services/checkVatService. Plik WSDL: https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl. WSDL definiuje dwie operacje: checkVat (basic) i checkVatApprox (qualified, z requesterIdentifier). Większość SDK SOAP (PHP SoapClient, Python zeep, .NET WCF) automatycznie generuje stuby z tego WSDL. Endpoint wymaga TLS 1.2+, nie wymaga uwierzytelniania.
Operacja checkVat — przykład PHP
Najprostsza integracja: $client = new SoapClient('https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl'); $response = $client->checkVat(['countryCode' => 'DE', 'vatNumber' => '123456789']); var_dump($response). Zwraca obiekt z polami: countryCode, vatNumber, requestDate (DateTime), valid (bool), name (string), address (string). Dla nieaktywnych numerów name i address są puste. Dla niektórych krajów (Niemcy, Hiszpania) name i address mogą być puste nawet przy aktywnym numerze — to decyzja krajowa.
Operacja checkVatApprox — qualified consultation
Tryb kwalifikowany: $response = $client->checkVatApprox(['countryCode' => 'DE', 'vatNumber' => '123456789', 'requesterCountryCode' => 'PL', 'requesterVatNumber' => '1234567890']). Dodatkowe pola w odpowiedzi: traderName, traderCompanyType, traderAddress, requestIdentifier (czyli identyfikator konsultacji!). To zapytanie powinno być używane do produkcji — bo tylko ono zwraca dowód weryfikacji. Wymaga aktywnego numeru VAT Twojej firmy jako requester.
Obsługa błędów SOAP
Wyjątek SoapFault zawiera kod błędu w property faultstring. Typowe wartości: 'INVALID_INPUT', 'MS_UNAVAILABLE', 'TIMEOUT', 'SERVICE_UNAVAILABLE', 'INVALID_REQUESTER_INFO', 'VAT_BLOCKED'. Owijanie w try/catch jest obowiązkowe: try { $r = $client->checkVat(...); } catch (SoapFault $e) { if ($e->faultstring === 'MS_UNAVAILABLE') { /* retry po 15 min */ } }. Nie traktuj wszystkich SoapFault tak samo — różne błędy wymagają różnych strategii.
Przykład Python z zeep
from zeep import Client; client = Client('https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl'); result = client.service.checkVat(countryCode='DE', vatNumber='123456789'); print(result.valid, result.name, result.address). Zeep automatycznie mapuje WSDL na obiekty Pythona. Dla asynchroniczności użyj zeep.AsyncClient z aiohttp. Pakiet 'vies' na PyPI to wrapper zbudowany na zeep — szybciej, ale mniej kontroli nad błędami.
Przykład Node.js z node-soap
const soap = require('node-soap'); soap.createClient('https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl', (err, client) => { client.checkVat({countryCode: 'DE', vatNumber: '123456789'}, (err, result) => { console.log(result.valid, result.name); }); }). Dla TypeScript polecamy bibliotekę 'soap-strict' z generowanymi typami. Wszystkie callback API można promisify dla async/await.
Przykład .NET z dotnet-svcutil
Wygeneruj proxy: dotnet-svcutil https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl. Użycie: var client = new checkVatPortTypeClient(); var response = await client.checkVatAsync(new checkVatRequest('DE', '123456789')); var isValid = response.valid; W .NET ważne jest skonfigurowanie binding'u na BasicHttpsBinding z TLS 1.2. Wbudowany WCF nie zawsze poprawnie obsługuje wszystkie pola WSDL VIES — czasem trzeba ręcznie edytować wygenerowane klasy.
Best practices produkcyjne
(1) Buforuj wyniki przez 24h — KE rekomenduje, nie wysyłaj tego samego zapytania kilka razy dziennie. (2) Implementuj retry z exponential backoff dla MS_UNAVAILABLE. (3) Loguj każdy requestIdentifier do bazy własnej — to Twój dowód. (4) Asynchronizuj — VIES może mieć 30s timeout, nie blokuj wątku UI. (5) Monitoruj rate (np. Prometheus) — przekroczenie 10/s skutkuje throttlingiem. (6) Testuj na sandbox (lokalnym mocku) nie na produkcyjnym VIES — nie marnuj limitów KE na testy.
Pełen przykład produkcyjny w PHP — z błędami i retry
<?php function checkVatProduction($country, $vat) { $maxAttempts = 4; $delays = [60, 300, 900, 3600]; for ($attempt = 0; $attempt < $maxAttempts; $attempt++) { try { $client = new SoapClient('https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl', ['exceptions' => true, 'connection_timeout' => 30]); $response = $client->checkVatApprox(['countryCode' => $country, 'vatNumber' => $vat, 'requesterCountryCode' => 'PL', 'requesterVatNumber' => '1234567890']); return ['valid' => $response->valid, 'name' => $response->traderName ?? null, 'address' => $response->traderAddress ?? null, 'consultationNumber' => $response->requestIdentifier ?? null, 'requestDate' => $response->requestDate]; } catch (SoapFault $e) { $err = $e->faultstring; if (in_array($err, ['INVALID_INPUT', 'INVALID_REQUESTER_INFO', 'VAT_BLOCKED'])) throw $e; if ($attempt === $maxAttempts - 1) throw $e; sleep($delays[$attempt]); } } } ?>. Ten kod obsługuje wszystkie standardowe scenariusze: retry dla błędów recoverable, immediate throw dla błędów permanent, exponential backoff, timeout 30 sekund (limit KE). Dla produkcji dodaj jeszcze: logging każdego zapytania do Twojej bazy z timestampem i wynikiem (audit trail), monitoring czasu odpowiedzi (metryki Prometheus), circuit breaker dla długotrwałych awarii (Polly w .NET, Resilience4j w Java, pyfaitch w Python).
Walka z TIMEOUT — konfiguracja socket'ów
TIMEOUT to drugi co do częstości błąd VIES (po MS_UNAVAILABLE). VIES KE ma timeout 30 sekund dla każdego zapytania — jeśli rejestr krajowy nie odpowie w tym czasie, zwracany jest TIMEOUT. Twój klient SOAP musi mieć timeout co najmniej tyle samo, by nie odrzucać prawidłowych powolnych odpowiedzi. W PHP: SoapClient (['connection_timeout' => 30]). W Python z zeep: client.transport.session.timeout = 35. W Node.js z node-soap: soap.createClient(url, {endpoint, options: {timeout: 35000}}). W .NET WCF: BasicHttpsBinding {SendTimeout = TimeSpan.FromSeconds(35), ReceiveTimeout = TimeSpan.FromSeconds(35)}. W Java: bindingProvider.getRequestContext().put(BindingProvider.MESSAGE_OUTBOUND_PROPERTY, 35000). Ważne: ustaw client timeout NIECO WIĘKSZY niż server-side timeout (np. 35 sekund dla 30-sekundowego serwera) — żeby zapytanie miało czas dotrzeć do serwera i wrócić bez odrzucenia po Twojej stronie. Zbyt krótki timeout u klienta = anulujesz prawidłowe zapytania w trakcie, bezpłatnie marnujesz quoty KE. Zbyt długi = klient zawiesza się przy awarii bez fail-fast.
REST API VIES vs SOAP — porównanie i wybór
KE udostępnia VIES przez dwa protokoły. SOAP (od 1993): https://ec.europa.eu/taxation_customs/vies/services/checkVatService — XML-based, formalna definicja WSDL, dobrze udokumentowany, stabilny od dziesięcioleci. REST (od 2020): https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-test-service — JSON-based, prostszy do integracji z nowoczesnymi frameworkami, mniej dokumentacji. Który wybrać? Dla produkcji: SOAP — bardziej stabilny, lepiej udokumentowany, większa szansa kompatybilności wstecznej przy zmianach KE. Większość SDK języków ma natywne wsparcie SOAP (PHP SoapClient, Python zeep, Java JAX-WS, .NET WCF). Dla prototypów i nowych integracji: REST — szybszy do uruchomienia, JSON jest naturalny dla JavaScript/Python/Go. Aktualnie REST KE nie zwraca identyfikatora konsultacji w sposób identyczny z SOAP (różnice w polach), więc dla obrony przy kontroli SOAP jest bezpieczniejszy. Funkcjonalnie oba zwracają te same dane. Wybór jest często sprawą smaku zespołu. Nasze SDK używa SOAP wewnętrznie ale wystawia API REST dla klientów — dobre obie strony.
Sandbox lokalny — symulacja VIES dla testów
Testowanie integracji z VIES na produkcyjnym endpoint KE jest złym pomysłem — konsumuje quoty, obciąża KE, daje niedeterministyczne wyniki. Profesjonalne rozwiązanie: lokalny mock VIES. Najpopularniejsze: vies-mock-server (Docker image dostępny na DockerHub, ok. 50k pobrań). Uruchomienie: docker run -p 8080:8080 vies-mock-server. Konfigurowalny: zwraca aktywne/nieaktywne/błąd dla konkretnych numerów (deterministycznie). Zachowuje się jak prawdziwy VIES — odpowiada na SOAP i REST, generuje identyfikatory konsultacji w testowym formacie. Dla CI/CD: idealne. Każdy commit może być testowany przeciw lokalnemu VIES bez konsumowania prawdziwych zasobów. Nasze SDK domyślnie ma flagę testMode = true, który przekierowuje zapytania do naszego sandbox /api/v1/sandbox/check — żebyś nie musiał stawiać własnego mock'a. Sandbox zwraca deterministyczne wyniki: DE123456789 → aktywny z testową firmą „Sandbox GmbH”, DE000000000 → nieaktywny, DE999999999 → MS_UNAVAILABLE. Idealne dla testów end-to-end Twojej integracji.
Migracja z SOAP do REST — kiedy warto
Pytanie strategiczne: czy migrować istniejącą integrację z SOAP do REST? Argumenty za. Pierwsze: nowoczesna architektura — REST naturalnie pasuje do mikrousług, serverless, edge computing. Drugie: prostsze deployowanie — REST bez WSDL, bez generowania proxy classes. Trzecie: lepsze wsparcie w nowoczesnych frameworkach (FastAPI, Express, Next.js). Czwarte: łatwiejsze cacheowanie HTTP (Cloudflare, Varnish) niż dla SOAP. Argumenty przeciw. Pierwsze: stabilność — SOAP w VIES jest od 1993, REST od 2020. SOAP nigdy nie wprowadził breaking changes. REST mógł. Drugie: dokumentacja — SOAP ma pełną WSDL z typami, REST ma tylko prosty opis. Trzecie: walidacja typów — SOAP wymusza poprawne typy w czasie wykonania, REST jest 'duck-typed' w JSON. Czwarte: identyfikator konsultacji — SOAP zwraca w polu requestIdentifier, REST w innym formacie (czasem niespójnym). Rekomendacja praktyczna. Istniejąca działająca integracja SOAP: nie migruj, nie naprawiaj co nie jest złamane. Nowa integracja od zera: REST dla MVP, SOAP gdy potrzebujesz produkcyjnej stabilności. Migracja: tylko jeśli architektonicznie znaczne korzyści (np. przejście na edge computing).
Bezpieczeństwo komunikacji SOAP — TLS i certyfikaty
VIES SOAP wymaga TLS 1.2 lub wyższego od 2018. Implementacja po stronie klienta. PHP: SoapClient od PHP 7.0 domyślnie używa OpenSSL z bieżącymi TLS — bez dodatkowej konfiguracji. Sprawdzenie: openssl_get_cert_locations(). Wersja TLS może być wymuszona przez stream_context: $context = stream_context_create(['ssl' => ['crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT]]); $client = new SoapClient($wsdl, ['stream_context' => $context]);. Python z zeep: wymuszenie TLS przez requests adapter. .NET: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; przed pierwszym wywołaniem. Java: -Dhttps.protocols=TLSv1.2 w VM args. Weryfikacja certyfikatu KE. KE używa certyfikatu wydanego przez Let's Encrypt (rotowany co 90 dni) lub QuoVadis (komercyjny). Nie ma certyfikatów EV w 2026 — KE przeszła na standardowe DV. Twój klient powinien weryfikować łańcuch certyfikatów względem standardowego trust store. Wyłączenie weryfikacji (verify_peer => false w PHP) jest nieakceptowalne dla produkcji — naraża na MITM. Dla testów lokalnych z self-signed certyfikatami: użyj sandbox ViesVAT, nie wyłączaj walidacji.
Migracja z SOAP do gRPC — przyszłość 2027+
Komisja Europejska rozważa wprowadzenie gRPC jako trzeciego protokołu dostępu do VIES od 2027. gRPC oferuje przewagi nad SOAP/REST: serializacja binarna (Protocol Buffers, mniejsze pakiety), HTTP/2 (multiplexing, mniejsza latencja), wsparcie streaming. Plan KE: pilot 2026, beta 2027, GA 2028. Wstępna specyfikacja proto file: service ViesService { rpc CheckVat(CheckVatRequest) returns (CheckVatResponse); rpc CheckVatBatch(BatchRequest) returns (stream BatchResponse); }. message CheckVatRequest { string country_code = 1; string vat_number = 2; string requester_country_code = 3; string requester_vat_number = 4; }. Dla deweloperów oznacza to: dodatkowy protokół do obsługi, ale przede wszystkim szybsze odpowiedzi (gRPC ~30% szybsze od REST dla małych zapytań). ViesVAT będzie wspierał gRPC od momentu jego GA, bez dodatkowych kosztów dla klientów Pro i Business. Migracja istniejących integracji SOAP/REST na gRPC nie będzie obowiązkowa — wszystkie 3 protokoły będą wspierane równolegle co najmniej do 2032.
Optymalizacja produkcyjna — connection pooling i keepalive
Dla integracji produkcyjnych z dużym wolumenem (1000+ zapytań/dzień) optymalizacja konfiguracji klienta SOAP ma wyraźny wpływ na koszty i wydajność. Connection pooling: utrzymuj pulę otwartych połączeń HTTPS z VIES KE zamiast otwierać nowe dla każdego zapytania. PHP: użyj cURL z CURLOPT_FORBID_REUSE = false (domyślnie) i odpowiednio długim KeepAlive. Python: requests.Session() lub aiohttp.ClientSession() — automatyczny connection pool. Node.js: agent z keepAlive: true (HTTP/HTTPS Agent). .NET: HttpClient z HttpClientFactory (zarządzany pool). Java: Apache HttpClient z PoolingHttpClientConnectionManager. Zysk: dla 1000 zapytań redukcja czasu o 30–50% (eliminacja TCP handshake + TLS handshake). DNS caching: keszuj rozdzielenie DNS dla ec.europa.eu (TTL 24h). Compression: SOAP odpowiedzi VIES są dość duże (1–5 KB XML); włącz gzip compression w nagłówku Accept-Encoding. Redukuje transfer o 70–80%. Te optymalizacje są wbudowane w nasze SDK domyślnie — bez konfiguracji u klienta.
Debugging SOAP — narzędzia i strategie
Diagnostyka problemów SOAP wymaga specjalistycznych narzędzi. SoapUI (darmowa wersja Open Source, płatna ReadyAPI) — najpopularniejsze narzędzie do testowania SOAP. Import WSDL z VIES, wykonaj próbne zapytania, analizuj odpowiedzi XML. Pozwala symulować różne błędy i obserwować zachowanie klienta. Postman z dodatkiem SOAP — alternatywa dla użytkowników preferujących Postman. Tcpdump/Wireshark dla niskopoziomowego śledzenia ruchu HTTPS (wymaga rozszyfrowania TLS, więc tylko w środowiskach testowych z własnym certyfikatem). Logging po stronie klienta SOAP: PHP SoapClient ma trace=true, który zapisuje surowe żądania i odpowiedzi. Python zeep ma history plugin. Node.js node-soap emituje eventy 'request' i 'response'. .NET WCF ma MessageInspector. Te narzędzia razem dają pełny wgląd w komunikację z VIES. Najczęstsze przyczyny błędów wykrywane podczas debuggingu: błędne dane w nagłówku SOAP (głównie SOAP-ENV namespace), nieprawidłowy format zapytania (brak wymaganych elementów), problemy z certyfikatami SSL, timeouty na poziomie sieciowym, niezgodności kodowania znaków (zwłaszcza dla nazw firm z znakami specjalnymi).
WSDL versioning i wsteczna kompatybilność
KE rzadko zmienia WSDL VIES — ostatnia istotna zmiana w 2020 przy wprowadzeniu REST. Ale nawet drobne aktualizacje WSDL mogą mieć wpływ na klientów. Dobre praktyki. Pierwsze: pin URL WSDL do konkretnej wersji jeśli to możliwe — KE udostępnia versioned URLs dla SOAP. Drugie: nie generuj proxy classes w czasie wykonania (slow startup), generuj statycznie podczas budowy aplikacji. Trzecie: monitoring zmian WSDL — co tydzień sprawdzaj diff WSDL względem ostatniej znanej wersji. Czwarte: testy regresyjne po każdej aktualizacji KE. KE komunikuje istotne zmiany przez DG TAXUD News (newsletter) i w technicznej dokumentacji. Wsteczna kompatybilność: KE zwykle zachowuje wsteczną kompatybilność (nowe pola dodawane jako opcjonalne, stare pola nie usuwane). Ale historycznie zdarzało się raz na 5–10 lat breaking change — wymagający aktualizacji klientów. ViesVAT monitoruje WSDL KE 24/7 i informuje klientów planu Pro+ o każdej zmianie z 30-dniowym wyprzedzeniem (większość zmian KE komunikuje wcześniej z konsultacji branżowych).
Najczęściej zadawane pytania
Czy SOAP zostanie wyłączony?
KE deklaruje wsparcie SOAP przez co najmniej kolejne 10 lat. REST API jest dodatkiem, nie zamiennikiem.
Czy są oficjalne SDK?
KE nie udostępnia oficjalnych SDK. Społeczność udostępnia liczne biblioteki: PHP vies, Python vatchecker, Node node-vat, .NET DotNetVIES.
Co z REST API?
REST jest dostępny pod ec.europa.eu/taxation_customs/vies/rest-api. Pełna funkcjonalność równoważna SOAP.
Czy potrzebuję klucza API?
Nie — VIES jest darmowy i nie wymaga uwierzytelniania.
Jakie są limity?
Soft-limit ok. 5–10/s. Powyżej throttling lub blokada IP.
Czy mogę użyć VIES z frontend (przeglądarka)?
Nie bezpośrednio — VIES nie pozwala na CORS. Musisz mieć backend proxy.