Quickstart
Install
go get github.com/koriebruh/go-snap-biRequires Go 1.21 or later.
Get an access token
Every call needs a bearer token first. TokenManager fetches and
caches it for you — concurrent callers during a refresh share one
in-flight request instead of each firing their own.
tm := &snap.TokenManager{
BaseURL: "https://partner.example.com",
ClientKey: clientKey,
Signer: rsaPrivateKey, // crypto.Signer, e.g. from snap.ParseRSAPrivateKeyPEM
}
accessToken, err := tm.AccessTokenB2B(ctx)
if err != nil {
// handle error
}See Authentication for B2B2C and token caching details.
Build a signed header
HeaderBuilder assembles the mandatory SNAP header set —
X-SIGNATURE, X-TIMESTAMP, X-PARTNER-ID, and the rest — and signs
the request for you. Pick exactly one of ClientSecret
(symmetric/HMAC) or Signer (asymmetric/RSA), matching what you
agreed with your partner at registration.
hb := snap.HeaderBuilder{
Method: http.MethodPost,
EndpointURL: "https://partner.example.com/v1.0/balance-inquiry",
AccessToken: accessToken,
ClientKey: clientKey,
PartnerID: partnerID,
ExternalID: externalID,
ChannelID: channelID,
Symmetric: true,
ClientSecret: clientSecret,
}See Headers & Signing for every field and what happens when one is missing.
Call an endpoint
Every domain package uses the same call shape:
func Endpoint(ctx, *snap.Transport, snap.HeaderBuilder, Request) (Response, error).
transport := &snap.Transport{}
resp, err := balanceinfo.BalanceInquiry(ctx, transport, hb, balanceinfo.BalanceInquiryRequest{
PartnerReferenceNo: "2020102900000000000001",
AccountNo: "1234567890",
})
if err != nil {
// errors.Is(err, snap.ErrBadRequest), snap.ErrUnauthorized, etc. —
// one sentinel per SNAP response-code HTTP-status class. See
// /concepts/errors.
}You don’t set hb.Body yourself — the calling function marshals the
typed request and sets it, so the same bytes are used for both signing
and the wire request.
Handle inbound notifications
Some flows (bulk cash-in, QR/MPM payments, direct debit, BI-FAST,
RTGS, SKNBI) deliver their result as an inbound HTTP call to your
service instead of a synchronous response. Verify every inbound
request with snap.ServerVerifier before trusting its body — see
Verifying inbound requests. Skip this step if
you’re only calling read/inquiry endpoints.