Categorygithub.com/birapi/go-corpbankclient
modulepackage
0.0.0-20220117174550-2f18736a6f61
Repository: https://github.com/birapi/go-corpbankclient.git
Documentation: pkg.go.dev

# README

Example to handle webhook notifications:

package main

import (
	"context"
	"errors"
	"log"
	"net/http"

	"github.com/birapi/go-corpbankclient"
)

func main() {
	client, err := corpbankclient.NewClient(corpbankclient.Credentials{
		APIKeyID:     "<API_KEY_ID>",
		APIKeySecret: "<API_KEY_SECRET>",
	}, nil)

	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/bank-transfers", client.WebhookHandler(func(c context.Context, t corpbankclient.Transaction) error {
		switch t.Direction {
		case corpbankclient.TrxDirectionIncoming:
			log.Printf("Incoming bank transfer from %s: %s %s", t.Sender.Name, t.Amount.StringFixed(2), t.Currency)

		case corpbankclient.TrxDirectionOutgoing:
			log.Printf("Outgoing bank transfer to %s: %s %s", t.Recipient.Name, t.Amount.StringFixed(2), t.Currency)

		default:
			return errors.New("unknown direction")
		}

		return nil
	}))

	log.Fatal(http.ListenAndServe(":8080", nil))
}

Example to make payment:

package main

import (
	"context"
	"log"
	"errors"

	"github.com/birapi/go-corpbankclient"
	"github.com/google/uuid"
	"github.com/shopspring/decimal"
)

func main() {
	client, err := corpbankclient.NewClient(corpbankclient.Credentials{
		APIKeyID:     "<API_KEY_ID>",
		APIKeySecret: "<API_KEY_SECRET>",
	}, nil)

	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()

	paymentResult, err := client.MakePayment(ctx, corpbankclient.PaymentOrder{
		SenderIBAN:           "<SENDER_BANK_ACCOUNT_IBAN>",
		RecipientIBAN:        "<RECIPIENT_BANK_ACCOUNT_IBAN>",
		RecipientName:        "<RECIPIENT_NAME>",
		RecipientIdentityNum: "<RECIPIENT_NATIONAL_ID_NUMBER>",
		TransferAmount:       decimal.NewFromInt(3), // transfer amount
		RefCode:              uuid.New().String(),   // a unique reference code
		Description:          "test",                // the description of the bank transfer
	})

	if err != nil {
		// the error type can be checked as follows
		if errors.Is(err, corpbankclient.ErrInsufficientBalance) {
			log.Fatal("insufficient balance")
		}

		log.Fatal(err)
	}

	log.Printf("Payment ID: %s", paymentResult.PaymentID)
}

Example to list of transactions:

package main

import (
	"context"
	"errors"
	"log"
	"time"

	"github.com/birapi/go-corpbankclient"
)

func main() {
	client, err := corpbankclient.NewClient(corpbankclient.Credentials{
		APIKeyID:     "<API_KEY_ID>",
		APIKeySecret: "<API_KEY_SECRET>",
	}, nil)

	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()

    // list the last 10 incoming transfers in the last 24 hours
	_, txList, err := client.Transactions(ctx,
		corpbankclient.WithPageSize(10),
		corpbankclient.WithFilterInDateRange(time.Now().Add(-24*time.Hour), time.Now()),
		corpbankclient.WithFilterIncomingTransactions(),
	)

	if err != nil {
		log.Fatal(err)
	}

	for _, t := range txList {
		switch t.Direction {
		case corpbankclient.TrxDirectionIncoming:
			log.Printf("Incoming bank transfer from %s at %s: %s %s", t.Sender.Name, t.Date.String(), t.Amount.StringFixed(2), t.Currency)

		case corpbankclient.TrxDirectionOutgoing:
			log.Printf("Outgoing bank transfer to %s at %s: %s %s", t.Recipient.Name, t.Date.String(), t.Amount.StringFixed(2), t.Currency)

		default:
			log.Fatal(errors.New("unknown direction"))
		}
	}
}

Examples for the rest of the functionality:

package main

import (
	"context"
	"log"

	"github.com/birapi/go-corpbankclient"
	"github.com/google/uuid"
)

func main() {
	client, err := corpbankclient.NewClient(corpbankclient.Credentials{
		APIKeyID:     "<API_KEY_ID>",
		APIKeySecret: "<API_KEY_SECRET>",
	}, nil)

	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()

	user, err := client.Me(ctx)
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Authenticated API user: %s", user.Email)

	balance, err := client.AccountBalance(ctx, uuid.MustParse("<BANK_ACCOUNT_ID>"))
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Account balance: %s", balance.Balance.StringFixed(2))

	_, apiKeys, err := client.APIKeys(ctx, corpbankclient.WithPageSize(100))
	if err != nil {
		log.Fatal(err)
	}

	for i, k := range apiKeys {
		log.Printf("API Key #%d: %s", i, k.ID)
	}

	// besides, the following functions can help to manage API keys
	// client.NewAPIKey()
	// client.EnableAPIKey()
	// client.DisableAPIKey()
	// client.DelAPIKey()
}

Example to make payment with a retry mechanism, using idempotency feature:

package main

import (
	"context"
	"errors"
	"log"
	"time"

	"github.com/birapi/go-corpbankclient"
	"github.com/cenkalti/backoff"
	"github.com/google/uuid"
	"github.com/shopspring/decimal"
)

func main() {
	client, err := corpbankclient.NewClient(corpbankclient.Credentials{
		APIKeyID:     "<API_KEY_ID>",
		APIKeySecret: "<API_KEY_SECRET>",
	}, nil)

	if err != nil {
		log.Fatal(err)
	}

	ctx := context.Background()

	retry := backoff.NewExponentialBackOff()
	retry.InitialInterval = 200 * time.Millisecond
	retry.MaxInterval = 30 * time.Second
	retry.MaxElapsedTime = 3 * time.Minute

	var paymentResult *corpbankclient.PaymentResult

	// following errors can not be recovered
	permanentErrors := []error{
		corpbankclient.ErrInsufficientBalance,
		corpbankclient.ErrCurrencyMismatch,
		corpbankclient.ErrIncorrectRecipientData,
		corpbankclient.ErrInvalidRecipientID,
		corpbankclient.ErrOutOfEFTHours,
	}

	idempotencyKey, err := uuid.NewRandom()
	if err != nil {
		log.Fatal(err)
	}

	err = backoff.RetryNotify(
		func() error {
			paymentResult, err = client.MakePayment(ctx, corpbankclient.PaymentOrder{
				SenderIBAN:           "<SENDER_BANK_ACCOUNT_IBAN>",
				RecipientIBAN:        "<RECIPIENT_BANK_ACCOUNT_IBAN>",
				RecipientName:        "<RECIPIENT_NAME>",
				RecipientIdentityNum: "<RECIPIENT_NATIONAL_ID_NUMBER>",
				TransferAmount:       decimal.NewFromInt(3), // transfer amount
				RefCode:              uuid.New().String(),   // a unique reference code
				Description:          "test",                // the description of the bank transfer
				IdempotencyKey:       idempotencyKey.String(),
			})

			for _, e := range permanentErrors {
				if errors.Is(err, e) {
					return backoff.Permanent(err)
				}
			}

			return err
		},

		backoff.WithContext(retry, ctx),

		func(e error, d time.Duration) {
			log.Printf("payment error (will retry after %s): %+v", d.String(), err)
		})

	if err != nil {
		// the error type can be checked as follows
		if errors.Is(err, corpbankclient.ErrInsufficientBalance) {
			log.Fatal("insufficient balance")
		}

		log.Fatal(err)
	}

	log.Printf("Payment ID: %s", paymentResult.PaymentID)
}

# Functions

No description provided by the author
WithFilterAccountIDs filters the list of bank transactions for the given list of account ID.
WithFilterIncomingTransactions filters the list of bank transactions for only incoming transfers.
WithPageSize filters the list of bank transactions by the given date range.
WithFilterOutgoingTransactions filters the list of bank transactions for only outgoing transfers.
WithPageNum allows customizing the requested page number.
WithPageSize allows customizing the requested page size.

# Constants

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Variables

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Structs

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Interfaces

No description provided by the author

# Type aliases

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author