credit-card-type
Advanced tools
Comparing version 7.1.0 to 8.0.0
@@ -0,1 +1,10 @@ | ||
8.0.0 | ||
===== | ||
- Improve pattern recognition for card types | ||
*Breaking Changes* | ||
- When adding or updating cards, this module no longer uses an `exactPattern` and `prefixPattern` model. Instead, it takes an array of patterns. See https://github.com/braintree/credit-card-type#pattern-detection for details. | ||
7.1.0 | ||
@@ -2,0 +11,0 @@ ===== |
@@ -36,19 +36,9 @@ !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.creditCardType=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | ||
function clone(originalObject, persistPatterns) { | ||
var dupe, prefixPattern, exactPattern; | ||
function clone(originalObject) { | ||
var dupe; | ||
if (!originalObject) { return null; } | ||
prefixPattern = originalObject.prefixPattern; | ||
exactPattern = originalObject.exactPattern; | ||
dupe = JSON.parse(JSON.stringify(originalObject)); | ||
if (persistPatterns) { | ||
dupe.prefixPattern = prefixPattern; | ||
dupe.exactPattern = exactPattern; | ||
} else { | ||
delete dupe.prefixPattern; | ||
delete dupe.exactPattern; | ||
} | ||
return dupe; | ||
@@ -62,9 +52,5 @@ } | ||
type: VISA, | ||
prefixPattern: /^4/, | ||
exactPattern: new RegExp('^' + | ||
'4' + | ||
'(?!' + | ||
'31274|51416|57393|0117[89]|38935|5763[12]' + // Elo cards | ||
')\\d{5,}' + | ||
'$'), | ||
patterns: [ | ||
4 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -81,4 +67,10 @@ lengths: [16, 18, 19], | ||
type: MASTERCARD, | ||
prefixPattern: /^(5|5[1-5]|2|22|222|222[1-9]|2[3-6]|27|27[0-2]|2720)$/, | ||
exactPattern: /^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[0-1]|2720)\d*$/, | ||
patterns: [ | ||
[51, 55], | ||
[2221, 2229], | ||
[223, 229], | ||
[23, 26], | ||
[270, 271], | ||
2720 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -95,5 +87,6 @@ lengths: [16], | ||
type: AMERICAN_EXPRESS, | ||
prefixPattern: /^(3|34|37)$/, | ||
exactPattern: /^3[47]\d*$/, | ||
isAmex: true, | ||
patterns: [ | ||
34, | ||
37 | ||
], | ||
gaps: [4, 10], | ||
@@ -110,4 +103,8 @@ lengths: [15], | ||
type: DINERS_CLUB, | ||
prefixPattern: /^(3|3[0689]|30[0-5])$/, | ||
exactPattern: /^3(0[0-5]|[689])\d*$/, | ||
patterns: [ | ||
[300, 305], | ||
36, | ||
38, | ||
39 | ||
], | ||
gaps: [4, 10], | ||
@@ -124,33 +121,7 @@ lengths: [14, 16, 19], | ||
type: DISCOVER, | ||
prefixPattern: /^(6|60|601|6011|65|65\d{1,4}|64|64[4-9])$/, | ||
exactPattern: new RegExp('^(' + | ||
'6011' + | ||
'|' + | ||
'65' + | ||
'(?!' + // Elo cards | ||
'003[1-3]' + | ||
'|' + | ||
'003[5-9]|004\\d|005[0-1]' + | ||
'|' + | ||
'040[5-9]|04[1-3]\\d' + | ||
'|' + | ||
'048[5-9]|049\\d|05[0-2]\\d|053[0-8]' + | ||
'|' + | ||
'054[1-9]|05[5-8]\\d|059[0-8]' + | ||
'|' + | ||
'070\\d|071[0-8]' + | ||
'|' + | ||
'072[0-7]' + | ||
'|' + | ||
'090[1-9]|09[1-6]\\d|097[0-8]' + | ||
'|' + | ||
'165[2-9]|16[6-7]\\d' + | ||
'|' + | ||
'50[0-1]\\d' + | ||
'|' + | ||
'502[1-9]|50[3-4]\\d|505[0-8]' + | ||
')\\d{4}' + | ||
'|' + | ||
'64[4-9]' + | ||
')\\d*$'), | ||
patterns: [ | ||
6011, | ||
[644, 649], | ||
65 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -167,4 +138,7 @@ lengths: [16, 19], | ||
type: JCB, | ||
prefixPattern: /^(2|21|213|2131|1|18|180|1800|3|35)$/, | ||
exactPattern: /^(2131|1800|35)\d*$/, | ||
patterns: [ | ||
2131, | ||
1800, | ||
[3528, 3589] | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -181,26 +155,24 @@ lengths: [16, 17, 18, 19], | ||
type: UNIONPAY, | ||
prefixPattern: /^((6|62|62\d|(621(?!83|88|98|99))|622(?!06)|627[0267]\d?|628(?!0|1)|629[1,2])|622018)$/, | ||
exactPattern: new RegExp('^(' + | ||
'(' + | ||
'620' + | ||
'|' + | ||
'(621(?!83|88|98|99))' + | ||
'|' + | ||
'622(?!06|018)' + | ||
'|' + | ||
'62[3-6]' + | ||
'|' + | ||
'627[026]' + | ||
'|' + | ||
'6277(?!80)\\d{2}' + // Elo card | ||
'|' + | ||
'628(?!0|1)' + | ||
'|' + | ||
'629[12]' + | ||
')\\d*' + | ||
'|' + | ||
'622018\\d{12}' + | ||
')$'), | ||
patterns: [ | ||
620, | ||
[624, 626], | ||
[62100, 62182], | ||
[62184, 62187], | ||
[62185, 62197], | ||
[62200, 62205], | ||
[622010, 622999], | ||
622018, | ||
[622019, 622999], | ||
[62207, 62209], | ||
[622126, 622925], | ||
[623, 626], | ||
6270, | ||
6272, | ||
6276, | ||
[627700, 627779], | ||
[627781, 627799], | ||
[6282, 6289], | ||
6291, | ||
6292 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -217,23 +189,11 @@ lengths: [16, 17, 18, 19], | ||
type: MAESTRO, | ||
prefixPattern: /^(5|5[06-9]|6\d*)$/, | ||
exactPattern: new RegExp('^(' + | ||
'5[6-9]' + | ||
'|' + | ||
'50' + | ||
'(?!' + // Elo card ranges | ||
'6699|067[0-6][0-9]' + | ||
'|' + | ||
'677[0-8]' + | ||
'|' + | ||
'9[0-9][0-9][0-9]' + | ||
')\\d{4}' + | ||
'|' + | ||
'67' + | ||
'|' + | ||
'63' + | ||
'(?!' + // More Elo card ranges | ||
'6297|6368' + | ||
')\\d{4}' + | ||
')\\d*$' | ||
), | ||
patterns: [ | ||
493698, | ||
[500000, 506698], | ||
[506779, 508999], | ||
[56, 59], | ||
63, | ||
67, | ||
6 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -250,105 +210,29 @@ lengths: [12, 13, 14, 15, 16, 17, 18, 19], | ||
type: ELO, | ||
prefixPattern: new RegExp('^(' + | ||
'[4-6]' + | ||
'|' + | ||
'4[035]|4[035]1' + | ||
'|' + | ||
'4011|40117|40117[89]' + | ||
'|' + | ||
'4312|43127|431274' + | ||
'|' + | ||
'438|4389|43893|438935' + | ||
'|' + | ||
'4514|45141|451416' + | ||
'|' + | ||
'457|457[36]|45739|45763|457393|45763[12]' + | ||
'|' + | ||
'50|50[69]' + | ||
'|' + | ||
'506[6-7]|50669|5067[0-7]|5067[0-6][0-9]|50677[0-8]' + | ||
'|' + | ||
'509[0-9]|509[0-9][0-9]|509[0-9][0-9][0-9]' + | ||
'|' + | ||
'6[235]|627|636|65[015]' + | ||
'|' + | ||
'6277|62778|627780' + | ||
'|' + | ||
'636[23]|63629|636297|63636|636368' + | ||
'|' + | ||
'650[0479]' + | ||
'|' + | ||
'6500[3-5]|65003[1-3]|65003[5-9]|65004[0-9]65005[01]' + | ||
'|' + | ||
'6504[0-3]|65040[5-9]|65041[0-9]' + | ||
'|' + | ||
'6505[4-9]|65054[1-9]|6505[5-8][0-9]|65059[0-8]' + | ||
'|' + | ||
'6507[0-2]|65070[0-9]|65071[0-8]|65072[0-7]' + | ||
'|' + | ||
'6509[0-7]|65090[1-9]|6509[1-6][0-9]|65097[0-8]' + | ||
'|' + | ||
'6516|6516[5-7]|65165[2-9]|6516[6-7][0-9]' + | ||
'|' + | ||
'6550|6550[0-5]|6550[01][0-9]|65502[1-9]|6550[3-4][0-9]|65505[0-8]' + | ||
')$'), | ||
exactPattern: new RegExp('^(' + | ||
// Elo only ranges | ||
'4(31274|51416|57393)' + | ||
'|' + | ||
'50(' + | ||
'4175' + | ||
'|' + | ||
'6699|67[0-6][0-9]|677[0-8]' + // 506699-506778 | ||
'|' + | ||
'9[0-9][0-9][0-9]' + // 509000-509999 | ||
')' + | ||
'|' + | ||
'627780' + | ||
'|' + | ||
'636(297|368)' + | ||
'|' + | ||
// Dual Branded with Visa | ||
'4(0117[89]|38935|5763[12])' + | ||
'|' + | ||
// Dual Branded with Discover | ||
'65(' + | ||
'003[1-3]' + // 650031-650033 | ||
'|' + | ||
'003[5-9]|004\\d|005[0-1]' + // 650035-650051 | ||
'|' + | ||
'040[5-9]|04[1-3]\\d' + // 650405-650439 | ||
'|' + | ||
'048[5-9]|049\\d|05[0-2]\\d|053[0-8]' + // 650485-650538 | ||
'|' + | ||
'054[1-9]|05[5-8]\\d|059[0-8]' + // 650541-650598 | ||
'|' + | ||
'070[0-9]|071[0-8]' + // 650700-650718 | ||
'|' + | ||
'072[0-7]' + // 650720-650727 | ||
'|' + | ||
'090[1-9]|09[1-6][0-9]|097[0-8]' + // 650901-650978 | ||
'|' + | ||
'165[2-9]|16[6-7][0-9]' + // 651652-651679 | ||
'|' + | ||
'50[0-1][0-9]' + // 655000-655019 | ||
'|' + | ||
'502[1-9]|50[3-4][0-9]|505[0-8]' + // 655021-655058 | ||
')' + | ||
')\\d*$'), | ||
patterns: [ | ||
401178, | ||
401179, | ||
438935, | ||
457631, | ||
457632, | ||
431274, | ||
451416, | ||
457393, | ||
504175, | ||
[506699, 506778], | ||
[509000, 509999], | ||
627780, | ||
636297, | ||
636368, | ||
[650031, 650033], | ||
[650035, 650051], | ||
[650405, 650439], | ||
[650485, 650538], | ||
[650541, 650598], | ||
[650700, 650718], | ||
[650720, 650727], | ||
[650901, 650978], | ||
[651652, 651679], | ||
[655000, 655019], | ||
[655021, 655058] | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -365,4 +249,5 @@ lengths: [16], | ||
type: MIR, | ||
prefixPattern: /^(2|22|220|220[0-4])$/, | ||
exactPattern: /^(220[0-4])\d*$/, | ||
patterns: [ | ||
[2200, 2204] | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -380,30 +265,124 @@ lengths: [16, 17, 18, 19], | ||
function isValidInputType(cardNumber) { | ||
return typeof cardNumber === 'string' || cardNumber instanceof String; | ||
} | ||
function hasEnoughResultsToDetermineBestMatch(results) { | ||
var numberOfResultsWithMaxStrengthProperty = results.filter(function (result) { | ||
return result.matchStrength; | ||
}).length; | ||
// if all possible results have a maxStrength property | ||
// that means the card number is sufficiently long | ||
// enough to determine conclusively what the type is | ||
return numberOfResultsWithMaxStrengthProperty > 0 && | ||
numberOfResultsWithMaxStrengthProperty === results.length; | ||
} | ||
function findBestMatch(results) { | ||
if (!hasEnoughResultsToDetermineBestMatch(results)) { | ||
return; | ||
} | ||
return results.reduce(function (bestMatch, result) { // eslint-disable-line consistent-return | ||
if (!bestMatch) { | ||
return result; | ||
} | ||
// if the current best match pattern is less specific | ||
// than this result, set the result as the new best match | ||
if (bestMatch.matchStrength < result.matchStrength) { | ||
return result; | ||
} | ||
return bestMatch; | ||
}); | ||
} | ||
function getAllCardTypes() { | ||
return testOrder.map(function (type) { | ||
return clone(findType(type)); | ||
}); | ||
} | ||
function creditCardType(cardNumber) { | ||
var type, value, i; | ||
var prefixResults = []; | ||
var exactResults = []; | ||
var bestMatch; | ||
var results = []; | ||
if (!(typeof cardNumber === 'string' || cardNumber instanceof String)) { | ||
if (!isValidInputType(cardNumber)) { | ||
return []; | ||
} | ||
for (i = 0; i < testOrder.length; i++) { | ||
type = testOrder[i]; | ||
value = findType(type); | ||
if (cardNumber.length === 0) { | ||
return getAllCardTypes(); | ||
} | ||
if (cardNumber.length === 0) { | ||
prefixResults.push(clone(value)); | ||
testOrder.forEach(function (type) { | ||
var cardConfiguration = findType(type); | ||
loopOverCardPatterns(cardNumber, cardConfiguration, results); | ||
}); | ||
bestMatch = findBestMatch(results); | ||
if (bestMatch) { | ||
return [bestMatch]; | ||
} | ||
return results; | ||
} | ||
function loopOverCardPatterns(cardNumber, cardConfiguration, results) { | ||
var i, pattern, patternLength, clonedCardConfiguration; | ||
for (i = 0; i < cardConfiguration.patterns.length; i++) { | ||
pattern = cardConfiguration.patterns[i]; | ||
if (!matches(cardNumber, pattern)) { | ||
continue; | ||
} | ||
if (value.exactPattern.test(cardNumber)) { | ||
exactResults.push(clone(value)); | ||
} else if (value.prefixPattern.test(cardNumber)) { | ||
prefixResults.push(clone(value)); | ||
clonedCardConfiguration = clone(cardConfiguration); | ||
if (Array.isArray(pattern)) { | ||
patternLength = String(pattern[0]).length; | ||
} else { | ||
patternLength = String(pattern).length; | ||
} | ||
if (cardNumber.length >= patternLength) { | ||
clonedCardConfiguration.matchStrength = patternLength; | ||
} | ||
results.push(clonedCardConfiguration); | ||
break; | ||
} | ||
} | ||
return exactResults.length ? exactResults : prefixResults; | ||
function matches(cardNumber, pattern) { | ||
if (Array.isArray(pattern)) { | ||
return matchesRange(cardNumber, pattern[0], pattern[1]); | ||
} | ||
return matchesPattern(cardNumber, pattern); | ||
} | ||
function matchesPattern(cardNumber, pattern) { | ||
pattern = String(pattern); | ||
return pattern.substring(0, cardNumber.length) === cardNumber.substring(0, pattern.length); | ||
} | ||
// Adapted from https://github.com/polvo-labs/card-type/blob/aaab11f80fa1939bccc8f24905a06ae3cd864356/src/cardType.js#L37-L42 | ||
function matchesRange(cardNumber, min, max) { | ||
var maxLengthToCheck = String(min).length; | ||
var substr = cardNumber.substr(0, maxLengthToCheck); | ||
var integerRepresentationOfCardNumber = parseInt(substr, 10); | ||
min = parseInt(String(min).substr(0, substr.length), 10); | ||
max = parseInt(String(max).substr(0, substr.length), 10); | ||
return integerRepresentationOfCardNumber >= min && integerRepresentationOfCardNumber <= max; | ||
} | ||
creditCardType.getTypeInfo = function (type) { | ||
@@ -410,0 +389,0 @@ return clone(findType(type)); |
@@ -1,1 +0,1 @@ | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.creditCardType=e()}}(function(){return function e(t,n,r){function a(p,d){if(!n[p]){if(!t[p]){var o="function"==typeof require&&require;if(!d&&o)return o(p,!0);if(i)return i(p,!0);var s=new Error("Cannot find module '"+p+"'");throw s.code="MODULE_NOT_FOUND",s}var c=n[p]={exports:{}};t[p][0].call(c.exports,function(e){var n=t[p][1][e];return a(n?n:e)},c,c.exports,e,t,n,r)}return n[p].exports}for(var i="function"==typeof require&&require,p=0;p<r.length;p++)a(r[p]);return a}({1:[function(e,t,n){"use strict";function r(e,t){var n,r,a;return e?(r=e.prefixPattern,a=e.exactPattern,n=JSON.parse(JSON.stringify(e)),t?(n.prefixPattern=r,n.exactPattern=a):(delete n.prefixPattern,delete n.exactPattern),n):null}function a(e){return s[e]||o[e]}function i(e){var t,n,i,p=[],o=[];if(!("string"==typeof e||e instanceof String))return[];for(i=0;i<d.length;i++)t=d[i],n=a(t),0!==e.length?n.exactPattern.test(e)?o.push(r(n)):n.prefixPattern.test(e)&&p.push(r(n)):p.push(r(n));return o.length?o:p}function p(e,t){var n=d.indexOf(e);if(!t&&n===-1)throw new Error('"'+e+'" is not a supported card type.');return n}var d,o={},s={},c="visa",f="mastercard",u="american-express",y="diners-club",x="discover",g="elo",l="jcb",P="unionpay",h="maestro",E="mir",m="CVV",C="CID",v="CVC",w="CVN",$="CVP2",T="CVE",R=[c,f,u,y,x,l,P,h,g,E];d=r(R),o[c]={niceType:"Visa",type:c,prefixPattern:/^4/,exactPattern:new RegExp("^4(?!31274|51416|57393|0117[89]|38935|5763[12])\\d{5,}$"),gaps:[4,8,12],lengths:[16,18,19],code:{name:m,size:3}},o[f]={niceType:"Mastercard",type:f,prefixPattern:/^(5|5[1-5]|2|22|222|222[1-9]|2[3-6]|27|27[0-2]|2720)$/,exactPattern:/^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[0-1]|2720)\d*$/,gaps:[4,8,12],lengths:[16],code:{name:v,size:3}},o[u]={niceType:"American Express",type:u,prefixPattern:/^(3|34|37)$/,exactPattern:/^3[47]\d*$/,isAmex:!0,gaps:[4,10],lengths:[15],code:{name:C,size:4}},o[y]={niceType:"Diners Club",type:y,prefixPattern:/^(3|3[0689]|30[0-5])$/,exactPattern:/^3(0[0-5]|[689])\d*$/,gaps:[4,10],lengths:[14,16,19],code:{name:m,size:3}},o[x]={niceType:"Discover",type:x,prefixPattern:/^(6|60|601|6011|65|65\d{1,4}|64|64[4-9])$/,exactPattern:new RegExp("^(6011|65(?!003[1-3]|003[5-9]|004\\d|005[0-1]|040[5-9]|04[1-3]\\d|048[5-9]|049\\d|05[0-2]\\d|053[0-8]|054[1-9]|05[5-8]\\d|059[0-8]|070\\d|071[0-8]|072[0-7]|090[1-9]|09[1-6]\\d|097[0-8]|165[2-9]|16[6-7]\\d|50[0-1]\\d|502[1-9]|50[3-4]\\d|505[0-8])\\d{4}|64[4-9])\\d*$"),gaps:[4,8,12],lengths:[16,19],code:{name:C,size:3}},o[l]={niceType:"JCB",type:l,prefixPattern:/^(2|21|213|2131|1|18|180|1800|3|35)$/,exactPattern:/^(2131|1800|35)\d*$/,gaps:[4,8,12],lengths:[16,17,18,19],code:{name:m,size:3}},o[P]={niceType:"UnionPay",type:P,prefixPattern:/^((6|62|62\d|(621(?!83|88|98|99))|622(?!06)|627[0267]\d?|628(?!0|1)|629[1,2])|622018)$/,exactPattern:new RegExp("^((620|(621(?!83|88|98|99))|622(?!06|018)|62[3-6]|627[026]|6277(?!80)\\d{2}|628(?!0|1)|629[12])\\d*|622018\\d{12})$"),gaps:[4,8,12],lengths:[16,17,18,19],code:{name:w,size:3}},o[h]={niceType:"Maestro",type:h,prefixPattern:/^(5|5[06-9]|6\d*)$/,exactPattern:new RegExp("^(5[6-9]|50(?!6699|067[0-6][0-9]|677[0-8]|9[0-9][0-9][0-9])\\d{4}|67|63(?!6297|6368)\\d{4})\\d*$"),gaps:[4,8,12],lengths:[12,13,14,15,16,17,18,19],code:{name:v,size:3}},o[g]={niceType:"Elo",type:g,prefixPattern:new RegExp("^([4-6]|4[035]|4[035]1|4011|40117|40117[89]|4312|43127|431274|438|4389|43893|438935|4514|45141|451416|457|457[36]|45739|45763|457393|45763[12]|50|50[69]|506[6-7]|50669|5067[0-7]|5067[0-6][0-9]|50677[0-8]|509[0-9]|509[0-9][0-9]|509[0-9][0-9][0-9]|6[235]|627|636|65[015]|6277|62778|627780|636[23]|63629|636297|63636|636368|650[0479]|6500[3-5]|65003[1-3]|65003[5-9]|65004[0-9]65005[01]|6504[0-3]|65040[5-9]|65041[0-9]|6505[4-9]|65054[1-9]|6505[5-8][0-9]|65059[0-8]|6507[0-2]|65070[0-9]|65071[0-8]|65072[0-7]|6509[0-7]|65090[1-9]|6509[1-6][0-9]|65097[0-8]|6516|6516[5-7]|65165[2-9]|6516[6-7][0-9]|6550|6550[0-5]|6550[01][0-9]|65502[1-9]|6550[3-4][0-9]|65505[0-8])$"),exactPattern:new RegExp("^(4(31274|51416|57393)|50(4175|6699|67[0-6][0-9]|677[0-8]|9[0-9][0-9][0-9])|627780|636(297|368)|4(0117[89]|38935|5763[12])|65(003[1-3]|003[5-9]|004\\d|005[0-1]|040[5-9]|04[1-3]\\d|048[5-9]|049\\d|05[0-2]\\d|053[0-8]|054[1-9]|05[5-8]\\d|059[0-8]|070[0-9]|071[0-8]|072[0-7]|090[1-9]|09[1-6][0-9]|097[0-8]|165[2-9]|16[6-7][0-9]|50[0-1][0-9]|502[1-9]|50[3-4][0-9]|505[0-8]))\\d*$"),gaps:[4,8,12],lengths:[16],code:{name:T,size:3}},o[E]={niceType:"Mir",type:E,prefixPattern:/^(2|22|220|220[0-4])$/,exactPattern:/^(220[0-4])\d*$/,gaps:[4,8,12],lengths:[16,17,18,19],code:{name:$,size:3}},i.getTypeInfo=function(e){return r(a(e))},i.removeCard=function(e){var t=p(e);d.splice(t,1)},i.addCard=function(e){var t=p(e.type,!0);s[e.type]=e,t===-1&&d.push(e.type)},i.updateCard=function(e,t){var n,a=s[e]||o[e];if(!a)throw new Error('"'+e+'" is not a recognized type. Use `addCard` instead.');if(t.type&&a.type!==t.type)throw new Error("Cannot overwrite type parameter.");n=r(a,!0),Object.keys(n).forEach(function(e){t[e]&&(n[e]=t[e])}),s[n.type]=n},i.changeOrder=function(e,t){var n=p(e);d.splice(n,1),d.splice(t,0,e)},i.resetModifications=function(){d=r(R),s={}},i.types={VISA:c,MASTERCARD:f,AMERICAN_EXPRESS:u,DINERS_CLUB:y,DISCOVER:x,JCB:l,UNIONPAY:P,MAESTRO:h,ELO:g,MIR:E},t.exports=i},{}]},{},[1])(1)}); | ||
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self),n.creditCardType=e()}}(function(){return function e(n,t,r){function i(s,o){if(!t[s]){if(!n[s]){var p="function"==typeof require&&require;if(!o&&p)return p(s,!0);if(a)return a(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=t[s]={exports:{}};n[s][0].call(u.exports,function(e){var t=n[s][1][e];return i(t?t:e)},u,u.exports,e,n,t,r)}return t[s].exports}for(var a="function"==typeof require&&require,s=0;s<r.length;s++)i(r[s]);return i}({1:[function(e,n,t){"use strict";function r(e){var n;return e?n=JSON.parse(JSON.stringify(e)):null}function i(e){return m[e]||h[e]}function a(e){return"string"==typeof e||e instanceof String}function s(e){var n=e.filter(function(e){return e.matchStrength}).length;return n>0&&n===e.length}function o(e){if(s(e))return e.reduce(function(e,n){return e?e.matchStrength<n.matchStrength?n:e:n})}function p(){return l.map(function(e){return r(i(e))})}function c(e){var n,t=[];return a(e)?0===e.length?p():(l.forEach(function(n){var r=i(n);u(e,r,t)}),n=o(t),n?[n]:t):[]}function u(e,n,t){var i,a,s,o;for(i=0;i<n.patterns.length;i++)if(a=n.patterns[i],f(e,a)){o=r(n),s=Array.isArray(a)?String(a[0]).length:String(a).length,e.length>=s&&(o.matchStrength=s),t.push(o);break}}function f(e,n){return Array.isArray(n)?d(e,n[0],n[1]):g(e,n)}function g(e,n){return n=String(n),n.substring(0,e.length)===e.substring(0,n.length)}function d(e,n,t){var r=String(n).length,i=e.substr(0,r),a=parseInt(i,10);return n=parseInt(String(n).substr(0,i.length),10),t=parseInt(String(t).substr(0,i.length),10),a>=n&&a<=t}function y(e,n){var t=l.indexOf(e);if(!n&&t===-1)throw new Error('"'+e+'" is not a supported card type.');return t}var l,h={},m={},v="visa",C="mastercard",S="american-express",E="diners-club",T="discover",b="elo",w="jcb",A="unionpay",O="maestro",z="mir",I="CVV",x="CID",M="CVC",N="CVN",V="CVP2",D="CVE",R=[v,C,S,E,T,w,A,O,b,z];l=r(R),h[v]={niceType:"Visa",type:v,patterns:[4],gaps:[4,8,12],lengths:[16,18,19],code:{name:I,size:3}},h[C]={niceType:"Mastercard",type:C,patterns:[[51,55],[2221,2229],[223,229],[23,26],[270,271],2720],gaps:[4,8,12],lengths:[16],code:{name:M,size:3}},h[S]={niceType:"American Express",type:S,patterns:[34,37],gaps:[4,10],lengths:[15],code:{name:x,size:4}},h[E]={niceType:"Diners Club",type:E,patterns:[[300,305],36,38,39],gaps:[4,10],lengths:[14,16,19],code:{name:I,size:3}},h[T]={niceType:"Discover",type:T,patterns:[6011,[644,649],65],gaps:[4,8,12],lengths:[16,19],code:{name:x,size:3}},h[w]={niceType:"JCB",type:w,patterns:[2131,1800,[3528,3589]],gaps:[4,8,12],lengths:[16,17,18,19],code:{name:I,size:3}},h[A]={niceType:"UnionPay",type:A,patterns:[620,[624,626],[62100,62182],[62184,62187],[62185,62197],[62200,62205],[622010,622999],622018,[622019,622999],[62207,62209],[622126,622925],[623,626],6270,6272,6276,[627700,627779],[627781,627799],[6282,6289],6291,6292],gaps:[4,8,12],lengths:[16,17,18,19],code:{name:N,size:3}},h[O]={niceType:"Maestro",type:O,patterns:[493698,[5e5,506698],[506779,508999],[56,59],63,67,6],gaps:[4,8,12],lengths:[12,13,14,15,16,17,18,19],code:{name:M,size:3}},h[b]={niceType:"Elo",type:b,patterns:[401178,401179,438935,457631,457632,431274,451416,457393,504175,[506699,506778],[509e3,509999],627780,636297,636368,[650031,650033],[650035,650051],[650405,650439],[650485,650538],[650541,650598],[650700,650718],[650720,650727],[650901,650978],[651652,651679],[655e3,655019],[655021,655058]],gaps:[4,8,12],lengths:[16],code:{name:D,size:3}},h[z]={niceType:"Mir",type:z,patterns:[[2200,2204]],gaps:[4,8,12],lengths:[16,17,18,19],code:{name:V,size:3}},c.getTypeInfo=function(e){return r(i(e))},c.removeCard=function(e){var n=y(e);l.splice(n,1)},c.addCard=function(e){var n=y(e.type,!0);m[e.type]=e,n===-1&&l.push(e.type)},c.updateCard=function(e,n){var t,i=m[e]||h[e];if(!i)throw new Error('"'+e+'" is not a recognized type. Use `addCard` instead.');if(n.type&&i.type!==n.type)throw new Error("Cannot overwrite type parameter.");t=r(i,!0),Object.keys(t).forEach(function(e){n[e]&&(t[e]=n[e])}),m[t.type]=t},c.changeOrder=function(e,n){var t=y(e);l.splice(t,1),l.splice(n,0,e)},c.resetModifications=function(){l=r(R),m={}},c.types={VISA:v,MASTERCARD:C,AMERICAN_EXPRESS:S,DINERS_CLUB:E,DISCOVER:T,JCB:w,UNIONPAY:A,MAESTRO:O,ELO:b,MIR:z},n.exports=c},{}]},{},[1])(1)}); |
425
index.js
@@ -35,19 +35,9 @@ 'use strict'; | ||
function clone(originalObject, persistPatterns) { | ||
var dupe, prefixPattern, exactPattern; | ||
function clone(originalObject) { | ||
var dupe; | ||
if (!originalObject) { return null; } | ||
prefixPattern = originalObject.prefixPattern; | ||
exactPattern = originalObject.exactPattern; | ||
dupe = JSON.parse(JSON.stringify(originalObject)); | ||
if (persistPatterns) { | ||
dupe.prefixPattern = prefixPattern; | ||
dupe.exactPattern = exactPattern; | ||
} else { | ||
delete dupe.prefixPattern; | ||
delete dupe.exactPattern; | ||
} | ||
return dupe; | ||
@@ -61,9 +51,5 @@ } | ||
type: VISA, | ||
prefixPattern: /^4/, | ||
exactPattern: new RegExp('^' + | ||
'4' + | ||
'(?!' + | ||
'31274|51416|57393|0117[89]|38935|5763[12]' + // Elo cards | ||
')\\d{5,}' + | ||
'$'), | ||
patterns: [ | ||
4 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -80,4 +66,10 @@ lengths: [16, 18, 19], | ||
type: MASTERCARD, | ||
prefixPattern: /^(5|5[1-5]|2|22|222|222[1-9]|2[3-6]|27|27[0-2]|2720)$/, | ||
exactPattern: /^(5[1-5]|222[1-9]|22[3-9]|2[3-6]|27[0-1]|2720)\d*$/, | ||
patterns: [ | ||
[51, 55], | ||
[2221, 2229], | ||
[223, 229], | ||
[23, 26], | ||
[270, 271], | ||
2720 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -94,5 +86,6 @@ lengths: [16], | ||
type: AMERICAN_EXPRESS, | ||
prefixPattern: /^(3|34|37)$/, | ||
exactPattern: /^3[47]\d*$/, | ||
isAmex: true, | ||
patterns: [ | ||
34, | ||
37 | ||
], | ||
gaps: [4, 10], | ||
@@ -109,4 +102,8 @@ lengths: [15], | ||
type: DINERS_CLUB, | ||
prefixPattern: /^(3|3[0689]|30[0-5])$/, | ||
exactPattern: /^3(0[0-5]|[689])\d*$/, | ||
patterns: [ | ||
[300, 305], | ||
36, | ||
38, | ||
39 | ||
], | ||
gaps: [4, 10], | ||
@@ -123,33 +120,7 @@ lengths: [14, 16, 19], | ||
type: DISCOVER, | ||
prefixPattern: /^(6|60|601|6011|65|65\d{1,4}|64|64[4-9])$/, | ||
exactPattern: new RegExp('^(' + | ||
'6011' + | ||
'|' + | ||
'65' + | ||
'(?!' + // Elo cards | ||
'003[1-3]' + | ||
'|' + | ||
'003[5-9]|004\\d|005[0-1]' + | ||
'|' + | ||
'040[5-9]|04[1-3]\\d' + | ||
'|' + | ||
'048[5-9]|049\\d|05[0-2]\\d|053[0-8]' + | ||
'|' + | ||
'054[1-9]|05[5-8]\\d|059[0-8]' + | ||
'|' + | ||
'070\\d|071[0-8]' + | ||
'|' + | ||
'072[0-7]' + | ||
'|' + | ||
'090[1-9]|09[1-6]\\d|097[0-8]' + | ||
'|' + | ||
'165[2-9]|16[6-7]\\d' + | ||
'|' + | ||
'50[0-1]\\d' + | ||
'|' + | ||
'502[1-9]|50[3-4]\\d|505[0-8]' + | ||
')\\d{4}' + | ||
'|' + | ||
'64[4-9]' + | ||
')\\d*$'), | ||
patterns: [ | ||
6011, | ||
[644, 649], | ||
65 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -166,4 +137,7 @@ lengths: [16, 19], | ||
type: JCB, | ||
prefixPattern: /^(2|21|213|2131|1|18|180|1800|3|35)$/, | ||
exactPattern: /^(2131|1800|35)\d*$/, | ||
patterns: [ | ||
2131, | ||
1800, | ||
[3528, 3589] | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -180,26 +154,24 @@ lengths: [16, 17, 18, 19], | ||
type: UNIONPAY, | ||
prefixPattern: /^((6|62|62\d|(621(?!83|88|98|99))|622(?!06)|627[0267]\d?|628(?!0|1)|629[1,2])|622018)$/, | ||
exactPattern: new RegExp('^(' + | ||
'(' + | ||
'620' + | ||
'|' + | ||
'(621(?!83|88|98|99))' + | ||
'|' + | ||
'622(?!06|018)' + | ||
'|' + | ||
'62[3-6]' + | ||
'|' + | ||
'627[026]' + | ||
'|' + | ||
'6277(?!80)\\d{2}' + // Elo card | ||
'|' + | ||
'628(?!0|1)' + | ||
'|' + | ||
'629[12]' + | ||
')\\d*' + | ||
'|' + | ||
'622018\\d{12}' + | ||
')$'), | ||
patterns: [ | ||
620, | ||
[624, 626], | ||
[62100, 62182], | ||
[62184, 62187], | ||
[62185, 62197], | ||
[62200, 62205], | ||
[622010, 622999], | ||
622018, | ||
[622019, 622999], | ||
[62207, 62209], | ||
[622126, 622925], | ||
[623, 626], | ||
6270, | ||
6272, | ||
6276, | ||
[627700, 627779], | ||
[627781, 627799], | ||
[6282, 6289], | ||
6291, | ||
6292 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -216,23 +188,11 @@ lengths: [16, 17, 18, 19], | ||
type: MAESTRO, | ||
prefixPattern: /^(5|5[06-9]|6\d*)$/, | ||
exactPattern: new RegExp('^(' + | ||
'5[6-9]' + | ||
'|' + | ||
'50' + | ||
'(?!' + // Elo card ranges | ||
'6699|067[0-6][0-9]' + | ||
'|' + | ||
'677[0-8]' + | ||
'|' + | ||
'9[0-9][0-9][0-9]' + | ||
')\\d{4}' + | ||
'|' + | ||
'67' + | ||
'|' + | ||
'63' + | ||
'(?!' + // More Elo card ranges | ||
'6297|6368' + | ||
')\\d{4}' + | ||
')\\d*$' | ||
), | ||
patterns: [ | ||
493698, | ||
[500000, 506698], | ||
[506779, 508999], | ||
[56, 59], | ||
63, | ||
67, | ||
6 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -249,105 +209,29 @@ lengths: [12, 13, 14, 15, 16, 17, 18, 19], | ||
type: ELO, | ||
prefixPattern: new RegExp('^(' + | ||
'[4-6]' + | ||
'|' + | ||
'4[035]|4[035]1' + | ||
'|' + | ||
'4011|40117|40117[89]' + | ||
'|' + | ||
'4312|43127|431274' + | ||
'|' + | ||
'438|4389|43893|438935' + | ||
'|' + | ||
'4514|45141|451416' + | ||
'|' + | ||
'457|457[36]|45739|45763|457393|45763[12]' + | ||
'|' + | ||
'50|50[69]' + | ||
'|' + | ||
'506[6-7]|50669|5067[0-7]|5067[0-6][0-9]|50677[0-8]' + | ||
'|' + | ||
'509[0-9]|509[0-9][0-9]|509[0-9][0-9][0-9]' + | ||
'|' + | ||
'6[235]|627|636|65[015]' + | ||
'|' + | ||
'6277|62778|627780' + | ||
'|' + | ||
'636[23]|63629|636297|63636|636368' + | ||
'|' + | ||
'650[0479]' + | ||
'|' + | ||
'6500[3-5]|65003[1-3]|65003[5-9]|65004[0-9]65005[01]' + | ||
'|' + | ||
'6504[0-3]|65040[5-9]|65041[0-9]' + | ||
'|' + | ||
'6505[4-9]|65054[1-9]|6505[5-8][0-9]|65059[0-8]' + | ||
'|' + | ||
'6507[0-2]|65070[0-9]|65071[0-8]|65072[0-7]' + | ||
'|' + | ||
'6509[0-7]|65090[1-9]|6509[1-6][0-9]|65097[0-8]' + | ||
'|' + | ||
'6516|6516[5-7]|65165[2-9]|6516[6-7][0-9]' + | ||
'|' + | ||
'6550|6550[0-5]|6550[01][0-9]|65502[1-9]|6550[3-4][0-9]|65505[0-8]' + | ||
')$'), | ||
exactPattern: new RegExp('^(' + | ||
// Elo only ranges | ||
'4(31274|51416|57393)' + | ||
'|' + | ||
'50(' + | ||
'4175' + | ||
'|' + | ||
'6699|67[0-6][0-9]|677[0-8]' + // 506699-506778 | ||
'|' + | ||
'9[0-9][0-9][0-9]' + // 509000-509999 | ||
')' + | ||
'|' + | ||
'627780' + | ||
'|' + | ||
'636(297|368)' + | ||
'|' + | ||
// Dual Branded with Visa | ||
'4(0117[89]|38935|5763[12])' + | ||
'|' + | ||
// Dual Branded with Discover | ||
'65(' + | ||
'003[1-3]' + // 650031-650033 | ||
'|' + | ||
'003[5-9]|004\\d|005[0-1]' + // 650035-650051 | ||
'|' + | ||
'040[5-9]|04[1-3]\\d' + // 650405-650439 | ||
'|' + | ||
'048[5-9]|049\\d|05[0-2]\\d|053[0-8]' + // 650485-650538 | ||
'|' + | ||
'054[1-9]|05[5-8]\\d|059[0-8]' + // 650541-650598 | ||
'|' + | ||
'070[0-9]|071[0-8]' + // 650700-650718 | ||
'|' + | ||
'072[0-7]' + // 650720-650727 | ||
'|' + | ||
'090[1-9]|09[1-6][0-9]|097[0-8]' + // 650901-650978 | ||
'|' + | ||
'165[2-9]|16[6-7][0-9]' + // 651652-651679 | ||
'|' + | ||
'50[0-1][0-9]' + // 655000-655019 | ||
'|' + | ||
'502[1-9]|50[3-4][0-9]|505[0-8]' + // 655021-655058 | ||
')' + | ||
')\\d*$'), | ||
patterns: [ | ||
401178, | ||
401179, | ||
438935, | ||
457631, | ||
457632, | ||
431274, | ||
451416, | ||
457393, | ||
504175, | ||
[506699, 506778], | ||
[509000, 509999], | ||
627780, | ||
636297, | ||
636368, | ||
[650031, 650033], | ||
[650035, 650051], | ||
[650405, 650439], | ||
[650485, 650538], | ||
[650541, 650598], | ||
[650700, 650718], | ||
[650720, 650727], | ||
[650901, 650978], | ||
[651652, 651679], | ||
[655000, 655019], | ||
[655021, 655058] | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -364,4 +248,5 @@ lengths: [16], | ||
type: MIR, | ||
prefixPattern: /^(2|22|220|220[0-4])$/, | ||
exactPattern: /^(220[0-4])\d*$/, | ||
patterns: [ | ||
[2200, 2204] | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -379,30 +264,124 @@ lengths: [16, 17, 18, 19], | ||
function isValidInputType(cardNumber) { | ||
return typeof cardNumber === 'string' || cardNumber instanceof String; | ||
} | ||
function hasEnoughResultsToDetermineBestMatch(results) { | ||
var numberOfResultsWithMaxStrengthProperty = results.filter(function (result) { | ||
return result.matchStrength; | ||
}).length; | ||
// if all possible results have a maxStrength property | ||
// that means the card number is sufficiently long | ||
// enough to determine conclusively what the type is | ||
return numberOfResultsWithMaxStrengthProperty > 0 && | ||
numberOfResultsWithMaxStrengthProperty === results.length; | ||
} | ||
function findBestMatch(results) { | ||
if (!hasEnoughResultsToDetermineBestMatch(results)) { | ||
return; | ||
} | ||
return results.reduce(function (bestMatch, result) { // eslint-disable-line consistent-return | ||
if (!bestMatch) { | ||
return result; | ||
} | ||
// if the current best match pattern is less specific | ||
// than this result, set the result as the new best match | ||
if (bestMatch.matchStrength < result.matchStrength) { | ||
return result; | ||
} | ||
return bestMatch; | ||
}); | ||
} | ||
function getAllCardTypes() { | ||
return testOrder.map(function (type) { | ||
return clone(findType(type)); | ||
}); | ||
} | ||
function creditCardType(cardNumber) { | ||
var type, value, i; | ||
var prefixResults = []; | ||
var exactResults = []; | ||
var bestMatch; | ||
var results = []; | ||
if (!(typeof cardNumber === 'string' || cardNumber instanceof String)) { | ||
if (!isValidInputType(cardNumber)) { | ||
return []; | ||
} | ||
for (i = 0; i < testOrder.length; i++) { | ||
type = testOrder[i]; | ||
value = findType(type); | ||
if (cardNumber.length === 0) { | ||
return getAllCardTypes(); | ||
} | ||
if (cardNumber.length === 0) { | ||
prefixResults.push(clone(value)); | ||
testOrder.forEach(function (type) { | ||
var cardConfiguration = findType(type); | ||
loopOverCardPatterns(cardNumber, cardConfiguration, results); | ||
}); | ||
bestMatch = findBestMatch(results); | ||
if (bestMatch) { | ||
return [bestMatch]; | ||
} | ||
return results; | ||
} | ||
function loopOverCardPatterns(cardNumber, cardConfiguration, results) { | ||
var i, pattern, patternLength, clonedCardConfiguration; | ||
for (i = 0; i < cardConfiguration.patterns.length; i++) { | ||
pattern = cardConfiguration.patterns[i]; | ||
if (!matches(cardNumber, pattern)) { | ||
continue; | ||
} | ||
if (value.exactPattern.test(cardNumber)) { | ||
exactResults.push(clone(value)); | ||
} else if (value.prefixPattern.test(cardNumber)) { | ||
prefixResults.push(clone(value)); | ||
clonedCardConfiguration = clone(cardConfiguration); | ||
if (Array.isArray(pattern)) { | ||
patternLength = String(pattern[0]).length; | ||
} else { | ||
patternLength = String(pattern).length; | ||
} | ||
if (cardNumber.length >= patternLength) { | ||
clonedCardConfiguration.matchStrength = patternLength; | ||
} | ||
results.push(clonedCardConfiguration); | ||
break; | ||
} | ||
} | ||
return exactResults.length ? exactResults : prefixResults; | ||
function matches(cardNumber, pattern) { | ||
if (Array.isArray(pattern)) { | ||
return matchesRange(cardNumber, pattern[0], pattern[1]); | ||
} | ||
return matchesPattern(cardNumber, pattern); | ||
} | ||
function matchesPattern(cardNumber, pattern) { | ||
pattern = String(pattern); | ||
return pattern.substring(0, cardNumber.length) === cardNumber.substring(0, pattern.length); | ||
} | ||
// Adapted from https://github.com/polvo-labs/card-type/blob/aaab11f80fa1939bccc8f24905a06ae3cd864356/src/cardType.js#L37-L42 | ||
function matchesRange(cardNumber, min, max) { | ||
var maxLengthToCheck = String(min).length; | ||
var substr = cardNumber.substr(0, maxLengthToCheck); | ||
var integerRepresentationOfCardNumber = parseInt(substr, 10); | ||
min = parseInt(String(min).substr(0, substr.length), 10); | ||
max = parseInt(String(max).substr(0, substr.length), 10); | ||
return integerRepresentationOfCardNumber >= min && integerRepresentationOfCardNumber <= max; | ||
} | ||
creditCardType.getTypeInfo = function (type) { | ||
@@ -409,0 +388,0 @@ return clone(findType(type)); |
{ | ||
"name": "credit-card-type", | ||
"version": "7.1.0", | ||
"version": "8.0.0", | ||
"description": "A library for determining credit card type", | ||
@@ -8,3 +8,4 @@ "main": "index.js", | ||
"lint": "eslint .", | ||
"test": "npm run lint && mocha test/**/*.js", | ||
"pretest": "npm run lint", | ||
"test": "mocha test/**/*.js", | ||
"build": "npm run lint && gulp build" | ||
@@ -11,0 +12,0 @@ }, |
@@ -124,5 +124,32 @@ Credit Card Type [![Build Status](https://travis-ci.org/braintree/credit-card-type.svg)](https://travis-ci.org/braintree/credit-card-type) [![npm version](https://badge.fury.io/js/credit-card-type.svg)](http://badge.fury.io/js/credit-card-type) [![Bower](https://badge.fury.io/bo/credit-card-type.svg)](http://badge.fury.io/bo/credit-card-type) | ||
#### Pattern Detection | ||
Each card type has a `patterns` attribute that is an array of numbers and ranges of numbers (represented by an array of 2 values, a min and a max). | ||
If the pattern is a number, the modules compares it against the card number. Partial matches for card numbers that are shorter than the pattern also match. Given the pattern `123`, then the card numbers `1`, `12`, `123`, `1234` will all match, but `2`, `13`, and `124` will not. | ||
If the pattern is an array of numbers, then the card number is checked to be within the range of those numbers. Again, partial matches are accepted. Given the range `[100, 123]`, then the card numbers `1`, `10`, `100`, `12`, `120`, | ||
`123` will all match, but `2`, `13`, and `124` will not. | ||
For detection, the module loops over each card type's `patterns` array, and if a match occurs, that card type is added to the array of results. | ||
In the case where multiple matches are made, if the entirety of the pattern is matched, the card type with the stronger pattern is preferred. For instance, Visa cards match anything that starts with a 4, but there are | ||
some Elo cards that begin with a 4. One example is `401178`. So for the card | ||
numbers, `4`, `40`, `401`, `4011`, `40117`, the module will report that this | ||
card is _either_ a Visa or an Elo card. Once the card number becomes `401178`, | ||
the modules sees that an exact match for the ELO bin has been made, and the module reports | ||
that the card can only be an Elo card. | ||
```javascript | ||
var visa = creditCardType.getTypeInfo(creditCardType.types.VISA); | ||
visa.prefixPattern = /^(4)$/; | ||
visa.exactPattern = /^(4[0-1])\d*$/; // restrict to only match visas that start with 40 or 41 | ||
creditCardType.addCard(visa); | ||
``` | ||
#### Adding Card Types | ||
You can add additional card brands not supportted by the the module with `addCard`. Pass in the configuration object. | ||
You can add additional card brands not supportted by the the module with `addCard`. Pass in the configuration object. | ||
@@ -133,4 +160,6 @@ ```javascript | ||
type: 'new-card', | ||
prefixPattern: /^(2|23|234)$/, | ||
exactPattern: /^(2345)\d*$/, | ||
patterns: [ | ||
2345, | ||
2376 | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -145,3 +174,3 @@ lengths: [16], | ||
You can also modify existing cards: | ||
If you add a card that already exists in the module, it will overwrite it. | ||
@@ -152,4 +181,6 @@ ```javascript | ||
type: creditCardType.types.VISA, | ||
prefixPattern: /^(4)$/, | ||
exactPattern: /^(4[0-1])\d*$/, // restrict to only match visas that start with 40 or 41 | ||
patterns: [ | ||
41111 | ||
[44, 47] | ||
], | ||
gaps: [4, 8, 12], | ||
@@ -164,15 +195,2 @@ lengths: [13, 16, 19], // add support for old, deprecated 13 digit visas | ||
The `exactPattern` regex is checked first. If that pattern is matched, the module takes that result over the `prefixPattern`. The `prefixPattern` is a softer matcher for when the exact card type has not yet been determined, so multiple card types may be returned. | ||
As an example, by default, the Visa `exactPattern` matches any card number that starts with 4. If you are adding a card type that has a bin range that starts with 4, you will not only have to call `addCard` with the new card type, but `addCard` with Visa to alter the `exactPattern` and `prefixPattern`; | ||
```javascript | ||
var visa = creditCardType.getTypeInfo(creditCardType.types.VISA); | ||
visa.prefixPattern = /^(4)$/; | ||
visa.exactPattern = /^(4[0-1])\d*$/; // restrict to only match visas that start with 40 or 41 | ||
creditCardType.addCard(visa); | ||
``` | ||
Adding new cards puts them at the bottom of the priority for testing. Priority is determined by an array. By default, the priority looks like: | ||
@@ -179,0 +197,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
289
38582
777
1