Skip to content

Commit 582ff53

Browse files
committedDec 22, 2021
initial commit
0 parents  commit 582ff53

12 files changed

+270
-0
lines changed
 

‎.gitignore

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
.idea/**/workspace.xml
2+
.idea/**/tasks.xml
3+
.idea/**/usage.statistics.xml
4+
.idea/**/dictionaries
5+
.idea/**/shelf
6+
.idea/**/contentModel.xml
7+
.idea/**/dataSources/
8+
.idea/**/dataSources.ids
9+
.idea/**/dataSources.local.xml
10+
.idea/**/sqlDataSources.xml
11+
.idea/**/dynamic.xml
12+
.idea/**/uiDesigner.xml
13+
.idea/**/dbnavigator.xml
14+
.idea/**/gradle.xml
15+
.idea/**/libraries
16+
cmake-build-*/
17+
.idea/**/mongoSettings.xml
18+
*.iws
19+
out/
20+
.idea_modules/
21+
atlassian-ide-plugin.xml
22+
.idea/replstate.xml
23+
com_crashlytics_export_strings.xml
24+
crashlytics.properties
25+
crashlytics-build.properties
26+
fabric.properties
27+
.idea/httpRequests
28+
.idea/caches/build_file_checksums.ser
29+
*.exe
30+
*.exe~
31+
*.dll
32+
*.so
33+
*.dylib
34+
*.test
35+
*.out

‎.idea/.gitignore

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/codeStyles/Project.xml

+42
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/codeStyles/codeStyleConfig.xml

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/misc.xml

+23
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎go.mod

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/asonnleitner/qr-payment
2+
3+
go 1.17

‎iban/iban.go

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package iban
2+
3+
import (
4+
"fmt"
5+
"github.com/asonnleitner/qr-payment/utils"
6+
"regexp"
7+
"strings"
8+
)
9+
10+
const (
11+
errInvalidAccountNumber = "Invalid account number"
12+
errCountryCodeNotSupported = "Country code not supported"
13+
)
14+
15+
var (
16+
czechBankAccountPattern = regexp.MustCompile(`^([0-9]{2,6}-)?([0-9]{2,10}/)([0-9]{4})$`)
17+
lettersPattern = regexp.MustCompile(`[A-Z]`)
18+
)
19+
20+
func ParseAccount(account, country string) string {
21+
var pattern *regexp.Regexp
22+
country = strings.ToUpper(country)
23+
account = strings.Replace(account, " ", "", -1)
24+
25+
switch country {
26+
case "CZ":
27+
pattern = czechBankAccountPattern
28+
default:
29+
panic(errCountryCodeNotSupported)
30+
}
31+
32+
prefix, number, bankCode := splitAccount(account, pattern)
33+
34+
return convertToIBAN(country, prefix, number, bankCode)
35+
}
36+
37+
func convertToIBAN(country, prefix, number, bankCode string) string {
38+
var bban string
39+
40+
if country == "CZ" {
41+
bban = bankCode + prefix + number
42+
} else {
43+
panic(errCountryCodeNotSupported)
44+
}
45+
46+
checksum := calculateChecksum(country, bban)
47+
48+
return fmt.Sprintf("%s%s%s", country, checksum, bban)
49+
}
50+
51+
func calculateChecksum(country, bban string) string {
52+
bban = bban + country + "00"
53+
54+
return fmt.Sprintf("%02d", 98-utils.Modulo(
55+
replaceLetters(bban), 97,
56+
))
57+
}
58+
59+
func splitAccount(account string, pattern *regexp.Regexp) (prefix, number, bankCode string) {
60+
account = strings.TrimSpace(account)
61+
62+
if !strings.Contains(account, "-") {
63+
account = "00-" + account
64+
}
65+
66+
if len(account) < 10 || len(account) > 22 {
67+
panic(errInvalidAccountNumber)
68+
}
69+
70+
parts := pattern.FindStringSubmatch(account)
71+
72+
prefix = utils.Padding(
73+
strings.Replace(parts[1], "-", "", -1), 6, "0", utils.PaddingLeft,
74+
)
75+
number = utils.Padding(
76+
strings.Replace(parts[2], "/", "", -1), 10, "0", utils.PaddingLeft,
77+
)
78+
bankCode = parts[3]
79+
return
80+
}
81+
82+
func replaceLetters(iban string) string {
83+
letters := lettersPattern.FindAllString(iban, -1)
84+
85+
for i := 0; i < len(letters); i++ {
86+
iban = strings.Replace(iban, letters[i], fmt.Sprintf("%d", letters[i][0]-'A'+10), -1)
87+
}
88+
89+
return iban
90+
}

‎main.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"github.com/asonnleitner/qr-payment/iban"
6+
)
7+
8+
func main() {
9+
IBAN := iban.ParseAccount("2171532/0800", "CZ")
10+
11+
fmt.Println(IBAN)
12+
}

‎qr-payment.iml

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<module type="WEB_MODULE" version="4">
3+
<component name="Go" enabled="true" />
4+
<component name="NewModuleRootManager" inherit-compiler-output="true">
5+
<exclude-output />
6+
<content url="file://$MODULE_DIR$" />
7+
<orderEntry type="sourceFolder" forTests="false" />
8+
</component>
9+
</module>

‎utils/utils.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package utils
2+
3+
import "strings"
4+
5+
const PaddingLeft = "left"
6+
const PaddingRight = "right"
7+
8+
func Padding(input string, length int, char string, direction string) string {
9+
if len(input) >= length {
10+
return input
11+
}
12+
13+
if direction == "left" {
14+
return strings.Repeat(char, length-len(input)) + input
15+
} else if direction == "right" {
16+
return input + strings.Repeat(char, length-len(input))
17+
} else {
18+
return input
19+
}
20+
}
21+
22+
func Modulo(dividend string, divisor int) int {
23+
var remainder int
24+
25+
for i := 0; i < len(dividend); i++ {
26+
remainder = (remainder*10 + int(dividend[i]-'0')) % divisor
27+
}
28+
29+
return remainder
30+
}

0 commit comments

Comments
 (0)
Please sign in to comment.