Skip to content

Commit

Permalink
Improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagozs committed Jan 27, 2022
1 parent c0b3930 commit be317c5
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 32 deletions.
52 changes: 33 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,42 @@

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

**UNDER DEVELOPMENT** *** Not ready for production
**UNDER DEVELOPMENT** *** Becareful ***

Example implementation.
```golang
opts := []pix.Options{
pix.OptPixKey("11955555555"),
pix.OptDescription("Teste"),
pix.OptMerchantName("Thiago Zilli Sarmento"),
pix.OptMerchantCity("Ararangua"),
pix.OptAmount("0.00"),
pix.OptKind(pix.STATIC),
}

p, err := pix.New(opts...)
if err != nil {
panic(err)
}
cpy := p.GenPayload()
if err != nil {
panic(err)
}
fmt.Println(cpy)
pix.OptPixKey("11955555555"),
pix.OptDescription("Teste"),
pix.OptMerchantName("Thiago Zilli Sarmento"),
pix.OptMerchantCity("Ararangua"),
pix.OptAmount("1.00"),
pix.OptAditionalInfo("gerado por go-pixgen"),
pix.OptKind(pix.STATIC),
}

p, err := pix.New(opts...)
if err != nil {
fmt.Println(err.Error())
return
}

if err := p.Validates(); err != nil {
fmt.Println(err.Error())
return
}

cpy := p.GenPayload()

fmt.Printf("Copy and Paste: %s\n", cpy)

bts, err := p.GenQRCode()
if err != nil {
fmt.Println(err.Error())
return
}

fmt.Printf("QRCode: %b\n", bts)
```

## Roadmap
Expand All @@ -34,7 +48,7 @@ fmt.Println(cpy)
- [x] Static
- [x] Dynamic
- [ ] Parse and validate EMV Codes
- [ ] Export generated/parsed payment to Image
- [x] Export generated/parsed payment to Image
- [x] Export generated/parsed payment to EMV Code
- [ ] Fetch, parse and validate remote payloads from dynamic payments
- [ ] Verify if has already expired
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ go 1.17

require (
github.com/r10r/crc16 v0.1.1
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/snksoft/crc v1.1.0
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
github.com/r10r/crc16 v0.1.1 h1:BsuCL6d+j0hBCQ/nNnwHmlTF0shVES2IagUgh1MS6yU=
github.com/r10r/crc16 v0.1.1/go.mod h1:I17p13f8bQGzqw5+futttVdERhbvzpgjlPZdwIJ0ka8=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M=
github.com/snksoft/crc v1.1.0 h1:HkLdI4taFlgGGG1KvsWMpz78PkOC9TkPVpTV/cuWn48=
github.com/snksoft/crc v1.1.0/go.mod h1:5/gUOsgAm7OmIhb6WJzw7w5g2zfJi4FrHYgGPdshE+A=
17 changes: 15 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,31 @@ func main() {
pix.OptDescription("Teste"),
pix.OptMerchantName("Thiago Zilli Sarmento"),
pix.OptMerchantCity("Ararangua"),
pix.OptAmount("0.00"),
pix.OptAmount("1.00"),
pix.OptAditionalInfo("gerado por go-pixgen"),
pix.OptKind(pix.STATIC),
}

p, err := pix.New(opts...)
if err != nil {
panic(err)
}

if err := p.Validates(); err != nil {
fmt.Println(err.Error())
return
}

cpy := p.GenPayload()
if err != nil {
panic(err)
}
fmt.Println(cpy)
fmt.Printf("Copy and Paste: %s\n", cpy)

bts, err := p.GenQRCode()
if err != nil {
panic(err)
}
fmt.Printf("QRCode: %b\n", bts)

}
1 change: 0 additions & 1 deletion pix/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package pix

const (
//EmvSchema
//TAG_ONETIME = "1"
TAG_INIT = "00"
TAG_MAI = "26"
TAG_MCC = "52"
Expand Down
59 changes: 53 additions & 6 deletions pix/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,44 @@ func (pix PixKind) String() string {
type Options func(o *OptionsParams) error

type OptionsParams struct {
id string
pixKey string
description string
amount string
merchant merchant
kind PixKind
id string
pixKey string
description string
amount string
aditionalInfo string
merchant merchant
kind PixKind
url string
qrcodeContent string
qrcodeSize int
}

type merchant struct {
name string
city string
}

func OptQRCodeSize(value int) Options {
return func(o *OptionsParams) error {
o.qrcodeSize = value
return nil
}
}

func OptUrl(value string) Options {
return func(o *OptionsParams) error {
o.url = value
return nil
}
}

func OptAditionalInfo(value string) Options {
return func(o *OptionsParams) error {
o.aditionalInfo = value
return nil
}
}

func OptKind(kind PixKind) Options {
return func(o *OptionsParams) error {
o.kind = kind
Expand Down Expand Up @@ -105,3 +130,25 @@ func (o *OptionsParams) GetAmount() string {
func (o *OptionsParams) GetKind() PixKind {
return o.kind
}

func (o *OptionsParams) GetAditionalInfo() string {
return o.aditionalInfo
}

func (o *OptionsParams) GetUrl() string {
return o.url
}

func (o *OptionsParams) GetQRCodeSize() int {
return o.qrcodeSize
}

func (o *OptionsParams) GetQRCodeContent() string {
return o.qrcodeContent
}

// ------------- setters

func (o *OptionsParams) SetQRCodeContent(value string) {
o.qrcodeContent = value
}
44 changes: 40 additions & 4 deletions pix/pix.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package pix

import (
"errors"
"fmt"
"regexp"
"strings"
"unicode/utf8"

"github.com/snksoft/crc"
"github.com/thiagozs/go-pixgen/qrcode"
)

type Pix struct {
Expand Down Expand Up @@ -64,6 +67,8 @@ func (p *Pix) GenPayload() string {

payload = p.FindAndReplaceCRC(payload)

p.params.SetQRCodeContent(payload)

return payload
}

Expand All @@ -77,15 +82,15 @@ func (p *Pix) generateMAI() string {
tags := []string{
p.getValue(TAG_MAI_GUI, BC_GUI),
p.getValue(TAG_MAI_PIXKEY, p.params.pixKey),
p.getValue(TAG_MAI_INFO_ADD, "Gerado por Pix-Utils"),
//p.getValue(TAG_MAI_INFO_ADD, p.params.infoAdicional),
}
if len(p.params.aditionalInfo) > 0 {
tags = append(tags, p.getValue(TAG_MAI_INFO_ADD, p.params.aditionalInfo))
}
return strings.Join(tags, "")
case DYNAMIC:
tags := []string{
p.getValue(TAG_MAI_GUI, BC_GUI),
p.getValue(TAG_MAI_URL, "https://www.pix.com.br/"),
//p.getValue(TAG_MAI_URL, p.params.url),
p.getValue(TAG_MAI_URL, p.params.url),
}
return strings.Join(tags, "")
default:
Expand All @@ -111,3 +116,34 @@ func (p *Pix) FindAndReplaceCRC(payload string) string {
payload = m.ReplaceAllString(payload, "")
return payload + p.getCRC16(payload)
}

func (p *Pix) Validates() error {
if p.params.pixKey == "" {
return errors.New("pixkey must not be empty")
}

if p.params.merchant.name == "" {
return errors.New("name must not be empty")
}

if p.params.merchant.city == "" {
return errors.New("city must not be empty")
}

if utf8.RuneCountInString(p.params.merchant.name) > 25 {
return errors.New("name must be at least 25 characters long")
}

if utf8.RuneCountInString(p.params.merchant.city) > 15 {
return errors.New("city must be at least 15 characters long")
}

return nil
}

func (p *Pix) GenQRCode() ([]byte, error) {
return qrcode.New(qrcode.QRCodeOptions{
Size: p.params.GetQRCodeSize(),
Content: p.params.GetQRCodeContent(),
})
}
16 changes: 16 additions & 0 deletions qrcode/qrcode.go
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
package qrcode

import (
"github.com/skip2/go-qrcode"
)

type QRCodeOptions struct {
Content string
Size int
}

func New(options QRCodeOptions) ([]byte, error) {
if options.Size == 0 {
options.Size = 256
}
return qrcode.Encode(options.Content, qrcode.Medium, options.Size)
}

0 comments on commit be317c5

Please sign in to comment.