Front End

20 abr, 2011

Validando cartões de crédito com JavaScript

Publicidade

Texto original de David Walsh, traduzido com autorização e disponível em http://davidwalsh.name/validate-credit-cards

?

Todos nós sabemos que
o JavaScript não deveria ser o único método de validação de formulários web,
mas a validação do lado do cliente previne processamentos desnecessários no
servidor ao utilizar um input obviamente inválido. Eu também considero que a
validação de formulários do lado do cliente gera uma grande melhoria em termos
de usabilidade (ou um pesadelo quando feito pobremente). Eu geralmente ouço
desenvolvedores reclamarem sobre a dificuldade de validar cartões de crédito,
especialmente quando só suportam cartões de crédito específicos. Por sorte, o
Dojo Tookit inclui o dojox.validate.creditCard,
um recurso capaz de validar um cartão de crédito eficientemente. Melhor ainda,
você pode facilmente, a partir de sua lógica, criar seu próprio validador.

O
JavaScript Dojo

O código de validação é bem compacto, mas bem comentado; leia esses
comentários ao olhar para o código:

dojo.provide("dojox.validate.creditCard");
/*=====

  dojox.validate.creditCard = {
    // summary:
    //    Module provides validation functions for Credit Cards, using account number
    //    rules in conjunction with the Luhn algorigthm, with a plugable card info database.
  };
 
=====*/
dojo.require("dojox.validate._base");

dojox.validate._cardInfo = {
  // summary: A dictionary list of credit card abbreviations
  //
  // description:
  //
  //    A hash of valid CC abbreviations and regular expressions
  //
  //    mc: Mastercard
  //    ec: Eurocard
  //    vi: Visa
  //    ax: American Express
  //    dc: Diners Club
  //    bl: Carte Blanch
  //    di: Discover
  //    jcb: JCB
  //    er: Enroute
  //
  //  example:
  //    Define your own card, gift-card, whatever. Starts with 7,
  //    is 15 total length.
  //  | dojo.mixin(dojox.validate._cardInfo, {
  //  |   "my":"7[0-9]{14}"
  //  | });
 
  'mc':'5[1-5][0-9]{14}',
  'ec':'5[1-5][0-9]{14}',
  'vi':'4(?:[0-9]{12}|[0-9]{15})',
  'ax':'3[47][0-9]{13}',
  'dc':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})',
  'bl':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})',
  'di':'6011[0-9]{12}',
  'jcb':'(?:3[0-9]{15}|(2131|1800)[0-9]{11})',
  'er':'2(?:014|149)[0-9]{11}'
}

dojox.validate.isValidCreditCard = function(value, ccType){
  // summary: Validate a credit card number by type with Luhn checking.
  //
  // description:
  //    Checks if a credit card type matches the # scheme in a passed value, and if
  //    the Luhn checksum is accurate (unless its an Enroute card, in which case
  //    the checkSum is skipped), returning a Boolean to check against.
  //
  // value: String|Int
  //    A Value (credit card number) to validate
  //
  // ccType: String
  //    A credit-card abbreviation.
  //
  // example:
  // |  if(dojox.validate.isValidCreditCard("12345", "mc")){
  // |    console.log('inconceivable');
  // |  }
 
  return ((ccType.toLowerCase() == 'er' || dojox.validate.isValidLuhn(value)) &&
      dojox.validate.isValidCreditCardNumber(value, ccType.toLowerCase())); // Boolean
}

dojox.validate.isValidCreditCardNumber = function(value, ccType){
  // summary:
  //    Checks if value matches the pattern for that card or any card types if none is specified
  //
  // value: String|Int
  //    CC #, white spaces and dashes are ignored
  //
  // ccType: String?
  //    One of the abbreviation values in `dojox.validate._cardInfo` --
  //    if Omitted, function returns a `|` delimited string of matching card types,
  //    or false if no matches found.

  value = String(value).replace(/[- ]/g,''); //ignore dashes and whitespaces

  var cardinfo = dojox.validate._cardInfo, results = [];
  if(ccType){
    var expr = '^' + cardinfo[ccType.toLowerCase()] + ' ;
    return expr ? !!value.match(expr) : false; // boolean
  }

  for(var p in cardinfo){
    if(value.match('^' + cardinfo[p] + ' )){
      results.push(p);
    }
  }
  return results.length ? results.join('|') : false; // String | boolean
}

dojox.validate.isValidCvv = function(/* String|Int */value, /* String */ccType) {
  // summary:
  //    Validate the security code (CCV) for a passed credit-card type.
  //
  // description:
  //
  // value:
 
  if(!dojo.isString(value)){
    value = String(value);
  }
  var format;
  switch (ccType.toLowerCase()){
    case 'mc':
    case 'ec':
    case 'vi':
    case 'di':
      format = '###';
      break;
    case 'ax':
      format = '####';
      break;
  }
 
  return !!format && value.length && dojox.validate.isNumberFormat(value, { format: format }); // Boolean
}

Você usaria o código acima ao requerer o recurso e ao executar o método
sValidCreditCard, passando o valor e o tipo do cartão. Mas e se você não usar o
Dojo Tookit? Você pode pegar o código do Dojo e o jogar dentro de seu próprio
aplicativo:

// Create an object
var creditCardValidator = {};
// Pin the cards to them
creditCardValidator.cards = {
  'mc':'5[1-5][0-9]{14}',
  'ec':'5[1-5][0-9]{14}',
  'vi':'4(?:[0-9]{12}|[0-9]{15})',
  'ax':'3[47][0-9]{13}',
  'dc':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})',
  'bl':'3(?:0[0-5][0-9]{11}|[68][0-9]{12})',
  'di':'6011[0-9]{12}',
  'jcb':'(?:3[0-9]{15}|(2131|1800)[0-9]{11})',
  'er':'2(?:014|149)[0-9]{11}'
};
// Add the card validator to them
creditCardValidator.validate = function(value,ccType) {
  value = String(value).replace(/[- ]/g,''); //ignore dashes and whitespaces

  var cardinfo = creditCardValidator.cards, results = [];
  if(ccType){
    var expr = '^' + cardinfo[ccType.toLowerCase()] + ' ;
    return expr ? !!value.match(expr) : false; // boolean
  }

  for(var p in cardinfo){
    if(value.match('^' + cardinfo[p] + ' )){
      results.push(p);
    }
  }
  return results.length ? results.join('|') : false; // String | boolean
};

Com o objeto creditCardValidator
completo, é hora de usar o recurso:

if(!creditCardValidator.validate(document.id("creditCardField"))) {
  alert("Invalid credit card!");
}

Aí está: validação simples de cartão de
crédito com o código retirado do Dojo Tookit. Problema resolvido!