wiegand significado programar etiquetas algorithm language-agnostic e-commerce

algorithm - significado - wiegand 26 bits



¿Cómo se detecta el tipo de tarjeta de crédito basado en el número? (26)

Los primeros seis dígitos de un número de tarjeta (incluido el dígito inicial de MII) se conocen como el número de identificación del emisor (IIN). Estos identifican la institución emisora ​​de la tarjeta que emitió la tarjeta al titular de la tarjeta. El resto del número es asignado por el emisor de la tarjeta. La longitud del número de tarjeta es su número de dígitos. Muchos emisores de tarjetas imprimen el IIN completo y el número de cuenta en su tarjeta.

Sobre la base de los datos anteriores, me gustaría guardar un fragmento de código JAVA para identificar la marca de la tarjeta.

Tipos de tarjetas de muestra

public static final String AMERICAN_EXPRESS = "American Express"; public static final String DISCOVER = "Discover"; public static final String JCB = "JCB"; public static final String DINERS_CLUB = "Diners Club"; public static final String VISA = "Visa"; public static final String MASTERCARD = "MasterCard"; public static final String UNKNOWN = "Unknown";

Prefijos de tarjeta

// Based on http://en.wikipedia.org/wiki/Bank_card_number#Issuer_identification_number_.28IIN.29 public static final String[] PREFIXES_AMERICAN_EXPRESS = {"34", "37"}; public static final String[] PREFIXES_DISCOVER = {"60", "62", "64", "65"}; public static final String[] PREFIXES_JCB = {"35"}; public static final String[] PREFIXES_DINERS_CLUB = {"300", "301", "302", "303", "304", "305", "309", "36", "38", "39"}; public static final String[] PREFIXES_VISA = {"4"}; public static final String[] PREFIXES_MASTERCARD = { "2221", "2222", "2223", "2224", "2225", "2226", "2227", "2228", "2229", "223", "224", "225", "226", "227", "228", "229", "23", "24", "25", "26", "270", "271", "2720", "50", "51", "52", "53", "54", "55" };

Compruebe si el número de entrada tiene alguno de los prefijos dados.

public String getBrand(String number) { String evaluatedType; if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_AMERICAN_EXPRESS)) { evaluatedType = AMERICAN_EXPRESS; } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DISCOVER)) { evaluatedType = DISCOVER; } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_JCB)) { evaluatedType = JCB; } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_DINERS_CLUB)) { evaluatedType = DINERS_CLUB; } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_VISA)) { evaluatedType = VISA; } else if (StripeTextUtils.hasAnyPrefix(number, PREFIXES_MASTERCARD)) { evaluatedType = MASTERCARD; } else { evaluatedType = UNKNOWN; } return evaluatedType; }

Finalmente, el método Utility.

/** * Check to see if the input number has any of the given prefixes. * * @param number the number to test * @param prefixes the prefixes to test against * @return {@code true} if number begins with any of the input prefixes */ public static boolean hasAnyPrefix(String number, String... prefixes) { if (number == null) { return false; } for (String prefix : prefixes) { if (number.startsWith(prefix)) { return true; } } return false; }

Referencia

Estoy tratando de averiguar cómo detectar el tipo de tarjeta de crédito basándose únicamente en su número. ¿Alguien sabe de una forma definitiva y confiable para encontrar esto?



Aquí hay una función de clase php que devuelve CCtype por CCnumber.
Este código no valida la tarjeta o no ejecuta el algoritmo Luhn. Intente encontrar el tipo de tarjeta de crédito según la tabla de esta página . básicamente utiliza la longitud del número de CC y el prefijo de CCcard para determinar el tipo de CCcard.

<?php class CreditcardType { public static $creditcardTypes = array( array(''Name''=>''American Express'',''cardLength''=>array(15),''cardPrefix''=>array(''34'', ''37'')) ,array(''Name''=>''Maestro'',''cardLength''=>array(12, 13, 14, 15, 16, 17, 18, 19),''cardPrefix''=>array(''5018'', ''5020'', ''5038'', ''6304'', ''6759'', ''6761'', ''6763'')) ,array(''Name''=>''Mastercard'',''cardLength''=>array(16),''cardPrefix''=>array(''51'', ''52'', ''53'', ''54'', ''55'')) ,array(''Name''=>''Visa'',''cardLength''=>array(13,16),''cardPrefix''=>array(''4'')) ,array(''Name''=>''JCB'',''cardLength''=>array(16),''cardPrefix''=>array(''3528'', ''3529'', ''353'', ''354'', ''355'', ''356'', ''357'', ''358'')) ,array(''Name''=>''Discover'',''cardLength''=>array(16),''cardPrefix''=>array(''6011'', ''622126'', ''622127'', ''622128'', ''622129'', ''62213'', ''62214'', ''62215'', ''62216'', ''62217'', ''62218'', ''62219'', ''6222'', ''6223'', ''6224'', ''6225'', ''6226'', ''6227'', ''6228'', ''62290'', ''62291'', ''622920'', ''622921'', ''622922'', ''622923'', ''622924'', ''622925'', ''644'', ''645'', ''646'', ''647'', ''648'', ''649'', ''65'')) ,array(''Name''=>''Solo'',''cardLength''=>array(16, 18, 19),''cardPrefix''=>array(''6334'', ''6767'')) ,array(''Name''=>''Unionpay'',''cardLength''=>array(16, 17, 18, 19),''cardPrefix''=>array(''622126'', ''622127'', ''622128'', ''622129'', ''62213'', ''62214'', ''62215'', ''62216'', ''62217'', ''62218'', ''62219'', ''6222'', ''6223'', ''6224'', ''6225'', ''6226'', ''6227'', ''6228'', ''62290'', ''62291'', ''622920'', ''622921'', ''622922'', ''622923'', ''622924'', ''622925'')) ,array(''Name''=>''Diners Club'',''cardLength''=>array(14),''cardPrefix''=>array(''300'', ''301'', ''302'', ''303'', ''304'', ''305'', ''36'')) ,array(''Name''=>''Diners Club US'',''cardLength''=>array(16),''cardPrefix''=>array(''54'', ''55'')) ,array(''Name''=>''Diners Club Carte Blanche'',''cardLength''=>array(14),''cardPrefix''=>array(''300'',''305'')) ,array(''Name''=>''Laser'',''cardLength''=>array(16, 17, 18, 19),''cardPrefix''=>array(''6304'', ''6706'', ''6771'', ''6709'')) ); private function __construct() {} public static function getType($CCNumber) { $CCNumber= trim($CCNumber); $type=''Unknown''; foreach (CreditcardType::$creditcardTypes as $card){ if (! in_array(strlen($CCNumber),$card[''cardLength''])) { continue; } $prefixes = ''/^(''.implode(''|'',$card[''cardPrefix'']).'')/''; if(preg_match($prefixes,$CCNumber) == 1 ){ $type= $card[''Name'']; break; } } return $type; } } ?>


El número de tarjeta de crédito / débito se conoce como PAN o Número de cuenta principal . Los primeros seis dígitos del PAN se toman del IIN , o Número de identificación del emisor , que pertenece al banco emisor (los IIN se conocían anteriormente como BIN - Números de identificación del banco, por lo que puede ver referencias a esa terminología en algunos documentos). Estos seis dígitos están sujetos a una norma internacional, ISO / IEC 7812 , y pueden utilizarse para determinar el tipo de tarjeta a partir del número.

Desafortunadamente, la base de datos real de ISO / IEC 7812 no está disponible públicamente, sin embargo, hay listas no oficiales, tanto comerciales como gratuitas, incluidas las de Wikipedia .

De todos modos, para detectar el tipo a partir del número, puede usar una expresión regular como las siguientes: Crédito por las expresiones originales

Visa: ^4[0-9]{6,}$ Los números de la tarjeta Visa comienzan con un 4.

MasterCard: ^5[1-5][0-9]{5,}|222[1-9][0-9]{3,}|22[3-9][0-9]{4,}|2[3-6][0-9]{5,}|27[01][0-9]{4,}|2720[0-9]{3,}$ Antes de 2016, los números de MasterCard comienzan con el los números del 51 al 55, pero esto solo detectará las tarjetas de crédito MasterCard ; hay otras tarjetas emitidas utilizando el sistema MasterCard que no entran en este rango de IIN. En 2016, agregarán números en el rango (222100-272099).

American Express: ^3[47][0-9]{5,}$ Los números de las tarjetas de American Express comienzan con 34 o 37.

Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$ números de las tarjetas de Diners Club comienzan con 300 hasta 305, 36 o 38. Hay Tarjetas de Diners Club que comienzan con 5 y tienen 16 dígitos. Estas son una empresa conjunta entre Diners Club y MasterCard, y deben procesarse como una MasterCard.

Descubrir: ^6(?:011|5[0-9]{2})[0-9]{3,}$ Los números de las tarjetas de Discover comienzan con 6011 o 65.

JCB: ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$ tarjetas de JCB comienzan con 2131, 1800 o 35.

Desafortunadamente, hay varios tipos de tarjetas procesadas con el sistema MasterCard que no viven en el rango IIN de MasterCard (números que comienzan con 51 ... 55); el caso más importante es el de las tarjetas Maestro, muchas de las cuales han sido emitidas desde los rangos IIN de otros bancos y, por lo tanto, están ubicadas en todo el espacio numérico. Como resultado, puede ser mejor asumir que cualquier tarjeta que no sea de otro tipo que acepte debe ser una MasterCard .

Importante : los números de tarjeta varían en longitud; por ejemplo, Visa ha emitido en el pasado tarjetas con PAN de 13 dígitos y tarjetas con PAN de 16 dígitos. La documentación de Visa actualmente indica que puede emitir o puede haber emitido números con entre 12 y 19 dígitos. Por lo tanto, no debe verificar la longitud del número de tarjeta, excepto para verificar que tenga al menos 7 dígitos (para un IIN completo más un dígito de verificación, que debe coincidir con el valor predicho por el algoritmo de Luhn ).

Una sugerencia más: antes de procesar un PAN de tarjetahabiente, elimine los espacios en blanco y los caracteres de puntuación de la entrada . ¿Por qué? Debido a que generalmente es mucho más fácil ingresar los dígitos en grupos, de manera similar a como se muestran en el frente de una tarjeta de crédito real, es decir,

4444 4444 4444 4444

Es mucho más fácil ingresar correctamente que

4444444444444444

Realmente no hay ningún beneficio en castigar al usuario porque han ingresado caracteres que no esperas aquí.

Esto también implica asegurarse de que los campos de entrada tengan espacio para al menos 24 caracteres, de lo contrario, los usuarios que ingresen espacios se quedarán sin espacio. Le recomiendo que amplíe el campo lo suficiente como para mostrar 32 caracteres y permita hasta 64; Eso le da mucho espacio para la expansión.

Aquí hay una imagen que da un poco más de perspicacia:

ACTUALIZACIÓN (2014): el método de suma de comprobación ya no parece ser una forma válida de verificar la autenticidad de una tarjeta como se indica en los comentarios de esta respuesta.

ACTUALIZACIÓN (2016): Mastercard implementará nuevos rangos de BIN a partir del pago Ach .


En Reconocimiento de rango de tarjeta (CRR), un inconveniente con los algoritmos que usan una serie de expresiones regulares u otros rangos de código rígido, es que los BIN / IIN cambian con el tiempo en mi experiencia. El co-branding de tarjetas es una complicación continua. Es posible que los diferentes adquirentes / comerciantes de tarjetas necesiten que usted trate la misma tarjeta de manera diferente, dependiendo, por ejemplo, de la geolocalización.

Además, en los últimos años con, por ejemplo, las tarjetas UnionPay en circulación más amplia, los modelos existentes no hacen frente a nuevos rangos que a veces se intercalan con rangos más amplios que reemplazan.
Conocer la geografía que su sistema necesita cubrir puede ayudar, ya que algunos rangos están restringidos para su uso en países específicos. Por ejemplo, los rangos 62 incluyen algunos sub-rangos AAA en los EE. UU., Pero si su base de comerciantes está fuera de los EE. UU., Es posible que pueda tratar a los 62 como UnionPay.
También se le puede pedir que trate una tarjeta de manera diferente según la ubicación del comerciante. Por ejemplo, para tratar ciertas tarjetas del Reino Unido como débito nacional, pero como crédito internacional.

Hay un conjunto muy útil de reglas mantenidas por uno de los principales bancos adquirentes. Por ejemplo, https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf y https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (Enlaces válidos a partir de junio de 2017, gracias al usuario que proporcionó un enlace a la referencia actualizada). Pero tenga en cuenta la advertencia de que, si bien estas reglas de CRR pueden representar el universo de emisión de tarjetas tal como se aplica a los comerciantes adquiridos por esa entidad, no incluye, por ejemplo, rangos identificados como CUP / UPI.

Estos comentarios se aplican a los escenarios de banda magnética (MagStripe) o PKE (Pan Key Entry). La situación es diferente otra vez en el mundo ICC / EMV.

Actualización: Otras respuestas en esta página (y también la página de WikiPedia vinculada) tienen JCB como siempre 16 de largo. Sin embargo, en mi empresa contamos con un equipo dedicado de ingenieros que certifican nuestros dispositivos y software POS a través de múltiples bancos y geografías de adquisición. El paquete de tarjetas de certificación más reciente que tiene este equipo de JCB tuvo un caso de aprobación para un PAN de 19 largos.


En javascript:

function detectCardType(number) { var re = { electron: /^(4026|417500|4405|4508|4844|4913|4917)/d+$/, maestro: /^(5018|5020|5038|5612|5893|6304|6759|6761|6762|6763|0604|6390)/d+$/, dankort: /^(5019)/d+$/, interpayment: /^(636)/d+$/, unionpay: /^(62|88)/d+$/, visa: /^4[0-9]{12}(?:[0-9]{3})?$/, mastercard: /^5[1-5][0-9]{14}$/, amex: /^3[47][0-9]{13}$/, diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/, discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/, jcb: /^(?:2131|1800|35/d{3})/d{11}$/ } for(var key in re) { if(re[key].test(number)) { return key } } }

Prueba de unidad:

describe(''CreditCard'', function() { describe(''#detectCardType'', function() { var cards = { ''8800000000000000'': ''UNIONPAY'', ''4026000000000000'': ''ELECTRON'', ''4175000000000000'': ''ELECTRON'', ''4405000000000000'': ''ELECTRON'', ''4508000000000000'': ''ELECTRON'', ''4844000000000000'': ''ELECTRON'', ''4913000000000000'': ''ELECTRON'', ''4917000000000000'': ''ELECTRON'', ''5019000000000000'': ''DANKORT'', ''5018000000000000'': ''MAESTRO'', ''5020000000000000'': ''MAESTRO'', ''5038000000000000'': ''MAESTRO'', ''5612000000000000'': ''MAESTRO'', ''5893000000000000'': ''MAESTRO'', ''6304000000000000'': ''MAESTRO'', ''6759000000000000'': ''MAESTRO'', ''6761000000000000'': ''MAESTRO'', ''6762000000000000'': ''MAESTRO'', ''6763000000000000'': ''MAESTRO'', ''0604000000000000'': ''MAESTRO'', ''6390000000000000'': ''MAESTRO'', ''3528000000000000'': ''JCB'', ''3589000000000000'': ''JCB'', ''3529000000000000'': ''JCB'', ''6360000000000000'': ''INTERPAYMENT'', ''4916338506082832'': ''VISA'', ''4556015886206505'': ''VISA'', ''4539048040151731'': ''VISA'', ''4024007198964305'': ''VISA'', ''4716175187624512'': ''VISA'', ''5280934283171080'': ''MASTERCARD'', ''5456060454627409'': ''MASTERCARD'', ''5331113404316994'': ''MASTERCARD'', ''5259474113320034'': ''MASTERCARD'', ''5442179619690834'': ''MASTERCARD'', ''6011894492395579'': ''DISCOVER'', ''6011388644154687'': ''DISCOVER'', ''6011880085013612'': ''DISCOVER'', ''6011652795433988'': ''DISCOVER'', ''6011375973328347'': ''DISCOVER'', ''345936346788903'': ''AMEX'', ''377669501013152'': ''AMEX'', ''373083634595479'': ''AMEX'', ''370710819865268'': ''AMEX'', ''371095063560404'': ''AMEX'' }; Object.keys(cards).forEach(function(number) { it(''should detect card '' + number + '' as '' + cards[number], function() { Basket.detectCardType(number).should.equal(cards[number]); }); }); }); });


Hace poco necesitaba esa funcionalidad, estaba transfiriendo el validador de la tarjeta de crédito Zend Framework a Ruby. ruby gem: https://github.com/Fivell/credit_card_validations zend framework: https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php

Ambos utilizan rangos INN para detectar el tipo. Aquí puedes leer sobre INN

De acuerdo con esto, puede detectar una tarjeta de crédito alternativamente (sin expresiones regulares, pero declarando algunas reglas sobre los prefijos y la posible longitud)

Así que tenemos las siguientes reglas para las tarjetas más usadas.

######## most used brands ######### visa: [ {length: [13, 16], prefixes: [''4'']} ], mastercard: [ {length: [16], prefixes: [''51'', ''52'', ''53'', ''54'', ''55'']} ], amex: [ {length: [15], prefixes: [''34'', ''37'']} ], ######## other brands ######## diners: [ {length: [14], prefixes: [''300'', ''301'', ''302'', ''303'', ''304'', ''305'', ''36'', ''38'']}, ], #There are Diners Club (North America) cards that begin with 5. These are a joint venture between Diners Club and MasterCard, and are processed like a MasterCard # will be removed in next major version diners_us: [ {length: [16], prefixes: [''54'', ''55'']} ], discover: [ {length: [16], prefixes: [''6011'', ''644'', ''645'', ''646'', ''647'', ''648'', ''649'', ''65'']} ], jcb: [ {length: [16], prefixes: [''3528'', ''3529'', ''353'', ''354'', ''355'', ''356'', ''357'', ''358'', ''1800'', ''2131'']} ], laser: [ {length: [16, 17, 18, 19], prefixes: [''6304'', ''6706'', ''6771'']} ], solo: [ {length: [16, 18, 19], prefixes: [''6334'', ''6767'']} ], switch: [ {length: [16, 18, 19], prefixes: [''633110'', ''633312'', ''633304'', ''633303'', ''633301'', ''633300'']} ], maestro: [ {length: [12, 13, 14, 15, 16, 17, 18, 19], prefixes: [''5010'', ''5011'', ''5012'', ''5013'', ''5014'', ''5015'', ''5016'', ''5017'', ''5018'', ''502'', ''503'', ''504'', ''505'', ''506'', ''507'', ''508'', ''6012'', ''6013'', ''6014'', ''6015'', ''6016'', ''6017'', ''6018'', ''6019'', ''602'', ''603'', ''604'', ''605'', ''6060'', ''677'', ''675'', ''674'', ''673'', ''672'', ''671'', ''670'', ''6760'', ''6761'', ''6762'', ''6763'', ''6764'', ''6765'', ''6766'', ''6768'', ''6769'']} ], # Luhn validation are skipped for union pay cards because they have unknown generation algoritm unionpay: [ {length: [16, 17, 18, 19], prefixes: [''622'', ''624'', ''625'', ''626'', ''628''], skip_luhn: true} ], dankrot: [ {length: [16], prefixes: [''5019'']} ], rupay: [ {length: [16], prefixes: [''6061'', ''6062'', ''6063'', ''6064'', ''6065'', ''6066'', ''6067'', ''6068'', ''6069'', ''607'', ''608''], skip_luhn: true} ] }

Luego, al buscar el prefijo y comparar la longitud, puede detectar la marca de la tarjeta de crédito. Además, no se olvide de luhn algoritm (se encuentra aquí http://en.wikipedia.org/wiki/Luhn ).


La respuesta de Anatoliy en PHP:

public static function detectCardType($num) { $re = array( "visa" => "/^4[0-9]{12}(?:[0-9]{3})?$/", "mastercard" => "/^5[1-5][0-9]{14}$/", "amex" => "/^3[47][0-9]{13}$/", "discover" => "/^6(?:011|5[0-9]{2})[0-9]{12}$/", ); if (preg_match($re[''visa''],$num)) { return ''visa''; } else if (preg_match($re[''mastercard''],$num)) { return ''mastercard''; } else if (preg_match($re[''amex''],$num)) { return ''amex''; } else if (preg_match($re[''discover''],$num)) { return ''discover''; } else { return false; } }


Los primeros números de la tarjeta de crédito se pueden usar para aproximar al vendedor:

  • Visa: 49,44 o 47
  • Visa electron: 42, 45, 48, 49
  • MasterCard: 51
  • Amex: 34
  • Cenas: 30, 36, 38
  • JCB: 35

Mi solución con jQuery:

function detectCreditCardType() { var type = new Array; type[1] = ''^4[0-9]{12}(?:[0-9]{3})?$''; // visa type[2] = ''^5[1-5][0-9]{14}$''; // mastercard type[3] = ''^6(?:011|5[0-9]{2})[0-9]{12}$''; // discover type[4] = ''^3[47][0-9]{13}$''; // amex var ccnum = $(''.creditcard'').val().replace(/[^/d.]/g, ''''); var returntype = 0; $.each(type, function(idx, re) { var regex = new RegExp(re); if(regex.test(ccnum) && idx>0) { returntype = idx; } }); return returntype; }

En caso de que se devuelva 0, el tipo de tarjeta de crédito no se detecta.

La clase de "tarjeta de crédito" se debe agregar al campo de entrada de la tarjeta de crédito.


Mira esto:

http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CC70060A01B

function isValidCreditCard(type, ccnum) { /* Visa: length 16, prefix 4, dashes optional. Mastercard: length 16, prefix 51-55, dashes optional. Discover: length 16, prefix 6011, dashes optional. American Express: length 15, prefix 34 or 37. Diners: length 14, prefix 30, 36, or 38. */ var re = new Regex({ "visa": "/^4/d{3}-?/d{4}-?/d{4}-?/d", "mc": "/^5[1-5]/d{2}-?/d{4}-?/d{4}-?/d{4}$/", "disc": "/^6011-?/d{4}-?/d{4}-?/d{4}$/", "amex": "/^3[47]/d{13}$/", "diners": "/^3[068]/d{12}$/"}[type.toLowerCase()]) if (!re.test(ccnum)) return false; // Remove all dashes for the checksum checks to eliminate negative numbers ccnum = ccnum.split("-").join(""); // Checksum ("Mod 10") // Add even digits in even length strings or odd digits in odd length strings. var checksum = 0; for (var 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 (var 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); } } if ((checksum % 10) == 0) return true; else return false; }


No intente detectar el tipo de tarjeta de crédito como parte del procesamiento de un pago. Usted se arriesga a rechazar transacciones válidas.

Si necesita proporcionar información a su procesador de pagos (por ejemplo, el objeto de la tarjeta de crédito de PayPal requiere el nombre del tipo de tarjeta ), entonces adivínelo a partir de la menor información disponible, por ejemplo

$credit_card[''pan''] = preg_replace(''/[^0-9]/'', '''', $credit_card[''pan'']); $inn = (int) mb_substr($credit_card[''pan''], 0, 2); // @see http://en.wikipedia.org/wiki/List_of_Bank_Identification_Numbers#Overview if ($inn >= 40 && $inn <= 49) { $type = ''visa''; } else if ($inn >= 51 && $inn <= 55) { $type = ''mastercard''; } else if ($inn >= 60 && $inn <= 65) { $type = ''discover''; } else if ($inn >= 34 && $inn <= 37) { $type = ''amex''; } else { throw new /UnexpectedValueException(''Unsupported card type.''); }

Esta implementación (utilizando solo los dos primeros dígitos) es suficiente para identificar todos los esquemas de tarjetas principales (y, en el caso de PayPal, todos los compatibles). De hecho, es posible que desee omitir la excepción por completo y predeterminar el tipo de tarjeta más popular. Permita que la pasarela de pago / procesador le informe si hay un error de validación en respuesta a su solicitud.

La realidad es que a su pasarela de pago no le importa el valor que proporcione .


Versión compacta de javascript

var getCardType = function (number) { var cards = { visa: /^4[0-9]{12}(?:[0-9]{3})?$/, mastercard: /^5[1-5][0-9]{14}$/, amex: /^3[47][0-9]{13}$/, diners: /^3(?:0[0-5]|[68][0-9])[0-9]{11}$/, discover: /^6(?:011|5[0-9]{2})[0-9]{12}$/, jcb: /^(?:2131|1800|35/d{3})/d{11}$/ }; for (var card in cards) { if (cards[card].test(number)) { return card; } } };


Actualizado: 15 de junio de 2016 (como una solución definitiva actualmente)

Tenga en cuenta que incluso doy mi voto para que el que está más votado, pero para dejar en claro que estas son las expresiones regulares realmente funciona, lo probé con miles de códigos BIN reales. ¡Lo más importante es usar cadenas de inicio (^) de lo contrario, dará resultados falsos en el mundo real!

JCB ^(?:2131|1800|35)[0-9]{0,}$ Comenzar con: 2131, 1800, 35 (3528-3589)

American Express ^3[47][0-9]{0,}$ Comenzar con: 34, 37

Diners Club ^3(?:0[0-59]{1}|[689])[0-9]{0,}$ Empieza con: 300-305, 309, 36, 38-39

Visa ^4[0-9]{0,}$ Inicio con: 4

MasterCard ^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$ Comience con : 2221-2720, 51-55

Maestro ^(5[06789]|6)[0-9]{0,}$ Maestro siempre creciendo en el rango: 60-69 , comenzó con / no otra cosa, pero comenzar con 5 debe codificarse como mastercard de todos modos. Las tarjetas Maestro se deben detectar al final del código porque algunas otras tienen un rango de 60-69. Por favor mira el código.

Descubra ^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$ Descubrir es bastante difícil de codificar, comienza con: 6011, 622126-622925, 644-649, 65

En javascript utilizo esta función. Esto es bueno cuando lo asignas a un evento onkeyup y da resultado tan pronto como sea posible.

function cc_brand_id(cur_val) { // the regular expressions check for possible matches as you type, hence the OR operators based on the number of chars // regexp string length {0} provided for soonest detection of beginning of the card numbers this way it could be used for BIN CODE detection also //JCB jcb_regex = new RegExp(''^(?:2131|1800|35)[0-9]{0,}$''); //2131, 1800, 35 (3528-3589) // American Express amex_regex = new RegExp(''^3[47][0-9]{0,}$''); //34, 37 // Diners Club diners_regex = new RegExp(''^3(?:0[0-59]{1}|[689])[0-9]{0,}$''); //300-305, 309, 36, 38-39 // Visa visa_regex = new RegExp(''^4[0-9]{0,}$''); //4 // MasterCard mastercard_regex = new RegExp(''^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$''); //2221-2720, 51-55 maestro_regex = new RegExp(''^(5[06789]|6)[0-9]{0,}$''); //always growing in the range: 60-69, started with / not something else, but starting 5 must be encoded as mastercard anyway //Discover discover_regex = new RegExp(''^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$''); ////6011, 622126-622925, 644-649, 65 // get rid of anything but numbers cur_val = cur_val.replace(//D/g, ''''); // checks per each, as their could be multiple hits //fix: ordering matter in detection, otherwise can give false results in rare cases var sel_brand = "unknown"; if (cur_val.match(jcb_regex)) { sel_brand = "jcb"; } else if (cur_val.match(amex_regex)) { sel_brand = "amex"; } else if (cur_val.match(diners_regex)) { sel_brand = "diners_club"; } else if (cur_val.match(visa_regex)) { sel_brand = "visa"; } else if (cur_val.match(mastercard_regex)) { sel_brand = "mastercard"; } else if (cur_val.match(discover_regex)) { sel_brand = "discover"; } else if (cur_val.match(maestro_regex)) { if (cur_val[0] == ''5'') { //started 5 must be mastercard sel_brand = "mastercard"; } else { sel_brand = "maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end } } return sel_brand; }

Aquí puedes jugar con él:

http://jsfiddle.net/upN3L/69/

Para PHP, use esta función, esto también detecta algunas tarjetas sub VISA / MC:

/** * Obtain a brand constant from a PAN * * @param type $pan Credit card number * @param type $include_sub_types Include detection of sub visa brands * @return string */ public static function getCardBrand($pan, $include_sub_types = false) { //maximum length is not fixed now, there are growing number of CCs has more numbers in length, limiting can give false negatives atm //these regexps accept not whole cc numbers too //visa $visa_regex = "/^4[0-9]{0,}$/"; $vpreca_regex = "/^428485[0-9]{0,}$/"; $postepay_regex = "/^(402360|402361|403035|417631|529948){0,}$/"; $cartasi_regex = "/^(432917|432930|453998)[0-9]{0,}$/"; $entropay_regex = "/^(406742|410162|431380|459061|533844|522093)[0-9]{0,}$/"; $o2money_regex = "/^(422793|475743)[0-9]{0,}$/"; // MasterCard $mastercard_regex = "/^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$/"; $maestro_regex = "/^(5[06789]|6)[0-9]{0,}$/"; $kukuruza_regex = "/^525477[0-9]{0,}$/"; $yunacard_regex = "/^541275[0-9]{0,}$/"; // American Express $amex_regex = "/^3[47][0-9]{0,}$/"; // Diners Club $diners_regex = "/^3(?:0[0-59]{1}|[689])[0-9]{0,}$/"; //Discover $discover_regex = "/^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$/"; //JCB $jcb_regex = "/^(?:2131|1800|35)[0-9]{0,}$/"; //ordering matter in detection, otherwise can give false results in rare cases if (preg_match($jcb_regex, $pan)) { return "jcb"; } if (preg_match($amex_regex, $pan)) { return "amex"; } if (preg_match($diners_regex, $pan)) { return "diners_club"; } //sub visa/mastercard cards if ($include_sub_types) { if (preg_match($vpreca_regex, $pan)) { return "v-preca"; } if (preg_match($postepay_regex, $pan)) { return "postepay"; } if (preg_match($cartasi_regex, $pan)) { return "cartasi"; } if (preg_match($entropay_regex, $pan)) { return "entropay"; } if (preg_match($o2money_regex, $pan)) { return "o2money"; } if (preg_match($kukuruza_regex, $pan)) { return "kukuruza"; } if (preg_match($yunacard_regex, $pan)) { return "yunacard"; } } if (preg_match($visa_regex, $pan)) { return "visa"; } if (preg_match($mastercard_regex, $pan)) { return "mastercard"; } if (preg_match($discover_regex, $pan)) { return "discover"; } if (preg_match($maestro_regex, $pan)) { if ($pan[0] == ''5'') {//started 5 must be mastercard return "mastercard"; } return "maestro"; //maestro is all 60-69 which is not something else, thats why this condition in the end } return "unknown"; //unknown for this system }


En swift puede crear una enumeración para detectar el tipo de tarjeta de crédito.

enum CreditCardType: Int { // Enum which encapsulates different card types and method to find the type of card. case Visa case Master case Amex case Discover func validationRegex() -> String { var regex = "" switch self { case .Visa: regex = "^4[0-9]{6,}$" case .Master: regex = "^5[1-5][0-9]{5,}$" case .Amex: regex = "^3[47][0-9]{13}$" case .Discover: regex = "^6(?:011|5[0-9]{2})[0-9]{12}$" } return regex } func validate(cardNumber: String) -> Bool { let predicate = NSPredicate(format: "SELF MATCHES %@", validationRegex()) return predicate.evaluateWithObject(cardNumber) } // Method returns the credit card type for given card number static func cardTypeForCreditCardNumber(cardNumber: String) -> CreditCardType? { var creditCardType: CreditCardType? var index = 0 while let cardType = CreditCardType(rawValue: index) { if cardType.validate(cardNumber) { creditCardType = cardType break } else { index++ } } return creditCardType } }

Llame al método CreditCardType.cardTypeForCreditCardNumber ("# número de tarjeta") que devuelve el valor enumático de CreditCardType.


Intenta esto. Para rápido.

func checkCardValidation(number : String) -> Bool { let reversedInts = number.characters.reversed().map { Int(String($0)) } return reversedInts.enumerated().reduce(0, {(sum, val) in let odd = val.offset % 2 == 1 return sum + (odd ? (val.element! == 9 ? 9 : (val.element! * 2) % 9) : val.element!) }) % 10 == 0 }

Utilizar.

if (self.checkCardValidation(number: "yourNumber") == true) { print("Card Number valid") }else{ print("Card Number not valid") }


Sólo una pequeña cuchara de alimentación:

$("#CreditCardNumber").focusout(function () { var regVisa = /^4[0-9]{12}(?:[0-9]{3})?$/; var regMasterCard = /^5[1-5][0-9]{14}$/; var regAmex = /^3[47][0-9]{13}$/; var regDiscover = /^6(?:011|5[0-9]{2})[0-9]{12}$/; if (regVisa.test($(this).val())) { $("#CCImage").html("<img height=''40px'' src=''@Url.Content("~/images/visa.png")''>"); } else if (regMasterCard.test($(this).val())) { $("#CCImage").html("<img height=''40px'' src=''@Url.Content("~/images/mastercard.png")''>"); } else if (regAmex.test($(this).val())) { $("#CCImage").html("<img height=''40px'' src=''@Url.Content("~/images/amex.png")''>"); } else if (regDiscover.test($(this).val())) { $("#CCImage").html("<img height=''40px'' src=''@Url.Content("~/images/discover.png")''>"); } else { $("#CCImage").html("NA"); } });


Busqué un poco por formato de tarjeta de crédito y formato de número de teléfono. Encontré muchos buenos consejos, pero nada realmente se adaptó a mis deseos exactos, así que creé quercusv.github.io/smartForm . Lo usas así:

var sf = smartForm.formatCC(myInputString); var cardType = sf.cardType;


Este es un ejemplo de algunas funciones booleanas escritas en Python que devuelven Truesi la tarjeta se detecta según el nombre de la función.

def is_american_express(cc_number): """Checks if the card is an american express. If us billing address country code, & is_amex, use vpos https://en.wikipedia.org/wiki/Bank_card_number#cite_note-GenCardFeatures-3 :param cc_number: unicode card number """ return bool(re.match(r''^3[47][0-9]{13}$'', cc_number)) def is_visa(cc_number): """Checks if the card is a visa, begins with 4 and 12 or 15 additional digits. :param cc_number: unicode card number """ # Standard Visa is 13 or 16, debit can be 19 if bool(re.match(r''^4'', cc_number)) and len(cc_number) in [13, 16, 19]: return True return False def is_mastercard(cc_number): """Checks if the card is a mastercard. Begins with 51-55 or 2221-2720 and 16 in length. :param cc_number: unicode card number """ if len(cc_number) == 16 and cc_number.isdigit(): # Check digit, before cast to int return bool(re.match(r''^5[1-5]'', cc_number)) or int(cc_number[:4]) in range(2221, 2721) return False def is_discover(cc_number): """Checks if the card is discover, re would be too hard to maintain. Not a supported card. :param cc_number: unicode card number """ if len(cc_number) == 16: try: # return bool(cc_number[:4] == ''6011'' or cc_number[:2] == ''65'' or cc_number[:6] in range(622126, 622926)) return bool(cc_number[:4] == ''6011'' or cc_number[:2] == ''65'' or 622126 <= int(cc_number[:6]) <= 622925) except ValueError: return False return False def is_jcb(cc_number): """Checks if the card is a jcb. Not a supported card. :param cc_number: unicode card number """ # return bool(re.match(r''^(?:2131|1800|35/d{3})/d{11}$'', cc_number)) # wikipedia return bool(re.match(r''^35(2[89]|[3-8][0-9])[0-9]{12}$'', cc_number)) # PawelDecowski def is_diners_club(cc_number): """Checks if the card is a diners club. Not a supported card. :param cc_number: unicode card number """ return bool(re.match(r''^3(?:0[0-6]|[68][0-9])[0-9]{11}$'', cc_number)) # 0-5 = carte blance, 6 = international def is_laser(cc_number): """Checks if the card is laser. Not a supported card. :param cc_number: unicode card number """ return bool(re.match(r''^(6304|670[69]|6771)'', cc_number)) def is_maestro(cc_number): """Checks if the card is maestro. Not a supported card. :param cc_number: unicode card number """ possible_lengths = [12, 13, 14, 15, 16, 17, 18, 19] return bool(re.match(r''^(50|5[6-9]|6[0-9])'', cc_number)) and len(cc_number) in possible_lengths # Child cards def is_visa_electron(cc_number): """Child of visa. Checks if the card is a visa electron. Not a supported card. :param cc_number: unicode card number """ return bool(re.match(r''^(4026|417500|4508|4844|491(3|7))'', cc_number)) and len(cc_number) == 16 def is_total_rewards_visa(cc_number): """Child of visa. Checks if the card is a Total Rewards Visa. Not a supported card. :param cc_number: unicode card number """ return bool(re.match(r''^41277777[0-9]{8}$'', cc_number)) def is_diners_club_carte_blanche(cc_number): """Child card of diners. Checks if the card is a diners club carte blance. Not a supported card. :param cc_number: unicode card number """ return bool(re.match(r''^30[0-5][0-9]{11}$'', cc_number)) # github PawelDecowski, jquery-creditcardvalidator def is_diners_club_carte_international(cc_number): """Child card of diners. Checks if the card is a diners club international. Not a supported card. :param cc_number: unicode card number """ return bool(re.match(r''^36[0-9]{12}$'', cc_number)) # jquery-creditcardvalidator


Las reglas de expresión regular que coinciden con los respectivos proveedores de tarjetas :

  • (4/d{12}(?:/d{3})?) para la visa.
  • (5[1-5]/d{14}) para MasterCard.
  • (3[47]/d{13}) para AMEX.
  • ((?:5020|5038|6304|6579|6761)/d{12}(?:/d/d)?) para el maestro.
  • (3(?:0[0-5]|[68][0-9])[0-9]{11}) para los comensales del club.
  • (6(?:011|5[0-9]{2})[0-9]{12}) para descubrir.
  • (35[2-8][89]/d/d/d{10}) para JCB.

Stripe ha proporcionado esta fantástica biblioteca javascript para la detección de esquemas de tarjetas. Permítame agregar algunos fragmentos de código y mostrarle cómo usarlo.

En primer lugar incluyelo en su página web como

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.2.3/jquery.payment.js " ></script>

En segundo lugar, utilice la función cardType para detectar el esquema de la tarjeta.

$(document).ready(function() { var type = $.payment.cardType("4242 4242 4242 4242"); //test card number console.log(type); });

Aquí están los enlaces de referencia para más ejemplos y demostraciones.

  1. Blog de la raya para jquery.payment.js
  2. Repositorio Github

Swift 2.1 Versión de la respuesta de Usman Y. Use una declaración de impresión para verificar, así que llame por algún valor de cadena

print(self.validateCardType(self.creditCardField.text!)) func validateCardType(testCard: String) -> String { let regVisa = "^4[0-9]{12}(?:[0-9]{3})?$" let regMaster = "^5[1-5][0-9]{14}$" let regExpress = "^3[47][0-9]{13}$" let regDiners = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$" let regDiscover = "^6(?:011|5[0-9]{2})[0-9]{12}$" let regJCB = "^(?:2131|1800|35//d{3})//d{11}$" let regVisaTest = NSPredicate(format: "SELF MATCHES %@", regVisa) let regMasterTest = NSPredicate(format: "SELF MATCHES %@", regMaster) let regExpressTest = NSPredicate(format: "SELF MATCHES %@", regExpress) let regDinersTest = NSPredicate(format: "SELF MATCHES %@", regDiners) let regDiscoverTest = NSPredicate(format: "SELF MATCHES %@", regDiscover) let regJCBTest = NSPredicate(format: "SELF MATCHES %@", regJCB) if regVisaTest.evaluateWithObject(testCard){ return "Visa" } else if regMasterTest.evaluateWithObject(testCard){ return "MasterCard" } else if regExpressTest.evaluateWithObject(testCard){ return "American Express" } else if regDinersTest.evaluateWithObject(testCard){ return "Diners Club" } else if regDiscoverTest.evaluateWithObject(testCard){ return "Discover" } else if regJCBTest.evaluateWithObject(testCard){ return "JCB" } return "" }


Uso https://github.com/bendrucker/creditcards-types/ para detectar el tipo de tarjeta de crédito del número. Un problema que encontré es descubrir el número de prueba 6011 1111 1111 1117

De https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/ podemos ver que es un número descubierto porque comienza en 6011. Pero el resultado que obtengo de los tipos de tarjetas de crédito es "Maestro". Abrí el tema al autor. Me respondió muy pronto y proporcionó este documento pdf https://www.discovernetwork.com/downloads/IPP_VAR_Compliance.pdf Desde el documento podemos ver claramente que 6011 1111 1111 1117 no está dentro del rango de tarjeta de crédito Discover.


public string GetCreditCardType(string CreditCardNumber) { Regex regVisa = new Regex("^4[0-9]{12}(?:[0-9]{3})?$"); Regex regMaster = new Regex("^5[1-5][0-9]{14}$"); Regex regExpress = new Regex("^3[47][0-9]{13}$"); Regex regDiners = new Regex("^3(?:0[0-5]|[68][0-9])[0-9]{11}$"); Regex regDiscover = new Regex("^6(?:011|5[0-9]{2})[0-9]{12}$"); Regex regJCB= new Regex("^(?:2131|1800|35//d{3})//d{11}$"); if(regVisa.IsMatch(CreditCardNumber)) return "VISA"; else if (regMaster.IsMatch(CreditCardNumber)) return "MASTER"; else if (regExpress.IsMatch(CreditCardNumber)) return "AEXPRESS"; else if (regDiners.IsMatch(CreditCardNumber)) return "DINERS"; else if (regDiscover.IsMatch(CreditCardNumber)) return "DISCOVERS"; else if (regJCB.IsMatch(CreditCardNumber)) return "JCB"; else return "invalid"; }

Aquí está la función para verificar el tipo de tarjeta de crédito usando Regex, c #


// abobjects.com, parvez ahmad ab bulk mailer use below script function isValidCreditCard2(type, ccnum) { if (type == "Visa") { // Visa: length 16, prefix 4, dashes optional. var re = /^4/d{3}?/d{4}?/d{4}?/d{4}$/; } else if (type == "MasterCard") { // Mastercard: length 16, prefix 51-55, dashes optional. var re = /^5[1-5]/d{2}?/d{4}?/d{4}?/d{4}$/; } else if (type == "Discover") { // Discover: length 16, prefix 6011, dashes optional. var re = /^6011?/d{4}?/d{4}?/d{4}$/; } else if (type == "AmEx") { // American Express: length 15, prefix 34 or 37. var re = /^3[4,7]/d{13}$/; } else if (type == "Diners") { // Diners: length 14, prefix 30, 36, or 38. var re = /^3[0,6,8]/d{12}$/; } if (!re.test(ccnum)) return false; return true; /* // Remove all dashes for the checksum checks to eliminate negative numbers ccnum = ccnum.split("-").join(""); // Checksum ("Mod 10") // Add even digits in even length strings or odd digits in odd length strings. var checksum = 0; for (var 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 (var 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); } } if ((checksum % 10) == 0) return true; else return false; */ } jQuery.validator.addMethod("isValidCreditCard", function(postalcode, element) { return isValidCreditCard2($("#cardType").val(), $("#cardNum").val()); }, "<br>credit card is invalid"); Type</td> <td class="text">&nbsp; <form:select path="cardType" cssclass="fields" style="border: 1px solid #D5D5D5;padding: 0px 0px 0px 0px;width: 130px;height: 22px;"> <option value="SELECT">SELECT</option> <option value="MasterCard">Mastercard</option> <option value="Visa">Visa</option> <option value="AmEx">American Express</option> <option value="Discover">Discover</option> </form:select> <font color="#FF0000">*</font> $("#signupForm").validate({ rules:{ companyName:{required: true}, address1:{required: true}, city:{required: true}, state:{required: true}, zip:{required: true}, country:{required: true}, chkAgree:{required: true}, confPassword:{required: true}, lastName:{required: true}, firstName:{required: true}, ccAddress1:{required: true}, ccZip:{ postalcode : true }, phone:{required: true}, email:{ required: true, email: true }, userName:{ required: true, minlength: 6 }, password:{ required: true, minlength: 6 }, cardNum:{ isValidCreditCard : true },


follow Luhn’s algorithm private boolean validateCreditCardNumber(String str) { int[] ints = new int[str.length()]; for (int i = 0; i < str.length(); i++) { ints[i] = Integer.parseInt(str.substring(i, i + 1)); } for (int i = ints.length - 2; i >= 0; i = i - 2) { int j = ints[i]; j = j * 2; if (j > 9) { j = j % 10 + 1; } ints[i] = j; } int sum = 0; for (int i = 0; i < ints.length; i++) { sum += ints[i]; } if (sum % 10 == 0) { return true; } else { return false; } } then call this method Edittext mCreditCardNumberEt; mCreditCardNumberEt.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { int cardcount= s.toString().length(); if(cardcount>=16) { boolean cardnumbervalid= validateCreditCardNumber(s.toString()); if(cardnumbervalid) { cardvalidtesting.setText("Valid Card"); cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.green)); } else { cardvalidtesting.setText("Invalid Card"); cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red)); } } else if(cardcount>0 &&cardcount<16) { cardvalidtesting.setText("Invalid Card"); cardvalidtesting.setTextColor(ContextCompat.getColor(context,R.color.red)); } else { cardvalidtesting.setText(""); } } @Override public void afterTextChanged(Editable s) { } });