Skip to content

Commit be317c5

Browse files
committed
Improvements
1 parent c0b3930 commit be317c5

File tree

8 files changed

+160
-32
lines changed

8 files changed

+160
-32
lines changed

README.md

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,42 @@
44

55
Generate ~~and validate~~ payments of Brazil Instant Payment System (Pix), making fast and simple to handle charges and proccess then in your project.
66

7-
**UNDER DEVELOPMENT** *** Not ready for production
7+
**UNDER DEVELOPMENT** *** Becareful ***
88

99
Example implementation.
1010
```golang
1111
opts := []pix.Options{
12-
pix.OptPixKey("11955555555"),
13-
pix.OptDescription("Teste"),
14-
pix.OptMerchantName("Thiago Zilli Sarmento"),
15-
pix.OptMerchantCity("Ararangua"),
16-
pix.OptAmount("0.00"),
17-
pix.OptKind(pix.STATIC),
18-
}
19-
20-
p, err := pix.New(opts...)
21-
if err != nil {
22-
panic(err)
23-
}
24-
cpy := p.GenPayload()
25-
if err != nil {
26-
panic(err)
27-
}
28-
fmt.Println(cpy)
12+
pix.OptPixKey("11955555555"),
13+
pix.OptDescription("Teste"),
14+
pix.OptMerchantName("Thiago Zilli Sarmento"),
15+
pix.OptMerchantCity("Ararangua"),
16+
pix.OptAmount("1.00"),
17+
pix.OptAditionalInfo("gerado por go-pixgen"),
18+
pix.OptKind(pix.STATIC),
19+
}
20+
21+
p, err := pix.New(opts...)
22+
if err != nil {
23+
fmt.Println(err.Error())
24+
return
25+
}
26+
27+
if err := p.Validates(); err != nil {
28+
fmt.Println(err.Error())
29+
return
30+
}
31+
32+
cpy := p.GenPayload()
33+
34+
fmt.Printf("Copy and Paste: %s\n", cpy)
35+
36+
bts, err := p.GenQRCode()
37+
if err != nil {
38+
fmt.Println(err.Error())
39+
return
40+
}
41+
42+
fmt.Printf("QRCode: %b\n", bts)
2943
```
3044

3145
## Roadmap
@@ -34,7 +48,7 @@ fmt.Println(cpy)
3448
- [x] Static
3549
- [x] Dynamic
3650
- [ ] Parse and validate EMV Codes
37-
- [ ] Export generated/parsed payment to Image
51+
- [x] Export generated/parsed payment to Image
3852
- [x] Export generated/parsed payment to EMV Code
3953
- [ ] Fetch, parse and validate remote payloads from dynamic payments
4054
- [ ] Verify if has already expired

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ go 1.17
44

55
require (
66
github.com/r10r/crc16 v0.1.1
7+
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
78
github.com/snksoft/crc v1.1.0
89
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
github.com/r10r/crc16 v0.1.1 h1:BsuCL6d+j0hBCQ/nNnwHmlTF0shVES2IagUgh1MS6yU=
22
github.com/r10r/crc16 v0.1.1/go.mod h1:I17p13f8bQGzqw5+futttVdERhbvzpgjlPZdwIJ0ka8=
3+
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
4+
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
35
github.com/snksoft/crc v1.1.0 h1:HkLdI4taFlgGGG1KvsWMpz78PkOC9TkPVpTV/cuWn48=
46
github.com/snksoft/crc v1.1.0/go.mod h1:5/gUOsgAm7OmIhb6WJzw7w5g2zfJi4FrHYgGPdshE+A=

main.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,31 @@ func main() {
1313
pix.OptDescription("Teste"),
1414
pix.OptMerchantName("Thiago Zilli Sarmento"),
1515
pix.OptMerchantCity("Ararangua"),
16-
pix.OptAmount("0.00"),
16+
pix.OptAmount("1.00"),
17+
pix.OptAditionalInfo("gerado por go-pixgen"),
1718
pix.OptKind(pix.STATIC),
1819
}
1920

2021
p, err := pix.New(opts...)
2122
if err != nil {
2223
panic(err)
2324
}
25+
26+
if err := p.Validates(); err != nil {
27+
fmt.Println(err.Error())
28+
return
29+
}
30+
2431
cpy := p.GenPayload()
2532
if err != nil {
2633
panic(err)
2734
}
28-
fmt.Println(cpy)
35+
fmt.Printf("Copy and Paste: %s\n", cpy)
36+
37+
bts, err := p.GenQRCode()
38+
if err != nil {
39+
panic(err)
40+
}
41+
fmt.Printf("QRCode: %b\n", bts)
2942

3043
}

pix/const.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package pix
22

33
const (
44
//EmvSchema
5-
//TAG_ONETIME = "1"
65
TAG_INIT = "00"
76
TAG_MAI = "26"
87
TAG_MCC = "52"

pix/options.go

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,44 @@ func (pix PixKind) String() string {
1414
type Options func(o *OptionsParams) error
1515

1616
type OptionsParams struct {
17-
id string
18-
pixKey string
19-
description string
20-
amount string
21-
merchant merchant
22-
kind PixKind
17+
id string
18+
pixKey string
19+
description string
20+
amount string
21+
aditionalInfo string
22+
merchant merchant
23+
kind PixKind
24+
url string
25+
qrcodeContent string
26+
qrcodeSize int
2327
}
2428

2529
type merchant struct {
2630
name string
2731
city string
2832
}
2933

34+
func OptQRCodeSize(value int) Options {
35+
return func(o *OptionsParams) error {
36+
o.qrcodeSize = value
37+
return nil
38+
}
39+
}
40+
41+
func OptUrl(value string) Options {
42+
return func(o *OptionsParams) error {
43+
o.url = value
44+
return nil
45+
}
46+
}
47+
48+
func OptAditionalInfo(value string) Options {
49+
return func(o *OptionsParams) error {
50+
o.aditionalInfo = value
51+
return nil
52+
}
53+
}
54+
3055
func OptKind(kind PixKind) Options {
3156
return func(o *OptionsParams) error {
3257
o.kind = kind
@@ -105,3 +130,25 @@ func (o *OptionsParams) GetAmount() string {
105130
func (o *OptionsParams) GetKind() PixKind {
106131
return o.kind
107132
}
133+
134+
func (o *OptionsParams) GetAditionalInfo() string {
135+
return o.aditionalInfo
136+
}
137+
138+
func (o *OptionsParams) GetUrl() string {
139+
return o.url
140+
}
141+
142+
func (o *OptionsParams) GetQRCodeSize() int {
143+
return o.qrcodeSize
144+
}
145+
146+
func (o *OptionsParams) GetQRCodeContent() string {
147+
return o.qrcodeContent
148+
}
149+
150+
// ------------- setters
151+
152+
func (o *OptionsParams) SetQRCodeContent(value string) {
153+
o.qrcodeContent = value
154+
}

pix/pix.go

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
package pix
22

33
import (
4+
"errors"
45
"fmt"
56
"regexp"
67
"strings"
8+
"unicode/utf8"
79

810
"github.com/snksoft/crc"
11+
"github.com/thiagozs/go-pixgen/qrcode"
912
)
1013

1114
type Pix struct {
@@ -64,6 +67,8 @@ func (p *Pix) GenPayload() string {
6467

6568
payload = p.FindAndReplaceCRC(payload)
6669

70+
p.params.SetQRCodeContent(payload)
71+
6772
return payload
6873
}
6974

@@ -77,15 +82,15 @@ func (p *Pix) generateMAI() string {
7782
tags := []string{
7883
p.getValue(TAG_MAI_GUI, BC_GUI),
7984
p.getValue(TAG_MAI_PIXKEY, p.params.pixKey),
80-
p.getValue(TAG_MAI_INFO_ADD, "Gerado por Pix-Utils"),
81-
//p.getValue(TAG_MAI_INFO_ADD, p.params.infoAdicional),
85+
}
86+
if len(p.params.aditionalInfo) > 0 {
87+
tags = append(tags, p.getValue(TAG_MAI_INFO_ADD, p.params.aditionalInfo))
8288
}
8389
return strings.Join(tags, "")
8490
case DYNAMIC:
8591
tags := []string{
8692
p.getValue(TAG_MAI_GUI, BC_GUI),
87-
p.getValue(TAG_MAI_URL, "https://www.pix.com.br/"),
88-
//p.getValue(TAG_MAI_URL, p.params.url),
93+
p.getValue(TAG_MAI_URL, p.params.url),
8994
}
9095
return strings.Join(tags, "")
9196
default:
@@ -111,3 +116,34 @@ func (p *Pix) FindAndReplaceCRC(payload string) string {
111116
payload = m.ReplaceAllString(payload, "")
112117
return payload + p.getCRC16(payload)
113118
}
119+
120+
func (p *Pix) Validates() error {
121+
if p.params.pixKey == "" {
122+
return errors.New("pixkey must not be empty")
123+
}
124+
125+
if p.params.merchant.name == "" {
126+
return errors.New("name must not be empty")
127+
}
128+
129+
if p.params.merchant.city == "" {
130+
return errors.New("city must not be empty")
131+
}
132+
133+
if utf8.RuneCountInString(p.params.merchant.name) > 25 {
134+
return errors.New("name must be at least 25 characters long")
135+
}
136+
137+
if utf8.RuneCountInString(p.params.merchant.city) > 15 {
138+
return errors.New("city must be at least 15 characters long")
139+
}
140+
141+
return nil
142+
}
143+
144+
func (p *Pix) GenQRCode() ([]byte, error) {
145+
return qrcode.New(qrcode.QRCodeOptions{
146+
Size: p.params.GetQRCodeSize(),
147+
Content: p.params.GetQRCodeContent(),
148+
})
149+
}

qrcode/qrcode.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
11
package qrcode
2+
3+
import (
4+
"github.com/skip2/go-qrcode"
5+
)
6+
7+
type QRCodeOptions struct {
8+
Content string
9+
Size int
10+
}
11+
12+
func New(options QRCodeOptions) ([]byte, error) {
13+
if options.Size == 0 {
14+
options.Size = 256
15+
}
16+
return qrcode.Encode(options.Content, qrcode.Medium, options.Size)
17+
}

0 commit comments

Comments
 (0)