Skip to content

birapi/go-corpbankclient

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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)
}

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages