简体   繁体   English

VIES 增值税号验证

[英]VIES VAT number validation

How to incorporate a form on our website to validate the VIES?如何在我们的网站上加入表格来验证 VIES? I find information to validate it through the website of the European Union.我通过欧盟的网站找到了验证它的信息。

http://ec.europa.eu/taxation_customs/vies/vieshome.do http://ec.europa.eu/taxation_customs/vies/vieshome.do

And what interest me is validate directly from the form of payment data from my website.我感兴趣的是直接从我网站上的支付数据形式验证。

Actually, the VIES database can be queried via their API.实际上,可以通过他们的 API 查询 VIES 数据库。
They support only the SOAP protocol, but that should be sufficient.它们仅支持 SOAP 协议,但这应该足够了。

Here's a simple example:这是一个简单的例子:

$client = new SoapClient("http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl");
var_dump($client->checkVat(array(
  'countryCode' => $countryCode,
  'vatNumber' => $vatNo
)));

Here's the WSDL: http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl这是 WSDL:http: //ec.europa.eu/taxation_customs/vies/checkVatService.wsdl

There are multiple providers of APIs which are based on the original one, but provide it using different protocols.有多个 API 提供者基于原始 API 提供,但使用不同的协议提供。 Simply told, they act like translators - using json with your application and connect using SOAP to the original API.简而言之,它们就像翻译器一样 - 在您的应用程序中使用 json 并使用 SOAP 连接到原始 API。 These have a major problem with the connection timeout.这些都有连接超时的主要问题。

There are times where the VIES database is responding slowly, thus requiring more time to return a response.有时 VIES 数据库响应缓慢,因此需要更多时间来返回响应。 This should be considered while designing your application.在设计应用程序时应考虑这一点。

If for some reasons you can't use SOAP on your server (no available, whatever) then file_get_contents is your friend.如果由于某些原因您不能在您的服务器上使用 SOAP(不可用,无论如何),那么file_get_contents就是您的朋友。

The implementation below does not depend on SOAP, Curl, XMLParser (Simple or not).下面的实现不依赖于 SOAP、Curl、XMLParser(简单与否)。 It is standard PHP code that should work on any PHP version you may have.它是标准的 PHP 代码,应该适用于您可能拥有的任何 PHP 版本。

The function returns the following items:该函数返回以下项目:

  • countryCode国家代码
  • vatNumber增值税号
  • requestDate查询日期
  • valid有效的
  • name姓名
  • address地址

Well, I hope it helps :-)好吧,我希望它有所帮助:-)

<?php
DEFINE ( 'VIES_URL', 'http://ec.europa.eu/taxation_customs/vies/services/checkVatService' );

/**
 * VIES VAT number validation
 *
 * @author Eugen Mihailescu
 *        
 * @param string $countryCode           
 * @param string $vatNumber         
 * @param int $timeout          
 */
function viesCheckVAT($countryCode, $vatNumber, $timeout = 30) {
    $response = array ();
    $pattern = '/<(%s).*?>([\s\S]*)<\/\1/';
    $keys = array (
            'countryCode',
            'vatNumber',
            'requestDate',
            'valid',
            'name',
            'address' 
    );

    $content = "<s11:Envelope xmlns:s11='http://schemas.xmlsoap.org/soap/envelope/'>
  <s11:Body>
    <tns1:checkVat xmlns:tns1='urn:ec.europa.eu:taxud:vies:services:checkVat:types'>
      <tns1:countryCode>%s</tns1:countryCode>
      <tns1:vatNumber>%s</tns1:vatNumber>
    </tns1:checkVat>
  </s11:Body>
</s11:Envelope>";

    $opts = array (
            'http' => array (
                    'method' => 'POST',
                    'header' => "Content-Type: text/xml; charset=utf-8; SOAPAction: checkVatService",
                    'content' => sprintf ( $content, $countryCode, $vatNumber ),
                    'timeout' => $timeout 
            ) 
    );

    $ctx = stream_context_create ( $opts );
    $result = file_get_contents ( VIES_URL, false, $ctx );

    if (preg_match ( sprintf ( $pattern, 'checkVatResponse' ), $result, $matches )) {
        foreach ( $keys as $key )
            preg_match ( sprintf ( $pattern, $key ), $matches [2], $value ) && $response [$key] = $value [2];
    }
    return $response;
}

print_r ( viesCheckVAT ( 'RO', '19386256' ) );
?>

This websites sends an ordinary HTML form to a server.该网站将普通的 HTML 表单发送到服务器。

The simplest solution is to pass the params in the URL and use file_get_contents to get the response.最简单的解决方案是传递 URL 中的参数并使用file_get_contents来获取响应。

The response can then be parsed to extract the information you want.然后可以解析响应以提取您想要的信息。 Not tested, but shows the idea:未经测试,但显示了这个想法:

$country1 = 'PL';
$country2 = 'PL';
$vatnum1 = '123456';
$vatnum2 = '789012';

//Prepare the URL
$url = 'http://ec.europa.eu/taxation_customs/vies/viesquer.do?ms='.$country1.'&iso='.$country1.'&vat='.$vatnum1.'&name=&companyType=&street1=&postcode=&city=&requesterMs='.$country2.'&requesterIso='.$country2.'&requesterVat='.$vatnum2.'&BtnSubmitVat=Verify';

$response = file_get_contents($url);
// Do sth with the response
echo $response;

Here is a full stack validation javascript based validation script with regex + modulo per country :这是一个基于 javascript 的全栈验证验证脚本,每个国家/地区使用正则表达式 + 取模

http://www.braemoor.co.uk/software/vat.shtml http://www.braemoor.co.uk/software/vat.shtml

Download link: http://www.braemoor.co.uk/software/downloads/jsvat.zip下载链接: http ://www.braemoor.co.uk/software/downloads/jsvat.zip

Using webservices is sometime not an option.使用网络服务有时不是一种选择。

Also see PHP ports for EU VAT validation:另请参阅用于欧盟增值税验证的 PHP 端口:

EDIT: Please note, that links above refer to unofficial validation libraries.编辑:请注意,上面的链接是指非官方的验证库。 That means some algos are not officially published, other may change in time.这意味着一些算法没有正式发布,其他的可能会及时改变。 Libraries referred above might be helpful if utilizing official VIES webservices is not possible (eg intranet without online access, VIES offline etc.).如果无法使用官方 VIES 网络服务(例如,无法在线访问的内部网、离线 VIES 等),上述库可能会有所帮助。 If the validation using these libs passes then EU VAT has a good chance say 90-95% that it could be valid, but definitely not 100%.如果使用这些库的验证通过,那么欧盟增值税很有可能会说 90-95% 是有效的,但绝对不是 100%。 Only VIES can ensure 100% validity.只有 VIES 才能保证 100% 的有效性。

This is a composer package, which wraps the VIES WebService.这是一个 composer 包,它包装了 VIES WebService。 You can use this fast and easy: https://github.com/drahosistvan/vatvalidation您可以快速轻松地使用它: https ://github.com/drahosistvan/vatvalidation

You can use now js lib for european VAT validation:您现在可以使用 js lib 进行欧洲增值税验证:

jsvat - small library to check validity of EU VAT number jsvat - 检查欧盟增值税号有效性的小型库

Based on braemoor's vat lib , but rewrite with modern js standarts (braemoor, for exapmpe stil use .eval() ) and added to bower and npm registry.基于braemoor 的 vat lib ,但使用现代 js 标准重写(braemoor,例如仍然使用.eval() )并添加到bowernpm注册表。 Also with unit tests.还有单元测试。

bower i jsvat --save

or或者

npm i jsvat --save

I needed this in ruby, so here is my code我在 ruby​​ 中需要这个,所以这是我的代码

  • gem install savon宝石安装 savon
  • add this method to your controller将此方法添加到您的控制器

    def validateVAT # create a client for the service client = Savon.client(wsdl: 'http://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl') response = client.call(:check_vat, message: {countryCode: params[:country_code], vatNumber: params[:vat]}) render json: { valid: response.body[:check_vat_response][:valid] }, status: :ok end

I used the REST service at http://vatid.eu , but since they were blocked by VIES (I guess due to high volume of requests), I have switched to http://apilayer.net/ .我在http://vatid.eu使用了 REST 服务,但由于它们被 VIES 阻止(我猜是由于大量请求),我已切换到http://apilayer.net/

The free plan is 100 requests per month, so I have implemented a small cache and I generate my own table of valid VAT numbers (renewable every year), so I don't spend requests checking the same VAT number more than once.免费计划是每月 100 个请求,因此我实现了一个小型缓存,并生成了自己的有效增值税号表(每年可更新),因此我不会多次检查同一个增值税号的请求。 Suits my needs ;)适合我的需要;)

Here my solution in node:这是我在节点中的解决方案:

import axios from "axios";
import { JSDOM } from "jsdom";

export async function checkVatNumber(vatIdentificationNumber: string) {
  const regexVat = new RegExp(/([A-Z]{2})([0-9A-Za-z\+\*\.]{2,12})/);
  const match = vatIdentificationNumber.match(regexVat);

  if (!match || match.length !== 3) return null;

  const [fullVat, countryCode, vatNumber] = match;

  let xmls = `
    <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
      <soapenv:Header/>
      <soapenv:Body>
      <tns1:checkVatApprox xmlns:tns1="urn:ec.europa.eu:taxud:vies:services:checkVat:types">
        <tns1:countryCode>${countryCode}</tns1:countryCode>
        <tns1:vatNumber>${vatNumber}</tns1:vatNumber>
      </tns1:checkVatApprox>
      </soapenv:Body>
    </soapenv:Envelope>
  `;

  const response = await axios.post(
    "http://ec.europa.eu/taxation_customs/vies/services/checkVatService",
    xmls,
    { headers: { "Content-Type": "text/xml" } }
  );

  const dom = new JSDOM(response.data, { contentType: "application/xml" });
  const valid = dom.window.document.querySelector("valid")?.textContent;
  const traderName =
    dom.window.document.querySelector("traderName")?.textContent;
  const traderCompanyType =
    dom.window.document.querySelector("traderCompanyType")?.textContent;
  const traderAddress =
    dom.window.document.querySelector("traderAddress")?.textContent;

  return { fullVat, valid, traderName, traderCompanyType, traderAddress };
}

Usage:用法:

const vatData = await checkVatNumber("IE6388047V");
console.log({ vatData });

// vatData: {
//   fullVat: 'IE6388047V',
//   valid: 'true',
//   traderName: 'GOOGLE IRELAND LIMITED',
//   traderCompanyType: '---',
//   traderAddress: '3RD FLOOR, GORDON HOUSE, BARROW STREET, DUBLIN 4'
// }

You have to install these dependencies:您必须安装这些依赖项:

npm install axios jsdom
npm i --save-dev @types/jsdom // <-- if using Typescript

Obviously you want to add some error handling here and there but you get the gist ;)显然你想在这里和那里添加一些错误处理,但你得到了要点;)

They have recently (Sept. 2022) been able to implement a new REST API .他们最近(2022 年 9 月)能够实施新的 REST API I found that out by inspecting the request of their web form.我通过检查他们的 web 表格的请求发现了这一点。 The API URL is: API URL 是:

https://ec.europa.eu/taxation_customs/vies/rest-api/ms/ /vat/ https://ec.europa.eu/taxation_customs/vies/rest-api/ms/ /vat/

So for example Vat ID = DE122268496因此,例如增值税 ID = DE122268496

https://ec.europa.eu/taxation_customs/vies/rest-api/ms/DE/vat/122268496 https://ec.europa.eu/taxation_customs/vies/rest-api/ms/DE/vat/122268496

Result:结果:

{
  "isValid" : true,
  "requestDate" : "2022-09-15T13:02:47.009Z",
  "userError" : "VALID",
  "name" : "---",
  "address" : "---",
  "requestIdentifier" : "",
  "vatNumber" : "122268496",
  "viesApproximate" : {
    "name" : "---",
    "street" : "---",
    "postalCode" : "---",
    "city" : "---",
    "companyType" : "---",
    "matchName" : 3,
    "matchStreet" : 3,
    "matchPostalCode" : 3,
    "matchCity" : 3,
    "matchCompanyType" : 3
  }
}

There is also a API for the VIES database. VIES 数据库还有一个 API。 https://vatlayer.com/documentation . https://vatlayer.com/documentation

I'm looking for a work around for splitting the address information.我正在寻找一种解决方法来拆分地址信息。 Now you can get it but it is one string.现在你可以得到它,但它是一个字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM