Giter VIP home page Giter VIP logo

dragonbe / vies Goto Github PK

View Code? Open in Web Editor NEW
262.0 19.0 59.0 872 KB

Component using the European Commission (EC) VAT Information Exchange System (VIES) to verify and validate VAT registration numbers in the EU, using PHP and Composer.

Home Page: http://ec.europa.eu/taxation_customs/vies/faqvies.do#item16

License: MIT License

PHP 100.00%
php vat-number vat-information-exchange vat-registration-number eu vat-validation vat-identification europe composer composer-package

vies's Issues

Grece is using custom country code EL instead of the international code GR

The two-letter country code for Greece is GR, but in VAT id's in Europe Greece uses the EL-prefix instead.

https://en.wikipedia.org/wiki/ISO_3166-2:GR

In our code we used this list to compare to the international country codes and because GR != EL this obviously failed: https://github.com/DragonBe/vies/blob/master/src/Vies/Vies.php#L63

We will now take the list from listEuropeanCountries and make sure we convert this, but opening this here as a note. Maybe we should note the exception in a comment in this method, or note that EL is not the international code for Greece, they just use that as a VAT prefix. So in a sense the method name is misleading...

Thanks for a great library!

Add cache, to save traffic to VIES service and improve performance

There are applications in which a VAT number may need to be checked more than once per day (customer makes multiple purchases in short period of time).

Do you think it would make sense to add a cache in order to reduce the traffic to the backend service and further improve performance.

A TTL of 1 day as default would make sense, in my opinion.

What do you think?

Improve quality of VAT validation

According to a colleague who works a lot with VAT, the following things need to be considered:

  • VAT number + Registered Company name give better validation result
  • VAT numbers in Spain require also company address for full validation
  • VAT number validation + Company details returned by some countries

Validating Belgium VAT numbers without leading zero

When validating a Belgium VAT number, they should start with a zero (after the country code). The ValidatorBE class fixes this nicely when it validates the number. If the number is 9 chararacters long, it will be prefixed with a zero.

The function validateVatSum then returns true and the VAT number is processed to the VIES service through a SOAP call. But the VAT number send to VIES is without the leading zero and thus it is validated false.

So it has no point of adding the leading zero if this is not also send to VIES. I would advise to also send the VAT number with leading zero to VIES. Or otherwise validate a VAT number without the leading zero as invalid directly in de ValidatorBE class.

Invalidate old Dutch OB numbers in favour of new VAT ID as of 2020

Since January 1, 2020 self employed people in the Netherlands received a new VAT identification number as replacement for their older number which contained their social security number (BSN).

In release 2.1.10 we made changes to allow this new number to be validated, but we left out the invalidation of the old number as it now is called "omzetbelastingnummer" or OB number.

On kleineondernemer.nl (Dutch) they describe how to invalidate these OB numbers.

As they describe it (translated by me):

For natural people the number looks like the following starting from 01-01-2020;

  • position 1 - 2; the country code
  • position 3 - 11; 9 numbers. This series of numbers never confirms to the so called eleven proof.
  • position 12; the letter "B"
  • position 13 - 14; 2 numbers. Control number confirms to modulo 97 over the whole number

Which means the old OB number which contains the social security number should now be checked against the eleven proof.

We now need to invalidate those Dutch VAT numbers that still confirm to the 11 proof as they contain the social security numbers which is a violation against GDPR.

Optional Argument Validation Fails for non-latin characters

The addOptionalArguments method throws an InvalidArgumentException if an argument contains exclusively non-ascii characters.

e.g. if the traderName is ΕΛΛΑΣ

– note that the E and the A are Greek, and not Latin, unicode characters here. For test purposes something like Äß also throws the exception.

The filterArgument strips away all greek letters (and accented characters such as ä and é). In the case of ΕΛΛΑΣ – this means an empty string is sent to validateArgument.

The regex in validateArgument is probably also problematic. Changing to this:

/^[a-zA-Z0-9α-ωΑ-Ω\s\.\-,]+$/

– Will allow the greek alphabet but I don’t know whether that’s sufficient.

False response data

I have noticed incorrect validations. Look at the example below. Same VAT number with different results:

  • Yes, valid VAT number (correct on VIES website)
  • ["valid":protected]=>bool(false) (incorrect response $vatResult->isValid())

Am I missing something?

http://ec.europa.eu/taxation_customs/vies/vatResponse.html

Yes, valid VAT number
Member State | SI |  
VAT Number | SI 21825831
Date when request received | 2019/05/24 11:49:44

object(DragonBe\Vies\CheckVatResponse)#4999 (7) {
  ["countryCode":protected]=>
  string(2) "SI"
  ["vatNumber":protected]=>
  string(8) "21825831"
  ["requestDate":protected]=>
  object(DateTime)#472 (3) {
    ["date"]=>
    string(26) "2019-05-24 11:53:56.789394"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(16) "Europe/Ljubljana"
  }
  ["valid":protected]=>
  bool(false)
  ["name":protected]=>
  string(3) "---"
  ["address":protected]=>
  string(3) "---"
  ["identifier":protected]=>
  string(0) ""
}

Two uncaught SoapFault exception

On iterating through a long list (ca. 2,000 items) of VAT numbers, validating each, I have received both these uncaught SoapFault exceptions.

PHP Fatal error: Uncaught SoapFault exception: [soap:Server] MS_MAX_CONCURRENT_REQ in [..]/vies/src/Vies/Vies.php:229

PHP Fatal error: Uncaught SoapFault exception: [soap:Server] MS_UNAVAILABLE in [..]/vies/src/Vies/Vies.php:229

Invalid VAT number doesn't mean that it's not real ;-)

if (! $this->validateVatSum($countryCode, $vatNumber)) {

This condition might be tricky... As my second test I've tried VAT CZ27082440 (the biggest e-shop in our country) which was evaluated by validateVatSum() method as invalid but it's existing and can be properly checked via VIES website.

I understand that the purpose of this is probably reducing requests to VEIS but IMHO I would not trust any EU administrator that a pattern (probably defined by law) for VAT number was fulfilled. As a result of this condition we get faked data, not real data from VIES.

Removing this condition or making it optional would help.

Uncaught SoapFault exceptions

On iterating through a long list (ca. 2,000 items) of VAT numbers, validating each, I have received all the following uncaught SoapFault exceptions.

PHP Fatal error: Uncaught SoapFault exception: [soap:Server] MS_MAX_CONCURRENT_REQ
in [..]/vies/src/Vies/Vies.php:229

PHP Fatal error: Uncaught SoapFault exception: [soap:Server] GLOBAL_MAX_CONCURRENT_REQ
in [..]/vies/src/Vies/Vies.php:229

PHP Fatal error: Uncaught SoapFault exception: [soap:Server] MS_UNAVAILABLE
in [..]/vies/src/Vies/Vies.php:229

Checks if the VIES service is online and available

There seems to be a new endpoint we could use to check if the VIES service is up and running.

For the SOAP service you may send your xml request by using the following WSDL link:

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

and by using the below values (common for all Member States/ CountryCodes) for each required result:

“vatNumber” value=100, response= VALID

“vatNumber” value=200, response = INVALID

I'll will try to implement it.

Czech VAT IDs may be longer than 8 digits

Hello. According to the source code of the class DragonBe\Vies\Validator\ValidatorCZ, a Czech VAT ID must be 8 digits long, but thatʼs wrong. Our law states that a VAT ID consists of the prefix “CZ” and one of the following:

  • for individiuals: their personal identification number, or other general identificator if specified by a special law
  • for companies and other legal entities: their taxpayer identification number
  • in case the entity doesnʼt have a general identificator assigned, the tax administrator can assign a custom identificator

Example: CZ699004237 is a valid VAT ID, but this library marks it as invalid.

Iʼm afraid that there is no way of strictly checking the formal validity of the VAT ID before submitting it to VIES. I personally have seen only VAT IDs that are (excluding the “CZ“ prefix) 8, 9 or 10 digits long, but I could not find any legal evidence that indicate these are the only valid formats.

Dutch Sole trader VAT number changed (2020).

For sole traders in the netherlands the format for VAT number changed.
We've now hotfixed this by removing the checksum check in the ValidatorNL.

I could not find a clear picture of how to checksum check these new VAT numbers yet.

Italian validator assumes numeric input

We got a nice error:

Stack trace:
#0 vendor/dragonbe/vies/src/Vies/Validator/ValidatorIT.php(52): {closure}(2, 'A non-numeric v...', '/data/www/...', 52, Array)
#1 vendor/dragonbe/vies/src/Vies/Vies.php(305): DragonBe\Vies\Validator\ValidatorIT->validate('AA123456789')
#2 vendor/dragonbe/vies/src/Vies/Vies.php(242): DragonBe\Vies\Vies->validateVatSum('IT', 'AA123456789')
#3 application/classes/supplier/vies.php(72): DragonBe\Vies\Vies->validateVat('IT', 'AA123456789', '..', '...')

Note that the number was invalid to start with, but a ctype_digit check would have prevented an error from being triggered. It tries to do some math calculation on a non-digit.

Use option proxy even at HeartBeat

Hello,
we are using Vies with proxy. Getting data from vies is fine, but HeartBeat does not work.

$option = array(
            'proxy_host' => $this->https_proxy['host'],
            'proxy_port' => $this->https_proxy['port'],
            'proxy_login'    => $this->domain_user['user'],
            'proxy_password' => $this->domain_user['password']
        );
        $vies->setOptions($option);

        if (false === $vies->getHeartBeat()->isAlive()) {
            $vat_numbers_data['result'] = 'VIES - Service is not available at the moment, please try again later.';
            $this->serviceModel->insertApiCallResponseLog($id_request, 500, [$vat_numbers_data]);
            return true;
        } else {
// do more
}

Validation failed for valid VAT numbers

Hi,
I encountered several cases, where the library returns false negatives (invalid vat while VIES web service returns valid):

FR45497709824
NL001439542B97

Am I doing anything wrong?

Thank you

Screenshot 2021-02-15 at 18 05 00

Screenshot 2021-02-15 at 18 05 34

Screenshot 2021-02-15 at 18 05 55

Add support for United Kingdom (Northern Ireland) ("GB-NIR")

In accordance with the agreed Protocol on Ireland and Northern Ireland following Brexit, EU customs rules and procedures generally continue to apply to goods entering and leaving Northern Ireland.

Source: https://ec.europa.eu/taxation_customs/uk_withdrawal_en

We therefore should add support for the "United Kingdom (Northern Ireland)".

Since the new XI VAT numbers for Northern Ireland businesses are just like the GB VAT numbers, we should be able to re-purpose the current GB validator:

Businesses should substitute "XI" country code in their GB VAT number on invoices so that the transactions can be identified separate from UK VAT transactions. So XI 123456789 - instead of GB 123456789.

Source (and other details): https://www.avalara.com/vatlive/en/vat-news/brexit-northern-ireland-vat-and-eoro--xi--number.html

deal with the webservice down

Hi,

I was wondering if there was any general guideline on the behavior to adopt when the service is down (which happens quite regularly) ?
Or is it a matter of it depends per application.

Thanks

Complete list of railway companies within the EU

In the examples/ directory, I've made an example testcase for validating VAT ID's for a couple of European railway companies in EURailwayVATChecker.php.

It would be nice if this list could be completed so we have a example company VAT ID's for all EU member states so people could see the responses returned by the EU VIES service. It's an easy way to get involved and to help making this project better.

European Railways Map provided by Dailyinfographics.eu

Irish VAT numbers can be 8 OR 9 characters

VAT numbers from Ireland (IE) can be 9 characters long - but the ValidatorIE class expects a length of 8.

if (strlen($vatNumber) != 8) {
    return false;
}

Which makes 9 character valid Irish VAT numbers fail a validation.

I've forked the repo and will look into fixing this and making a pull request once it's working.

EDIT: Another source for the 8 OR 9 length.

Response requestDate wrong

Soap response:

'requestDate' => '2019-08-31+02:00',

means you got Y-m-dP

P
Difference to Greenwich time (GMT) with colon between hours and minutes (added in PHP 5.1.3)
Example: +02:00

see https://www.php.net/manual/de/function.date.php

You are currenty using Y-m-d\+H:i which set it to 2am always :)

So in example:
response:
'requestDate' => '2019-08-31+02:00',

current code:
date_create_from_format('Y-m-d\+H:i', $response->requestDate)
returns:

DateTime::__set_state(array(
    'date' => '2019-08-31 02:00:00.000000',
    'timezone_type' => 3,
    'timezone' => 'UTC',
))

should use:
date_create_from_format('Y-m-dP', $response->requestDate)
BUT
this would automatically add current time due to the api does not provide time.

So a solution would be (since we get no time) to set the time to zero.

$datetime = date_create_from_format('Y-m-dP', $response->requestDate);
$datetime->setTime(0, 0, 0, 0);

DateTime::__set_state(array(
    'date' => '2019-08-31 00:00:00.000000',
    'timezone_type' => 1,
    'timezone' => '+02:00',
))

PR: #69

EDIT: the warning in te main readme should be removed.
WARNING: VIES service returns invalid time, use your own time setting!

PR: #71

EDIT: i just saw you have the format already implemented but not used anywhere:
\DragonBe\Vies\CheckVatResponse::VIES_DATETIME_FORMAT
public const VIES_DATETIME_FORMAT = 'Y-m-dP';

gonna change that ...

Meaningful constants

When we first started out creating this service, we only looked at validation of VAT ID's for EU countries and named our constants in such a way that we weren't ready for other validation types.

Now with issue #82 a new type of validation was presented for companies outside of EU that require a VAT ID to perform business within the EU. We have implemented this validation already in PR #85 but the naming convention of the constants VIES_EU_COUNTRY_TOTAL and VIES_EU_COUNTRY_LIST no longer represent their true values.

These constants require to be changed into a more meaningful label that reflects this new situation.

[Insight] Usage of a function in loops should be avoided - in src/Vies/Validator.php, line 445

in src/Vies/Validator.php, line 445

This loop uses a function. To avoid the overhead of executing the function n times, you should precalculate it before the loop.

            return false;
        }
        $weights = array(6, 5, 7, 2, 3, 4, 5, 6, 7);
        $checksum = (int)$vatNumber[9];
        $checkval = 0;
        for ($i = 0; $i < count($weights); $i++) {
            $checkval += (int)$vatNumber[$i] * $weights[$i];
        }
        $checkval = $checkval % 11;
        if ($checkval != $checksum) {
            return false;

Posted from SensioLabsInsight

Remove support for the United Kingdom ("GB")

On 31 December 2020, the transition period for the United Kingdom's withdrawal from the EU ended. This means that the UK is now formally a third country and EU law no longer applies there.

For the purposes of customs, the UK is treated as any other non-EU country as of 1 January 2021. In particular, customs procedures and formalities now apply to trade between the UK and the EU.

Source: https://ec.europa.eu/taxation_customs/uk_withdrawal_en

We therefore should remove support for the United Kingdom.

Implementing a Symfony constraint based on this library

We have been using this great library for a while now, and I have begun to extract some code we have in a few classes for this to something more generic and useful. Today we are using Symfony and a callback validator, but I am extracting it into a separate class like described here: https://symfony.com/doc/current/validation/custom_constraint.html

Would a PR be welcome with this functionality? Any pointers on how / where you like it?
I am thinking it will take a string input like this SE12345678901 and do the validation using this library.

Validation of Irish VAT ID failed for valid VAT ID

I was validating supplier VAT ID's and noticed that for Slack Technologies LTD (IE3336483DH) the validation failed while the VIES service confirms it's a valid VAT ID.

image

Looks like there's a failure in validating Irish VAT ID's

Making VIES package more inclusive

The technology industry is progressing towards a more inclusive society with many leading initiatives, including GitHub, taking steps to remove non-inclusive terminology from their operations. As an open source contributor having an open source project, I want to take up my responsibility and join the efforts.

Therefor I will take steps to make this project welcoming to many. I'm thinking about the following actions:

  • rename the default base branch from "master" to "main"
  • scan the code and tests for non-inclusive terms and rename them
  • update my CONTRIBTING and CODE_OF_CONDUCT documents

Please provide constructive feedback on this proposed change.

Add Docker image build CI

As title, I think it should be nice to have the Docker image building with CI.

IMHO, I think we can use GitHub Actions or Travis CI to accomplish this issue.

@DragonBe, do you have any suggestion about this?

Once this issue is accepted, I think I would be happy to work on this 😄 .

Improve quality of VAT validation -- companyCountryCode

Before we know whether to ask a customer for a VATIN, we have to first find out in which country his or her company is registered. If this country code is one of the 28 EU member states, then we should ask the customer for a VATIN in a B2B application.

Therefore, we know to which member state a VATIN should belong. For example, a German company (countryCode: DE), must enter a VATIN starting with "DE". Similarly, a Belgium company (countryCode: BE) must enter a VATIN starting with "BE".

As everyone validating VATINs has to implement this logic in his or her own program code, I feel it would be useful for DragonBe\Vies to accept a "companyCountryCode" i.e. the code of the country of the customer's registered company. In the case that the "companyCountryCode" does not match the country code of the VATIN, then an error would be raised before the validateVatSum() stage, and certainly before speaking to the SOAP service.

What do you think?

32 Bit Support

FR's, NL's and SK's VATIN validations fail on 32 bit platform.
Is this project going to support the x32 ABI or the i386 ABI?

VIES_EU_COUNTRY_LIST Visibility

VIES_EU_COUNTRY_LIST is a protected const, but all other code is using self::VIES_EU_COUNTRY_LIST.

the protected visibility gives the illusion you can extend the class and for example remove UK (#98 ), but this wouldn't work.

VIES_EU_COUNTRY_LIST should either be private or beter; other methods should use: static::VIES_EU_COUNTRY_LIST

pcntl required but unused

Hey,

I'm wondering why you are requiring the PCNTL extension to be installed, since, as far as I can see, it is not used in the code. This makes it so that I cannot use the package on my Windows development machine.

Cheers,
Koen

SI Validator bug

The following tax number is false:SI95796550
This is valid on online validation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.