Skip to content

Instantly share code, notes, and snippets.

@DiegoSalazar
Last active October 22, 2024 21:47
Show Gist options
  • Save DiegoSalazar/4075533 to your computer and use it in GitHub Desktop.
Save DiegoSalazar/4075533 to your computer and use it in GitHub Desktop.
Luhn algorithm in Javascript. Check valid credit card numbers
// Takes a credit card string value and returns true on valid number
function valid_credit_card(value) {
// Accept only digits, dashes or spaces
if (/[^0-9-\s]+/.test(value)) return false;
// The Luhn Algorithm. It's so pretty.
let nCheck = 0, bEven = false;
value = value.replace(/\D/g, "");
for (var n = value.length - 1; n >= 0; n--) {
var cDigit = value.charAt(n),
nDigit = parseInt(cDigit, 10);
if (bEven && (nDigit *= 2) > 9) nDigit -= 9;
nCheck += nDigit;
bEven = !bEven;
}
return (nCheck % 10) == 0;
}
@weider86-zz
Copy link

Thank you! It works nice!

I only added a validation to empty string (""), because it was returning true. Thank you a lot!

@pranith-bm-ai
Copy link

I tried this out, but I realised I was looking rather naively at my problem. This works great at evaluating the complete card number.

I wanted to evaluate the card number while it is being typed, but I found there are challenges in determining the length of card number (can range from 13 to 19 digits) preemptively.

@DiegoSalazar
Copy link
Author

@pranith-bm-ai You can deduce from the first few numbers what kind of credit card it is and then you'll know what its length is supposed to be, see: https://www.freeformatter.com/credit-card-number-generator-validator.html#cardFormats

@altsanti
Copy link

I would add the line "if (!value) return false;" on top, to also take care of the situation of an empty input (or input with spaces).

@emandeguzman
Copy link

emandeguzman commented Apr 23, 2020

I tested against https://www.paypalobjects.com/en_US/vhelp/paypalmanager_help/credit_card_numbers.htm

76009244561 did not return true

But I'm not sure if this number is really valid. all luhn verification code seem to fail when I use this number.

@JonHualde
Copy link

Working well, thank you very much Diego!

@sureshshivale
Copy link

sureshshivale commented Jul 17, 2020

Thank you! Nice work !
I'm Getting false result for Dankort (PBS) | 76009244561

Can someone answer for me on this ?

@mariacosta07911
Copy link

Thanks! Great Job!
I used this Credit Card Generator and it's showing almost accurate result.
they maintained maximum bank's bin code database. you must have to visit this site.

@finch0921
Copy link

Hi buddy,
I pull your code in my local repository, I found issues with your code It validate all types of Credit cards (like Amex, Visa, Diners Club) most of the card number are found invalid.

After that I use credit card validator on CardGenerators.com that gives me perfect result. It also validate 15, 16 and 19 digit credit cards.

@Tofandel
Copy link

Tofandel commented Sep 17, 2021

The code can be rewritten as:

function valid_credit_card(value) {
  // Accept only digits, dashes or spaces
	if (/[^0-9-\s]+/.test(value)) return false;

	// The Luhn Algorithm. It's so pretty.
	let nCheck = 0;
	value = value.replace(/\D/g, "");

	for (let n = 0; n < value.length; n++) {
		let nDigit = parseInt(value[n], 10);

		if (!((n + value.length) % 2) && (nDigit *= 2) > 9) nDigit -= 9;

		nCheck += nDigit;
	}

	return (nCheck % 10) === 0;
}

Or even cleaner

export const luhn = (value) => {
    let nCheck = 0;
    if (value && /[0-9-\s]+/.test(value)) {
        value = value.replace(/\D/g, '');

        value.split('').forEach((v, n) => {
            let nDigit = parseInt(v, 10);

            if (!((value.length + n) % 2) && (nDigit *= 2) > 9) {
                nDigit -= 9;
            }

            nCheck += nDigit;
        });
    }

    return (nCheck % 10) === 0;
};

@asfo
Copy link

asfo commented Feb 24, 2023

A shitty one-liner:

const luhn = numbers => numbers.split('').map((value, index) => index % 2 === 0 ? Number(value) * 2 <= 9 ? Number(value) * 2 : Number(Number(`${Number(value) * 2}`.split('')[0]) + Number(`${Number(value) * 2}`.split('')[1])) : Number(value)).reduce((a, b) => a + b).toString().split('')[1] === '0';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment