netresearch/sdk-eu-vat

PHP SDK for EU VAT Retrieval Service SOAP API

v1.0.0 2025-06-24 21:43 UTC

This package is auto-updated.

Last update: 2025-06-25 07:04:16 UTC


README

Build Status Coverage Status Latest Stable Version License

A modern PHP 8.2+ SDK for the EU VAT Retrieval Service that provides reliable access to official VAT rates for all EU member states with precision financial calculations.

Features

  • ๐Ÿฆ Financial-Grade Precision: Uses brick/math BigDecimal for exact VAT calculations
  • ๐Ÿ›ก๏ธ Enterprise Ready: Comprehensive error handling, logging, and telemetry
  • ๐Ÿงช Thoroughly Tested: 368 tests with 95%+ coverage and real service validation
  • ๐Ÿ”„ Modern SOAP: Built on php-soap/ext-soap-engine for reliable SOAP operations
  • ๐Ÿ“Š Observability: Built-in request/response logging and metrics
  • ๐Ÿš€ Performance: Optimized with WSDL caching and connection pooling support
  • ๐Ÿ“– Well Documented: Comprehensive PHPDoc and usage examples

Installation

composer require netresearch/sdk-eu-vat

Requirements: PHP 8.2+, ext-soap and ext-libxml extensions

๐Ÿ’ก Having installation issues? See the Installation Guide for troubleshooting help.

Quick Start

<?php

use Netresearch\EuVatSdk\Factory\VatRetrievalClientFactory;
use Netresearch\EuVatSdk\DTO\Request\VatRatesRequest;

// Create client
$client = VatRetrievalClientFactory::create();

// Request VAT rates for Germany
$request = new VatRatesRequest(
    memberStates: ['DE'],
    situationOn: new DateTime('2024-01-01')
);

try {
    $response = $client->retrieveVatRates($request);
    
    foreach ($response->getResults() as $result) {
        echo sprintf(
            "VAT rate for %s: %s%%\n",
            $result->getMemberState(),
            $result->getVatRate()->getValue()->__toString()
        );
    }
} catch (\Netresearch\EuVatSdk\Exception\VatServiceException $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

Advanced Usage

Multiple Countries

$request = new VatRatesRequest(
    memberStates: ['DE', 'FR', 'IT', 'ES'],
    situationOn: new DateTime('2024-01-01')
);

$response = $client->retrieveVatRates($request);

// Group results by country
foreach ($response->getResults() as $result) {
    printf(
        "%s: %s%% (%s rate)\n",
        $result->getMemberState(),
        $result->getVatRate()->getValue()->__toString(),
        $result->getVatRate()->getType()
    );
}

Precision Financial Calculations

use Brick\Math\BigDecimal;

$vatRate = $result->getVatRate();

// Get precise decimal value
$rate = $vatRate->getValue(); // Returns BigDecimal

// Calculate VAT amount (100 EUR at 19% VAT)
$netAmount = BigDecimal::of('100.00');
$vatAmount = $netAmount->multipliedBy($rate)->dividedBy('100', 2);
$grossAmount = $netAmount->plus($vatAmount);

// Be explicit when printing
echo "Net: โ‚ฌ" . $netAmount->__toString() . "\n";
echo "VAT: โ‚ฌ" . $vatAmount->__toString() . "\n"; 
echo "Gross: โ‚ฌ" . $grossAmount->__toString() . "\n";

Custom Configuration

use Netresearch\EuVatSdk\Client\ClientConfiguration;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// Create custom logger
$logger = new Logger('vat-service');
$logger->pushHandler(new StreamHandler('vat-service.log', Logger::INFO));

// Configure client
$config = ClientConfiguration::production($logger)
    ->withTimeout(30)
    ->withDebug(true);

$client = VatRetrievalClientFactory::create($config);

Error Handling

The SDK provides comprehensive exception handling:

use Netresearch\EuVatSdk\Exception\{
    InvalidRequestException,
    ServiceUnavailableException,
    ConfigurationException,
    VatServiceException
};

try {
    $response = $client->retrieveVatRates($request);
} catch (InvalidRequestException $e) {
    // Client-side validation errors (invalid country codes, dates)
    echo "Invalid request: " . $e->getMessage();
} catch (ServiceUnavailableException $e) {
    // Service is down or network issues
    echo "Service unavailable: " . $e->getMessage();
} catch (ConfigurationException $e) {
    // Invalid SDK configuration
    echo "Configuration error: " . $e->getMessage();
} catch (VatServiceException $e) {
    // Any other SDK-related error
    echo "VAT service error: " . $e->getMessage();
}

Testing

The SDK includes comprehensive test suites:

# Run all tests
composer test

# Run only unit tests
composer test:unit

# Run integration tests (requires network)
composer test:integration

# Run static analysis
composer analyse

# Run code style checks
composer cs:check

# Fix code style issues
composer cs:fix

Test Environment

Integration tests use php-vcr to record and replay real SOAP interactions:

# Refresh recorded cassettes with live service calls
REFRESH_CASSETTES=true composer test:integration

# Enable debug output for tests
DEBUG_TESTS=true composer test

Examples

See the examples/ directory for comprehensive usage examples:

Framework Integration

Symfony

# config/services.yaml
services:
    # Configure the ClientConfiguration service first, injecting the logger here
    Netresearch\EuVatSdk\Client\ClientConfiguration:
        factory: ['Netresearch\EuVatSdk\Client\ClientConfiguration', 'production']
        arguments:
            - '@?logger' # Pass the logger, if it exists

    # The client service now only needs the pre-configured configuration service
    Netresearch\EuVatSdk\Client\VatRetrievalClientInterface:
        factory: ['Netresearch\EuVatSdk\Factory\VatRetrievalClientFactory', 'create']
        arguments:
            - '@Netresearch\EuVatSdk\Client\ClientConfiguration'

Laravel

// config/app.php
'providers' => [
    // ...
    App\Providers\VatServiceProvider::class,
];

// app/Providers/VatServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Netresearch\EuVatSdk\Client\ClientConfiguration;
use Netresearch\EuVatSdk\Client\VatRetrievalClientInterface;
use Netresearch\EuVatSdk\Factory\VatRetrievalClientFactory;
use Psr\Log\LoggerInterface;

class VatServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(VatRetrievalClientInterface::class, function ($app) {
            $logger = $app->make(LoggerInterface::class);
            
            return VatRetrievalClientFactory::create(
                ClientConfiguration::production($logger)
            );
        });
    }
}

Performance

The SDK is optimized for production use:

  • WSDL Caching: Automatic WSDL caching reduces initialization overhead
  • Connection Reuse: Efficient SOAP connection handling
  • Memory Efficient: Optimized DTOs and response handling for efficient batch processing
  • Benchmarks: ~10ms typical response time for single country requests

Recommended Production Settings

$config = ClientConfiguration::production($logger)
    ->withTimeout(30)                    // 30 second timeout
    ->withSoapOptions([                  // Optimize SOAP client
        'cache_wsdl' => WSDL_CACHE_DISK,
        'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
        'connection_timeout' => 30,
    ]);

Security

Input Validation

All inputs are strictly validated:

  • Country codes must be valid 2-character ISO codes
  • Dates are validated and normalized
  • SOAP responses are schema-validated

Error Information Disclosure

Error messages are carefully crafted to be helpful for debugging while avoiding sensitive information disclosure.

Dependencies

All dependencies are regularly scanned for security vulnerabilities:

composer audit

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with tests
  4. Run the test suite (composer test)
  5. Run static analysis (composer analyse)
  6. Commit your changes (git commit -m 'Add amazing feature')
  7. Push to the branch (git push origin feature/amazing-feature)
  8. Open a Pull Request

Development Requirements

  • PHP 8.2+
  • Composer 2.0+
  • All quality tools must pass (PHPStan level 8, PHPCS PSR-12)

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support

  • Documentation: Full API documentation available in the docs/ directory
  • Issues: Report bugs and feature requests on GitHub Issues
  • Security: Report security vulnerabilities to security@netresearch.de

Changelog

See CHANGELOG.md for a detailed list of changes and upgrade instructions.

Note: This SDK provides access to official EU VAT data. Please ensure compliance with your local tax regulations and consult with tax professionals for specific tax advice.