github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/internal/pkg/helper/creditcard.go (about) 1 package helper 2 3 import ( 4 "math/rand" 5 "strconv" 6 "strings" 7 "time" 8 ) 9 10 const ( 11 defaultCardType = "visa" 12 ) 13 14 func GenerateCreditCard(cardType string) (ret string) { 15 cardProperties, exists := AvailableCardTypes[cardType] 16 17 if !exists { 18 cardType = defaultCardType 19 cardProperties, _ = AvailableCardTypes[cardType] 20 } 21 22 rand.Seed(time.Now().UnixNano()) 23 24 var card = CreditCard{ 25 Issuer: cardProperties.LongName, 26 Pan: GeneratePAN(cardProperties), 27 ExpiryDate: GenerateExpiryDate(), 28 CVV: GenerateCVV(cardProperties.CvvSize), 29 } 30 31 ret = card.Pan.Raw 32 33 return 34 } 35 36 type CreditCard struct { 37 Issuer string `json:"issuer"` 38 Pan PAN `json:"pan"` 39 ExpiryDate ExpiryDate `json:"expiryDate"` 40 CVV string `json:"cvv"` 41 } 42 43 type ExpiryDate struct { 44 Month int `json:"month"` 45 Year int `json:"year"` 46 } 47 48 type PAN struct { 49 Raw string `json:"raw"` 50 Formatted string `json:"formatted"` 51 } 52 type CardProperties struct { 53 LongName string 54 Prefix []string 55 PanSize int 56 CvvSize int 57 } 58 59 var AvailableCardTypes = map[string]CardProperties{ 60 "amex": { 61 LongName: "American Express", 62 Prefix: []string{"37", "34"}, 63 PanSize: 15, 64 CvvSize: 4, 65 }, 66 "visa": { 67 LongName: "Visa", 68 Prefix: []string{"4"}, 69 PanSize: 16, 70 CvvSize: 3, 71 }, 72 "mc": { 73 LongName: "Mastercard", 74 Prefix: []string{"51", "52", "53", "54", "55"}, 75 PanSize: 16, 76 CvvSize: 3, 77 }, 78 "dci": { 79 LongName: "Diners Club International", 80 Prefix: []string{"36", "38"}, 81 PanSize: 16, 82 CvvSize: 3, 83 }, 84 "jcb": { 85 LongName: "Japan Credit Bureau", 86 Prefix: []string{"35"}, 87 PanSize: 16, 88 CvvSize: 3, 89 }, 90 "discover": { 91 LongName: "Discover", 92 Prefix: []string{"6011", "65"}, 93 PanSize: 16, 94 CvvSize: 3, 95 }, 96 } 97 98 func calculateLuhn(digits string) string { 99 number, _ := strconv.Atoi(digits) 100 checkNumber := checksum(number) 101 if checkNumber == 0 { 102 return "0" 103 } 104 105 return strconv.Itoa(10 - checkNumber) 106 } 107 108 func checksum(number int) int { 109 var sum int 110 for i := 0; number > 0; i++ { 111 digit := number % 10 112 if i%2 == 0 { // even 113 digit = digit * 2 114 if digit > 9 { 115 digit = digit%10 + digit/10 116 } 117 } 118 sum += digit 119 number = number / 10 120 } 121 122 return sum % 10 123 } 124 125 func GeneratePAN(properties CardProperties) PAN { 126 var prefix = properties.Prefix[rand.Intn(len(properties.Prefix))] 127 for len(prefix) < properties.PanSize-1 { 128 prefix = prefix + generateRandomNumberOfSize(1) 129 } 130 131 number := prefix + calculateLuhn(prefix) 132 return PAN{ 133 Raw: number, 134 Formatted: FormatPan(properties.LongName, number), 135 } 136 } 137 138 func FormatPan(cardType string, pan string) string { 139 var formattedPan string 140 for i := 0; i < len(pan); i++ { 141 formattedPan = formattedPan + string(pan[i]) 142 switch cardType { 143 case "American Express": 144 if i == 3 || i == 9 { 145 formattedPan = formattedPan + " " 146 } 147 default: 148 if (i+1)%4 == 0 { 149 formattedPan = formattedPan + " " 150 } 151 } 152 } 153 154 return strings.TrimSpace(formattedPan) 155 } 156 157 func generateRandomNumberOfSize(size int) string { 158 var numbers = []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} 159 var randomNumber []string 160 for i := 0; i < size; i++ { 161 randomNumber = append(randomNumber, numbers[rand.Intn(len(numbers))]) 162 } 163 return strings.Join(randomNumber, "") 164 } 165 166 func GenerateCVV(size int) string { 167 return generateRandomNumberOfSize(size) 168 } 169 170 func GenerateExpiryDate() ExpiryDate { 171 var year = time.Now().Year() + rand.Intn(6) 172 var month = rand.Intn(12) + 1 173 174 return ExpiryDate{ 175 Month: month, 176 Year: year, 177 } 178 }