VAT Number Validation with Geissweb EU VAT
Hyvä POS is in closed beta
Hyvä POS is currently in a closed beta (pilot phase) with a small group of merchants. It is not yet generally available: the App Store release follows the pilot, and features and configuration may still change, possibly in backwards-incompatible ways, before the general release. Want to take part? Sign up at hyva.io/pos.
hyva-themes/magento2-hyva-pos-geissweb-euvat-bridge validates a customer's VAT number through Geissweb EU VAT Enhanced when a cashier creates or edits a customer at the register. It is a customer validator in the POS validator pool: the module's syntax check runs first, then its VIES lookup, which the module caches and retries with the requester VAT number and retry count from its own configuration.
What the cashier sees
Both of Magento's VAT numbers are checked: the customer account's Tax/VAT number (taxvat) and, since bridge 1.1.0, the VAT number on the draft's address (vatId). The rows land under the field that carried the number. A number both fields carry is looked up once (spacing, dots and case do not make it a second number) and the verdict is reported on each field; two different numbers are two lookups. The address check needs a hyva-themes/magento2-hyva-pos that carries the address VAT id on the validation request.
| Code | Severity | When |
|---|---|---|
vat_number_invalid_format |
error | The number does not have the format of its country's VAT numbers. VIES is not asked. |
vat_number_not_registered |
error | VIES answered: the number is not registered. |
vat_number_unverified |
warning | VIES gave no verdict: the service or the member state did not answer, or the module threw. The cashier decides; Save anyway is offered when the store allows overrides. |
vat_number_verified |
info | Registered, with the trader's name when VIES returns one. |
An error blocks the save. The built-in TaxvatValidator keeps its length and character checks and the normalize suggestion (upper case, no spaces); the bridge adds the lookup.
Which country is checked
The number's own prefix when it has one (EL is Greece's VAT prefix and is read as GR), otherwise the address country of the draft. There are no rows for a number without either, for a country outside the store's EU country list (general/country/eu_countries, plus GB, which the module checks through HMRC), for a country excluded in the module's settings, and when the module's Enable VAT number validation is off.
Requirements and configuration
geissweb/module-euvat1.25 or later, with a requester VAT number and a domestic country configured under Stores → Configuration → Geissweb → EU VAT Enhanced. The bridge does not register when the module is absent, so it can stay installed on a store without it.- The module's Enable VAT number validation switch and its excluded countries apply to the register as well.
- The validator is listed as Geissweb EU VAT number (VIES lookup) in the merchant's Customer Validators setting (Stores > Configuration > Hyvä POS > Terminal Defaults > Customers, website scope). Empty, the default, runs every installed validator, so the bridge works as soon as it is installed; a store that has made a selection has to include this one for the lookup to run.
Install
composer require hyva-themes/magento2-hyva-pos-geissweb-euvat-bridge
bin/magento module:enable Hyva_PosGeisswebEuvatBridge
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:flush
Verify
curl -s -X POST https://your-store/rest/V1/pos/customer-validate \
-H "Authorization: Bearer <pos token>" -H "Content-Type: application/json" \
-d '{"request":{"email":"vat@example.com","firstname":"A","lastname":"B","websiteId":1,"taxvat":"NL861802329B01","countryCode":"NL"}}'
A registered number answers an info row with code vat_number_verified and the trader's name; an unregistered one an error row with vat_number_not_registered. The first lookup of a number takes the VIES round trip (one to three seconds); the module caches the answer.
Tests
Run the suite from the module root with PHPUnit 10. The tests run with or without Geissweb installed; the bootstrap stubs the module's classes when they are absent. The conformance kit of the core module is included.