luhn
This commit is contained in:
commit
06198ced9a
6 changed files with 125 additions and 0 deletions
0
Dockerfile
Normal file
0
Dockerfile
Normal file
0
README.md
Normal file
0
README.md
Normal file
0
cmd/api.go
Normal file
0
cmd/api.go
Normal file
3
go.mod
Normal file
3
go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module git.tertyshy.dev/cards
|
||||
|
||||
go 1.23.2
|
62
lib/validate.go
Normal file
62
lib/validate.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
package validate
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Card struct {
|
||||
Pan string
|
||||
Month string
|
||||
Year string
|
||||
}
|
||||
|
||||
type ValidationResult struct {
|
||||
Code int
|
||||
Error error
|
||||
}
|
||||
|
||||
func Luhn(pan string) bool {
|
||||
if pan == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
lastIndex := len(pan) - 1
|
||||
|
||||
asDigits := []int{}
|
||||
|
||||
for _, char := range strings.Split(pan, "") {
|
||||
digit, err := strconv.Atoi(char)
|
||||
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
asDigits = append(asDigits, digit)
|
||||
}
|
||||
|
||||
sum := 0
|
||||
|
||||
// do we really need reversed array?
|
||||
for i, digit := range slices.Backward(asDigits[:lastIndex]) {
|
||||
|
||||
if i%2 == len(pan)%2 {
|
||||
if digit > 4 {
|
||||
sum += 2*digit - 9
|
||||
} else {
|
||||
sum += 2 * digit
|
||||
}
|
||||
} else {
|
||||
sum += digit
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return asDigits[lastIndex] == (10-(sum%10))%10
|
||||
}
|
||||
|
||||
func Validate(card Card) (bool, ValidationResult) {
|
||||
|
||||
return true, ValidationResult{}
|
||||
}
|
60
lib/validate_test.go
Normal file
60
lib/validate_test.go
Normal file
|
@ -0,0 +1,60 @@
|
|||
package validate
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestLuhn(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pan string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
"Mastercard",
|
||||
"5555555555554444",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"Visa",
|
||||
"4111111111111111",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"example from wiki",
|
||||
"17893729974",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"another example",
|
||||
"79927398713",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"worong check digit",
|
||||
"17893729975",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"off by one error",
|
||||
"27893729974",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"empty",
|
||||
"",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"not a digit",
|
||||
"27893a29974",
|
||||
false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := Luhn(tt.pan)
|
||||
if got != tt.want {
|
||||
t.Errorf("Luhn(%s) = %v, want %v", tt.name, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue