46 lines
1.3 KiB
JavaScript
46 lines
1.3 KiB
JavaScript
function ibanMod97(iban) {
|
|
const rearranged = iban.slice(4) + iban.slice(0, 4)
|
|
const expanded = rearranged
|
|
.split('')
|
|
.map((char) => {
|
|
const code = char.charCodeAt(0)
|
|
if (code >= 65 && code <= 90) return String(code - 55)
|
|
return char
|
|
})
|
|
.join('')
|
|
|
|
let remainder = expanded
|
|
while (remainder.length > 2) {
|
|
const block = remainder.slice(0, 9)
|
|
remainder = String(parseInt(block, 10) % 97) + remainder.slice(block.length)
|
|
}
|
|
return parseInt(remainder, 10) % 97
|
|
}
|
|
|
|
/** digits24: the 24 digits after the "IR" prefix */
|
|
function isValidIranSheba(digits24) {
|
|
if (!/^\d{24}$/.test(String(digits24 || ''))) return false
|
|
return ibanMod97(`IR${digits24}`) === 1
|
|
}
|
|
|
|
/** Standard Iranian national-code (کد ملی) checksum */
|
|
function isValidIranNationalCode(code) {
|
|
const value = String(code || '')
|
|
if (!/^\d{10}$/.test(value)) return false
|
|
if (/^(\d)\1{9}$/.test(value)) return false
|
|
|
|
const digits = value.split('').map(Number)
|
|
const sum = digits
|
|
.slice(0, 9)
|
|
.reduce((acc, digit, index) => acc + digit * (10 - index), 0)
|
|
const remainder = sum % 11
|
|
const checkDigit = remainder < 2 ? remainder : 11 - remainder
|
|
|
|
return checkDigit === digits[9]
|
|
}
|
|
|
|
module.exports = {
|
|
isValidIranSheba,
|
|
isValidIranNationalCode,
|
|
}
|