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  }