diff --git a/README.md b/README.md index ba7fd19..5ba15f8 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,13 @@ if err != nil { } fmt.Println(copyPaste) // will output: "00020126580014BR.GOV.BCB.PIX0122jonnasfonini@gmail.com0210Invoice #4520400005303986540520.675802BR5913Jonnas Fonini6005Marau62410503***50300017BR.GOV.BCB.BRCODE01051.0.06304CF13" + +optionsFromCode, err := pix.ReadPix(copyPaste) +if err != nil { + panic(err) +} + +fmt.Println(optionsFromCode) ``` ### Generating a QR code from a Copy and Paste code diff --git a/pix/pix.go b/pix/pix.go index af5b978..4057a8e 100644 --- a/pix/pix.go +++ b/pix/pix.go @@ -2,23 +2,22 @@ // // As a simple example: // -// options := pix.Options{ -// Name: "Jonnas Fonini", -// Key: "jonnasfonini@gmail.com", -// City: "Marau", -// Amount: 20.67, // optional -// Description: "Invoice #4", // optional -// TransactionID: "***", // optional -// } +// options := pix.Options{ +// Name: "Jonnas Fonini", +// Key: "jonnasfonini@gmail.com", +// City: "Marau", +// Amount: 20.67, // optional +// Description: "Invoice #4", // optional +// TransactionID: "***", // optional +// } // -// copyPaste, err := pix.Pix(options) +// copyPaste, err := pix.Pix(options) // -// if err != nil { -// panic(err) -// } -// -// fmt.Println(copyPaste) // will output: "00020126580014BR.GOV.BCB.PIX0122jonnasfonini@gmail.com0210Invoice #4520400005303986540520.675802BR5913Jonnas Fonini6005Marau62410503***50300017BR.GOV.BCB.BRCODE01051.0.06304CF13" +// if err != nil { +// panic(err) +// } // +// fmt.Println(copyPaste) // will output: "00020126580014BR.GOV.BCB.PIX0122jonnasfonini@gmail.com0210Invoice #4520400005303986540520.675802BR5913Jonnas Fonini6005Marau62410503***50300017BR.GOV.BCB.BRCODE01051.0.06304CF13" package pix import ( @@ -66,7 +65,6 @@ func Pix(options Options) (string, error) { } data := buildDataMap(options) - str := parseData(data) // Add the CRC at the end @@ -182,6 +180,64 @@ func parseData(data intMap) string { return str } +// ReadPix generates a Options struct using a copyPaste PIX code +func ReadPix(copyPaste string) (Options, error) { + data := buildUsingGuideMap(copyPaste, buildDataMap(Options{})) + options, err := readDataMap(data) + return options, err +} + +func readDataMap(data intMap) (op Options, err error) { + keyMap, ok := data[26].(intMap) + if !ok { + return op, fmt.Errorf("data[26] is not (intMap)") + } + txMap := data[62].(intMap) + if txMap[5].(string) == "***" { + txMap[5] = "" + } + + op = Options{ + Key: keyMap[1].(string), + Description: keyMap[2].(string), + Amount: data[54].(float64), + Name: data[59].(string), + City: data[60].(string), + TransactionID: txMap[5].(string), + } + + return op, err +} + +func buildUsingGuideMap(copyPaste string, guide intMap) intMap { + data := make(intMap) + + k := 0 + for k < len(copyPaste) { + index, _ := strconv.Atoi(copyPaste[k : k+2]) + k += 2 + + lenght, _ := strconv.Atoi(copyPaste[k : k+2]) + k += 2 + + value := copyPaste[k : k+lenght] + k += lenght + + v := reflect.ValueOf(guide[index]) + switch v.Kind() { + case reflect.Map: + m := guide[index].(intMap) + data[index] = buildUsingGuideMap(value, m) + case reflect.String: + data[index] = value + case reflect.Float64: + data[index], _ = strconv.ParseFloat(value, 64) + } + } + + return data +} + func sortKeys(data intMap) []int { keys := make([]int, len(data)) i := 0 diff --git a/pix/pix_test.go b/pix/pix_test.go index c4c0945..6667216 100644 --- a/pix/pix_test.go +++ b/pix/pix_test.go @@ -2,6 +2,7 @@ package pix import ( "bytes" + "encoding/json" "errors" "image" "testing" @@ -12,15 +13,25 @@ import ( ) // test that input matches the value we want. If not, report an error on t. -func testValue(t *testing.T, input Options, want string) { - v, err := Pix(input) +func testValue(t *testing.T, options Options, copyPaste string) { + v, err := Pix(options) + + if err != nil { + t.Errorf("Pix(%v) returned an error: %v", options, err) + } + + if diff := cmp.Diff(copyPaste, v); diff != "" { + t.Errorf("Pix(%v) mismatch:\n%s", options, diff) + } + vp, err := ReadPix(copyPaste) if err != nil { - t.Errorf("Pix(%v) returned an error: %v", input, err) + t.Errorf("ReadPix(%v) returned an error: %v", options, err) } - if diff := cmp.Diff(want, v); diff != "" { - t.Errorf("Pix(%v) mismatch:\n%s", input, diff) + if diff := cmp.Diff(options, vp); diff != "" { + opJSON, _ := json.Marshal(options) + t.Errorf("ReadPix('%s') mismatch:\n%s", opJSON, diff) } }