1package faker
  2
  3import (
  4	"reflect"
  5	"strconv"
  6	"strings"
  7
  8	"github.com/go-faker/faker/v4/pkg/options"
  9)
 10
 11const (
 12	numberBytes = "0123456789"
 13)
 14
 15// creditCard struct
 16type creditCard struct {
 17	ccType   string
 18	length   int
 19	prefixes []int
 20}
 21
 22var creditCards = map[string]creditCard{
 23	"visa":             {"VISA", 16, []int{4539, 4556, 4916, 4532, 4929, 40240071, 4485, 4716, 4}},
 24	"mastercard":       {"MasterCard", 16, []int{51, 52, 53, 54, 55}},
 25	"american express": {"American Express", 15, []int{34, 37}},
 26	"discover":         {"Discover", 16, []int{6011}},
 27	"jcb":              {"JCB", 16, []int{3528, 3538, 3548, 3558, 3568, 3578, 3588}},
 28	"diners club":      {"Diners Club", 14, []int{36, 38, 39}},
 29}
 30
 31var cacheCreditCard string
 32
 33// GetPayment returns a new Render interface of Payment struct
 34func GetPayment() Render {
 35	pay := &Payment{}
 36	return pay
 37}
 38
 39// Render contains Whole Random Credit Card Generators with their types
 40type Render interface {
 41	CreditCardType(v reflect.Value) (interface{}, error)
 42	CreditCardNumber(v reflect.Value) (interface{}, error)
 43}
 44
 45// Payment struct
 46type Payment struct{}
 47
 48func (p Payment) cctype() string {
 49	n := len(creditCards)
 50	if cacheCreditCard != "" {
 51		return cacheCreditCard
 52	}
 53	var ccTypes []string
 54
 55	for _, cc := range creditCards {
 56		ccTypes = append(ccTypes, cc.ccType)
 57	}
 58	cacheCreditCard = ccTypes[rand.Intn(n)]
 59	return cacheCreditCard
 60}
 61
 62// CreditCardType returns one of the following credit values:
 63// VISA, MasterCard, American Express, Discover, JCB and Diners Club
 64func (p Payment) CreditCardType(v reflect.Value) (interface{}, error) {
 65	return p.cctype(), nil
 66}
 67
 68// CCType get a credit card type randomly in string (VISA, MasterCard, etc)
 69func CCType(opts ...options.OptionFunc) string {
 70	return singleFakeData(CreditCardType, func() interface{} {
 71		p := Payment{}
 72		return p.cctype()
 73	}, opts...).(string)
 74}
 75
 76func (p Payment) ccnumber() string {
 77	ccType := p.cctype()
 78	cacheCreditCard = ccType
 79	card := creditCards[strings.ToLower(ccType)]
 80	prefix := strconv.Itoa(card.prefixes[rand.Intn(len(card.prefixes))])
 81
 82	num := prefix
 83	digit := randomStringNumber(card.length - len(prefix))
 84
 85	num += digit
 86	return num
 87}
 88
 89// CreditCardNumber generated credit card number according to the card number rules
 90func (p Payment) CreditCardNumber(v reflect.Value) (interface{}, error) {
 91	return p.ccnumber(), nil
 92}
 93
 94// CCNumber get a credit card number randomly in string (VISA, MasterCard, etc)
 95func CCNumber(opts ...options.OptionFunc) string {
 96	return singleFakeData(CreditCardNumber, func() interface{} {
 97		p := Payment{}
 98		return p.ccnumber()
 99	}, opts...).(string)
100}