1+ package io .multiform_validator ;
2+
3+ import java .util .HashMap ;
4+ import java .util .Map ;
5+ import java .util .regex .Pattern ;
6+ import org .jetbrains .annotations .NotNull ;
7+
8+ public class CreditCard {
9+ private static final String INPUT_VALUE_CANNOT_BE_EMPTY = "Input value cannot be empty." ;
10+
11+ private CreditCard () {
12+ throw new UnsupportedOperationException ("This is a utility class and cannot be instantiated" );
13+ }
14+
15+ /**
16+ * Validate a credit card number.
17+ *
18+ * @param cardNumber The credit card number to be validated.
19+ * @return True if the credit card number is valid, false otherwise.
20+ */
21+ public static boolean isCreditCardValid (@ NotNull String cardNumber ) {
22+ if (cardNumber .isBlank ()) {
23+ throw new IllegalArgumentException (INPUT_VALUE_CANNOT_BE_EMPTY );
24+ }
25+
26+ final String cleanedCreditCardInput = cardNumber .replaceAll ("\\ D" , "" );
27+
28+ if (cleanedCreditCardInput .isBlank () || !Number .isNumber (cleanedCreditCardInput )) {
29+ return false ;
30+ }
31+
32+ final int [] creditCardDigits =
33+ cleanedCreditCardInput .chars ().map (Character ::getNumericValue ).toArray ();
34+ final int creditCardLength = creditCardDigits .length ;
35+
36+ int sum = 0 ;
37+ boolean isEven = false ;
38+
39+ for (int i = creditCardLength - 1 ; i >= 0 ; i --) {
40+ int digit = creditCardDigits [i ];
41+
42+ if (isEven ) {
43+ digit *= 2 ;
44+
45+ if (digit > 9 ) {
46+ digit -= 9 ;
47+ }
48+ }
49+
50+ sum += digit ;
51+ isEven = !isEven ;
52+ }
53+
54+ return sum % 10 == 0 ;
55+ }
56+
57+ /**
58+ * Identify the flag of a credit card.
59+ *
60+ * @param cardNumber The credit card number to be identified.
61+ * @return The flag of the credit card.
62+ */
63+ public static String identifyFlagCard (@ NotNull String cardNumber ) {
64+ if (cardNumber .isBlank ()) {
65+ throw new IllegalArgumentException (INPUT_VALUE_CANNOT_BE_EMPTY );
66+ }
67+
68+ Map <String , Pattern > flags = new HashMap <>();
69+ flags .put ("Visa" , Pattern .compile ("^4" ));
70+ flags .put ("Mastercard" , Pattern .compile ("^5[1-5]" ));
71+ flags .put ("American Express" , Pattern .compile ("^3[47]" ));
72+ flags .put ("Discover" , Pattern .compile ("^6(?:011|5)" ));
73+ flags .put ("JCB" , Pattern .compile ("^(?:2131|1800|35\\ d{3})" ));
74+ flags .put ("Diners Club" , Pattern .compile ("^3(?:0[0-5]|[68])" ));
75+ flags .put ("Maestro" , Pattern .compile ("^(?:5[0678]\\ d\\ d|6304|6390|67\\ d\\ d)" ));
76+ flags .put ("UnionPay" , Pattern .compile ("^(62|88)" ));
77+ flags .put ("Elo" , Pattern .compile ("^63[789]" ));
78+ flags .put ("Hipercard" , Pattern .compile ("^(3841|60)" ));
79+
80+ return flags .entrySet ().stream ()
81+ .filter (flag -> flag .getValue ().matcher (cardNumber ).find ())
82+ .findFirst ()
83+ .map (Map .Entry ::getKey )
84+ .orElse ("Unknown" );
85+ }
86+ }
0 commit comments