Turns out the European Commission has a service where people can verify VAT numbers: The VAT Information Exchange System (VIES). Good thing since we don’t want to have to figure out how each individual European country handles VAT numbers. There is a web based user interface where users can manually input the number they want to check, but more interestingly for developers, there is a web service that uses SOAP.

I’m going to do is to call this SOAP service, but also wrap it in a REST API so it fits neatly into the rest of my API — slow clap for the bad pun.

The WSDL that describes the interface for the VAT service is here.

http://ec.europa.eu/taxation_customs/vies/checkVatTestService.wsdl

The Spring guide for SOAP web services suggests using a maven plugin for JAXB to generate the corresponding Java classes.

<build>
    <plugins>
       ...

        <plugin>
            ...
            <configuration>
                <schemaLanguage>WSDL</schemaLanguage>
                <generatePackage>vies.wsdl</generatePackage>
                <schemas>
                    <schema>
                        <url>http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl</url>
                    </schema>
                </schemas>
            </configuration>
        </plugin>
    </plugins>
</build>

With this added to pom.xml, we can run the jax2b plugin with the generate goal.

mvn jaxb2:generate

These classes can also can be generated using IntelliJ.

With the code generated, we can create a web service client.

public class VatClient extends WebServiceGatewaySupport {
    @Value("${vies.url}")
    private String url;

    @Value("${vies.wsdl}")
    private String wsdl;

    public CheckVatResponse checkVat(String countryCode, String vatNumber) {
        CheckVat request = new CheckVat();
        request.setCountryCode(countryCode);
        request.setVatNumber(vatNumber);

        return (CheckVatResponse) getWebServiceTemplate()
                .marshalSendAndReceive(url, request, new SoapActionCallback(wsdl));
    }
}

I’m placing strings in application.properties:

vies.url=http://ec.europa.eu/taxation_customs/vies/services/checkVatService
vies.wsdl=http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl

Jaxb2Marshaller configuration.

@Configuration
public class VatConfig {
    @Value("${vies.wsdl}")
    private String wsdl;

    @Bean
    public Jaxb2Marshaller marshaller() {
        Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
        marshaller.setContextPath("vies.wsdl");
        return marshaller;
    }

    @Bean
    public VatClient vatClient(Jaxb2Marshaller marshaller) {
        VatClient client = new VatClient();
        client.setDefaultUri(wsdl);
        client.setMarshaller(marshaller);
        client.setUnmarshaller(marshaller);
        return client;
    }
}

A controller for our API.

@RestController
public class VatController {
    @Autowired
    private VatClient vatClient;

    @GetMapping("vat")
    public ResponseEntity<?> vat(@RequestParam String countryCode, @RequestParam String vatNumber) {
        CheckVatResponse checkVatResponse = vatClient.checkVat(countryCode, vatNumber);
        if (checkVatResponse == null) {
            return ResponseEntity.status(500).build();
        }
        return ResponseEntity.status(200).body(checkVatResponse);
    }
}

Let’s call our REST API with the VAT number for a well known public company, Volvo.

curl 'http://localhost:8080/vat?countryCode=SE&vatNumber=556012579001'

The response we get indicates the VAT number is valid and gives us some information about the company.

{
    "countryCode": "SE",
    "vatNumber": "556012579001",
    ...
    {
        ...
        "value": "Aktiebolaget Volvo",
        ...
    },
    "address":
    {
        ...
        "value": "DC 24000 \nARSC2 \n405 08 GÖTEBORG",
        ...
    }
}

Source on GitHub.