Luhn Checksum Validation for Card Numbers

Validate payment card numbers with the Luhn algorithm, tolerate spaces and hyphens, and compute the missing check digit.

JavascriptForm Validation

Code

snippet
export function isValidCardNumber(input) {
  const digits = normalize(input);
  if (digits.length < 12 || digits.length > 19) return false;
  return luhnSum(digits) % 10 === 0;
}

export function cardCheckDigit(partial) {
  const digits = normalize(partial);
  if (digits.length < 11 || digits.length > 18) {
    throw new RangeError("partial number must contain 11 to 18 digits");
  }
  const remainder = luhnSum(`${digits}0`) % 10;
  return String((10 - remainder) % 10);
}

function normalize(input) {
  if (typeof input !== "string" && typeof input !== "number") {
    throw new TypeError("card number must be a string or number");
  }
  const value = String(input).replace(/[\s-]/g, "");
  if (!/^\d*$/.test(value)) {
    throw new Error("card number may only contain digits, spaces and hyphens");
  }
  return value;
}

function luhnSum(digits) {
  let sum = 0;
  let double = false;
  for (let index = digits.length - 1; index >= 0; index -= 1) {
    let value = Number(digits[index]);
    if (double) {
      value *= 2;
      if (value > 9) value -= 9;
    }
    sum += value;
    double = !double;
  }
  return sum;
}

const sample = "4242 4242 4242 4242";
console.log(isValidCardNumber(sample));
console.log(isValidCardNumber("4242424242424241"));
console.log(cardCheckDigit("424242424242424"));