Go SDK for AzamPay Tanzania APIs.
go get github.com/kateile/go-azampay/v2@latestimport "github.com/kateile/go-azampay/v2"api := azampay.NewAzamPay(false, azampay.Credentials{
AppName: os.Getenv("AZAM_APP_NAME"),
ClientId: os.Getenv("AZAM_CLIENT_ID"),
ClientSecret: os.Getenv("AZAM_CLIENT_SECRET"),
Token: os.Getenv("AZAM_API_KEY"),
})
if err := api.GenerateSession(); err != nil {
log.Fatal(err)
}Pass true to NewAzamPay for production.
Enable debug logging to log sanitized AzamPay requests and responses with log/slog:
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
api.Debug = true
api.SetLogger(logger)Request and response JSON is redacted before logging for sensitive keys such as clientSecret, accessToken, Authorization, X-API-KEY, password, and token-like fields.
resp, err := api.MobileCheckout(azampay.MNOPayload{
AccountNumber: "255700000000",
Amount: 2000,
Currency: "TZS",
ExternalID: "order-123",
Provider: azampay.ProviderAirtel,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(resp.TransactionID)resp, err := api.BankCheckout(azampay.BankCheckoutPayload{
Amount: 10000,
CurrencyCode: "TZS",
MerchantAccountNumber: "1234567890",
MerchantMobileNumber: "255700000000",
OTP: "123456",
Provider: azampay.BankProviderCRDB,
ReferenceID: "order-123",
})checkoutURL, err := api.PostCheckout(azampay.PostCheckoutPayload{
Amount: "10000",
AppName: "my-app",
ClientID: "client-id",
Currency: "TZS",
ExternalID: "order-123",
Language: "en",
RedirectFailURL: "https://example.com/fail",
RedirectSuccessURL: "https://example.com/success",
RequestOrigin: "https://example.com",
VendorID: "vendor-id",
VendorName: "Vendor",
Cart: azampay.Cart{Items: []azampay.Item{
{Name: "Product"},
}},
})AzamPay disbursement requests require a checksum:
checksum, err := azampay.GenerateChecksum("input-string-from-your-integration", publicKeyPEM)
if err != nil {
log.Fatal(err)
}
resp, err := api.Disburse(azampay.CreateTransferPayload{
Source: azampay.Source{
CountryCode: "TZ",
FullName: "Sender",
BankName: azampay.DisburseProviderAirtel,
AccountNumber: "255700000001",
Currency: "TZS",
},
Destination: azampay.Destination{
CountryCode: "TZ",
FullName: "Receiver",
BankName: azampay.DisburseProviderTigo,
AccountNumber: "255700000002",
Currency: "TZS",
},
TransferDetails: azampay.TransferDetails{
Type: "internal",
Amount: 5000,
DateInEpoch: float64(time.Now().Unix()),
},
ExternalReferenceID: "ref-123",
Checksum: checksum,
})Disbursement errors can be inspected with errors.As:
var disbursementErr *azampay.DisbursementError
if errors.As(err, &disbursementErr) {
fmt.Println(disbursementErr.Message)
}lookup, err := api.NameLookup(azampay.NameLookupPayload{
BankName: "airtel",
AccountNumber: "255700000000",
Checksum: checksum,
})
status, err := api.GetTransactionStatus(azampay.TransactionStatusPayload{
BankName: azampay.DisburseProviderAirtel,
PGReferenceID: "pg-reference-id",
})updates := api.ListenForWebhook("/api/v1/Checkout/Callback")
for update := range updates {
if err := azampay.VerifyCallbackSignature(update, publicKeyPEM, crypto.SHA256); err != nil {
log.Println("invalid callback signature:", err)
continue
}
fmt.Println(update.TransactionStatus, update.ExternalReference)
}payload := azampay.BillPayStatusCheckPayload{
MerchantReferenceID: "merchant-ref-123",
}
hash, err := azampay.CalculateBillPayHash(payload, []byte("shared-secret"))
ok, err := azampay.VerifyBillPayHash(payload, hash, []byte("shared-secret"))
claims, err := azampay.ValidateBillPayJWT(jwtToken, []byte("shared-secret"), time.Now())ValidateBillPayJWT verifies HS256 signatures, requires userId, iat, and exp, and enforces the documented 120-second maximum token validity.