Szamlazzhu vat checkout compatibility
Skill Lonsdale201/wp-agent-skills/szamlazzhu/szamlazzhu-vat-checkout-compatibility
A community-maintained collection of agent skills for WordPress plugin and theme development.
npx -y skills add Lonsdale201/wp-agent-skills --skill szamlazzhu-vat-checkout-compatibilityAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 21 stars21 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Make WooCommerce checkout, B2B, VAT/tax-number, address, and headless checkout code compatible with Integration for Szamlazz.hu & WooCommerce. Covers the classic checkout field `wc_szamlazz_adoszam`, order meta `_billing_wc_szamlazz_adoszam` and `_wc_szamlazz_adoszam_data`, user meta `wc_szamlazz_adoszam`, Checkout Block/Store API extension namespace `wc-szamlazz-vat-number`, the cart `vat_number` vs checkout `billing_vat_number` payload split, NAV/VIES validation filters, EU VAT exemption, company billing rules, admin/customer address display, and how another plugin should map its own VAT fields into Szamlazz.hu invoice XML without creating duplicate checkout state.
The file declares its own license as GPLv3. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
16.7 KB, as published. Nobody here has run it
Szamlazz.hu VAT/Checkout Compatibility
Use this skill when a plugin/theme must cooperate with the Szamlazz.hu WooCommerce VAT/tax-number workflow. The goal is one source of truth for company billing and VAT data, so invoices, checkout validation, customer addresses, subscription renewals, admin orders, and Store API checkout all agree.
The plugin's VAT feature loads only when its vat_number_type option is not no. Guard your integration for sites where the Szamlazz.hu VAT UI is disabled.
Version 6.2 added the "VAT number for all countries" path and made wc_szamlazz_vat_number_validation_results run for invalid VAT results too. Version 6.2.2 further adjusts EU VAT validation behavior. This skill was rechecked against the local 6.2.2 source and WooCommerce 10.9.4.
When to use this skill
Trigger when ANY of these are true:
- Adding or auditing a WooCommerce B2B/company billing field.
- Mapping another plugin's VAT number into Szamlazz.hu invoices.
- Supporting classic checkout and Checkout Blocks/Store API with the same VAT state.
- Debugging required VAT/company validation, EU VAT exemption, or VIES/NAV validation.
- The code touches
wc_szamlazz_adoszam,_billing_wc_szamlazz_adoszam,_wc_szamlazz_adoszam_data,wc-szamlazz-vat-number,wc_szamlazz_xml_adoszam,wc_szamlazz_vat_number_validation_results, orwoocommerce_store_api_checkout_update_order_from_request.
Canonical data contract
| Surface | Key/namespace | Meaning |
|---|---|---|
| Classic checkout POST field | wc_szamlazz_adoszam | Shopper-entered HU tax number or EU VAT number. |
| Company toggle field | wc_szamlazz_company_toggle | Checkbox mode, when configured. |
| Company radio field | wc_szamlazz_company_toggle_radio | individual or company, when configured. |
| Order meta | _billing_wc_szamlazz_adoszam | Canonical order VAT/tax number used for invoices. |
| Legacy order meta | wc_szamlazz_adoszam | Backward compatibility; plugin migrates/read-falls back. |
| Order meta | _wc_szamlazz_adoszam_data | Validation payload from NAV/VIES. |
| User meta | wc_szamlazz_adoszam | Saved billing VAT number for logged-in customers. |
| Store API namespace | wc-szamlazz-vat-number | Checkout Blocks/cart extension state. |
| Cart extensions update data | vat_number | POST /wc/store/v1/cart/extensions update callback input. |
| Checkout extension data | customer_type, billing_vat_number, billing_vat_number_info | Final checkout payload saved to order meta. |
| WC session | vat-number-data | Current Store API/classic AJAX validation state. |
Do not create a second permanent VAT meta key and expect Szamlazz.hu invoices to see it. Either populate the canonical meta at checkout/order creation, or map your custom field through invoice filters.
Read the VAT number
Use the plugin helper when available because it handles the legacy key.
function myplugin_get_szamlazz_vat_number( WC_Order $order ): string {
if ( class_exists( 'WC_Szamlazz_Vat_Number_Field' ) ) {
return (string) WC_Szamlazz_Vat_Number_Field::get_order_vat_number( $order );
}
return (string) ( $order->get_meta( '_billing_wc_szamlazz_adoszam' ) ?: $order->get_meta( 'wc_szamlazz_adoszam' ) );
}
Use WC_Order::get_meta() and update_meta_data(). Do not query wp_postmeta; HPOS may store orders in WooCommerce order tables.
Map another VAT field into invoices
If another plugin already owns the checkout VAT field, do not duplicate UI. Feed Szamlazz.hu invoice XML with the two dedicated filters.
add_filter(
'wc_szamlazz_xml_adoszam',
static function ( string $tax_number, WC_Order $order ): string {
if ( $tax_number ) {
return $tax_number;
}
$custom = (string) $order->get_meta( '_myplugin_hu_tax_number' );
return $custom ?: $tax_number;
},
10,
2
);
add_filter(
'wc_szamlazz_xml_adoszam_eu',
static function ( string $eu_vat, WC_Order $order ): string {
if ( $eu_vat ) {
return $eu_vat;
}
$custom = strtoupper( preg_replace( '/[^A-Z0-9]/', '', (string) $order->get_meta( '_myplugin_eu_vat_number' ) ) );
return preg_match( '/^[A-Z]{2}/', $custom ) ? $custom : $eu_vat;
},
10,
2
);
The invoice builder automatically moves a two-letter-prefixed value from Hungarian adoszam to EU adoszamEU when needed, and removes tax numbers for non-EU countries. Still map HU and EU fields explicitly when your plugin can distinguish them.
Populate canonical meta at checkout
When your plugin replaces the Szamlazz.hu visible field, save the canonical order meta once, before invoice generation.
add_action(
'woocommerce_checkout_create_order',
static function ( WC_Order $order, array $data ): void {
if ( empty( $_POST['myplugin_vat_number'] ) ) {
return;
}
$vat_number = sanitize_text_field( wp_unslash( $_POST['myplugin_vat_number'] ) );
$order->update_meta_data( '_billing_wc_szamlazz_adoszam', $vat_number );
if ( class_exists( 'WC_Szamlazz_Vat_Number_Field' ) ) {
$validation = preg_match( '/^[A-Z]{2}/', $vat_number )
? WC_Szamlazz_Vat_Number_Field::get_eu_vat_number_data( $vat_number )
: WC_Szamlazz_Vat_Number_Field::get_vat_number_data( $vat_number );
if ( $validation ) {
$order->update_meta_data( '_wc_szamlazz_adoszam_data', $validation );
}
}
},
20,
2
);
Sanitize with wp_unslash() + sanitize_text_field(). Do not call the validation API repeatedly on every keypress from your own JS; the plugin already has checkout AJAX/Store API flows and VIES caching.
Classic checkout behavior
The plugin adds wc_szamlazz_adoszam through woocommerce_billing_fields, aligns it through woocommerce_checkout_fields, validates on woocommerce_after_checkout_validation, saves order meta on woocommerce_checkout_update_order_meta, saves user meta on woocommerce_checkout_update_user_meta, and displays it in admin/customer billing addresses.
Validation rules include:
- Hungarian tax number format and Számlázz.hu taxpayer XML lookup.
- Optional EU VAT format and VIES lookup.
- Company name required when VAT is present, depending on UI mode.
- VAT required when company billing is selected or company name is entered for configured countries.
- Optional global VAT requirement for non-HU/non-EU company customers.
Customize messages with the message filters. Do not remove validation by unhooking the whole class unless you own every invoice path.
Useful validation/message filters:
wc_szamlazz_tax_validation_nav_messagewc_szamlazz_tax_validation_format_messagewc_szamlazz_tax_validation_required_messagewc_szamlazz_company_validation_required_messagewc_szamlazz_company_billing_validation_required_messagewc_szamlazz_eu_vat_number_validation_country_mismatch_messagewc_szamlazz_vat_number_validation_failed_message
Validation result filters
The plugin exposes NAV/VIES validation results through wc_szamlazz_vat_number_validation_results. Return the same array shape. Hungarian NAV validation passes two accepted arguments ($result, $vat_number); EU VIES validation passes a third $raw_response argument for cache hits, service failures, invalid responses, and successful VIES payloads.
add_filter(
'wc_szamlazz_vat_number_validation_results',
static function ( array $result, string $vat_number, $raw_response = null ): array {
if ( myplugin_is_trusted_internal_customer_vat( $vat_number ) ) {
$result['valid'] = true;
$result['note'] = 'Trusted internal customer override';
}
return $result;
},
10,
3
);
Classic checkout blocks false EU validation results by default through wc_szamlazz_should_fail_eu_vat_validation. Return false only when you intentionally want to fail open for invalid VIES results:
add_filter( 'wc_szamlazz_should_fail_eu_vat_validation', '__return_false' );
That filter does not make VIES outages fail closed by itself. Transport errors, non-2xx responses, empty bodies, invalid JSON, and VIES MS_MAX_CONCURRENT_REQ are converted to valid => true before checkout validation so the checkout does not stall on an upstream outage. If your B2B workflow must fail closed on those service-error branches, use wc_szamlazz_vat_number_validation_results and turn responses with an outage note or empty raw response back to valid => false.
Store API / Checkout Blocks contract
The plugin registers Store API data after woocommerce_blocks_loaded under namespace wc-szamlazz-vat-number for cart and checkout. There are two related but different payload surfaces:
- Cart extension update:
POST /wp-json/wc/store/v1/cart/extensionscalls the plugin's update callback withdata.vat_numberand stores validation output inWC()->session['vat-number-data']. - Final checkout:
POST /wp-json/wc/store/v1/checkoutsends extension data created bysetExtensionData():customer_type,billing_vat_number, and optionalbilling_vat_number_info.
Do not send only billing_vat_number to /cart/extensions; the update callback checks vat_number. Do not send only vat_number to /checkout; the save callback reads billing_vat_number.
Its registered schema includes:
| Field | Values |
|---|---|
customer_type | individual or company |
billing_vat_number | string |
billing_vat_number_info | object |
Its update callback writes vat-number-data into the WooCommerce session and may set WC()->customer->set_is_vat_exempt( true ) for valid non-HU EU VAT numbers.
Headless/block checkout should first validate/update the cart extension:
{
"namespace": "wc-szamlazz-vat-number",
"data": {
"vat_number": "12345678-1-12"
}
}
Then submit the final extension data with the checkout request:
{
"billing_address": {
"company": "Example Kft.",
"country": "HU"
},
"extensions": {
"wc-szamlazz-vat-number": {
"customer_type": "company",
"billing_vat_number": "12345678-1-12"
}
}
}
If your own Store API extension collects VAT, prefer writing the same wc-szamlazz-vat-number extension namespace before checkout. If you cannot do that, copy your data to _billing_wc_szamlazz_adoszam in woocommerce_store_api_checkout_update_order_from_request before any invoice automation can run.
add_action(
'woocommerce_store_api_checkout_update_order_from_request',
static function ( WC_Order $order, WP_REST_Request $request ): void {
$extensions = (array) $request->get_param( 'extensions' );
$data = (array) ( $extensions['myplugin-b2b'] ?? array() );
if ( empty( $data['vat_number'] ) || $order->get_meta( '_billing_wc_szamlazz_adoszam' ) ) {
return;
}
$order->update_meta_data( '_billing_wc_szamlazz_adoszam', sanitize_text_field( $data['vat_number'] ) );
},
5,
2
);
The Szamlazz.hu checkout-save callback runs on woocommerce_store_api_checkout_update_order_from_request at priority 10 and assumes the wc-szamlazz-vat-number namespace is present when its block is active. Use an earlier priority than 10 if your data must be available to its validation. Test both POST /wp-json/wc/store/v1/cart/extensions and POST /wp-json/wc/store/v1/checkout.
EU VAT exemption
The plugin can set the current Woo customer VAT-exempt during checkout:
vat_exempt_abroadfor virtual company orders outside EU countries.vat_exempt_eu_vatfor valid non-HU EU VAT numbers.- Store API update callback for
wc-szamlazz-vat-number.
Extension points are wc_szamlazz_should_set_eu_vat_exempt to override the decision and wc_szamlazz_after_set_vat_exempt to run follow-up cart logic.
Do not set VAT exemption permanently on the user for a single cart decision. This is checkout/session state.
Admin orders and renewals
The plugin adds the VAT number to admin billing fields and migrates legacy order meta when an admin order screen renders. In Subscriptions flows, the compatibility module excludes generated Szamlazz.hu document meta from renewal copies, but it does not exclude _billing_wc_szamlazz_adoszam; it also updates active/on-hold subscription VAT meta when the customer saves billing address changes with "update all subscriptions".
For custom admin order creation:
- Save
_billing_wc_szamlazz_adoszamon the order object before saving. - Save
_wc_szamlazz_adoszam_dataif you already validated the number. - For renewal/subscription flows, keep
_billing_wc_szamlazz_adoszamon the subscription or parent order so WooCommerce Subscriptions renewal meta copying can carry it forward. The Szamlazz.hu compatibility module explicitly excludes generated document meta from renewals, not VAT meta.
Copy with $renewal->update_meta_data( '_billing_wc_szamlazz_adoszam', $source_order->get_meta( '_billing_wc_szamlazz_adoszam' ) ) and save the order object.
Security and privacy
VAT numbers are personal/business identifiers. Treat them like billing data:
- Use WooCommerce checkout nonces or Store API nonce/cart token flows.
- Sanitize input and escape output.
- Do not log full VAT numbers unless debug logging is explicitly enabled and access-controlled.
- Do not expose validation payloads through public REST endpoints without current-customer authorization.
- Do not cache VIES/NAV responses in public page caches.
Critical rules
- Do not render a second VAT field unless you intentionally replace and map to the Szamlazz.hu contract.
- Do not save only user meta; invoices read order meta.
- Do not assume classic checkout hooks run for Checkout Blocks or headless Store API.
- Do not assume Store API extension data appears as top-level checkout fields; it lives under
extensions['wc-szamlazz-vat-number']. - Do not block all non-HU customers with HU tax-number rules; EU and global VAT paths differ.
- Do not use direct postmeta queries; HPOS-safe order APIs are required.
Smoke test checklist
- Classic checkout, logged-out HU company VAT.
- Checkout Blocks/Store API company VAT with
extensions['wc-szamlazz-vat-number']. - EU VAT with matching billing country, including
GR/ELprefix handling. - Individual customer with company name but no VAT, under each configured UI mode.
- Subscription renewal or copied order retaining VAT meta.
- Generated invoice XML contains
adoszamfor HU andadoszamEUfor EU numbers.
Cross-references
- Use
szamlazzhu-document-xml-compatibilitywhen VAT data must affect the final XML or document creation timing. - Use
wc-store-apifor nonce/cart-token,/cart/extensions, and headless checkout request details. - Use
wc-cart-checkout-classicfor classic checkout field placement and validation. - Use
wc-hpos-compatibilityfor order meta persistence. - Use
wcs-subscription-hooksandwcs-renewal-schedulerwhen VAT must survive subscription renewals.
References
- Official documentation: https://wordpress.org/plugins/integration-for-szamlazzhu-woocommerce/
- Official documentation: https://docs.szamlazz.hu/hu/agent/querying_taxpayer/xml
- Official documentation: https://ec.europa.eu/taxation_customs/vies/
- Verified source paths:
wp-content/plugins/integration-for-szamlazzhu-woocommerce/includes/class-vat-number.phpwp-content/plugins/integration-for-szamlazzhu-woocommerce/includes/block/vat-number-block.phpwp-content/plugins/integration-for-szamlazzhu-woocommerce/includes/block/vat-number-block-endpoints.phpwp-content/plugins/integration-for-szamlazzhu-woocommerce/includes/block/vat-number-block-integration.phpwp-content/plugins/integration-for-szamlazzhu-woocommerce/index.phpwp-content/plugins/integration-for-szamlazzhu-woocommerce/includes/compatibility/modules/class-wc-szamlazz-subscriptions.php