Tôi đang cố gắng tìm ra cách phát hiện loại thẻ tín dụng hoàn toàn dựa trên số của nó. Có ai biết một cách dứt khoát, đáng tin cậy để tìm thấy điều này?
Tôi đang cố gắng tìm ra cách phát hiện loại thẻ tín dụng hoàn toàn dựa trên số của nó. Có ai biết một cách dứt khoát, đáng tin cậy để tìm thấy điều này?
Câu trả lời:
Số thẻ tín dụng / thẻ ghi nợ được gọi là PAN hoặc Số tài khoản chính . Sáu chữ số đầu tiên của PAN được lấy từ IIN , hoặc Số nhận dạng nhà phát hành , thuộc ngân hàng phát hành (IIN trước đây được gọi là BIN - Số nhận dạng ngân hàng - vì vậy bạn có thể thấy các tham chiếu đến thuật ngữ đó trong một số tài liệu). Sáu chữ số này tuân theo tiêu chuẩn quốc tế, ISO / IEC 7812 và có thể được sử dụng để xác định loại thẻ từ số.
Thật không may, cơ sở dữ liệu ISO / IEC 7812 thực tế không có sẵn công khai, tuy nhiên, có những danh sách không chính thức, cả thương mại và miễn phí, kể cả trên Wikipedia .
Dù sao, để phát hiện loại từ số, bạn có thể sử dụng biểu thức chính quy như các biểu thức bên dưới: Tín dụng cho các biểu thức gốc
Visa: Số ^4[0-9]{6,}$
thẻ Visa bắt đầu bằng số 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,}$
Trước năm 2016, số MasterCard bắt đầu bằng các số từ 51 đến 55, nhưng điều này sẽ chỉ phát hiện thẻ tín dụng MasterCard ; có những thẻ khác được phát hành bằng hệ thống MasterCard không thuộc phạm vi IIN này. Trong năm 2016, họ sẽ thêm số trong phạm vi (222100-272099).
American Express: ^3[47][0-9]{5,}$
Số thẻ American Express bắt đầu bằng 34 hoặc 37.
Diners Club: ^3(?:0[0-5]|[68][0-9])[0-9]{4,}$
Số thẻ Diners Club bắt đầu bằng 300 đến 305, 36 hoặc 38. Có thẻ Diners Club bắt đầu bằng 5 và có 16 chữ số. Đây là một liên doanh giữa Diners Club và MasterCard và nên được xử lý như MasterCard.
Khám phá: ^6(?:011|5[0-9]{2})[0-9]{3,}$
Khám phá số thẻ bắt đầu bằng 6011 hoặc 65.
JCB: ^(?:2131|1800|35[0-9]{3})[0-9]{3,}$
Thẻ JCB bắt đầu bằng 2131, 1800 hoặc 35.
Thật không may, có một số loại thẻ được xử lý với hệ thống MasterCard không nằm trong phạm vi IIN của MasterCard (số bắt đầu từ 51 ... 55); trường hợp quan trọng nhất là thẻ Maestro, nhiều thẻ được phát hành từ các phạm vi IIN của các ngân hàng khác và do đó được đặt trên khắp không gian số. Do đó, tốt nhất có thể giả định rằng bất kỳ thẻ nào không thuộc loại nào khác mà bạn chấp nhận phải là MasterCard .
Quan trọng : số thẻ có chiều dài khác nhau; chẳng hạn, Visa trước đây đã phát hành thẻ với PAN có 13 chữ số và thẻ có PAN 16 chữ số. Tài liệu của Visa hiện chỉ ra rằng nó có thể phát hành hoặc có thể đã ban hành các số có từ 12 đến 19 chữ số. Do đó, bạn không nên kiểm tra độ dài của số thẻ, ngoài việc xác minh rằng nó có ít nhất 7 chữ số (đối với IIN hoàn chỉnh cộng với một chữ số kiểm tra, phải khớp với giá trị được dự đoán bởi thuật toán Luhn ).
Một gợi ý nữa: trước khi xử lý PAN của chủ thẻ, hãy loại bỏ mọi ký tự khoảng trắng và dấu chấm câu khỏi đầu vào . Tại sao? Bởi vì việc nhập các chữ số theo nhóm thường dễ dàng hơn nhiều , tương tự như cách chúng được hiển thị ở mặt trước của thẻ tín dụng thực tế, nghĩa là
4444 4444 4444 4444
nhập chính xác dễ hơn nhiều
4444444444444444
Thực sự không có lợi ích gì trong việc trừng phạt người dùng vì họ đã nhập các ký tự mà bạn không mong đợi ở đây.
Điều này cũng ngụ ý đảm bảo rằng các trường nhập cảnh của bạn có chỗ cho ít nhất 24 ký tự, nếu không, người dùng vào không gian sẽ hết phòng. Tôi khuyên bạn nên làm cho trường đủ rộng để hiển thị 32 ký tự và cho phép tối đa 64; cung cấp nhiều khoảng trống để mở rộng.
Đây là một hình ảnh cung cấp một cái nhìn sâu sắc hơn một chút:
CẬP NHẬT (2014): Phương thức tổng kiểm tra dường như không còn là một cách hợp lệ để xác minh tính xác thực của thẻ như đã lưu ý trong các nhận xét về câu trả lời này.
CẬP NHẬT (2016): Mastercard là để triển khai các phạm vi BIN mới bắt đầu Ach Payment .
Trong 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
}
}
}
Bài kiểm tra đơn vị:
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]);
});
});
});
});
Cập nhật: ngày 15 tháng 6 năm 2016 (như một giải pháp tối ưu hiện tại)
Xin lưu ý rằng tôi thậm chí bỏ phiếu cho người được bình chọn hàng đầu, nhưng để làm rõ đây là các biểu thức chính thực sự hoạt động tôi đã thử nghiệm nó với hàng ngàn mã BIN thực. Điều quan trọng nhất là sử dụng chuỗi bắt đầu (^) nếu không nó sẽ cho kết quả sai trong thế giới thực!
JCB ^(?:2131|1800|35)[0-9]{0,}$
Bắt đầu với: 2131, 1800, 35 (3528-3589)
American Express ^3[47][0-9]{0,}$
Bắt đầu với: 34, 37
Câu lạc bộ thực khách ^3(?:0[0-59]{1}|[689])[0-9]{0,}$
Bắt đầu với: 300-305, 309, 36, 38-39
Visa ^4[0-9]{0,}$
Bắt đầu với: 4
Thẻ MasterCard ^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[01]|2720)[0-9]{0,}$
Bắt đầu với: 2221-2720, 51-55
Maestro ^(5[06789]|6)[0-9]{0,}$
Maestro luôn phát triển trong phạm vi: 60-69 , bắt đầu bằng / không phải thứ gì khác, nhưng bắt đầu 5 phải được mã hóa dưới dạng thẻ mastercard. Thẻ Maestro phải được phát hiện ở cuối mã vì một số thẻ khác có trong khoảng 60-69. Hãy nhìn vào mã.
Khám phá Khám ^(6011|65|64[4-9]|62212[6-9]|6221[3-9]|622[2-8]|6229[01]|62292[0-5])[0-9]{0,}$
phá khá khó để viết mã, bắt đầu với: 6011, 622126-622925, 644-649, 65
Trong javascript tôi sử dụng chức năng này. Điều này là tốt khi bạn gán nó cho một sự kiện onkeyup và nó cho kết quả càng sớm càng tốt.
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;
}
Tại đây bạn có thể chơi với nó:
Đối với PHP sử dụng chức năng này, điều này cũng phát hiện một số thẻ VISA / MC phụ:
/**
* 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";
}
Đây là chức năng kiểm tra loại thẻ tín dụng bằng Regex, c #
Kiểm tra này:
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;
}
Gần đây tôi cần chức năng như vậy, tôi đã chuyển Trình xác thực thẻ tín dụng Zend Framework sang ruby. đá quý ruby: https://github.com/Fivell/credit_card_validations zend framework: https://github.com/zendframework/zf2/blob/master/l Library / Zend / Valator / HolyitCard.php
Cả hai đều sử dụng phạm vi INN để phát hiện loại. Ở đây bạn có thể đọc về INN
Theo đó, bạn có thể phát hiện thẻ tín dụng thay thế (không có biểu thức chính quy, nhưng khai báo một số quy tắc về tiền tố và độ dài có thể)
Vì vậy, chúng tôi có các quy tắc tiếp theo cho hầu hết các thẻ được sử dụng
######## 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}
]
}
Sau đó, bằng cách tìm kiếm tiền tố và so sánh độ dài, bạn có thể phát hiện thương hiệu thẻ tín dụng. Cũng đừng quên luhn algoritm (nó được giải thích ở đây http://en.wikipedia.org/wiki/Luhn ).
CẬP NHẬT
danh sách các quy tắc cập nhật có thể được tìm thấy ở đây https://raw.githubusercontent.com/Fivell/credit_card_validations/master/lib/data/brands.yaml
Đây là mã C # hoặc VB hoàn chỉnh cho tất cả các loại điều liên quan đến CC trên bảng mã.
Bài viết này đã được một vài năm không có bình luận tiêu cực.
Phiên bản javascript nhỏ gọn
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;
}
}
};
Câu trả lời của Anatoliy trong 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;
}
}
Đây là một hàm lớp php trả về CCtype bởi CCnumber.
Mã này không xác thực thẻ hoặc không chạy thuật toán Luhn chỉ cố gắng tìm loại thẻ tín dụng dựa trên bảng trong trang này . về cơ bản sử dụng chiều dài CCnumber và tiền tố CCcard để xác định loại 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;
}
}
Đừng cố gắng phát hiện loại thẻ tín dụng như là một phần của việc xử lý thanh toán. Bạn đang có nguy cơ từ chối các giao dịch hợp lệ.
Nếu bạn cần cung cấp thông tin cho bộ xử lý thanh toán của mình (ví dụ: đối tượng thẻ tín dụng PayPal yêu cầu đặt tên loại thẻ ), thì hãy đoán nó từ thông tin ít nhất có sẵn, ví dụ:
$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.');
}
Việc triển khai này (chỉ sử dụng hai chữ số đầu tiên) là đủ để xác định tất cả các lược đồ thẻ chính (và trong trường hợp của PayPal là tất cả các lược đồ thẻ được hỗ trợ). Trong thực tế, bạn có thể muốn bỏ qua ngoại lệ hoàn toàn và mặc định cho loại thẻ phổ biến nhất. Hãy để cổng thanh toán / bộ xử lý cho bạn biết nếu có lỗi xác thực đáp ứng yêu cầu của bạn.
Thực tế là cổng thanh toán của bạn không quan tâm đến giá trị bạn cung cấp .
Các số đầu tiên của thẻ tín dụng có thể được sử dụng để ước tính nhà cung cấp:
Trong Nhận dạng phạm vi thẻ (CRR), một nhược điểm với các thuật toán sử dụng một loạt biểu thức chính quy hoặc các phạm vi được mã hóa cứng khác, đó là các BIN / IIN thay đổi theo thời gian theo kinh nghiệm của tôi. Việc hợp tác xây dựng thương hiệu thẻ là một sự phức tạp đang diễn ra. Những người mua / người bán thẻ khác nhau có thể cần bạn đối xử với cùng một loại thẻ khác nhau, tùy thuộc vào vị trí địa lý.
Ngoài ra, trong vài năm gần đây, ví dụ như thẻ UnionPay được lưu hành rộng hơn, các mô hình hiện tại không đối phó với các phạm vi mới đôi khi xen kẽ với các phạm vi rộng hơn mà chúng thay thế.
Biết địa lý mà hệ thống của bạn cần bao quát có thể giúp ích, vì một số phạm vi bị hạn chế sử dụng ở các quốc gia cụ thể. Ví dụ: phạm vi 62 bao gồm một số phạm vi phụ AAA ở Hoa Kỳ, nhưng nếu cơ sở thương mại của bạn ở bên ngoài Hoa Kỳ, bạn có thể coi tất cả 62 là UnionPay.
Bạn cũng có thể được yêu cầu đối xử với một thẻ khác nhau dựa trên vị trí thương gia. Ví dụ: coi một số thẻ của Vương quốc Anh là ghi nợ trong nước, nhưng là tín dụng quốc tế.
Có một bộ quy tắc rất hữu ích được duy trì bởi một Ngân hàng Mua lại lớn. Ví dụ: https://www.barclaycard.co.uk/business/files/BIN-Rules-EIRE.pdf và https://www.barclaycard.co.uk/business/files/BIN-Rules-UK.pdf . (Liên kết hợp lệ kể từ tháng 6 năm 2017, nhờ người dùng đã cung cấp liên kết đến tài liệu tham khảo được cập nhật.) nó không bao gồm các phạm vi được xác định là CUP / UPI.
Những nhận xét này áp dụng cho các tình huống sọc từ (MagStripe) hoặc PKE (Pan Key Entry). Tình hình lại khác trong thế giới ICC / EMV.
Cập nhật: Các câu trả lời khác trên trang này (và cả trang WikiPedia được liên kết) có JCB luôn luôn dài 16. Tuy nhiên, trong công ty của tôi, chúng tôi có một đội ngũ kỹ sư chuyên dụng chứng nhận các thiết bị và phần mềm POS của chúng tôi trên nhiều ngân hàng và khu vực địa lý. Gói chứng nhận gần đây nhất của nhóm này có từ JCB, đã có một trường hợp vượt qua cho một PAN dài 19.
Phiên bản Swift 2.1 của câu trả lời của Usman Y. Sử dụng một câu lệnh in để xác minh để gọi theo một số giá trị chuỗi
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 đã cung cấp thư viện javascript tuyệt vời này để phát hiện sơ đồ thẻ. Hãy để tôi thêm một vài đoạn mã và chỉ cho bạn cách sử dụng nó.
Trước hết, hãy đưa nó vào trang web của bạn dưới dạng
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery.payment/1.2.3/jquery.payment.js " ></script>
Thứ hai sử dụng chức năng cardType để phát hiện sơ đồ thẻ.
$(document).ready(function() {
var type = $.payment.cardType("4242 4242 4242 4242"); //test card number
console.log(type);
});
Dưới đây là các liên kết tham khảo cho nhiều ví dụ và bản demo.
Trong swift, bạn có thể tạo một enum để phát hiện loại thẻ tín dụng.
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
}
}
Gọi phương thức CreditCardType.cardTypeForCreditCardNumber ("# số thẻ") để trả về giá trị enum của CreditCardType.
Giải pháp của tôi với 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;
}
Trong trường hợp 0 được trả về, loại thẻ tín dụng không bị phát hiện.
Lớp "thẻ tín dụng" nên được thêm vào trường nhập thẻ tín dụng.
Tôi đã tìm kiếm xung quanh khá nhiều để định dạng thẻ tín dụng và định dạng số điện thoại. Tìm thấy rất nhiều lời khuyên hay nhưng không có gì thực sự phù hợp với mong muốn chính xác của tôi nên tôi đã tạo ra đoạn mã này . Bạn sử dụng nó như thế này:
var sf = smartForm.formatCC(myInputString);
var cardType = sf.cardType;
// 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
},
Chỉ cần một thìa nhỏ cho ă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");
}
});
Dưới đây là một ví dụ về một số hàm boolean được viết bằng Python trả về True
nếu thẻ được phát hiện theo tên hàm.
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
Sáu chữ số đầu tiên của một số thẻ (bao gồm cả chữ số MII ban đầu) được gọi là số nhận dạng nhà phát hành (IIN). Chúng xác định tổ chức phát hành thẻ đã cấp thẻ cho chủ thẻ. Phần còn lại của số được phân bổ bởi tổ chức phát hành thẻ. Độ dài của số thẻ là số chữ số của nó. Nhiều tổ chức phát hành thẻ in toàn bộ IIN và số tài khoản trên thẻ của họ.
Dựa trên các sự kiện trên, tôi muốn giữ một đoạn mã JAVA để xác định thương hiệu thẻ.
Các loại thẻ mẫu
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";
Tiền tố thẻ
// 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"
};
Kiểm tra xem số đầu vào có bất kỳ tiền tố nào không.
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;
}
Cuối cùng, phương thức 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;
}
Tài liệu tham khảo
Hãy thử điều này cho kotlin. Thêm Regex và thêm vào câu lệnh khi.
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"
}
}
Các quy tắc biểu thức chính quy phù hợp với các nhà cung cấp thẻ tương ứng :
(4\d{12}(?:\d{3})?)
cho VISA.(5[1-5]\d{14})
đối với thẻ MasterCard.(3[47]\d{13})
cho AMEX.((?:5020|5038|6304|6579|6761)\d{12}(?:\d\d)?)
cho Maestro.(3(?:0[0-5]|[68][0-9])[0-9]{11})
cho câu lạc bộ thực khách.(6(?:011|5[0-9]{2})[0-9]{12})
để khám phá(35[2-8][89]\d\d\d{10})
cho JCB.Tôi sử dụng https://github.com/bendrucker/creditcards-types/ để phát hiện loại thẻ tín dụng từ số. Một vấn đề tôi gặp phải là khám phá số kiểm tra 6011 1111 1111 1117
từ https://www.cybersource.com/developers/other_resource/quick_Vferences/test_cc_numbers/ chúng ta có thể thấy đó là một số khám phá vì nó bắt đầu từ 6011. Nhưng kết quả tôi nhận được từ các loại thẻ tín dụng là "Maestro". Tôi đã mở vấn đề cho tác giả. Anh ấy đã trả lời tôi rất sớm và cung cấp tài liệu pdf này https://www.discbadetwork.com/doads/IPP_VAR_Compliance.pdf Từ tài liệu chúng tôi có thể thấy rõ rằng 6011 1111 1111 1117 không rơi vào phạm vi khám phá thẻ tín dụng.
Hãy thử điều này. Cho nhanh chóng.
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
}
Sử dụng.
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) {
}
});