UNPKG

@alibaba-aero/griphook

Version:

Validate and visualize Iranian bank info

215 lines (185 loc) 6.34 kB
import { banks } from './banks.json'; let cache = {}; /** * Will Find Bank Info Based On Value Of A Key * @method findBankByValue * @param {String} value * @param {String} Key * @returns {Object} */ const findBankByValue = (value, key) => { // Check If value Was Cached if (cache[key]) { return cache[key]; } else { const bank = banks.find(bank => bank[key] === value); if (!bank) return {}; cache[value] = { ...bank }; return bank; }; }; /** * Will Find Bank Info Based On English Name * @method findBankByName * @param {String} bankName * @returns {Object} */ const findBankByName = (bankName) => { return findBankByValue(bankName, 'name'); } /** * Will Find Bank Info Based On Farsi Name * @method findBankByName * @param {String} bankName * @returns {Object} */ const findBankByFarsiName = (bankName) => { return findBankByValue(bankName, 'name_farsi'); } /** * Will Check Whether Given String Is A Valid PAN Or Not * See This Link For More Info: https://www.geeksforgeeks.org/luhn-algorithm/ * @method validatePAN * @param {String|Number} cardNumber * @returns {Boolean} */ const validatePAN = (cardNumber) => { // Check Characters if (!/^\d{16}$/.test(cardNumber)) return false; // Check Luhn Algorithm const digitsSum = Array.from('0' + String(cardNumber)).map(x => parseInt(x)).reduce((acc, cur, idx) => { const mul = idx % 2 === 1 ? 2 : 1; // Double The Current Digit If Was On Odd Index return acc + (cur * mul) - (cur * mul > 9 ? 9 : 0); // Make Sure Not To Exceed 9 When Doubling }) || 0; return digitsSum % 10 === 0; }; /** * Will Censor Parts Of A Credit Card And Put A Dash Between Every Four Digits * @method visualizePAN * @param {String|Number} cardNumber * @param {Object} _options * @returns {String} */ const visualizePAN = (cardNumber, _options) => { cardNumber = String(cardNumber); // Make Sure Working With Is String // Check Characters if (!/^[\d*]+$/.test(cardNumber)) return cardNumber; const options = { spacerChar: '-', censor: false, censorChar: '*', censorLength: 4, ..._options, }; let pan = cardNumber; // Censor Center Part Of PAN if (options.censor && cardNumber.length > options.censorLength && cardNumber.length === 16) { const panSegment = (cardNumber.length - options.censorLength) / 2; pan = cardNumber.slice(0, Math.ceil(panSegment)) + options.censorChar.repeat(options.censorLength) + cardNumber.slice(Math.floor(panSegment) * -1); } return pan.match(/.{1,4}/g).join(options.spacerChar); }; /** * Will Find Bank Info With PAN IIN+ * See This Link For More Info: https://en.wikipedia.org/wiki/Payment_card_number * @method findBankByPAN * @param {String|Number} cardNumber * @returns {Object} */ const findBankByPAN = (cardNumber) => { cardNumber = String(cardNumber); // Make Sure Working With Is String // Check Characters if (!/^[\d*]+$/.test(cardNumber) || cardNumber.length < 6) return {}; const iin = cardNumber.slice(0, 6); // Extract Issuer Identification Number // Check If IIN Was Cached if (cache[iin]) { return cache[iin]; } else { const bank = banks.find(bank => bank.pan_iin.includes(iin)); if (!bank) return {}; cache[iin] = { ...bank }; return bank; }; }; /** * Will Check Whether Given String Is A Valid IBAN Or Not * See This Link For More Info: https://en.wikipedia.org/wiki/International_Bank_Account_Number * @method validatePAN * @param {String|Number} cardNumber * @returns {Boolean} */ const validateIBAN = (accountNumber) => { // Check Chartacters if (!/^IR\d{24}$/.test(accountNumber)) return false; const code = accountNumber.match(/^([A-Z]{2})(\d{2})([A-Z\d]+)$/); // Match And Capture (0) The Country Code, (1) The Check Digits, And (3) The Rest // Check Syntax And Length if (!code) return false; function mod97(string) { let checksum = string.slice(0, 2); let fragment; for (let offset = 2; offset < string.length; offset += 7) { fragment = String(checksum) + string.substring(offset, offset + 7); checksum = parseInt(fragment, 10) % 97; } return checksum; } // // Rearrange country Code & Check Digits, Convert Chars To Ints let digits = (code[3] + code[1] + code[2]).replace(/[A-Z]/g, letter => { return letter.charCodeAt(0) - 55; }); // // Final Check return mod97(digits) === 1; }; /** * Will Put A Dash Between Every Four Digits * @method visualizeIBAN * @param {String|Number} cardNumber * @param {Object} _options * @returns {String} */ const visualizeIBAN = (accountNumber, _options) => { accountNumber = String(accountNumber); // Make Sure Working With Is String // Check Characters if (!/^IR[\d*]+$/.test(accountNumber)) return accountNumber; const options = { spacerChar: '-', ..._options, }; let iban = accountNumber; return iban.match(/.{1,4}/g).join(options.spacerChar); }; /** * Will Find Bank Info With IBAN NationalBankCode * See This Link For More Info: https://en.wikipedia.org/wiki/International_Bank_Account_Number * @method findBankByIBAN * @param {String|Number} accountNumber * @returns {Object} */ const findBankByIBAN = (accountNumber) => { accountNumber = String(accountNumber); // Make Sure Working With Is String // Check Characters if (!/^IR[\d*]+$/.test(accountNumber) || accountNumber.length < 7) return {}; const nationalBankCode = accountNumber.slice(4, 7); // Extract Issuer Identification Number // Check If nationalBankCode Was Cached if (cache[nationalBankCode]) { return cache[nationalBankCode]; } else { const bank = banks.find(bank => bank.iban_nbc === nationalBankCode); if (!bank) return {}; cache[nationalBankCode] = { ...bank }; return bank; }; }; export { banks, findBankByName, findBankByFarsiName, validatePAN, visualizePAN, findBankByPAN, validateIBAN, visualizeIBAN, findBankByIBAN, };