|
1 |
| -/** |
2 |
| - * |
3 |
| - * Card Validation Library |
4 |
| - * |
5 |
| - * @author Naseef O |
6 |
| - * |
7 |
| - */ |
8 |
| - |
9 |
| -/** |
10 |
| -* Cards details |
11 |
| -* Todo -> add other cards |
12 |
| -*/ |
13 |
| -const cardDetails = { |
14 |
| - Visa: { |
15 |
| - code: "Visa", |
16 |
| - displayName: "Visa", |
17 |
| - lengths: [16], |
18 |
| - cvvLength: 3, |
19 |
| - imageUrl: "./assets/visa.svg", |
20 |
| - }, |
21 |
| - MasterCard: { |
22 |
| - code: "MasterCard", |
23 |
| - displayName: "MasterCard", |
24 |
| - lengths: [16], |
25 |
| - cvvLength: 3, |
26 |
| - imageUrl: "./assets/mastercard.svg", |
27 |
| - }, |
28 |
| - Amex: { |
29 |
| - code: "Amex", |
30 |
| - displayName: "American Express", |
31 |
| - lengths: [15], |
32 |
| - cvvLength: 4, |
33 |
| - imageUrl: "./assets/amex.svg", |
34 |
| - }, |
35 |
| -}; |
36 |
| - |
37 |
| -/** |
38 |
| - * This method is used to identify card type |
39 |
| - * |
40 |
| - * @param {String} cardNumber |
41 |
| - * @returns |
42 |
| - */ |
43 |
| -const identifyCardType = (cardNumber) => { |
44 |
| - // Todo --> check to identify other cards |
45 |
| - if (!cardNumber) return null; |
46 |
| - // visa |
47 |
| - let re = new RegExp("^4"); |
48 |
| - if (cardNumber.match(re) != null) { return "Visa"; } |
49 |
| - |
50 |
| - // Mastercard |
51 |
| - // Updated for Mastercard 2017 BINs expansion |
52 |
| - if (/^(5[1-5][0-9]{14}|2(22[1-9][0-9]{12}|2[3-9][0-9]{13}|[3-6][0-9]{14}|7[0-1][0-9]{13}|720[0-9]{12}))$/.test(cardNumber)) { |
53 |
| - return "MasterCard"; |
54 |
| - } |
55 |
| - |
56 |
| - // AMEX |
57 |
| - re = new RegExp("^3[47]"); |
58 |
| - if (cardNumber.match(re) != null) { return "Amex"; } |
59 |
| - |
60 |
| - // Discover |
61 |
| - re = new RegExp("^(6011|622(12[6-9]|1[3-9][0-9]|[2-8][0-9]{2}|9[0-1][0-9]|92[0-5]|64[4-9])|65)"); |
62 |
| - if (cardNumber.match(re) != null) { return "Discover"; } |
63 |
| - |
64 |
| - // Diners |
65 |
| - re = new RegExp("^36"); |
66 |
| - if (cardNumber.match(re) != null) { return "Diners"; } |
67 |
| - |
68 |
| - // Diners - Carte Blanche |
69 |
| - re = new RegExp("^30[0-5]"); |
70 |
| - if (cardNumber.match(re) != null) { return "Diners - Carte Blanche"; } |
71 |
| - |
72 |
| - // JCB |
73 |
| - re = new RegExp("^35(2[89]|[3-8][0-9])"); |
74 |
| - if (cardNumber.match(re) != null) { return "JCB"; } |
75 |
| - |
76 |
| - // Visa Electron |
77 |
| - re = new RegExp("^(4026|417500|4508|4844|491(3|7))"); |
78 |
| - if (cardNumber.match(re) != null) { return "Visa Electron"; } |
79 |
| -}; |
80 |
| - |
81 |
| -/** |
82 |
| - * This method is used to get card details from card number |
83 |
| - * |
84 |
| - * @param {String} cardNumber |
85 |
| - * @returns |
86 |
| - */ |
87 |
| -const getCardNumberDetails = (cardNumber) => { |
88 |
| - const cardType = identifyCardType(cardNumber); |
89 |
| - return cardType ? cardDetails[cardType] : null; |
90 |
| -}; |
91 |
| - |
92 |
| -/** |
93 |
| - * This method is used to get card details from card type |
94 |
| - * |
95 |
| - * @param {String} cardNumber |
96 |
| - * @returns |
97 |
| - */ |
98 |
| -const getCardDetailsByDetails = (cardType) => (cardType ? cardDetails[cardType] : null); |
99 |
| - |
100 |
| -/** |
101 |
| - * This method is used to get card default image |
102 |
| - * |
103 |
| - * @param {String} cardType |
104 |
| - * @returns |
105 |
| - */ |
106 |
| -const getCardDefaultImageByDetails = (cardType) => { |
107 |
| - if (cardType && cardDetails[cardType]) { |
108 |
| - return cardDetails[cardType].defaultImageUrl; |
109 |
| - } |
110 |
| - return ""; |
111 |
| -}; |
112 |
| - |
113 |
| -/** |
114 |
| - * This method is used to check the card number is valid |
115 |
| - * |
116 |
| - * @param {String} cardNumber |
117 |
| - * @param {String} type |
118 |
| - * @returns |
119 |
| - */ |
120 |
| -const isValidCardNumber = (cardNumber, type) => cardDetails[type] |
121 |
| - && cardDetails[type].lengths.includes(cardNumber.length); |
122 |
| - |
123 |
| - |
124 |
| - |
125 |
| -/** |
126 |
| -* Checking is valid card length by card number and card type , |
127 |
| -* default it's 16 for cyber-source-integration |
128 |
| -* |
129 |
| -* @param {*} cardNumber |
130 |
| -* @returns |
131 |
| -*/ |
132 |
| -const isValidCardLength = (cardNumber) => { |
133 |
| - const valid = false; |
134 |
| - if (cardNumber) { |
135 |
| - const card = getCardNumberDetails(cardNumber); |
136 |
| - if (card |
137 |
| - && card.lengths.includes(cardNumber.length)) { |
138 |
| - return true; |
139 |
| - } if (cardNumber.length === 16) { |
140 |
| - return true; |
141 |
| - } |
142 |
| - } |
143 |
| - return valid; |
144 |
| -}; |
145 |
| - |
146 |
| -const formatCardNumber = (e, value, position) => { |
147 |
| - const format = (val) => val.replace(/[^\dA-Z]/gi, "") |
148 |
| - .toUpperCase() |
149 |
| - .replace(/(.{4})/g, "$1 ") |
150 |
| - .trim(); |
151 |
| - const countSpaces = (text) => { |
152 |
| - const spaces = text.match(/(\s+)/g); |
153 |
| - return spaces ? spaces.length : 0; |
154 |
| - }; |
155 |
| - const element = e.target; |
156 |
| - element.value = format(value); |
157 |
| - if (position !== element.value.length) { |
158 |
| - const beforeCaret = value.substr(0, position); |
159 |
| - const countPrevious = countSpaces(beforeCaret); |
160 |
| - const countCurrent = countSpaces(format(beforeCaret)); |
161 |
| - element.selectionEnd = position + (countCurrent - countPrevious); |
162 |
| - } |
163 |
| -}; |
164 |
| - |
165 |
| -export { |
166 |
| - getCardNumberDetails, |
167 |
| - isValidCardNumber, |
168 |
| - getCardDetailsByDetails, |
169 |
| - getCardDefaultImageByDetails, |
170 |
| - isValidCardLength, |
171 |
| - formatCardNumber, |
172 |
| -}; |
| 1 | +// Set options as a parameter, environment variable, or rc file. |
| 2 | +// eslint-disable-next-line no-global-assign |
| 3 | +require = require("esm")(module/* , options */) |
| 4 | +module.exports = require("./main.js") |
0 commit comments