84 lines
3.1 KiB
JavaScript
84 lines
3.1 KiB
JavaScript
/**
|
||
* PlusFit24 – IBAN Validierung
|
||
* Prüft: Format, Ländercode, Länge, Prüfziffer (Modulo 97)
|
||
*/
|
||
|
||
const IBAN_LENGTHS = {
|
||
AL:28, AD:24, AT:20, AZ:28, BH:22, BE:16, BA:20, BR:29, BG:22,
|
||
CR:22, HR:21, CY:28, CZ:24, DK:18, DO:28, EE:20, FO:18, FI:18,
|
||
FR:27, GE:22, DE:22, GI:23, GL:18, GT:28, HU:28, IS:26, IE:22,
|
||
IL:23, IT:27, JO:30, KZ:20, KW:30, LV:21, LB:28, LI:21, LT:20,
|
||
LU:20, MK:19, MT:31, MR:27, MU:30, MC:27, MD:24, ME:22, NL:18,
|
||
NO:15, PK:24, PS:29, PL:28, PT:25, QA:29, RO:24, SM:27, SA:24,
|
||
RS:22, SK:24, SI:19, ES:24, SE:24, CH:21, TN:24, TR:26, AE:23,
|
||
GB:22, VG:24
|
||
};
|
||
|
||
function formatIBAN(value) {
|
||
const clean = value.replace(/[^A-Z0-9]/gi, '').toUpperCase();
|
||
return clean.replace(/(.{4})/g, '$1 ').trim();
|
||
}
|
||
|
||
function validateIBAN(iban) {
|
||
const clean = iban.replace(/\s/g, '').toUpperCase();
|
||
|
||
if (clean.length < 5) return { valid: false, error: 'IBAN zu kurz' };
|
||
|
||
const country = clean.substring(0, 2);
|
||
if (!/^[A-Z]{2}$/.test(country)) return { valid: false, error: 'Ungültiger Ländercode' };
|
||
|
||
const checkDigits = clean.substring(2, 4);
|
||
if (!/^\d{2}$/.test(checkDigits)) return { valid: false, error: 'Prüfziffern ungültig' };
|
||
|
||
const expectedLength = IBAN_LENGTHS[country];
|
||
if (!expectedLength) return { valid: false, error: 'Ländercode "' + country + '" nicht unterstützt' };
|
||
if (clean.length !== expectedLength) {
|
||
return { valid: false, error: country + '-IBAN muss ' + expectedLength + ' Zeichen haben (aktuell: ' + clean.length + ')' };
|
||
}
|
||
|
||
if (!/^[A-Z0-9]+$/.test(clean.substring(4))) {
|
||
return { valid: false, error: 'IBAN enthält ungültige Zeichen' };
|
||
}
|
||
|
||
// Modulo-97 Prüfung
|
||
const rearranged = clean.substring(4) + clean.substring(0, 4);
|
||
const numeric = rearranged.split('').map(c => {
|
||
const code = c.charCodeAt(0);
|
||
return code >= 65 ? (code - 55).toString() : c;
|
||
}).join('');
|
||
|
||
let remainder = 0;
|
||
for (let i = 0; i < numeric.length; i++) {
|
||
remainder = (remainder * 10 + parseInt(numeric[i])) % 97;
|
||
}
|
||
|
||
if (remainder !== 1) return { valid: false, error: 'Prüfziffer falsch – IBAN ungültig' };
|
||
|
||
return { valid: true, formatted: formatIBAN(clean) };
|
||
}
|
||
|
||
function attachIBANValidation(inputEl, statusEl, messageEl) {
|
||
inputEl.addEventListener('input', function () {
|
||
const rawClean = this.value.replace(/[^A-Z0-9]/gi, '').toUpperCase();
|
||
this.value = formatIBAN(rawClean);
|
||
|
||
if (rawClean.length < 5) {
|
||
if (statusEl) statusEl.textContent = '';
|
||
if (messageEl) { messageEl.textContent = ''; messageEl.className = 'iban-message'; }
|
||
this.classList.remove('input-error', 'input-valid');
|
||
return;
|
||
}
|
||
|
||
const result = validateIBAN(rawClean);
|
||
if (result.valid) {
|
||
if (statusEl) statusEl.textContent = '✅';
|
||
if (messageEl) { messageEl.textContent = 'IBAN gültig'; messageEl.className = 'iban-message success'; }
|
||
this.classList.remove('input-error'); this.classList.add('input-valid');
|
||
} else {
|
||
if (statusEl) statusEl.textContent = '❌';
|
||
if (messageEl) { messageEl.textContent = result.error; messageEl.className = 'iban-message error'; }
|
||
this.classList.remove('input-valid'); this.classList.add('input-error');
|
||
}
|
||
});
|
||
}
|