번호를 기준으로 신용 카드 유형을 감지하는 방법을 찾으려고합니다. 누구든지 이것을 찾을 수있는 결정적이고 확실한 방법을 알고 있습니까?
번호를 기준으로 신용 카드 유형을 감지하는 방법을 찾으려고합니다. 누구든지 이것을 찾을 수있는 결정적이고 확실한 방법을 알고 있습니까?
답변:
신용 / 직불 카드 번호를 PAN 또는 기본 계정 번호라고 합니다. PAN의 처음 6 자리 숫자 는 발급 은행에 속한 IIN 또는 발급자 식별 번호 에서 가져옵니다 ( IIN 은 이전에 BIN (은행 식별 번호)로 알려 졌으므로 일부 문서에서 해당 용어에 대한 참조를 볼 수 있습니다). 이 6 자리 숫자는 국제 표준 ISO / IEC 7812의 적용을받습니다. 번호에서 카드 유형을 결정하는 데 사용할 수 있습니다.
불행히도 실제 ISO / IEC 7812 데이터베이스는 공개적으로 사용할 수 없지만 Wikipedia를 포함하여 상업용 및 무료의 비공식 목록이 있습니다 .
어쨌든 숫자에서 유형을 감지하려면 다음과 같은 정규 표현식을 사용할 수 있습니다. 원래 표현식에 대한 크레딧
비자 : ^4[0-9]{6,}$
비자 카드 번호는 4로 시작합니다.
마스터 카드 : ^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,}$
2016 년 이전에 마스터 카드 번호는 51부터 55까지의 숫자로 시작 하지만 마스터 카드 신용 카드 만 감지합니다 . 이 IIN 범위에 속하지 않는 MasterCard 시스템을 사용하여 발급 된 다른 카드가 있습니다. 2016 년에는 범위 (222100-272099)의 숫자를 추가합니다.
American Express : ^3[47][0-9]{5,}$
American Express 카드 번호는 34 또는 37로 시작합니다.
Diners Club : ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$
Diners Club 카드 번호는 300에서 305, 36 또는 38로 시작합니다. Diners Club 카드는 5로 시작하고 16 자리입니다. Diners Club과 MasterCard의 합작 투자이며 마스터 카드처럼 처리해야합니다.
검색 : ^6(?:011|5[0-9]{2})[0-9]{3,}$
검색 카드 번호는 6011 또는 65로 시작합니다.
JCB : ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$
JCB 카드는 2131, 1800 또는 35로 시작합니다.
불행하게도, 마스터 카드의 IIN 범위에 속하지 않는 마스터 카드 시스템으로 처리 된 여러 종류의 카드가 있습니다 (번호는 51 ~ 55로 시작). 가장 중요한 경우는 다른 은행의 IIN 범위에서 발행 된 Maestro 카드의 경우이며, 숫자 공간 전체에 있습니다. 결과적으로, 귀하가 수락하는 다른 유형이 아닌 카드는 마스터 카드 여야한다고 가정하는 것이 가장 좋습니다 .
중요 : 카드 번호는 길이가 다릅니다. 예를 들어, Visa는 과거에 13 자리 PAN이있는 카드와 16 자리 PAN이있는 카드를 발행했습니다. Visa의 문서는 현재 12 자리에서 19 자리 사이의 숫자를 발행하거나 발행했을 수 있음을 나타냅니다. 따라서 카드 번호의 길이를 확인하지 말고 카드 번호가 7 자리 이상인지 확인하십시오 (완전한 IIN과 하나의 확인 숫자의 경우 Luhn 알고리즘에 의해 예측 된 값과 일치해야 함 ).
추가 힌트 : 카드 소지자 PAN을 처리하기 전에 입력에서 공백 및 문장 부호 문자를 제거하십시오 . 왜? 일반적으로 실제 신용 카드의 앞면에 표시되는 방식과 유사하게 그룹으로 숫자를 입력하는 것이 훨씬 쉽습니다.
4444 4444 4444 4444
보다 정확하게 입력하는 것이 훨씬 쉽습니다
4444444444444444
사용자가 여기에 예상하지 못한 문자를 입력했기 때문에 사용자를 쫓는 데는 아무런 이점이 없습니다.
이것은 또한 입력 필드 에 최소 24자를 위한 공간이 있어야 함을 의미 합니다. 그렇지 않으면 공백을 입력 한 사용자는 공간이 부족합니다. 32자를 표시하고 최대 64자를 허용 할 수 있도록 필드를 넓게 만드는 것이 좋습니다. 확장을위한 충분한 여유 공간을 제공합니다.
약간 더 통찰력을주는 이미지는 다음과 같습니다.
업데이트 (2014) : 체크섬 방법은 더 이상 이 답변에 대한 의견에 언급 된대로 카드의 진위 를 확인하는 유효한 방법으로 보이지 않습니다 .
업데이트 (2016) : 마스터 카드는 Ach Payment 시작하는 새로운 BIN 범위를 구현 합니다.
자바 스크립트에서 :
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
}
}
}
단위 테스트 :
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]);
});
});
});
});
업데이트 : 2016 년 6 월 15 일 (현재 최고의 솔루션)
나는 심지어 하나의 투표권을 포기하지만, 정규 표현식이 실제로 작동한다는 것을 분명히하기 위해 수천 개의 실제 BIN 코드로 테스트했습니다. 가장 중요한 것은 시작 문자열 (^)을 사용하는 것입니다. 그렇지 않으면 실제 세계에서 잘못된 결과를 줄 것입니다!
JCB ^(?:2131|1800|35)[0-9]{0,}$
시작 : 2131, 1800, 35 (3528-3589)
American Express ^3[47][0-9]{0,}$
시작 : 34, 37
Diners Club ^3(?:0[0-59]{1}|[689])[0-9]{0,}$
시작 : 300-305, 309, 36, 38-39
비자 ^4[0-9]{0,}$
시작 : 4
마스터 카드 ^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$
시작 : 2221-2720, 51-55
Maestro ^(5[06789]|6)[0-9]{0,}$
Maestro는 항상 60-69 범위에서 성장하고 있습니다. 다른 것으로 시작되지는 않았지만 5를 시작하면 어쨌든 마스터 카드로 인코딩되어야합니다. 다른 일부는 60-69 범위에 있기 때문에 Maestro 카드는 코드 끝에서 감지해야합니다. 코드를보십시오.
발견 ^(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
에서 자바 스크립트 나는이 기능을 사용합니다. 이것은 onkeyup 이벤트에 할당 할 때 좋으며 가능한 빨리 결과를 제공합니다.
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;
}
여기서 당신은 그것으로 재생할 수 있습니다 :
PHP의 경우이 기능을 사용하면 일부 하위 VISA / MC 카드도 감지됩니다.
/**
* Obtain a brand constant from a PAN
*
* @param string $pan Credit card number
* @param bool $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
}
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";
}
다음은 Regex, c #을 사용하여 신용 카드 유형을 확인하는 기능입니다.
이것 좀 봐:
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;
}
최근에 그러한 기능이 필요했습니다. Zend Framework 신용 카드 검사기를 루비로 포팅했습니다. 루비 젬 : https://github.com/Fivell/credit_card_validations 젠드 프레임 워크 : https://github.com/zendframework/zf2/blob/master/library/Zend/Validator/CreditCard.php
둘 다 유형 감지에 INN 범위를 사용합니다. INN에 대해 읽을 수 있습니다
이에 따르면 신용 카드를 다른 방법으로 감지 할 수 있습니다 (정규 표현식없이 접두사와 가능한 길이에 대한 규칙을 선언하십시오)
가장 많이 사용되는 카드에 대한 다음 규칙이 있습니다.
######## 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}
]
}
그런 다음 접두사를 검색하고 길이를 비교하여 신용 카드 브랜드를 감지 할 수 있습니다. 또한 luhn 알고리즘에 대해서도 잊지 마십시오 ( http://en.wikipedia.org/wiki/Luhn에서 설명 ).
최신 정보
업데이트 된 규칙 목록은 https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml 에서 확인할 수 있습니다.
다음 은 codeproject에 대한 모든 CC 관련 사항 에 대한 완전한 C # 또는 VB 코드입니다 .
이 기사는 몇 년 동안 부정적인 의견이 없었습니다.
소형 자바 스크립트 버전
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;
}
}
};
PHP에서 Anatoliy의 답변 :
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;
}
}
다음은 PHP 클래스 함수가 CCnumber로 CCtype을 반환하는 것입니다.
이 코드는 카드의 유효성을 검사하지 않거나 Luhn 알고리즘을 실행하지 않습니다 . 이 페이지의 표를 기반으로 신용 카드 유형 만 찾으려고 합니다 . 기본적으로 CCnumber 길이와 CCcard 접두사를 사용하여 CCcard 유형을 결정합니다.
<?php
class CreditcardType
{
public static $creditcardTypes = [
[
'Name' => 'American Express',
'cardLength' => [15],
'cardPrefix' => ['34', '37'],
], [
'Name' => 'Maestro',
'cardLength' => [12, 13, 14, 15, 16, 17, 18, 19],
'cardPrefix' => ['5018', '5020', '5038', '6304', '6759', '6761', '6763'],
], [
'Name' => 'Mastercard',
'cardLength' => [16],
'cardPrefix' => ['51', '52', '53', '54', '55'],
], [
'Name' => 'Visa',
'cardLength' => [13, 16],
'cardPrefix' => ['4'],
], [
'Name' => 'JCB',
'cardLength' => [16],
'cardPrefix' => ['3528', '3529', '353', '354', '355', '356', '357', '358'],
], [
'Name' => 'Discover',
'cardLength' => [16],
'cardPrefix' => ['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'],
], [
'Name' => 'Solo',
'cardLength' => [16, 18, 19],
'cardPrefix' => ['6334', '6767'],
], [
'Name' => 'Unionpay',
'cardLength' => [16, 17, 18, 19],
'cardPrefix' => ['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'],
], [
'Name' => 'Diners Club',
'cardLength' => [14],
'cardPrefix' => ['300', '301', '302', '303', '304', '305', '36'],
], [
'Name' => 'Diners Club US',
'cardLength' => [16],
'cardPrefix' => ['54', '55'],
], [
'Name' => 'Diners Club Carte Blanche',
'cardLength' => [14],
'cardPrefix' => ['300', '305'],
], [
'Name' => 'Laser',
'cardLength' => [16, 17, 18, 19],
'cardPrefix' => ['6304', '6706', '6771', '6709'],
],
];
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;
}
}
지불 처리의 일부로 신용 카드 유형을 감지하려고 시도하지 마십시오. 유효한 거래가 거부 될 위험이 있습니다.
결제 처리자에게 정보를 제공해야하는 경우 (예 : PayPal 신용 카드 개체는 카드 유형의 이름을 지정해야 함 ) 사용 가능한 최소 정보 (예 :
$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.');
}
이 구현 (처음 두 자리 만 사용)은 모든 주요 (및 PayPal의 경우 지원되는 모든) 카드 체계를 식별하기에 충분합니다. 실제로 예외를 모두 건너 뛰고 기본적으로 가장 많이 사용되는 카드 유형으로 설정할 수 있습니다. 지불 게이트웨이 / 프로세서가 요청에 대한 응답으로 유효성 검사 오류가 있는지 알려줍니다.
현실은 당신의 지불 게이트웨이 가 당신이 제공하는 가치에 관심이 없다는 것 입니다.
CRR (Card Range Recognition)에서 일련의 정규식 또는 기타 하드 코딩 된 범위를 사용하는 알고리즘의 단점은 BIN / IIN이 내 경험에서 시간이 지남에 따라 변경된다는 것입니다. 카드의 공동 브랜딩은 진행중인 합병증입니다. 다른 카드 취득자 / 상인은 예를 들어 지리적 위치에 따라 동일한 카드를 다르게 취급해야 할 수도 있습니다.
또한, 지난 몇 년간 더 많은 유통량을 가진 UnionPay 카드를 사용하는 기존 모델은 때때로 더 넓은 범위에 인터리브되는 새로운 범위에 대응하지 않습니다.
일부 국가에서는 특정 지역에서만 사용하도록 제한되어 있으므로 시스템에서 다루어야 할 지역을 아는 것이 도움이 될 수 있습니다. 예를 들어, 범위 62에는 미국의 일부 AAA 하위 범위가 포함되지만 판매자 기반이 미국 이외의 지역 인 경우 62를 모두 UnionPay로 취급 할 수 있습니다.
판매자 위치에 따라 카드를 다르게 취급하라는 요청을받을 수도 있습니다. 예를 들어 특정 영국 카드는 국내에서 직불로 취급하지만 국제적으로 신용으로 취급합니다.
하나의 주요 인수 은행이 유지 관리하는 매우 유용한 규칙 세트가 있습니다. 예 : https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf 및 https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (업데이트 된 참조에 대한 링크를 제공 한 사용자 덕분에 2017 년 6 월 현재 유효한 링크입니다.) 그러나 이러한 CRR 규칙은 해당 엔티티가 획득 한 판매자에게 적용되는 카드 발급 세계를 나타낼 수 있다는 점에 유의하십시오. 예를 들어 CUP / UPI로 식별 된 범위는 포함되지 않습니다.
이 의견은 자기 띠 (MagStripe) 또는 PKE (팬 키 입력) 시나리오에 적용됩니다. ICC / EMV 세계에서는 상황이 다시 다릅니다.
업데이트 :이 페이지 (및 연결된 WikiPedia 페이지)의 다른 답변은 JCB가 항상 16입니다. 그러나 우리 회사에는 여러 인수 은행 및 지역에서 POS 장치 및 소프트웨어를 인증하는 전담 엔지니어 팀이 있습니다. 이 팀이 JCB에서 보유한 가장 최근의 인증 팩 카드에는 19 개의 긴 PAN에 대한 패스 케이스가있었습니다.
Usman Y의 답변 스위프트 2.1 버전. print 문을 사용하여 문자열 값으로 호출 확인
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 ""
}
Stripe는 카드 체계 감지를위한 이 환상적인 자바 스크립트 라이브러리를 제공했습니다 . 몇 가지 코드 스 니펫을 추가하고 사용 방법을 보여 드리겠습니다.
먼저 웹 페이지에 다음과 같이 포함하십시오
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.2.3/jquery.payment.js " ></script>
둘째, 카드 체계를 감지하기 위해 cardType 기능을 사용하십시오.
$(document).ready(function() {
var type = $.payment.cardType("4242 4242 4242 4242"); //test card number
console.log(type);
});
더 많은 예제와 데모에 대한 참조 링크는 다음과 같습니다.
신속하게 신용 카드 유형을 감지하는 열거 형을 만들 수 있습니다.
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
}
}
CreditCardType 열거 형 값을 리턴하는 CreditCardType.cardTypeForCreditCardNumber ( "# card number") 메소드를 호출하십시오.
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;
}
0이 반환되면 신용 카드 유형이 감지되지 않습니다.
신용 카드 입력 필드에 "신용 카드"클래스를 추가해야합니다.
// 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"> <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
},
작은 숟가락 먹이기 :
$("#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");
}
});
다음은 True
함수 이름에 따라 카드가 감지되면 반환되는 Python으로 작성된 일부 부울 함수의 예입니다 .
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
카드 번호의 처음 6 자리 숫자 (초기 MII 숫자 포함)를 발급자 식별 번호 (IIN)라고합니다. 이들은 카드 소지자에게 카드를 발급 한 카드 발급 기관을 식별합니다. 나머지 번호는 카드 발급자가 할당합니다. 카드 번호의 길이는 자릿수입니다. 많은 카드 발급 기관이 카드에 전체 IIN 및 계좌 번호를 인쇄합니다.
위의 사실을 바탕으로 카드 브랜드를 식별하기 위해 JAVA 코드를 보관하고 싶습니다 .
샘플 카드 종류
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";
카드 접두사
// 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"
};
입력 번호에 지정된 접두사가 있는지 확인하십시오.
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;
}
마지막으로 유틸리티 방법
/**
* 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;
}
참고
kotlin에 사용해보십시오. 정규식을 추가하고 when 문에 추가하십시오.
private fun getCardType(number: String): String {
val visa = Regex("^4[0-9]{12}(?:[0-9]{3})?$")
val mastercard = Regex("^5[1-5][0-9]{14}$")
val amx = Regex("^3[47][0-9]{13}$")
return when {
visa.matches(number) -> "Visa"
mastercard.matches(number) -> "Mastercard"
amx.matches(number) -> "American Express"
else -> "Unknown"
}
}
경기 정규 표현식 규칙 각각의 카드 공급 업체 :
(4\d{12}(?:\d{3})?)
비자를 위해.(5[1-5]\d{14})
MasterCard를 위해.(3[47]\d{13})
AMEX를 위해.((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?)
마에스트로.(3(?:0[0-5]|[68][0-9])[0-9]{11})
다이너스 클럽.(6(?:011|5[0-9]{2})[0-9]{12})
엑스에 대한.(35[2-8][89]\d\d\d{10})
JCB를 위해.https://github.com/bendrucker/creditcards-types/ 를 사용 하여 번호에서 신용 카드 유형을 감지합니다. 내가 만난 한 가지 문제는 테스트 번호 6011 1111 1111 1117을 발견하는 것입니다.
https://www.cybersource.com/developers/other_resources/quick_references/test_cc_numbers/ 에서 6011부터 시작하기 때문에 검색 번호임을 알 수 있습니다. 그러나 신용 카드 유형에서 얻은 결과는 "Maestro"입니다. 저자에게 문제를 열었습니다. 그는 곧 나에게 대답하고이 PDF 문서 제공 https://www.discovernetwork.com/downloads/IPP_VAR_Compliance.pdf 우리는 1111 1111 1117 6011이 발견 신용 카드의 범위에 해당하지 않는 명확하게 볼 수있는 문서에서합니다.
이것을 사용해보십시오.
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
}
사용하다.
if (self.checkCardValidation(number: "yourNumber") == true) {
print("Card Number valid")
}else{
print("Card Number not valid")
}
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) {
}
});