Refactor invoice PDF generation and VAT validation

- Updated PDF template to display a fixed software code instead of "SOFTWARE".
- Changed VAT label to include tax label dynamically and set to 0% for certain conditions.
- Enhanced JavaScript for VAT number validation with asynchronous checks against the VIES database.
- Implemented debounce for VAT number input to optimize validation calls.
- Updated country settings to include country codes for VAT validation.
- Modified email sending functions in webhook handlers to use dynamic attachment names for invoices.
This commit is contained in:
“VeLiTi”
2026-02-06 16:02:56 +01:00
parent 4b83f596f1
commit 3131c2c5b2
12 changed files with 542 additions and 163 deletions

86
api/v2/post/vat_check.php Normal file
View File

@@ -0,0 +1,86 @@
<?php
defined($security_key) or exit;
//------------------------------------------
// VAT Number Validation (VIES Proxy)
//------------------------------------------
// CONTENT FROM API (POST)
$post_content = json_decode($input, true);
// Validate input
if (empty($post_content['countryCode']) || empty($post_content['vatNumber'])) {
http_response_code(400);
echo json_encode([
'error' => 'Missing required parameters: countryCode and vatNumber'
]);
exit;
}
$countryCode = strtoupper(trim($post_content['countryCode']));
$vatNumber = $post_content['vatNumber'];
// Remove all whitespace from VAT number
$vatNumber = preg_replace('/\s+/', '', $vatNumber);
// Remove country code prefix if included in VAT number
if (strpos($vatNumber, $countryCode) === 0) {
$vatNumber = substr($vatNumber, strlen($countryCode));
}
// VIES API endpoint
$viesUrl = 'https://ec.europa.eu/taxation_customs/vies/rest-api/check-vat-number';
// Prepare request data
$requestData = json_encode([
'countryCode' => $countryCode,
'vatNumber' => $vatNumber
]);
// Initialize cURL
$ch = curl_init($viesUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $requestData);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Accept: application/json'
]);
curl_setopt($ch, CURLOPT_TIMEOUT, 10); // 10 second timeout
// Execute request
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlError = curl_error($ch);
curl_close($ch);
// Check for cURL errors
if ($curlError) {
http_response_code(500);
echo json_encode([
'error' => 'Failed to connect to VIES service',
'details' => $curlError
]);
exit;
}
// Parse VIES response regardless of HTTP code
$viesData = json_decode($response, true);
// If we can't parse JSON, return an error
if (json_last_error() !== JSON_ERROR_NONE) {
http_response_code(500);
echo json_encode([
'error' => 'Invalid response from VIES service',
'httpCode' => $httpCode,
'response' => $response
]);
exit;
}
// Always return 200 OK to the client with the VIES data
// The client will check the 'valid' field in the response
http_response_code(200);
echo json_encode($viesData);
?>