-
Notifications
You must be signed in to change notification settings - Fork 80
/
credit_cards.go
92 lines (80 loc) · 1.96 KB
/
credit_cards.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package fake
import (
"fmt"
"sort"
"strconv"
"strings"
)
type creditCard struct {
vendor string
length int
prefixes []int
}
func (c creditCard) RandomPrefix() int {
return c.prefixes[r.Intn(len(c.prefixes))]
}
var (
creditCards = map[string]creditCard{
"visa": {"VISA", 16, []int{4539, 4556, 4916, 4532, 4929, 40240071, 4485, 4716, 4}},
"mastercard": {"MasterCard", 16, []int{51, 52, 53, 54, 55}},
"amex": {"American Express", 15, []int{34, 37}},
"discover": {"Discover", 16, []int{6011}},
}
creditCardsKeys = make([]string, len(creditCards))
)
func init() {
n := 0
for key := range creditCards {
creditCardsKeys[n] = key
n++
}
sort.Strings(creditCardsKeys)
}
// CreditCardType returns one of the following credit values:
// VISA, MasterCard, American Express and Discover
func CreditCardType() string {
n := len(creditCards)
var vendors []string
for _, cc := range creditCards {
vendors = append(vendors, cc.vendor)
}
return vendors[r.Intn(n)]
}
// CreditCardNum generated credit card number according to the card number rules
func CreditCardNum(vendor string) string {
if vendor != "" {
vendor = strings.ToLower(vendor)
} else {
vendor = creditCardsKeys[r.Intn(len(creditCardsKeys))]
}
card, ok := creditCards[vendor]
if !ok {
panic(fmt.Sprintf("unsupported vendor %q", vendor))
}
prefix := strconv.Itoa(card.RandomPrefix())
num := []rune(prefix)
for i := 0; i < card.length-len(prefix)-1; i++ {
num = append(num, rune(strconv.Itoa(r.Intn(10))[0]))
}
num = append(num, creditCardNumChecksum(num))
return string(num)
}
func creditCardNumChecksum(num []rune) rune {
// See: https://en.wikipedia.org/wiki/Luhn_algorithm
sum := 0
pos := 0
for i := len(num) - 1; i >= 0; i-- {
n := int(num[i] - '0')
if pos%2 == 0 {
n *= 2
if n > 9 {
n -= 9
}
}
sum += n
pos++
}
// https://en.wikipedia.org/wiki/Talk:Luhn_algorithm#Formula_error
checksum := 10 - (sum%10)%10
return rune(strconv.Itoa(checksum)[0])
}