-
Notifications
You must be signed in to change notification settings - Fork 0
/
decode.go
154 lines (126 loc) · 3.54 KB
/
decode.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package swiss_qr_code
import (
"bufio"
"bytes"
"fmt"
)
// Documentation https://www.six-group.com/dam/download/banking-services/standardization/qr-bill/ig-qr-bill-v2.2-en.pdf
type QrCode struct {
Header Header
CreditorInformation CreditorInformation
Creditor Party
UltimateCreditor *Party
PaymentAmount PaymentAmount
UltimateDebtor *Party
PaymentReference PaymentReference
AdditionalInformation AdditionalInformation
AlternativeSchemes AlternativeSchemes
}
type QRType string
type VersionMajMin struct {
Major int
Minor int
}
type Header struct {
QRType QRType
Version VersionMajMin
CodingType CodingType
}
type Party struct {
AddressType AddressType
Name string
StrtNmOrAdrLine1 string
BldgNbOrAdrLine2 string
PostalCode string
Town string
CountryCode string
}
type PaymentAmount struct {
Amount *MoneyValue
Currency Currency
}
type CreditorInformation struct {
IBAN string
}
type PaymentReference struct {
Type PaymentReferenceType
Reference string
}
type AdditionalInformation struct {
Unstructured string
Trailer string
BillInformation string
}
type AlternativeSchemes struct {
Params []string
}
func Decode(text string) (qrCode *QrCode, err error) {
d := decoder{
r: bufio.NewScanner(bytes.NewBufferString(text)),
}
qrCode = &QrCode{}
header := Header{}
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("%v", r)
}
}()
// Header
header.QRType = parseOrFail(d, parseQrType)
header.Version = parseOrFail(d, parseQrVersion)
header.CodingType = parseOrFail(d, parseQrCodingType)
qrCode.Header = header
qrCode.CreditorInformation = CreditorInformation{}
qrCode.CreditorInformation.IBAN = parseOrFail(d, parseIBAN)
// Party
creditor, err := parseParty(d, false)
if err != nil {
return nil, fmt.Errorf("unable to parse creditor")
}
qrCode.Creditor = *creditor
// Ultimate Party (optional)
ultimateCreditor, err := parseParty(d, true)
if err != nil {
return nil, fmt.Errorf("unable to parse ultimate creditor: %v", err)
}
qrCode.UltimateCreditor = ultimateCreditor
paymentAmount := PaymentAmount{}
paymentAmount.Amount = parseOrFail(d, parseAmount)
paymentAmount.Currency = parseOrFail(d, parseCurrency)
qrCode.PaymentAmount = paymentAmount
// Ultimate Debtor
ultimateDebtor, err := parseParty(d, true)
if err != nil {
return nil, fmt.Errorf("unable to parse ultimate debtor: %v", err)
}
qrCode.UltimateDebtor = ultimateDebtor
// Payment Reference
paymentReference := PaymentReference{}
paymentReference.Type = parseOrFail(d, parsePaymentReference)
switch paymentReference.Type {
case ReferenceQRR:
paymentReference.Reference = parseOrFail(d, parseX(27))
case ScorReference:
paymentReference.Reference = parseOrFail(d, parseX(25))
case NonReference:
paymentReference.Reference = parseOrFail(d, parseX(0))
}
qrCode.PaymentReference = paymentReference
// Additional Information
additionalInformation := AdditionalInformation{}
additionalInformation.Unstructured = parseOrFail(d, parseX(140))
additionalInformation.Trailer = parseOrFail(d, parseTrailer)
additionalInformation.BillInformation = parseOrSkip(d, parseX(140))
qrCode.AdditionalInformation = additionalInformation
// Alternative Schemes (Optional)
alternativeSchemes := AlternativeSchemes{}
alternativeSchemes.Params = []string{
parseOrSkip(d, parseX(100)),
parseOrSkip(d, parseX(100)),
}
qrCode.AlternativeSchemes = alternativeSchemes
if d.err != nil {
return nil, d.err
}
return qrCode, nil
}