开发者

How to validate a credit card number

I just want to validate a credit card number in the JavaScript code. I have used a regular expression for digit numbers, but I don't know why it is not working!

Here is my function as per below:

function validate_creditcardnumber()
{
    var re16digit = /^\d{16}$/
    if (document.myform.CreditCardNumber.value.search(re16d开发者_如何学运维igit) == -1)
        alert("Please enter your 16 digit credit card numbers");
    return false;
}


I hope the following two links help to solve your problem.

FYI, various credit cards are available in the world. So, your thought is wrong. Credit cards have some format. See the following links. The first one is pure JavaScript and the second one is using jQuery.

  • Update: 16-May-2022 - Link is not a valid JavaScript Credit Card Validation Function

UPDATE 17-May-2022

The code was updated. As the above link is dead, the original page can be accessed from the wayback-machine URL -

  • jQuery-Validation-Extension

Demo:

var ccErrorNo = 0;
var ccErrors = new Array ()

ccErrors [0] = "Unknown card type";
ccErrors [1] = "No card number provided";
ccErrors [2] = "Credit card number is in invalid format";
ccErrors [3] = "Credit card number is invalid";
ccErrors [4] = "Credit card number has an inappropriate number of digits";
ccErrors [5] = "Warning! This credit card number is associated with a scam attempt";

function checkCreditCard (cardnumber, cardname) {
     
  // Array to hold the permitted card characteristics
  var cards = new Array();

  // Define the cards we support. You may add addtional card types as follows.
  
  //  Name:         As in the selection box of the form - must be same as user's
  //  Length:       List of possible valid lengths of the card number for the card
  //  prefixes:     List of possible prefixes for the card
  //  checkdigit:   Boolean to say whether there is a check digit
  
  cards [0] = {name: "Visa", 
               length: "13,16", 
               prefixes: "4",
               checkdigit: true};
  cards [1] = {name: "MasterCard", 
               length: "16", 
               prefixes: "51,52,53,54,55",
               checkdigit: true};
  cards [2] = {name: "DinersClub", 
               length: "14,16", 
               prefixes: "36,38,54,55",
               checkdigit: true};
  cards [3] = {name: "CarteBlanche", 
               length: "14", 
               prefixes: "300,301,302,303,304,305",
               checkdigit: true};
  cards [4] = {name: "AmEx", 
               length: "15", 
               prefixes: "34,37",
               checkdigit: true};
  cards [5] = {name: "Discover", 
               length: "16", 
               prefixes: "6011,622,64,65",
               checkdigit: true};
  cards [6] = {name: "JCB", 
               length: "16", 
               prefixes: "35",
               checkdigit: true};
  cards [7] = {name: "enRoute", 
               length: "15", 
               prefixes: "2014,2149",
               checkdigit: true};
  cards [8] = {name: "Solo", 
               length: "16,18,19", 
               prefixes: "6334,6767",
               checkdigit: true};
  cards [9] = {name: "Switch", 
               length: "16,18,19", 
               prefixes: "4903,4905,4911,4936,564182,633110,6333,6759",
               checkdigit: true};
  cards [10] = {name: "Maestro", 
               length: "12,13,14,15,16,18,19", 
               prefixes: "5018,5020,5038,6304,6759,6761,6762,6763",
               checkdigit: true};
  cards [11] = {name: "VisaElectron", 
               length: "16", 
               prefixes: "4026,417500,4508,4844,4913,4917",
               checkdigit: true};
  cards [12] = {name: "LaserCard", 
               length: "16,17,18,19", 
               prefixes: "6304,6706,6771,6709",
               checkdigit: true};
               
  // Establish card type
  var cardType = -1;
  for (var i=0; i<cards.length; i++) {

    // See if it is this card (ignoring the case of the string)
    if (cardname.toLowerCase () == cards[i].name.toLowerCase()) {
      cardType = i;
      break;
    }
  }
  
  // If card type not found, report an error
  if (cardType == -1) {
     ccErrorNo = 0;
     return false; 
  }
   
  // Ensure that the user has provided a credit card number
  if (cardnumber.length == 0)  {
     ccErrorNo = 1;
     return false; 
  }
    
  // Now remove any spaces from the credit card number
  cardnumber = cardnumber.replace (/\s/g, "");
  
  // Check that the number is numeric
  var cardNo = cardnumber
  var cardexp = /^[0-9]{13,19}$/;
  if (!cardexp.exec(cardNo))  {
     ccErrorNo = 2;
     return false; 
  }
       
  // Now check the modulus 10 check digit - if required
  if (cards[cardType].checkdigit) {
    var checksum = 0;                                  // running checksum total
    var mychar = "";                                   // next char to process
    var j = 1;                                         // takes value of 1 or 2
  
    // Process each digit one by one starting at the right
    var calc;
    for (i = cardNo.length - 1; i >= 0; i--) {
    
      // Extract the next digit and multiply by 1 or 2 on alternative digits.
      calc = Number(cardNo.charAt(i)) * j;
    
      // If the result is in two digits add 1 to the checksum total
      if (calc > 9) {
        checksum = checksum + 1;
        calc = calc - 10;
      }
    
      // Add the units element to the checksum total
      checksum = checksum + calc;
    
      // Switch the value of j
      if (j ==1) {j = 2} else {j = 1};
    } 
  
    // All done - if checksum is divisible by 10, it is a valid modulus 10.
    // If not, report an error.
    if (checksum % 10 != 0)  {
     ccErrorNo = 3;
     return false; 
    }
  }  
  
  // Check it's not a spam number
  if (cardNo == '5490997771092064') { 
    ccErrorNo = 5;
    return false; 
  }

  // The following are the card-specific checks we undertake.
  var LengthValid = false;
  var PrefixValid = false; 
  var undefined; 

  // We use these for holding the valid lengths and prefixes of a card type
  var prefix = new Array ();
  var lengths = new Array ();
    
  // Load an array with the valid prefixes for this card
  prefix = cards[cardType].prefixes.split(",");
      
  // Now see if any of them match what we have in the card number
  for (i=0; i<prefix.length; i++) {
    var exp = new RegExp ("^" + prefix[i]);
    if (exp.test (cardNo)) PrefixValid = true;
  }
      
  // If it isn't a valid prefix there's no point at looking at the length
  if (!PrefixValid) {
     ccErrorNo = 3;
     return false; 
  }
    
  // See if the length is valid for this card
  lengths = cards[cardType].length.split(",");
  for (j=0; j<lengths.length; j++) {
    if (cardNo.length == lengths[j]) LengthValid = true;
  }
  
  // See if all is OK by seeing if the length was valid. We only check the length if all else was 
  // hunky dory.
  if (!LengthValid) {
     ccErrorNo = 4;
     return false; 
  };   
  
  // The credit card is in the required format.
  return true;
}


function testCreditCard() {
  myCardNo = document.getElementById('CardNumber').value;
  myCardType = document.getElementById('CardType').value;
  if (checkCreditCard(myCardNo, myCardType)) {
    alert("Credit card has a valid format")
  } else {
    alert(ccErrors[ccErrorNo])
  };
}
<!-- 
<script src="https://www.braemoor.co.uk/software/_private/creditcard.js"></script>
-->

<!-- COPIED THE DEMO CODE FROM THE SOURCE WEBSITE (https://www.braemoor.co.uk/software/creditcard.shtml) -->

<table>
  <tbody>
    <tr>
      <td style="padding-right: 30px;">American Express</td>
      <td>3400 0000 0000 009</td>
    </tr>
    <tr>
      <td>Carte Blanche</td>
      <td>3000 0000 0000 04</td>
    </tr>
    <tr>
      <td>Discover</td>
      <td>6011 0000 0000 0004</td>
    </tr>
    <tr>
      <td>Diners Club</td>
      <td>3852 0000 0232 37</td>
    </tr>
    <tr>
      <td>enRoute</td>
      <td>2014 0000 0000 009</td>
    </tr>
    <tr>
      <td>JCB</td>
      <td>3530 111333300000</td>
    </tr>
    <tr>
      <td>MasterCard</td>
      <td>5500 0000 0000 0004</td>
    </tr>
    <tr>
      <td>Solo</td>
      <td>6334 0000 0000 0004</td>
    </tr>
    <tr>
      <td>Switch</td>
      <td>4903 0100 0000 0009</td>
    </tr>
    <tr>
      <td>Visa</td>
      <td>4111 1111 1111 1111</td>
    </tr>
    <tr>
      <td>Laser</td>
      <td>6304 1000 0000 0008</td>
    </tr>
  </tbody>
</table>
<hr /> Card Number:
<select tabindex="11" id="CardType" style="margin-left: 10px;">
  <option value="AmEx">American Express</option>
  <option value="CarteBlanche">Carte Blanche</option>
  <option value="DinersClub">Diners Club</option>
  <option value="Discover">Discover</option>
  <option value="EnRoute">enRoute</option>
  <option value="JCB">JCB</option>
  <option value="Maestro">Maestro</option>
  <option value="MasterCard">MasterCard</option>
  <option value="Solo">Solo</option>
  <option value="Switch">Switch</option>
  <option value="Visa">Visa</option>
  <option value="VisaElectron">Visa Electron</option>
  <option value="LaserCard">Laser</option>
</select> <input type="text" id="CardNumber" maxlength="24" size="24" style="margin-left: 10px;"> <button id="mybutton" type="button" onclick="testCreditCard();" style="margin-left: 10px; color: #f00;">Check</button>

<p style="color: red; font-size: 10px;"> COPIED THE DEMO CODE FROM TEH SOURCE WEBSITE (https://www.braemoor.co.uk/software/creditcard.shtml) </p>


http://www.w3resource.com/javascript/form/credit-card-validation.php + the Luhn algorithm:

var checkLuhn = function (cardNo) {
    var s = 0;
    var doubleDigit = false;
    for (var i = cardNo.length - 1; i >= 0; i--) {
        var digit = +cardNo[i];
        if (doubleDigit) {
            digit *= 2;
            if (digit > 9)
                digit -= 9;
        }
        s += digit;
        doubleDigit = !doubleDigit;
    }
    return s % 10 == 0;
}

P.S.: Do not use regex for this, as it is done by the link. But it is useful to use text definitions of each card. Here it is:

American Express: Starting with 34 or 37, length 15 digits.

Visa: Starting with 4, length 13 or 16 digits.

MasterCard: Starting with 51 through 55, length 16 digits.

Discover: Starting with 6011, length 16 digits or starting with 5, length 15 digits.

Diners Club: Starting with 300 through 305, 36, or 38, length 14 digits.

JCB: Starting with 2131 or 1800, length 15 digits or starting with 35, length 16 digits.

I have it done like this:

var validateCardNo = function (no) {
    return (no && checkLuhn(no) &&
        no.length == 16 && (no[0] == 4 || no[0] == 5 && no[1] >= 1 && no[1] <= 5 ||
        (no.indexOf("6011") == 0 || no.indexOf("65") == 0)) ||
        no.length == 15 && (no.indexOf("34") == 0 || no.indexOf("37") == 0) ||
        no.length == 13 && no[0] == 4)
}


You can use this snippet to validate 16 digits card numbers with the Luhn algorithm:

function validateCardNumber(number) {
    var regex = new RegExp("^[0-9]{16}$");
    if (!regex.test(number))
        return false;

    return luhnCheck(number);
}

function luhnCheck(val) {
    var sum = 0;
    for (var i = 0; i < val.length; i++) {
        var intVal = parseInt(val.substr(i, 1));
        if (i % 2 == 0) {
            intVal *= 2;
            if (intVal > 9) {
                intVal = 1 + (intVal % 10);
            }
        }
        sum += intVal;
    }
    return (sum % 10) == 0;
}


A credit card number is not a bunch of random numbers. There is a formula for checking if it is correct.

After a quick Google search I found this JavaScript which will check a credit card number to be valid.

http://javascript.internet.com/forms/credit-card-number-validation.html

URL Broken: Internet archive: http://web.archive.org/web/20100129174150/http://javascript.internet.com/forms/credit-card-number-validation.html?

<!-- TWO STEPS TO INSTALL CREDIT CARD NUMBER VALIDATION:

  1.  Copy the code into the HEAD of your HTML document
  2.  Add the last code into the BODY of your HTML document  -->

<!-- STEP ONE: Paste this code into the HEAD of your HTML document  -->

<HEAD>

  <script type="text/javascript">
    <!--
    /* This script and many more are available free online at
    The JavaScript Source!! http://javascript.internet.com
    Created by: David Leppek :: https://www.azcode.com/Mod10

    Basically, the algorithm takes each digit, from right to left and muliplies each second
    digit by two. If the multiple is two-digits long (i.e.: 6 * 2 = 12) the two digits of
    the multiple are then added together for a new number (1 + 2 = 3). You then add up the
    string of numbers, both unaltered and new values and get a total sum. This sum is then
    divided by 10 and the remainder should be zero if it is a valid credit card. Hense the
    name Mod 10 or Modulus 10.
    */
    function Mod10(ccNumb) {  // v2.0
      var valid = "0123456789"  // Valid digits in a credit card number
      var len = ccNumb.length;  // The length of the submitted cc number
      var iCCN = parseInt(ccNumb);  // Integer of ccNumb
      var sCCN = ccNumb.toString();  // String of ccNumb
      sCCN = sCCN.replace (/^\s+|\s+$/g,'');  // Strip spaces
      var iTotal = 0;  // Integer total set at zero
      var bNum = true;  // By default assume it is a number
      var bResult = false;  // By default assume it is NOT a valid cc
      var temp;  // Temporary variable for parsing string
      var calc;  // Used for calculation of each digit

      // Determine if the ccNumb is in fact all numbers
      for (var j=0; j<len; j++) {
        temp = "" + sCCN.substring(j, j+1);
        if (valid.indexOf(temp) == "-1"){
          bNum = false;
        }
      }

      // If it is NOT a number, you can either alert to the fact, or just pass a failure
      if (!bNum) {
        /* alert("Not a Number"); */
        bResult = false;
      }

      // Determine if it is the proper length
      if ((len == 0) && (bResult)) {  // Nothing, the field is blank AND passed above # check
        bResult = false;
      }
      else { // ccNumb is a number and the proper length - let's
             //  see if it is a valid card number

        if (len >= 15) {  // 15 or 16 for Amex or V/MC
          for (var i=len;i>0;i--) {  // LOOP through the digits of the card
            calc = parseInt(iCCN) % 10;  // Right most digit
            calc = parseInt(calc);  // Assure it is an integer
            iTotal += calc;  // Running total of the card number as we loop - Do Nothing to first digit
            i--;  // Decrement the count - move to the next digit in the card
            iCCN = iCCN / 10;                               // Subtracts right most digit from ccNumb
            calc = parseInt(iCCN) % 10;     // NEXT right most digit
            calc = calc *2;                                 // multiply the digit by two

            // Instead of some screwy method of converting 16 to a string
            // and then parsing 1 and 6 and then adding them to make 7,
            // I use a simple switch statement to change the value
            // of calc2 to 7 if 16 is the multiple.
            switch(calc) {
              case 10: calc = 1; break;  // 5*2=10 & 1+0 = 1
              case 12: calc = 3; break;  // 6*2=12 & 1+2 = 3
              case 14: calc = 5; break;  // 7*2=14 & 1+4 = 5
              case 16: calc = 7; break;  // 8*2=16 & 1+6 = 7
              case 18: calc = 9; break;  // 9*2=18 & 1+8 = 9
              default: calc = calc;      // 4*2= 8 &   8 = 8  - the same for all lower numbers
            }
            iCCN = iCCN / 10;  // Subtracts right most digit from ccNum
            iTotal += calc;  // Running total of the card number as we loop
          } // END OF LOOP

          if ((iTotal%10)==0){  // Check to see if the sum Mod 10 is zero
            bResult = true;  // This IS (or could be) a valid credit card number.
          }
          else {
            bResult = false;  // This could NOT be a valid credit card number
          }
        }
      }

      // Change alert to on-page display or other indication as needed.
      if (bResult) {
        alert("This IS a valid Credit Card Number!");
      }
      if (!bResult) {
        alert("This is NOT a valid Credit Card Number!");
      }
      return bResult; // Return the results
    }
    // -->
  </script>

</HEAD>


<!-- STEP TWO: Copy this code into the BODY of your HTML document  -->

<BODY>

<div align="center">
  <form name="Form1">
    <table width="50%" border="0" cellspacing="0" cellpadding="5">
      <tr>
        <td width="50%" align="right">Credit Card Number:   </td>
        <td width="50%">
          <input name="CreditCard" type="text" value="4012888888881881" size="18" maxlength="16" style="border: 1px solid #000098; padding: 3px;">
        </td>
      </tr>
      <tr>
        <td colspan="2" align="center">
          <input type="button" name="Button" style="color: #fff; background: #000098; font-weight:bold; border: solid 1px #000;" value="TEST CARD NUMBER" onClick="return Mod10(document.Form1.CreditCard.value);">
        </td>
      </tr>
    </table>
  </form>
</div>

<p><center>
  <font face="arial, helvetica" size"-2">Free JavaScripts provided<br>
  by <a href="http://javascriptsource.com">The JavaScript Source</a></font>
</center><p>

<!-- Script Size:  4.97 KB -->


Luhn's algorithm is used for adding validation of credit and debit card numbers. This JavaScript function should work out.

function validate_creditcardnumber(inputNum) {
    var digit, digits, flag, sum, _i, _len;
    flag = true;
    sum = 0;
    digits = (inputNum + '').split('').reverse();
    for (_i = 0, _len = digits.length; _i < _len; _i++) {
      digit = digits[_i];
      digit = parseInt(digit, 10);
      if ((flag = !flag)) {
        digit *= 2;
      }
      if (digit > 9) {
        digit -= 9;
      }
      sum += digit;
    }
    return sum % 10 === 0;
  };


Use this:

function AmexCardnumber(inputtxt) {
  var cardno = /^(?:3[47][0-9]{13})$/;
  return cardno.test(inputtxt);
}

function VisaCardnumber(inputtxt) {
  var cardno = /^(?:4[0-9]{12}(?:[0-9]{3})?)$/;
  return cardno.test(inputtxt);
}

function MasterCardnumber(inputtxt) {
  var cardno = /^(?:5[1-5][0-9]{14})$/;
  return cardno.test(inputtxt);
}

function DiscoverCardnumber(inputtxt) {
  var cardno = /^(?:6(?:011|5[0-9][0-9])[0-9]{12})$/;
  return cardno.test(inputtxt);
}

function DinerClubCardnumber(inputtxt) {
  var cardno = /^(?:3(?:0[0-5]|[68][0-9])[0-9]{11})$/;
  return cardno.test(inputtxt);
}

function JCBCardnumber(inputtxt) {
  var cardno = /^(?:(?:2131|1800|35\d{3})\d{11})$/;
  return cardno.test(inputtxt);
}

function IsValidCreditCardNumber(cardNumber) {

  var cardType = null;
  if (VisaCardnumber(cardNumber)) {
    cardType = "visa";
  } else if (MasterCardnumber(cardNumber)) {
    cardType = "mastercard";
  } else if (AmexCardnumber(cardNumber)) {
    cardType = "americanexpress";
  } else if (DiscoverCardnumber(cardNumber)) {
    cardType = "discover";
  } else if (DinerClubCardnumber(cardNumber)) {
    cardType = "dinerclub";
  } else if (JCBCardnumber(cardNumber)) {
    cardType = "jcb";
  }

  return cardType;
}


You define the variable name re16digit but later refer to it as re10digit, which will throw an error. To simplify your code, you should use RegExp.prototype.test() rather than String.prototype.search():

function validate_creditcardnumber() {
    var re16digit = /^\d{16}$/;
    if (!re16digit.test(document.myform.CreditCardNumber.value)) {
        alert("Please enter your 16 digit credit card numbers");
        return false;
    }
}

Working demo: http://jsfiddle.net/Dxjkh/

As others have mentioned, you may be better off using a JavaScript implementation of the Luhn Algorithm. It's also worth mentioning that a check for 16 digits will fail for American Express (15 digits) and Diners (14 digits) cards.


You should really use .test():

if (!re16digit.test(document.myform.CreditCardNumber.value)) {
  alert("Please ... ");
}

You should also look around for implementations of (one or more of) the card number checksum algorithms. They're very simple.


Maybe you should take a look here: http://en.wikipedia.org/wiki/Luhn_algorithm

Here is Java snippet which validates a credit card number which should be easy enough to convert to JavaScript:

  public static boolean isValidCC(String number) {

    final int[][] sumTable = {{0,1,2,3,4,5,6,7,8,9},{0,2,4,6,8,1,3,5,7,9}};
    int sum = 0, flip = 0;

    for (int i = number.length() - 1; i >= 0; i--) {
      sum += sumTable[flip++ & 0x1][Character.digit(number.charAt(i), 10)];
    }
    return sum % 10 == 0;
  }


Maybe have a look at this solution: https://codepen.io/quinlo/pen/YONMEa

//pop in the appropriate card icon when detected
cardnumber_mask.on("accept", function () {
    console.log(cardnumber_mask.masked.currentMask.cardtype);
    switch (cardnumber_mask.masked.currentMask.cardtype) {
        case 'american express':
            ccicon.innerHTML = amex;
            ccsingle.innerHTML = amex_single;
            swapColor('green');
            break;
        case 'visa':
            ccicon.innerHTML = visa;
            ccsingle.innerHTML = visa_single;
            swapColor('lime');
            break;
        case 'diners':
            ccicon.innerHTML = diners;
            ccsingle.innerHTML = diners_single;
            swapColor('orange');
            break;
        case 'discover':
            ccicon.innerHTML = discover;
            ccsingle.innerHTML = discover_single;
            swapColor('purple');
            break;
        case ('jcb' || 'jcb15'):
            ccicon.innerHTML = jcb;
            ccsingle.innerHTML = jcb_single;
            swapColor('red');
            break;
        case 'maestro':
            ccicon.innerHTML = maestro;
            ccsingle.innerHTML = maestro_single;
            swapColor('yellow');
            break;
        case 'mastercard':
            ccicon.innerHTML = mastercard;
            ccsingle.innerHTML = mastercard_single;
            swapColor('lightblue');

            break;
        case 'unionpay':
            ccicon.innerHTML = unionpay;
            ccsingle.innerHTML = unionpay_single;
            swapColor('cyan');
            break;
        default:
            ccicon.innerHTML = '';
            ccsingle.innerHTML = '';
            swapColor('grey');
            break;
    }

});


This works: http://jsfiddle.net/WHKeK/

function validate_creditcardnumber()
{
    var re16digit=/^\d{16}$/
    if (document.myform.CreditCardNumber.value.search(re16digit) == -1)
        alert("Please enter your 16 digit credit card numbers");
    return false;    
}

You have a typo. You call the variable re16digit, but in your search you have re10digit.


These are my two cents.

Note #1: this is not a perfect validation method, but it is OK for my needs.
Note #2: IIN ranges can be changed (and will be), so it is a good idea to check this link to be sure that we are up to date.

function validateCCNum(ccnum)
{
    var ccCheckRegExp = /[^\d\s-]/;
    var isValid = !ccCheckRegExp.test(ccnum);
    var i;

    if (isValid) {
        var cardNumbersOnly = ccnum.replace(/[\s-]/g,"");
        var cardNumberLength = cardNumbersOnly.length;

        var arrCheckTypes = ['visa', 'mastercard', 'amex', 'discover', 'dinners', 'jcb'];
        for(i=0; i<arrCheckTypes.length; i++) {
            var lengthIsValid = false;
            var prefixIsValid = false;
            var prefixRegExp;

            switch (arrCheckTypes[i]) {
                case "mastercard":
                    lengthIsValid = (cardNumberLength === 16);
                    prefixRegExp = /5[1-5][0-9]|(2(?:2[2-9][^0]|2[3-9]|[3-6]|22[1-9]|7[0-1]|72[0]))\d*/;
                    break;

                case "visa":
                    lengthIsValid = (cardNumberLength === 16 || cardNumberLength === 13);
                    prefixRegExp = /^4/;
                    break;

                case "amex":
                    lengthIsValid = (cardNumberLength === 15);
                    prefixRegExp = /^3([47])/;
                    break;

                case "discover":
                    lengthIsValid = (cardNumberLength === 15 || cardNumberLength === 16);
                    prefixRegExp = /^(6011|5)/;
                    break;

                case "dinners":
                    lengthIsValid = (cardNumberLength === 14);
                    prefixRegExp = /^(300|301|302|303|304|305|36|38)/;
                    break;

                case "jcb":
                    lengthIsValid = (cardNumberLength === 15 || cardNumberLength === 16);
                    prefixRegExp = /^(2131|1800|35)/;
                    break;

                default:
                    prefixRegExp = /^$/;
            }

            prefixIsValid = prefixRegExp.test(cardNumbersOnly);
            isValid = prefixIsValid && lengthIsValid;

            // Check if we found a correct one
            if(isValid) {
                break;
            }
        }
    }

    if (!isValid) {
        return false;
    }

    // Remove all dashes for the checksum checks to eliminate negative numbers
    ccnum = ccnum.replace(/[\s-]/g,"");
    // Checksum ("Mod 10")
    // Add even digits in even length strings or odd digits in odd length strings.
    var checksum = 0;
    for (i = (2 - (ccnum.length % 2)); i <= ccnum.length; i += 2) {
        checksum += parseInt(ccnum.charAt(i - 1));
    }

    // Analyze odd digits in even length strings or even digits in odd length strings.
    for (i = (ccnum.length % 2) + 1; i < ccnum.length; i += 2) {
        var digit = parseInt(ccnum.charAt(i - 1)) * 2;
        if (digit < 10) {
            checksum += digit;
        } else {
            checksum += (digit - 9);
        }
    }

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

Thanks to @Peter Mortensen for the comment :)


In order to validate a card number, you need to check it against the Luhn Algorithm.

Here is a JS code sample of an API method to check a given card number against the Luhn Algorithm. The response of this method can also be made to provide general information about the card (such as brand, country issued in, issuing bank and more):

const options = {
  method: 'GET',
  headers: {Accept: 'application/json', 'X-Api-Key': '[APIkey]'}
};

fetch('https://api.epaytools.com/Tools/luhn?number=[CardNumber]&metaData=true', options)
  .then(response => response.json())
  .then(response => console.log(response))
  .catch(err => console.error(err));

All you have to do is register with the provider - PCI Booking, to use this method. While they are a paid service, they also offer free accounts where you can perform these types of actions.

Important note, the main thing to consider is what is the purpose of validating the card number. As was mentioned in one of the responses, the Luhn Algorithm simply checks that the number provided matches the format of a card number. However, many test card numbers, for example 4580458045804580, will also pass the Luhn Algorithm. You can use 3D Secure authentication when asking the card owner to enter the card details, (and PCI Booking also offers a service for that), but this might not fit your flow. And this only validates that the card is real and the person entering the card is the card owner. To know that a card is valid to be used for a payment, then you would have to use a payment processor and submit an actual charge or pre-authorization on the card. So it is important to figure out what is the purpose behind the validation attempt and why do you need a valid card for.


I'm sure all of these algorithms are great, but you cannot verify that a card number is valid just by running an algorithm on it.

Algorithms make sure the format is correct and its checksums are valid. However, they do not guarantee the bank will accept the card... For that, you need to actually pass the card number to your bank for approval.


This code works:

function check_credit_card_validity_contact_bank(random_id) {
    var cb_visa_pattern = /^4/;
    var cb_mast_pattern = /^5[1-5]/;
    var cb_amex_pattern = /^3[47]/;
    var cb_disc_pattern = /^6(011|5|4[4-9]|22(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]))/;
    var credit_card_number = jQuery("#credit_card_number_text_field_"+random_id).val();
    var cb_is_visa = cb_visa_pattern.test( credit_card_number ) === true;
    var cb_is_master = cb_mast_pattern.test( credit_card_number ) === true;
    var cb_is_amex = cb_amex_pattern.test( credit_card_number ) === true;
    var isDisc = cb_disc_pattern.test( credit_card_number ) === true;
    cb_is_amex ? jQuery("#credit_card_number_text_field_"+random_id).mask("999999999999999") : jQuery("#credit_card_number_text_field_"+random_id).mask("9999999999999999");
    var credit_card_number = jQuery("#credit_card_number_text_field_"+random_id).val();
    cb_is_amex ? jQuery("#credit_card_number_text_field_"+random_id).mask("9999 9999 9999 999") : jQuery("#credit_card_number_text_field_"+random_id).mask("9999 9999 9999 9999");

    if( cb_is_visa || cb_is_master || cb_is_amex || isDisc) {
        if( cb_is_visa || cb_is_master || isDisc) {
            var sum = 0;
            for (var i = 0; i < credit_card_number.length; i++) {
                var intVal = parseInt(credit_card_number.substr(i, 1));
                if (i % 2 == 0) {
                    intVal *= 2;
                    if (intVal > 9)
                    {
                        intVal = 1 + (intVal % 10);
                    }
                }
                sum += intVal;
            }
            var contact_bank_check_validity = (sum % 10) == 0 ? true : false;
        }

        jQuery("#text_appear_after_counter_credit_card_"+random_id).css("display","none");
        if( cb_is_visa  && contact_bank_check_validity) {
           jQuery("#credit_card_number_text_field_"+random_id).css({"background-image":"url(<?php echo plugins_url("assets/global/img/cc-visa.svg", dirname(__FILE__)); ?>)","background-repeat":"no-repeat","padding-left":"40px", "padding-bottom":"5px"});
        } else if( cb_is_master && contact_bank_check_validity) {
             jQuery("#credit_card_number_text_field_"+random_id).css({"background-image":"url(<?php echo plugins_url("assets/global/img/cc-mastercard.svg", dirname(__FILE__)); ?>)","background-repeat":"no-repeat","padding-left":"40px", "padding-bottom":"5px"});
        } else if( cb_is_amex) {
           jQuery("#credit_card_number_text_field_"+random_id).unmask();
           jQuery("#credit_card_number_text_field_"+random_id).mask("9999 9999 9999 999");
           jQuery("#credit_card_number_text_field_"+random_id).css({"background-image":"url(<?php echo plugins_url("assets/global/img/cc-amex.svg", dirname(__FILE__)); ?>)","background-repeat":"no-repeat","padding-left":"40px","padding-bottom":"5px"});
        } else if( isDisc && contact_bank_check_validity) {
             jQuery("#credit_card_number_text_field_"+random_id).css({"background-image":"url(<?php echo plugins_url("assets/global/img/cc-discover.svg", dirname(__FILE__)); ?>)","background-repeat":"no-repeat","padding-left":"40px","padding-bottom":"5px"});
        } else {
            jQuery("#credit_card_number_text_field_"+random_id).css({"background-image":"url(<?php echo plugins_url("assets/global/img/credit-card.svg", dirname(__FILE__)); ?>)","background-repeat":"no-repeat","padding-left":"40px" ,"padding-bottom":"5px"});
            jQuery("#text_appear_after_counter_credit_card_"+random_id).css("display","block").html(<?php echo json_encode($cb_invalid_card_number);?>).addClass("field_label");
        }
    }
    else {
        jQuery("#credit_card_number_text_field_"+random_id).css({"background-image":"url(<?php echo plugins_url("assets/global/img/credit-card.svg", dirname(__FILE__)); ?>)","background-repeat":"no-repeat","padding-left":"40px" ,"padding-bottom":"5px"});
        jQuery("#text_appear_after_counter_credit_card_"+random_id).css("display","block").html(<?php echo json_encode($cb_invalid_card_number);?>).addClass("field_label");
    }
}


Find the source code from github for credit card validiations , it will work 100%


I have written a beautiful single line function for validating a card using the Luhn Algorithm. Please note it assumes that the input is numerical string, as this is what input elements usually provide. Whether or not the card number is real is up to the bank or payment processor to determine, this is just a first step check to see if the input is a valid card number. Enjoy!

function isValidCard(input){return (input.length==16)?input.split('').map((x, i)=>+((i%2==0)?(x*2>9)?1+((x*2)%10):x*2:x)).reduce((t, x)=>t+x)%10==0:false;}


Luhn algorithm for checking card validation.

    const cardValidator = (cardNumber = 4539689887705798) => {
    let cardNumers = cardNumber.toString().split("");
    cardNumers = cardNumers.map(Number);
    let sum = 0;
    for (let i = 0; i < cardNumers.length; i++) {
        let digit = cardNumers[i];
        if (i % 2 === 0) {
            digit *= 2;
            if(digit > 9) digit -= 9;
        }
        sum = sum + digit;
    }
    return sum % 10 === 0;
}


Here is my es6 solution

function isValidCardNo(cardNo) {
  let even = false;
  return cardNo.split("").reverse().map(Number).reduce((sum, d) =>
    sum += ((even = !even) ? d : (d < 5) ? d * 2 : (d - 5) * 2 + 1), 0
  ) % 10 === 0;
}

console.log(isValidCardNo('4111111111111111'));  // true
console.log(isValidCardNo('4111111111111112'));  // false


Single line Luhn algorithm implementation:

const checkLuhn = num => !(num
  .replace(/\D/g, '') //remove non-digits
  .split('') //make an array
  .reverse() //last digit first
  .map((e, i) => e * (i % 2 + 1)) //double every even element
  .join('') //instead of if(d > 9)
  .split('') // d -=9
  .reduce((e, t) => t - 0 + e, 0) //sum elements
  % 10); // 0 is falsy and !0 is truey
  
  //test 
console.log(checkLuhn('5555555555554444')); // MC, expected true
console.log(checkLuhn('378282246310005')); // AmEx, expected true
console.log(checkLuhn('4111 1111 1111 1111')); // Visa, expected true
console.log(checkLuhn('4111111111111112')); // Visa, expected false

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜