-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Strings: Credit Card Validation #830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
raklaptudirm
merged 10 commits into
TheAlgorithms:master
from
Bhargavishnu:add_cc_validator
Nov 4, 2021
Merged
Changes from all commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
7a20549
Add credit card number validator
Bhargavishnu 9974cd0
Test Cases: ValidateCreditCard
Bhargavishnu 5e62db6
Auto-update DIRECTORY.md
58cc761
Fix: Spell check
Bhargavishnu a5f9d1b
Merge branch 'add_cc_validator' of https://github.com/Bhargavishnu/Ja…
Bhargavishnu 8c3c65b
Add references and move const inside function
Bhargavishnu 5ba815a
Add comments
Bhargavishnu 5b43dc7
Fix trailing spaces
Bhargavishnu fa78bf1
Add short description
Bhargavishnu f76e83f
Remove trailing spaces
Bhargavishnu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/** | ||
* Validate a given credit card number | ||
* | ||
* The core of the validation of credit card numbers is the Luhn algorithm. | ||
* | ||
* The validation sum should be completely divisible by 10 which is calculated as follows, | ||
* every first digit is added directly to the validation sum. | ||
* For every second digit in the credit card number, the digit is multiplied by 2. | ||
* If the product is greater than 10 the digits of the product are added. | ||
* This resultant digit is considered for the validation sum rather than the digit itself. | ||
* | ||
* Ref: https://www.geeksforgeeks.org/luhn-algorithm/ | ||
*/ | ||
|
||
const luhnValidation = (creditCardNumber) => { | ||
let validationSum = 0 | ||
creditCardNumber.split('').forEach((digit, index) => { | ||
let currentDigit = parseInt(digit) | ||
if (index % 2 === 0) { | ||
// Multiply every 2nd digit from the left by 2 | ||
currentDigit *= 2 | ||
// if product is greater than 10 add the individual digits of the product to get a single digit | ||
if (currentDigit > 9) { | ||
currentDigit %= 10 | ||
currentDigit += 1 | ||
} | ||
} | ||
validationSum += currentDigit | ||
}) | ||
|
||
return validationSum % 10 === 0 | ||
} | ||
|
||
const validateCreditCard = (creditCardString) => { | ||
const validStartSubString = ['4', '5', '6', '37', '34', '35'] // Valid credit card numbers start with these numbers | ||
|
||
if (typeof creditCardString !== 'string') { | ||
throw new TypeError('The given value is not a string') | ||
} | ||
|
||
const errorMessage = `${creditCardString} is an invalid credit card number because ` | ||
if (isNaN(creditCardString)) { | ||
throw new TypeError(errorMessage + 'it has nonnumerical characters.') | ||
} | ||
const creditCardStringLength = creditCardString.length | ||
if (!((creditCardStringLength >= 13) && (creditCardStringLength <= 16))) { | ||
throw new Error(errorMessage + 'of its length.') | ||
} | ||
if (!validStartSubString.some(subString => creditCardString.startsWith(subString))) { | ||
throw new Error(errorMessage + 'of its first two digits.') | ||
} | ||
if (!luhnValidation(creditCardString)) { | ||
throw new Error(errorMessage + 'it fails the Luhn check.') | ||
} | ||
|
||
return true | ||
} | ||
|
||
export { validateCreditCard } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { validateCreditCard } from '../ValidateCreditCard' | ||
|
||
describe('Validate credit card number', () => { | ||
it('should throw error if card number is boolean', () => { | ||
const invalidCC = true | ||
expect(() => validateCreditCard(invalidCC)).toThrow( | ||
'The given value is not a string' | ||
) | ||
}) | ||
it('returns true if the credit card number is valid', () => { | ||
const validCreditCard = '4111111111111111' | ||
const validationResult = validateCreditCard(validCreditCard) | ||
expect(validationResult).toBe(true) | ||
}) | ||
it('should throw an error on non-numeric character in given credit card number', () => { | ||
const nonNumericCCNumbers = ['123ABCDEF', 'ABCDKDKD', 'ADS232'] | ||
nonNumericCCNumbers.forEach(nonNumericCC => expect(() => validateCreditCard(nonNumericCC)).toThrow( | ||
`${nonNumericCC} is an invalid credit card number because ` + 'it has nonnumerical characters.' | ||
)) | ||
}) | ||
it('should throw an error on credit card with invalid length', () => { | ||
const ccWithInvalidLength = ['41111', '4111111111111111111111'] | ||
ccWithInvalidLength.forEach(invalidCC => expect(() => validateCreditCard(invalidCC)).toThrow( | ||
`${invalidCC} is an invalid credit card number because ` + 'of its length.' | ||
)) | ||
}) | ||
it('should throw an error on credit card with invalid start substring', () => { | ||
const ccWithInvalidStartSubstring = ['12345678912345', '23456789123456', '789123456789123', '891234567891234', '912345678912345', '31345678912345', '32345678912345', '33345678912345', '38345678912345'] | ||
ccWithInvalidStartSubstring.forEach(invalidCC => expect(() => validateCreditCard(invalidCC)).toThrow( | ||
`${invalidCC} is an invalid credit card number because ` + 'of its first two digits.' | ||
)) | ||
}) | ||
it('should throw an error on credit card with luhn check fail', () => { | ||
const invalidCCs = ['411111111111111', '371211111111111', '49999999999999'] | ||
invalidCCs.forEach(invalidCC => expect(() => validateCreditCard(invalidCC)).toThrow( | ||
`${invalidCC} is an invalid credit card number because ` + 'it fails the Luhn check.' | ||
)) | ||
}) | ||
}) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.