调用欧盟VAT号码验证WebService始终返回无效结果的问题
1. VAT号码格式错误(最可能的原因)
你传入的VAT号码DE814416365包含了国家代码前缀,但VIES服务要求vatNumber参数只需要传入纯数字部分,国家代码已经通过countryCode参数单独传递。比如DE开头的VAT号码,应该只传814416365,而不是DE814416365。
这是VIES API的通用规则:countryCode是两位国家代码(如DE、FR),vatNumber是对应国家的纯数字(或符合该国格式的字符)部分,不能包含国家代码前缀。
2. JAX-WS版本不兼容问题
你的pom.xml中使用的jaxws-maven-plugin版本是2.3.2,这个版本基于旧的javax.xml.ws规范,而你依赖的是Jakarta EE 4.0.0(jakarta.xml.ws-api),版本不匹配会导致生成的代码需要手动修改导入语句,可能隐藏其他潜在问题。
建议把插件版本升级到4.0.0,和依赖版本保持一致:
<plugin> <groupId>com.sun.xml.ws</groupId> <artifactId>jaxws-maven-plugin</artifactId> <version>4.0.0</version> <configuration> <wsdlUrls> <wsdlUrl>https://ec.europa.eu/taxation_customs/vies/services/checkVatService.wsdl</wsdlUrl> </wsdlUrls> <keep>true</keep> <packageName>com.ffleuchten.vatchecker.generated</packageName> <sourceDestDir>src/main/java</sourceDestDir> </configuration> </plugin>
重新生成代码后,就不需要手动修改javax到jakarta的导入了。
3. RequestDate参数处理问题
你手动构造了requestDate并传入,但VIES服务的requestDate是输出参数(由服务返回当前请求的日期),不需要你传入值。你可以直接初始化一个空的Holder:
Holder<XMLGregorianCalendar> requestDateHolder = new Holder<>();
服务会自动填充这个值,手动传入可能导致格式不兼容(比如你用LocalDate转的格式可能不符合服务要求)。
4. 验证服务可用性
你可以先使用欧盟官方的VIES在线验证工具测试DE814416365是否有效,排除号码本身无效的情况。如果在线工具也显示无效,那就是号码的问题;如果在线工具显示有效,再回到代码排查。
修改后的测试代码示例
调整后的核心代码部分:
private void run() { try { System.out.println("checking VAT number " .concat(this.vatNumber) .concat(" with country code ") .concat(this.countryCode) .concat("...")); CheckVatService service = new CheckVatService(); CheckVatPortType port = service.getCheckVatPort(); // 注意:vatNumber不要带国家代码前缀 Holder<String> countryCodeHolder = new Holder<>(this.countryCode); Holder<String> vatNumberHolder = new Holder<>(this.vatNumber); // 不需要手动设置requestDate,由服务返回 Holder<XMLGregorianCalendar> requestDateHolder = new Holder<>(); Holder<Boolean> validHolder = new Holder<>(); Holder<String> nameHolder = new Holder<>(); Holder<String> adressHolder = new Holder<>(); port.checkVat(countryCodeHolder, vatNumberHolder, requestDateHolder, validHolder, nameHolder, adressHolder); String result = "VAT number " + countryCodeHolder.value + vatNumberHolder.value + " is " + (validHolder.value ? "valid" : "invalid"); if (validHolder.value) { result += ", belongs to " + nameHolder.value + " at " + adressHolder.value; } result += "!"; System.out.println(result); System.out.println("VAT number checked! exiting now..."); System.exit(0); } catch (Exception e) { e.printStackTrace(); System.exit(1); } }
内容的提问来源于stack exchange,提问作者roediGERhard

