Skip to content

Instantly share code, notes, and snippets.

@libetl
Created November 10, 2019 19:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save libetl/c4523078404ab622af6332d320a9729b to your computer and use it in GitHub Desktop.
Save libetl/c4523078404ab622af6332d320a9729b to your computer and use it in GitHub Desktop.
CreditCardNumberChecker.ts
type CardType = 'MasterCard' | 'Visa' | 'American Express' |
'JCB' | 'Diners Club' | 'Discover' | 'unknown'
type MajorIndustryIdentifier =
'ISO/TC 68' | 'Airlines' | 'Travel and entertainment and banking/financial' |
'Banking and financial' | 'Merchandising and banking/financial' |
'Petroleum' | 'Healthcare and telecommunications' | 'National assignment' |
'unknown'
type CreditCardGuessedInformation = {
complete: boolean, valid: boolean,
cardType?: CardType, majorIndustryIdentifier?: MajorIndustryIdentifier
}
type CreditCardNumber = string
export const guessInformationFrom:
(creditCardNumber: CreditCardNumber) => CreditCardGuessedInformation =
(creditCardNumber: CreditCardNumber) => ({
complete: getFullType(creditCardNumber) !== 'unknown',
cardType: getFullType(creditCardNumber) !== 'unknown' ?
getFullType(creditCardNumber) : getCreditCardType(creditCardNumber),
majorIndustryIdentifier: getMajorIndustryIdentifier(creditCardNumber),
valid: validate(creditCardNumber)
})
const getCreditCardType: (number: CreditCardNumber) => CardType = (number) =>
/^5[1-5]/.test(number) ? 'MasterCard' :
/^4/.test(number) ? 'Visa' :
/^3[47]/.test(number) ? 'American Express' :
/^(?:2131|1800|35)/.test(number) ? 'JCB' :
/^3(?:0[0-5]|[68])/.test(number) ? 'Diners Club' :
/^6(?:011|5)/.test(number) ? 'Discover' : 'unknown'
const getFullType: (number: CreditCardNumber) => CardType = (number) =>
/^5[1-5][0-9]{14}$/.test(number) ? 'MasterCard' :
/^4[0-9]{12}(?:[0-9]{3})?$/.test(number) ? 'Visa' :
/^3[47][0-9]{13}$/.test(number) ? 'American Express' :
/^(?:2131|1800|35\d{3})\d{11}$/.test(number) ? 'JCB' :
/^3(?:0[0-5]|[68][0-9])[0-9]{11}$/.test(number) ? 'Diners Club' :
/^6(?:011|5[0-9]{2})[0-9]{12}$/.test(number) ? 'Discover' : 'unknown'
const validate: (number: CreditCardNumber) => boolean = (number) => {
const checksum = parseInt(number.charAt(number.length - 1))
const digits = number.substring(0, number.length - 1);
const mod9 = [0, 1, 2, 3, 4, -4, -3, -2, -1, 0];
let sum = 0;
for (let i = 0; i < digits.length; i++) sum += parseInt(digits.substring(i, i + 1));
for (let i = digits.length - 1; i >= 0; i -= 2) {
sum += mod9[parseInt(digits.substring(i, i + 1))]
}
return 10 - sum % 10 === checksum
}
const getMajorIndustryIdentifier: (number: CreditCardNumber) => MajorIndustryIdentifier = (number) => {
switch (parseInt(number.charAt(0))) {
case 0:
return 'ISO/TC 68';
case 1:
case 2:
return 'Airlines';
case 3:
return 'Travel and entertainment and banking/financial';
case 4:
case 5:
return 'Banking and financial';
case 6:
return 'Merchandising and banking/financial';
case 7:
return 'Petroleum';
case 8:
return 'Healthcare and telecommunications';
case 9:
return 'National assignment';
default:
return 'unknown'
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment