Documentation
¶
Overview ¶
Package squad provides a Go client for the Squad by GTCO payment gateway API.
Getting Started ¶
client := squad.New("sandbox_sk_your_key_here")
resp, err := client.Transactions.InitiatePayment(ctx, &squad.InitiatePaymentParams{
Email: "customer@example.com",
Amount: squad.NGN(5000), // ₦5,000
Currency: "NGN",
CallbackURL: "https://yoursite.com/callback",
})
Environments ¶
The sandbox environment is automatically selected when your key starts with "sandbox_sk_". For production, use your live key or explicitly call WithProduction().
Idempotency ¶
key, _ := squad.GenerateIdempotencyKey() ctx = squad.WithIdempotencyKey(ctx, key) resp, err := client.Transactions.InitiatePayment(ctx, params)
Pagination ¶
iter := client.Transfers.All(ctx, nil)
for iter.Next() {
fmt.Println(iter.Item().TransactionRef)
}
Webhook Verification ¶
event, err := squad.ParseWebhook(body, r.Header.Get("x-squad-signature"), secretKey)
Webhook Router ¶
router := squad.NewWebhookRouter(secretKey).
OnTransactionSuccess(handlePayment).
OnVirtualAccountCredit(handleCredit)
http.Handle("/webhook/squad", router)
Index ¶
- Constants
- Variables
- func FromCents(cents int64) float64
- func FromKobo(kobo int64) float64
- func GenerateIdempotencyKey() (string, error)
- func IsBadRequest(err error) bool
- func IsNotFound(err error) bool
- func IsUnauthorized(err error) bool
- func NGN(naira float64) int64
- func USD(dollars float64) int64
- func VerifySignature(payload []byte, signature string, secret string) bool
- func WithIdempotencyKey(ctx context.Context, key string) context.Context
- type AccountLookupResponse
- type BuyAirtimeParams
- type BuyCableParams
- type BuyDataParams
- type BuyElectricityParams
- type CablePackage
- type CablePackagesResponse
- type ChargeToken
- type Client
- type CreateSubMerchantParams
- type CreateVirtualAccountParams
- type CustomerInfo
- type DataPlan
- type DataPlansResponse
- type DeleteSubMerchantResponse
- type Dispute
- type DisputeActionResponse
- type DisputeEvidence
- type DisputeListParams
- type DisputeListResponse
- type DisputeService
- func (s *DisputeService) AcceptDispute(ctx context.Context, ticketID string) (*DisputeActionResponse, error)
- func (s *DisputeService) All(ctx context.Context, params *DisputeListParams) *Iter[Dispute]
- func (s *DisputeService) GetAllDisputes(ctx context.Context, params *DisputeListParams) (*DisputeListResponse, error)
- func (s *DisputeService) GetDisputeDetail(ctx context.Context, ticketID string) (*Dispute, error)
- func (s *DisputeService) GetDisputeEvidence(ctx context.Context, ticketID string) (*DisputeEvidence, error)
- func (s *DisputeService) RejectDispute(ctx context.Context, ticketID string) (*DisputeActionResponse, error)
- func (s *DisputeService) UploadEvidence(ctx context.Context, ticketID string, fileData []byte, fileName string) (*EvidenceUploadResponse, error)
- type ElectricityBiller
- type ElectricityBillersResponse
- type ElectricityResponse
- type Error
- type EventType
- type EvidenceUploadResponse
- type FundsTransferParams
- type InitiatePaymentParams
- type InitiatePaymentResponse
- type IntraTransferParams
- type Iter
- type Logger
- type MissedWebhookParams
- type MissedWebhookResponse
- type Option
- func WithAfterResponse(fn func(*http.Request, *http.Response, time.Duration)) Option
- func WithAutoIdempotency() Option
- func WithBaseURL(url string) Option
- func WithBeforeRequest(fn func(*http.Request)) Option
- func WithHTTPClient(hc *http.Client) Option
- func WithLogger(l Logger) Option
- func WithProduction() Option
- func WithSandbox() Option
- func WithTimeout(d time.Duration) Option
- func WithUserAgent(ua string) Option
- type RefundTransactionParams
- type RefundTransactionResponse
- type SMSResponse
- type SendSMSParams
- type SimulateResponse
- type SimulateVirtualAccountParams
- type SubMerchant
- type SubMerchantListParams
- type SubMerchantListResponse
- type SubMerchantService
- func (s *SubMerchantService) All(ctx context.Context, params *SubMerchantListParams) *Iter[SubMerchant]
- func (s *SubMerchantService) Create(ctx context.Context, params *CreateSubMerchantParams) (*SubMerchant, error)
- func (s *SubMerchantService) Delete(ctx context.Context, merchantID string) (*DeleteSubMerchantResponse, error)
- func (s *SubMerchantService) Get(ctx context.Context, merchantID string) (*SubMerchant, error)
- func (s *SubMerchantService) List(ctx context.Context, params *SubMerchantListParams) (*SubMerchantListResponse, error)
- type TransactionService
- func (s *TransactionService) AllMissedWebhooks(ctx context.Context, params *MissedWebhookParams) *Iter[VerifyTransactionResponse]
- func (s *TransactionService) GetMissedWebhookTransactions(ctx context.Context, params *MissedWebhookParams) (*MissedWebhookResponse, error)
- func (s *TransactionService) GetUSSDbanks(ctx context.Context) (*USSDbanksResponse, error)
- func (s *TransactionService) InitiatePayment(ctx context.Context, params *InitiatePaymentParams) (*InitiatePaymentResponse, error)
- func (s *TransactionService) RefundTransaction(ctx context.Context, params *RefundTransactionParams) (*RefundTransactionResponse, error)
- func (s *TransactionService) VerifyTransaction(ctx context.Context, transactionRef string) (*VerifyTransactionResponse, error)
- type TransferListParams
- type TransferListResponse
- type TransferResponse
- type TransferService
- func (s *TransferService) AccountLookup(ctx context.Context, bankCode, accountNumber string) (*AccountLookupResponse, error)
- func (s *TransferService) All(ctx context.Context, params *TransferListParams) *Iter[TransferStatusResponse]
- func (s *TransferService) FundsTransfer(ctx context.Context, params *FundsTransferParams) (*TransferResponse, error)
- func (s *TransferService) GetAllTransactions(ctx context.Context, params *TransferListParams) (*TransferListResponse, error)
- func (s *TransferService) GetTransactionStatus(ctx context.Context, transactionRef string) (*TransferStatusResponse, error)
- func (s *TransferService) IntraTransfer(ctx context.Context, params *IntraTransferParams) (*TransferResponse, error)
- type TransferStatusResponse
- type USSDBank
- type USSDbanksResponse
- type UpdateVirtualAccountParams
- type VASService
- func (s *VASService) BuyAirtime(ctx context.Context, params *BuyAirtimeParams) (*VASTransactionResponse, error)
- func (s *VASService) BuyCable(ctx context.Context, params *BuyCableParams) (*VASTransactionResponse, error)
- func (s *VASService) BuyData(ctx context.Context, params *BuyDataParams) (*VASTransactionResponse, error)
- func (s *VASService) BuyElectricity(ctx context.Context, params *BuyElectricityParams) (*ElectricityResponse, error)
- func (s *VASService) GetCablePackages(ctx context.Context, cableProvider string) (*CablePackagesResponse, error)
- func (s *VASService) GetDataPlans(ctx context.Context, networkProvider string) (*DataPlansResponse, error)
- func (s *VASService) GetElectricityBillers(ctx context.Context) (*ElectricityBillersResponse, error)
- func (s *VASService) SendSMS(ctx context.Context, params *SendSMSParams) (*SMSResponse, error)
- type VASTransactionResponse
- type VerifyTransactionResponse
- type VirtualAccount
- type VirtualAccountService
- func (s *VirtualAccountService) AllTransactions(ctx context.Context, customerIdentifier string, params *VirtualAccountTxParams) *Iter[VirtualAccountTransaction]
- func (s *VirtualAccountService) Create(ctx context.Context, params *CreateVirtualAccountParams) (*VirtualAccount, error)
- func (s *VirtualAccountService) GetTransactions(ctx context.Context, customerIdentifier string, params *VirtualAccountTxParams) (*VirtualAccountTxResponse, error)
- func (s *VirtualAccountService) Query(ctx context.Context, virtualAccountNumber string) (*VirtualAccount, error)
- func (s *VirtualAccountService) Simulate(ctx context.Context, params *SimulateVirtualAccountParams) (*SimulateResponse, error)
- func (s *VirtualAccountService) Update(ctx context.Context, params *UpdateVirtualAccountParams) (*VirtualAccount, error)
- type VirtualAccountTransaction
- type VirtualAccountTxParams
- type VirtualAccountTxResponse
- type WebhookDisputeBody
- type WebhookEvent
- type WebhookRouter
- func (r *WebhookRouter) OnDisputeOpened(fn func(context.Context, *WebhookDisputeBody) error) *WebhookRouter
- func (r *WebhookRouter) OnDisputeResolved(fn func(context.Context, *WebhookDisputeBody) error) *WebhookRouter
- func (r *WebhookRouter) OnError(fn func(http.ResponseWriter, *http.Request, error)) *WebhookRouter
- func (r *WebhookRouter) OnTransactionFailed(fn func(context.Context, *WebhookTransactionBody) error) *WebhookRouter
- func (r *WebhookRouter) OnTransactionSuccess(fn func(context.Context, *WebhookTransactionBody) error) *WebhookRouter
- func (r *WebhookRouter) OnTransferFailed(fn func(context.Context, *WebhookTransferBody) error) *WebhookRouter
- func (r *WebhookRouter) OnTransferReversed(fn func(context.Context, *WebhookTransferBody) error) *WebhookRouter
- func (r *WebhookRouter) OnTransferSuccess(fn func(context.Context, *WebhookTransferBody) error) *WebhookRouter
- func (r *WebhookRouter) OnUnknown(fn func(context.Context, *WebhookEvent) error) *WebhookRouter
- func (r *WebhookRouter) OnVirtualAccountCredit(fn func(context.Context, *WebhookVirtualAccountBody) error) *WebhookRouter
- func (r *WebhookRouter) ServeHTTP(w http.ResponseWriter, req *http.Request)
- type WebhookTransactionBody
- type WebhookTransferBody
- type WebhookVirtualAccountBody
Constants ¶
const ( // Version is the current SDK version. Version = "1.1.0" // DefaultTimeout is the default HTTP request timeout. DefaultTimeout = 30 * time.Second // SandboxBaseURL is the Squad sandbox API base URL. SandboxBaseURL = "https://sandbox-api-d.squadco.com" // ProductionBaseURL is the Squad production API base URL. ProductionBaseURL = "https://api-d.squadco.com" )
Variables ¶
var ( ErrForbidden = &Error{HTTPStatus: 403, Status: 403, Message: "forbidden"} ErrBadRequest = &Error{HTTPStatus: 400, Status: 400, Message: "bad request"} ErrNotFound = &Error{HTTPStatus: 404, Status: 404, Message: "not found"} )
Sentinel errors for common API failure modes.
var ErrInvalidSignature = fmt.Errorf("squad: webhook signature validation failed")
ErrInvalidSignature is returned by ParseWebhook when HMAC-SHA512 validation fails.
Functions ¶
func FromCents ¶
FromCents converts a cents amount back to dollars for display purposes.
squad.FromCents(5000) // → 50.00 ($50.00)
func FromKobo ¶
FromKobo converts a kobo amount back to naira for display purposes.
squad.FromKobo(500000) // → 5000.00 (₦5,000)
func GenerateIdempotencyKey ¶
GenerateIdempotencyKey generates a cryptographically random 32-character hex key. Use this when you don't have a natural business key (e.g. order ID) to use.
key, err := squad.GenerateIdempotencyKey() // Store key alongside the order before initiating payment. ctx = squad.WithIdempotencyKey(ctx, key)
func IsBadRequest ¶
IsBadRequest reports whether err is a 400 validation failure.
func IsNotFound ¶
IsNotFound reports whether err is a 404 not-found failure.
func IsUnauthorized ¶
IsUnauthorized reports whether err is a 401 authorization failure.
func NGN ¶
NGN converts a naira amount to kobo (the lowest denomination used by the Squad API).
squad.NGN(5000) // → 500000 kobo (₦5,000) squad.NGN(1) // → 100 kobo (₦1)
func USD ¶
USD converts a dollar amount to cents (the lowest denomination for USD transactions).
squad.USD(50) // → 5000 cents ($50.00) squad.USD(0.50) // → 50 cents ($0.50)
func VerifySignature ¶
VerifySignature checks whether the HMAC-SHA512 signature matches the payload. signature is the hex-encoded value from the "x-squad-signature" header. secret is the merchant's Squad secret key.
Uses constant-time comparison to prevent timing attacks.
func WithIdempotencyKey ¶
WithIdempotencyKey attaches an idempotency key to the context. The SDK sends it as X-Idempotency-Key on all POST requests, preventing duplicate charges when a request is retried after a network failure.
The key should be unique per business operation and attempt. Store it before making the request so you can reuse it on retry.
key, _ := squad.GenerateIdempotencyKey() ctx = squad.WithIdempotencyKey(ctx, "order-"+orderID+"-"+key) resp, err := client.Transactions.InitiatePayment(ctx, params) // On network error, retry with the SAME ctx to use the same key.
Types ¶
type AccountLookupResponse ¶
type AccountLookupResponse struct {
AccountName string `json:"account_name"`
AccountNumber string `json:"account_number"`
BankCode string `json:"bank_code"`
BankName string `json:"bank_name"`
}
AccountLookupResponse is returned by AccountLookup after verifying a bank account.
type BuyAirtimeParams ¶
type BuyAirtimeParams struct {
PhoneNumber string `json:"phone_number"`
Amount int64 `json:"amount"`
Network string `json:"network_provider"` // "MTN", "AIRTEL", "GLO", "9MOBILE"
TransactionRef string `json:"transaction_ref"`
}
BuyAirtimeParams holds parameters for purchasing airtime. PhoneNumber should be in international format without "+": "2348012345678". Minimum amount is 50 NGN. Charges come from the Squad wallet.
type BuyCableParams ¶
type BuyCableParams struct {
SmartCardNumber string `json:"smart_card_number"`
PackageCode string `json:"package_code"`
Provider string `json:"cable_provider"` // "DSTV", "GOTV", "STARTIMES"
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount,omitempty"`
}
BuyCableParams holds parameters for subscribing to a cable TV package.
type BuyDataParams ¶
type BuyDataParams struct {
PhoneNumber string `json:"phone_number"`
PlanCode string `json:"plan_code"`
Network string `json:"network_provider"`
TransactionRef string `json:"transaction_ref"`
}
BuyDataParams holds parameters for purchasing a data bundle.
type BuyElectricityParams ¶
type BuyElectricityParams struct {
MeterNumber string `json:"meter_number"`
Amount int64 `json:"amount"`
BillerCode string `json:"biller_code"`
MeterType string `json:"meter_type"` // "prepaid" or "postpaid"
TransactionRef string `json:"transaction_ref"`
PhoneNumber string `json:"phone_number,omitempty"`
}
BuyElectricityParams holds parameters for purchasing electricity units.
type CablePackage ¶
type CablePackage struct {
PackageCode string `json:"package_code"`
PackageName string `json:"package_name"`
Amount int64 `json:"amount"`
CycleType string `json:"cycle_type"` // "monthly", "quarterly"
}
CablePackage describes a single cable TV subscription package.
type CablePackagesResponse ¶
type CablePackagesResponse struct {
Packages []CablePackage `json:"packages"`
}
CablePackagesResponse holds available cable TV packages for a provider.
type ChargeToken ¶
type ChargeToken struct {
Token string `json:"token"`
ExpiryMonth int `json:"expiry_month"`
ExpiryYear int `json:"expiry_year"`
}
ChargeToken holds card tokenization data used for recurring charges.
type Client ¶
type Client struct {
// Transactions handles payment initiation, verification, and refunds.
Transactions *TransactionService
// VirtualAccounts handles NUBAN virtual account creation and management.
VirtualAccounts *VirtualAccountService
// Transfers handles fund transfers to Nigerian bank accounts.
Transfers *TransferService
// Disputes handles chargeback disputes and evidence submission.
Disputes *DisputeService
// VAS handles value-added services: airtime, data, cable TV, electricity, and SMS.
VAS *VASService
// SubMerchants manages sub-merchant accounts for aggregators and platforms.
SubMerchants *SubMerchantService
// contains filtered or unexported fields
}
Client is the root SDK object. All API services are accessible as fields. A Client is safe for concurrent use across goroutines.
func New ¶
New constructs a ready-to-use Client.
secretKey is your Squad secret key (sandbox_sk_* for sandbox, live secret for production). The sandbox environment is automatically selected when the key starts with "sandbox_sk_". Pass functional options to override defaults.
client := squad.New("sandbox_sk_xxx")
client := squad.New("live_sk_xxx", squad.WithLogger(squad.StdLogger()))
type CreateSubMerchantParams ¶
type CreateSubMerchantParams struct {
DisplayName string `json:"display_name"`
AccountName string `json:"account_name"`
AccountNumber string `json:"account_number"`
BankCode string `json:"bank_code"`
Email string `json:"email"`
MobileNumber string `json:"mobile_number,omitempty"`
}
CreateSubMerchantParams holds parameters for onboarding a sub-merchant. Requires an aggregator-level Squad account.
type CreateVirtualAccountParams ¶
type CreateVirtualAccountParams struct {
CustomerIdentifier string `json:"customer_identifier"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
MiddleName string `json:"middle_name,omitempty"`
MobileNum string `json:"mobile_num"`
Email string `json:"email"`
BVN string `json:"bvn"`
DOB string `json:"dob"` // "DD/MM/YYYY"
Address string `json:"address,omitempty"`
Gender string `json:"gender,omitempty"` // "1" = male, "2" = female
BeneficiaryAccount string `json:"beneficiary_account,omitempty"`
}
CreateVirtualAccountParams holds all parameters to create a NUBAN virtual account. CBN profiling on the Squad dashboard is required before this endpoint is available.
type CustomerInfo ¶
type CustomerInfo struct {
CustomerName string `json:"customer_name"`
CustomerEmail string `json:"customer_email"`
CustomerPhone string `json:"customer_phone_number"`
MerchantID string `json:"merchant_id"`
}
CustomerInfo is embedded in transaction responses.
type DataPlan ¶
type DataPlan struct {
PlanCode string `json:"plan_code"`
PlanName string `json:"plan_name"`
Amount int64 `json:"amount"`
Validity string `json:"validity"`
Network string `json:"network"`
}
DataPlan describes a single data bundle offering for a network provider.
type DataPlansResponse ¶
type DataPlansResponse struct {
Plans []DataPlan `json:"plans"`
}
DataPlansResponse holds available data plans for a network provider.
type DeleteSubMerchantResponse ¶
type DeleteSubMerchantResponse struct {
MerchantID string `json:"merchant_id"`
Status string `json:"status"`
Message string `json:"message"`
}
DeleteSubMerchantResponse is returned when a sub-merchant is removed.
type Dispute ¶
type Dispute struct {
TicketID string `json:"ticket_id"`
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
Status string `json:"dispute_status"`
Reason string `json:"dispute_reason"`
CustomerEmail string `json:"customer_email"`
CustomerName string `json:"customer_name"`
DueDate string `json:"due_date"`
MerchantResponse string `json:"merchant_response"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
Dispute represents a single chargeback or dispute record.
type DisputeActionResponse ¶
type DisputeActionResponse struct {
TicketID string `json:"ticket_id"`
Status string `json:"status"`
Message string `json:"message"`
}
DisputeActionResponse is returned by AcceptDispute and RejectDispute.
type DisputeEvidence ¶
type DisputeEvidence struct {
TicketID string `json:"ticket_id"`
EvidenceURL string `json:"evidence_url"`
FileName string `json:"file_name"`
UploadedAt string `json:"uploaded_at"`
}
DisputeEvidence represents evidence attached to a dispute.
type DisputeListParams ¶
type DisputeListParams struct {
Page int `json:"page,omitempty"`
PerPage int `json:"per_page,omitempty"`
StartDate string `json:"start_date,omitempty"`
EndDate string `json:"end_date,omitempty"`
Status string `json:"status,omitempty"` // "open", "closed", "pending"
}
DisputeListParams holds pagination and filter parameters for listing disputes.
type DisputeListResponse ¶
type DisputeListResponse struct {
Disputes []Dispute `json:"disputes"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
}
DisputeListResponse holds a paginated list of disputes.
type DisputeService ¶
type DisputeService struct {
// contains filtered or unexported fields
}
DisputeService handles chargeback disputes and evidence submission.
func (*DisputeService) AcceptDispute ¶
func (s *DisputeService) AcceptDispute(ctx context.Context, ticketID string) (*DisputeActionResponse, error)
AcceptDispute accepts a chargeback (merchant concedes the dispute).
func (*DisputeService) All ¶
func (s *DisputeService) All(ctx context.Context, params *DisputeListParams) *Iter[Dispute]
All returns a lazy iterator over all disputes, fetching pages on demand. Filters from params (Status, StartDate, EndDate) are preserved across pages.
iter := client.Disputes.All(ctx, &squad.DisputeListParams{Status: "open"})
for iter.Next() {
d := iter.Item()
fmt.Println(d.TicketID, d.Reason)
}
func (*DisputeService) GetAllDisputes ¶
func (s *DisputeService) GetAllDisputes(ctx context.Context, params *DisputeListParams) (*DisputeListResponse, error)
GetAllDisputes retrieves a paginated list of all disputes on the merchant account.
func (*DisputeService) GetDisputeDetail ¶
GetDisputeDetail retrieves the full details of a single dispute by its ticket ID.
func (*DisputeService) GetDisputeEvidence ¶
func (s *DisputeService) GetDisputeEvidence(ctx context.Context, ticketID string) (*DisputeEvidence, error)
GetDisputeEvidence retrieves any previously uploaded evidence for a dispute.
func (*DisputeService) RejectDispute ¶
func (s *DisputeService) RejectDispute(ctx context.Context, ticketID string) (*DisputeActionResponse, error)
RejectDispute contests a chargeback (merchant disputes the claim). Evidence must be uploaded via UploadEvidence before calling this method.
func (*DisputeService) UploadEvidence ¶
func (s *DisputeService) UploadEvidence(ctx context.Context, ticketID string, fileData []byte, fileName string) (*EvidenceUploadResponse, error)
UploadEvidence uploads a file as evidence for a dispute. fileData is the raw file bytes (PDF, PNG, or JPG). fileName includes the extension. Call this before RejectDispute — evidence must be present to contest a chargeback.
type ElectricityBiller ¶
type ElectricityBiller struct {
BillerCode string `json:"biller_code"`
BillerName string `json:"biller_name"`
MeterTypes []string `json:"meter_types"` // ["prepaid", "postpaid"]
}
ElectricityBiller describes a DISCO (electricity distribution company).
type ElectricityBillersResponse ¶
type ElectricityBillersResponse struct {
Billers []ElectricityBiller `json:"billers"`
}
ElectricityBillersResponse holds the list of available electricity DISCOs.
type ElectricityResponse ¶
type ElectricityResponse struct {
VASTransactionResponse
MeterNumber string `json:"meter_number"`
Units string `json:"units"`
ElectricityToken string `json:"electricity_token"`
}
ElectricityResponse is returned by BuyElectricity, including the token for the meter.
type Error ¶
Error represents a Squad API error response. It wraps both the HTTP-level status and Squad's application-level status code.
type EventType ¶
type EventType string
EventType is the string identifier for a Squad webhook event.
const ( EventTransactionSuccess EventType = "charge.success" EventTransactionFailed EventType = "charge.failed" EventVirtualAccountCredit EventType = "virtual-account.credit" EventTransferSuccess EventType = "transfer.success" EventTransferFailed EventType = "transfer.failed" EventTransferReversed EventType = "transfer.reversed" EventDisputeOpened EventType = "dispute.opened" EventDisputeResolved EventType = "dispute.resolved" )
Squad webhook event type constants.
type EvidenceUploadResponse ¶
type EvidenceUploadResponse struct {
TicketID string `json:"ticket_id"`
FileName string `json:"file_name"`
UploadURL string `json:"upload_url"`
Status string `json:"status"`
}
EvidenceUploadResponse is returned after a successful evidence upload.
type FundsTransferParams ¶
type FundsTransferParams struct {
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
BankCode string `json:"bank_code"`
AccountNumber string `json:"account_number"`
AccountName string `json:"account_name"`
Currency string `json:"currency_id"` // "NGN"
Remark string `json:"remark,omitempty"`
}
FundsTransferParams holds parameters for transferring funds to a Nigerian bank account. Amount is in kobo (lowest denomination). Settlement is T+1 by default.
type InitiatePaymentParams ¶
type InitiatePaymentParams struct {
Email string `json:"email"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
InitiatorCustomerID string `json:"initiator_customer_id,omitempty"`
TransactionRef string `json:"transaction_ref,omitempty"`
CallbackURL string `json:"callback_url,omitempty"`
PaymentChannels []string `json:"payment_channels,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
PassCharge bool `json:"pass_charge,omitempty"`
CustomerName string `json:"customer_name,omitempty"`
IsRecurring bool `json:"is_recurring,omitempty"`
PlanCode string `json:"plan_code,omitempty"`
ChargeToken *ChargeToken `json:"charge_token,omitempty"`
}
InitiatePaymentParams holds all parameters for creating a new payment transaction. Amount must be in the lowest currency denomination (kobo for NGN: 100000 = ₦1,000).
type InitiatePaymentResponse ¶
type InitiatePaymentResponse struct {
CheckoutURL string `json:"checkout_url"`
MerchantAmount float64 `json:"merchant_amount"`
AppliedFee float64 `json:"applied_fee"`
TotalAmount float64 `json:"total_amount"`
Currency string `json:"currency"`
TransactionRef string `json:"transaction_ref"`
}
InitiatePaymentResponse is the Data payload returned by InitiatePayment. Redirect the end-user to CheckoutURL to complete payment.
type IntraTransferParams ¶
type IntraTransferParams struct {
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
SenderIdentifier string `json:"sender_identifier"`
ReceiverIdentifier string `json:"receiver_identifier"`
Narration string `json:"narration,omitempty"`
}
IntraTransferParams holds parameters for a Squad-to-Squad wallet transfer.
type Iter ¶
type Iter[T any] struct { // contains filtered or unexported fields }
Iter is a generic lazy iterator for paginated Squad API responses. Pages are fetched on demand — only when the current buffer is exhausted.
Usage:
iter := client.Transfers.All(ctx, &squad.TransferListParams{PerPage: 50})
for iter.Next() {
t := iter.Item()
fmt.Println(t.TransactionRef, squad.FromKobo(t.Amount))
}
if err := iter.Err(); err != nil {
log.Fatal(err)
}
type Logger ¶
Logger is the interface for SDK-level request/response logging. Implement this to integrate with your application's logging library.
Compatible with log/slog, go.uber.org/zap, sirupsen/logrus, rs/zerolog, and others. Fields are passed as key-value pairs: key string, value any, key string, value any, ...
// log/slog example:
type slogAdapter struct{ l *slog.Logger }
func (a slogAdapter) Info(msg string, kv ...any) { a.l.Info(msg, kv...) }
func (a slogAdapter) Error(msg string, kv ...any) { a.l.Error(msg, kv...) }
client := squad.New(key, squad.WithLogger(slogAdapter{slog.Default()}))
type MissedWebhookParams ¶
type MissedWebhookParams struct {
Page int `json:"page,omitempty"`
PerPage int `json:"per_page,omitempty"`
Action string `json:"action,omitempty"`
}
MissedWebhookParams holds query parameters for GetMissedWebhookTransactions.
type MissedWebhookResponse ¶
type MissedWebhookResponse struct {
Transactions []VerifyTransactionResponse `json:"transactions"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
}
MissedWebhookResponse is the Data payload returned by GetMissedWebhookTransactions.
type Option ¶
type Option func(*config)
Option is a functional option for configuring a Client.
func WithAfterResponse ¶
WithAfterResponse registers a hook called after every HTTP response is received. duration is the total round-trip time. Use this for metrics, tracing, or audit logging.
squad.WithAfterResponse(func(req *http.Request, resp *http.Response, d time.Duration) {
metrics.RecordLatency("squad", req.URL.Path, resp.StatusCode, d)
})
func WithAutoIdempotency ¶
func WithAutoIdempotency() Option
WithAutoIdempotency automatically generates and attaches an X-Idempotency-Key header to every POST request that does not already have one set via WithIdempotencyKey. This protects against accidental duplicate charges from network-level retries.
func WithBaseURL ¶
WithBaseURL sets a custom base URL. Useful for proxies, local mocks, or testing. Must include scheme and host with no trailing slash: "https://my-proxy.example.com"
func WithBeforeRequest ¶
WithBeforeRequest registers a hook called before every HTTP request is sent. Use this for custom header injection, request signing, or distributed tracing.
squad.WithBeforeRequest(func(req *http.Request) {
req.Header.Set("X-Correlation-ID", getCorrelationID())
})
func WithHTTPClient ¶
WithHTTPClient replaces the default *http.Client. Use this to inject transports with retry logic, tracing, or custom TLS config.
func WithLogger ¶
WithLogger attaches a Logger to the client for request/response logging. By default all logging is discarded. Use StdLogger() for development output.
client := squad.New(key, squad.WithLogger(squad.StdLogger()))
func WithProduction ¶
func WithProduction() Option
WithProduction explicitly sets the production base URL.
func WithSandbox ¶
func WithSandbox() Option
WithSandbox configures the client to use Squad's sandbox environment. This is also inferred automatically when the secret key starts with "sandbox_sk_".
func WithTimeout ¶
WithTimeout sets the HTTP request timeout, overriding the default 30-second timeout.
func WithUserAgent ¶
WithUserAgent appends a custom string to the User-Agent header.
type RefundTransactionParams ¶
type RefundTransactionParams struct {
GatewayTransactionRef string `json:"gateway_transaction_ref"`
TransactionRef string `json:"transaction_ref"`
RefundType string `json:"refund_type"`
ReasonForRefund string `json:"reason_for_refund"`
Amount int64 `json:"refund_amount,omitempty"`
RRN string `json:"rrn,omitempty"`
}
RefundTransactionParams holds parameters for initiating a transaction refund. RefundType must be "Full" or "Partial". For partial refunds, Amount is required.
type RefundTransactionResponse ¶
type RefundTransactionResponse struct {
GatewayRef string `json:"gateway_ref"`
TransactionRef string `json:"transaction_ref"`
RefundStatus string `json:"refund_status"`
AmountRefunded int64 `json:"amount_refunded"`
}
RefundTransactionResponse is the Data payload returned by RefundTransaction.
type SMSResponse ¶
type SMSResponse struct {
TransactionRef string `json:"transaction_ref"`
Status string `json:"status"`
Recipients []string `json:"recipients"`
MessageID string `json:"message_id"`
}
SMSResponse is returned by SendSMS.
type SendSMSParams ¶
type SendSMSParams struct {
To []string `json:"to"`
From string `json:"from"`
Body string `json:"body"`
TransactionRef string `json:"transaction_ref"`
}
SendSMSParams holds parameters for sending an SMS to one or more recipients.
type SimulateResponse ¶
type SimulateResponse struct {
TransactionRef string `json:"transaction_ref"`
Status string `json:"status"`
}
SimulateResponse is returned by Simulate.
type SimulateVirtualAccountParams ¶
type SimulateVirtualAccountParams struct {
VirtualAccountNumber string `json:"virtual_account_number"`
Amount float64 `json:"amount"`
}
SimulateVirtualAccountParams holds parameters for a sandbox credit simulation.
type SubMerchant ¶
type SubMerchant struct {
ID string `json:"id"`
MerchantID string `json:"merchant_id"`
DisplayName string `json:"display_name"`
AccountName string `json:"account_name"`
AccountNumber string `json:"account_number"`
BankCode string `json:"bank_code"`
BankName string `json:"bank_name"`
Email string `json:"email"`
Status string `json:"status"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
SubMerchant represents a sub-merchant account under an aggregator.
type SubMerchantListParams ¶
type SubMerchantListParams struct {
Page int `json:"page,omitempty"`
PerPage int `json:"per_page,omitempty"`
}
SubMerchantListParams holds pagination parameters for listing sub-merchants.
type SubMerchantListResponse ¶
type SubMerchantListResponse struct {
Merchants []SubMerchant `json:"merchants"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
}
SubMerchantListResponse holds a paginated list of sub-merchants.
type SubMerchantService ¶
type SubMerchantService struct {
// contains filtered or unexported fields
}
SubMerchantService manages sub-merchant accounts for aggregators and marketplace platforms. Requires an aggregator-level Squad account with the appropriate permissions.
func (*SubMerchantService) All ¶
func (s *SubMerchantService) All(ctx context.Context, params *SubMerchantListParams) *Iter[SubMerchant]
All returns a lazy iterator over all sub-merchants, fetching pages on demand.
iter := client.SubMerchants.All(ctx, nil)
for iter.Next() {
fmt.Println(iter.Item().DisplayName)
}
func (*SubMerchantService) Create ¶
func (s *SubMerchantService) Create(ctx context.Context, params *CreateSubMerchantParams) (*SubMerchant, error)
Create onboards a new sub-merchant under the aggregator account. The sub-merchant receives their own merchant ID and dashboard access.
func (*SubMerchantService) Delete ¶
func (s *SubMerchantService) Delete(ctx context.Context, merchantID string) (*DeleteSubMerchantResponse, error)
Delete removes a sub-merchant from the aggregator account.
func (*SubMerchantService) Get ¶
func (s *SubMerchantService) Get(ctx context.Context, merchantID string) (*SubMerchant, error)
Get retrieves the details of a sub-merchant by their merchant ID.
func (*SubMerchantService) List ¶
func (s *SubMerchantService) List(ctx context.Context, params *SubMerchantListParams) (*SubMerchantListResponse, error)
List returns a paginated list of all sub-merchants under the aggregator account.
type TransactionService ¶
type TransactionService struct {
// contains filtered or unexported fields
}
TransactionService handles payment initiation, verification, and refunds.
func (*TransactionService) AllMissedWebhooks ¶
func (s *TransactionService) AllMissedWebhooks(ctx context.Context, params *MissedWebhookParams) *Iter[VerifyTransactionResponse]
AllMissedWebhooks returns a lazy iterator over all missed webhook transactions.
iter := client.Transactions.AllMissedWebhooks(ctx, nil)
for iter.Next() {
tx := iter.Item()
fmt.Println(tx.TransactionRef, tx.Status)
}
func (*TransactionService) GetMissedWebhookTransactions ¶
func (s *TransactionService) GetMissedWebhookTransactions(ctx context.Context, params *MissedWebhookParams) (*MissedWebhookResponse, error)
GetMissedWebhookTransactions retrieves transactions whose webhooks were not delivered. Use for reconciliation. Delete processed entries to prevent re-delivery.
func (*TransactionService) GetUSSDbanks ¶
func (s *TransactionService) GetUSSDbanks(ctx context.Context) (*USSDbanksResponse, error)
GetUSSDbanks returns the list of banks that support USSD payment collection.
func (*TransactionService) InitiatePayment ¶
func (s *TransactionService) InitiatePayment(ctx context.Context, params *InitiatePaymentParams) (*InitiatePaymentResponse, error)
InitiatePayment creates a new payment transaction and returns a checkout URL. Redirect the end-user to Response.CheckoutURL to complete payment via the Squad modal.
func (*TransactionService) RefundTransaction ¶
func (s *TransactionService) RefundTransaction(ctx context.Context, params *RefundTransactionParams) (*RefundTransactionResponse, error)
RefundTransaction initiates a full or partial refund for a completed transaction. Set params.RefundType to "Full" or "Partial". Partial refunds require params.Amount.
func (*TransactionService) VerifyTransaction ¶
func (s *TransactionService) VerifyTransaction(ctx context.Context, transactionRef string) (*VerifyTransactionResponse, error)
VerifyTransaction retrieves the current status of a transaction by its reference. Call this after the user returns from the checkout URL or inside a webhook handler.
type TransferListParams ¶
type TransferListParams struct {
Page int `json:"page,omitempty"`
PerPage int `json:"per_page,omitempty"`
StartDate string `json:"start_date,omitempty"`
EndDate string `json:"end_date,omitempty"`
Status string `json:"status,omitempty"` // "Success", "Processing", "Failed"
}
TransferListParams holds pagination and filter parameters for listing transfers.
type TransferListResponse ¶
type TransferListResponse struct {
Transfers []TransferStatusResponse `json:"transfers"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
}
TransferListResponse holds a paginated list of transfer records.
type TransferResponse ¶
type TransferResponse struct {
TransactionRef string `json:"transaction_reference"`
Amount int64 `json:"amount"`
Fee float64 `json:"transaction_charge"`
Status string `json:"status"`
AccountName string `json:"account_name"`
AccountNumber string `json:"account_number"`
BankCode string `json:"bank_code"`
BankName string `json:"bank_name"`
CreatedAt string `json:"created_at"`
}
TransferResponse is the Data payload returned by both FundsTransfer and IntraTransfer.
type TransferService ¶
type TransferService struct {
// contains filtered or unexported fields
}
TransferService handles fund transfers to Nigerian bank accounts and Squad wallets.
func (*TransferService) AccountLookup ¶
func (s *TransferService) AccountLookup(ctx context.Context, bankCode, accountNumber string) (*AccountLookupResponse, error)
AccountLookup verifies a bank account number and returns the account holder's name. Always call this before FundsTransfer to validate the destination account.
func (*TransferService) All ¶
func (s *TransferService) All(ctx context.Context, params *TransferListParams) *Iter[TransferStatusResponse]
All returns a lazy iterator over all transfer transactions, fetching pages on demand. Filters from params (StartDate, EndDate, Status) are preserved across pages.
iter := client.Transfers.All(ctx, &squad.TransferListParams{Status: "Success"})
for iter.Next() {
fmt.Println(iter.Item().TransactionRef, squad.FromKobo(iter.Item().Amount))
}
func (*TransferService) FundsTransfer ¶
func (s *TransferService) FundsTransfer(ctx context.Context, params *FundsTransferParams) (*TransferResponse, error)
FundsTransfer transfers funds from the Squad merchant wallet to any Nigerian bank account. Use AccountLookup first to verify the destination account before transferring.
func (*TransferService) GetAllTransactions ¶
func (s *TransferService) GetAllTransactions(ctx context.Context, params *TransferListParams) (*TransferListResponse, error)
GetAllTransactions returns a paginated list of all transfer transactions.
func (*TransferService) GetTransactionStatus ¶
func (s *TransferService) GetTransactionStatus(ctx context.Context, transactionRef string) (*TransferStatusResponse, error)
GetTransactionStatus retrieves the current status of a previously initiated transfer.
func (*TransferService) IntraTransfer ¶
func (s *TransferService) IntraTransfer(ctx context.Context, params *IntraTransferParams) (*TransferResponse, error)
IntraTransfer transfers funds between two Squad wallet holders.
type TransferStatusResponse ¶
type TransferStatusResponse struct {
TransactionRef string `json:"transaction_ref"`
Status string `json:"status"`
Amount int64 `json:"amount"`
Fee float64 `json:"fee"`
ResponseCode string `json:"response_code"`
ResponseMessage string `json:"response_message"`
UpdatedAt string `json:"updated_at"`
}
TransferStatusResponse is returned by GetTransactionStatus.
type USSDBank ¶
type USSDBank struct {
BankCode string `json:"bank_code"`
BankName string `json:"bank_name"`
USSD string `json:"ussd"`
}
USSDBank describes a single bank supporting USSD payments.
type USSDbanksResponse ¶
type USSDbanksResponse struct {
Banks []USSDBank `json:"banks"`
}
USSDbanksResponse is the Data payload returned by GetUSSDbanks.
type UpdateVirtualAccountParams ¶
type UpdateVirtualAccountParams struct {
CustomerIdentifier string `json:"customer_identifier"`
BVN string `json:"bvn,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
MiddleName string `json:"middle_name,omitempty"`
MobileNum string `json:"mobile_num,omitempty"`
}
UpdateVirtualAccountParams holds fields that can be modified on an existing virtual account.
type VASService ¶
type VASService struct {
// contains filtered or unexported fields
}
VASService handles value-added services: airtime, data, cable TV, electricity, and SMS. All purchases are charged from the Squad merchant wallet.
func (*VASService) BuyAirtime ¶
func (s *VASService) BuyAirtime(ctx context.Context, params *BuyAirtimeParams) (*VASTransactionResponse, error)
BuyAirtime purchases airtime and credits the specified phone number. Minimum purchase amount is 50 NGN. Supported networks: MTN, AIRTEL, GLO, 9MOBILE.
func (*VASService) BuyCable ¶
func (s *VASService) BuyCable(ctx context.Context, params *BuyCableParams) (*VASTransactionResponse, error)
BuyCable subscribes to a cable TV package for a smart card number. Use GetCablePackages to retrieve valid package codes before calling this.
func (*VASService) BuyData ¶
func (s *VASService) BuyData(ctx context.Context, params *BuyDataParams) (*VASTransactionResponse, error)
BuyData purchases a data bundle for a phone number. Use GetDataPlans to retrieve valid plan codes before calling this.
func (*VASService) BuyElectricity ¶
func (s *VASService) BuyElectricity(ctx context.Context, params *BuyElectricityParams) (*ElectricityResponse, error)
BuyElectricity purchases electricity units for a prepaid or postpaid meter. The returned ElectricityToken must be entered into the customer's meter.
func (*VASService) GetCablePackages ¶
func (s *VASService) GetCablePackages(ctx context.Context, cableProvider string) (*CablePackagesResponse, error)
GetCablePackages retrieves available cable TV subscription packages for the given provider. cableProvider is one of: "DSTV", "GOTV", "STARTIMES".
func (*VASService) GetDataPlans ¶
func (s *VASService) GetDataPlans(ctx context.Context, networkProvider string) (*DataPlansResponse, error)
GetDataPlans retrieves available data bundle plans for the given network provider. networkProvider is one of: "MTN", "AIRTEL", "GLO", "9MOBILE".
func (*VASService) GetElectricityBillers ¶
func (s *VASService) GetElectricityBillers(ctx context.Context) (*ElectricityBillersResponse, error)
GetElectricityBillers retrieves the list of available electricity distribution companies (DISCOs).
func (*VASService) SendSMS ¶
func (s *VASService) SendSMS(ctx context.Context, params *SendSMSParams) (*SMSResponse, error)
SendSMS sends a personalised SMS message to one or more recipients.
type VASTransactionResponse ¶
type VASTransactionResponse struct {
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
Status string `json:"status"`
PhoneNumber string `json:"phone_number,omitempty"`
Network string `json:"network,omitempty"`
CreatedAt string `json:"created_at"`
}
VASTransactionResponse is the common response for airtime, data, and cable purchases.
type VerifyTransactionResponse ¶
type VerifyTransactionResponse struct {
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"transaction_amount"`
Fee float64 `json:"fee"`
SettlementAmount float64 `json:"settlement_amount"`
Status string `json:"transaction_status"`
Channel string `json:"channel"`
Currency string `json:"currency"`
Customer CustomerInfo `json:"customer_info"`
Meta map[string]any `json:"meta,omitempty"`
IsRecurring bool `json:"is_recurring"`
ChargeToken *ChargeToken `json:"charge_token,omitempty"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
VerifyTransactionResponse is the Data payload returned by VerifyTransaction.
type VirtualAccount ¶
type VirtualAccount struct {
VirtualAccountNumber string `json:"virtual_account_number"`
CustomerIdentifier string `json:"customer_identifier"`
FirstName string `json:"first_name"`
LastName string `json:"last_name"`
MiddleName string `json:"middle_name"`
MobileNum string `json:"mobile_num"`
Email string `json:"email"`
UniqueID string `json:"unique_id"`
BeneficiaryAccount string `json:"beneficiary_account"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
VirtualAccount is the core virtual account object returned by the API.
type VirtualAccountService ¶
type VirtualAccountService struct {
// contains filtered or unexported fields
}
VirtualAccountService handles NUBAN virtual account creation and management.
func (*VirtualAccountService) AllTransactions ¶
func (s *VirtualAccountService) AllTransactions(ctx context.Context, customerIdentifier string, params *VirtualAccountTxParams) *Iter[VirtualAccountTransaction]
AllTransactions returns a lazy iterator over all transactions for a virtual account. Filters from params (StartDate, EndDate, Action) are preserved across pages.
iter := client.VirtualAccounts.AllTransactions(ctx, "cust-001", nil)
for iter.Next() {
tx := iter.Item()
fmt.Println(tx.TransactionRef, tx.SenderName)
}
func (*VirtualAccountService) Create ¶
func (s *VirtualAccountService) Create(ctx context.Context, params *CreateVirtualAccountParams) (*VirtualAccount, error)
Create creates a NUBAN-compliant virtual account for a customer. The account is permanently tied to CustomerIdentifier and receives payments on their behalf. CBN profiling must be completed on the Squad dashboard before calling this endpoint.
func (*VirtualAccountService) GetTransactions ¶
func (s *VirtualAccountService) GetTransactions(ctx context.Context, customerIdentifier string, params *VirtualAccountTxParams) (*VirtualAccountTxResponse, error)
GetTransactions retrieves paginated transactions for a virtual account by customer identifier.
func (*VirtualAccountService) Query ¶
func (s *VirtualAccountService) Query(ctx context.Context, virtualAccountNumber string) (*VirtualAccount, error)
Query retrieves the details of a virtual account by its account number.
func (*VirtualAccountService) Simulate ¶
func (s *VirtualAccountService) Simulate(ctx context.Context, params *SimulateVirtualAccountParams) (*SimulateResponse, error)
Simulate credits a sandbox virtual account with a test transaction. This method returns an error when called against a production base URL.
func (*VirtualAccountService) Update ¶
func (s *VirtualAccountService) Update(ctx context.Context, params *UpdateVirtualAccountParams) (*VirtualAccount, error)
Update modifies metadata on an existing virtual account.
type VirtualAccountTransaction ¶
type VirtualAccountTransaction struct {
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
SenderName string `json:"sender_name"`
SenderBank string `json:"sender_bank"`
SenderAccountNumber string `json:"sender_account_number"`
Status string `json:"transaction_status"`
CreatedAt string `json:"created_at"`
}
VirtualAccountTransaction is a single credit transaction on a virtual account.
type VirtualAccountTxParams ¶
type VirtualAccountTxParams struct {
Page int `json:"page,omitempty"`
PerPage int `json:"per_page,omitempty"`
StartDate string `json:"start_date,omitempty"` // "YYYY-MM-DD"
EndDate string `json:"end_date,omitempty"`
Action string `json:"action,omitempty"`
}
VirtualAccountTxParams holds query parameters for fetching virtual account transactions.
type VirtualAccountTxResponse ¶
type VirtualAccountTxResponse struct {
Transactions []VirtualAccountTransaction `json:"transactions"`
Total int `json:"total"`
Page int `json:"page"`
PerPage int `json:"per_page"`
}
VirtualAccountTxResponse holds paginated transactions for a virtual account.
type WebhookDisputeBody ¶
type WebhookDisputeBody struct {
TicketID string `json:"ticket_id"`
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
Status string `json:"dispute_status"`
Reason string `json:"dispute_reason"`
CreatedAt string `json:"created_at"`
}
WebhookDisputeBody holds the body payload for dispute events.
type WebhookEvent ¶
type WebhookEvent struct {
Event EventType `json:"event"`
Body json.RawMessage `json:"body"`
}
WebhookEvent is the top-level structure of all Squad webhook payloads. Use event.Event to determine the event type, then call ParseBody() to decode the body.
func ParseWebhook ¶
func ParseWebhook(payload []byte, signature string, secret string) (*WebhookEvent, error)
ParseWebhook parses and validates an inbound Squad webhook.
payload is the raw HTTP request body bytes. signature is the value of the "x-squad-signature" header. secret is the merchant's Squad secret key (same key used for API calls).
Returns ErrInvalidSignature if the HMAC-SHA512 signature does not match. Returns a parse error if the JSON payload is malformed.
func (*WebhookEvent) ParseBody ¶
func (e *WebhookEvent) ParseBody() (any, error)
ParseBody decodes the Body field into the appropriate typed struct based on Event. Returns one of:
- *WebhookTransactionBody for EventTransactionSuccess / EventTransactionFailed
- *WebhookVirtualAccountBody for EventVirtualAccountCredit
- *WebhookTransferBody for EventTransferSuccess / EventTransferFailed / EventTransferReversed
- *WebhookDisputeBody for EventDisputeOpened / EventDisputeResolved
- json.RawMessage for unknown or future event types
type WebhookRouter ¶
type WebhookRouter struct {
// contains filtered or unexported fields
}
WebhookRouter is an http.Handler that validates Squad webhook signatures and dispatches each event to its registered typed handler function.
Register handlers with the fluent On* methods, then mount the router as an HTTP handler:
router := squad.NewWebhookRouter(os.Getenv("SQUAD_SECRET_KEY")).
OnTransactionSuccess(handlePayment).
OnVirtualAccountCredit(handleCredit).
OnDisputeOpened(handleDispute)
http.Handle("/webhook/squad", router)
func NewWebhookRouter ¶
func NewWebhookRouter(secret string) *WebhookRouter
NewWebhookRouter creates a new WebhookRouter that validates signatures using secret. secret is the same Squad secret key used to initialise the Client.
func (*WebhookRouter) OnDisputeOpened ¶
func (r *WebhookRouter) OnDisputeOpened(fn func(context.Context, *WebhookDisputeBody) error) *WebhookRouter
OnDisputeOpened registers a handler for dispute.opened events.
func (*WebhookRouter) OnDisputeResolved ¶
func (r *WebhookRouter) OnDisputeResolved(fn func(context.Context, *WebhookDisputeBody) error) *WebhookRouter
OnDisputeResolved registers a handler for dispute.resolved events.
func (*WebhookRouter) OnError ¶
func (r *WebhookRouter) OnError(fn func(http.ResponseWriter, *http.Request, error)) *WebhookRouter
OnError registers a custom error handler called when signature validation fails, JSON parsing fails, or a dispatched handler returns an error. The default behaviour is to write an HTTP 400 or 403 response.
func (*WebhookRouter) OnTransactionFailed ¶
func (r *WebhookRouter) OnTransactionFailed(fn func(context.Context, *WebhookTransactionBody) error) *WebhookRouter
OnTransactionFailed registers a handler for charge.failed events.
func (*WebhookRouter) OnTransactionSuccess ¶
func (r *WebhookRouter) OnTransactionSuccess(fn func(context.Context, *WebhookTransactionBody) error) *WebhookRouter
OnTransactionSuccess registers a handler for charge.success events.
func (*WebhookRouter) OnTransferFailed ¶
func (r *WebhookRouter) OnTransferFailed(fn func(context.Context, *WebhookTransferBody) error) *WebhookRouter
OnTransferFailed registers a handler for transfer.failed events.
func (*WebhookRouter) OnTransferReversed ¶
func (r *WebhookRouter) OnTransferReversed(fn func(context.Context, *WebhookTransferBody) error) *WebhookRouter
OnTransferReversed registers a handler for transfer.reversed events.
func (*WebhookRouter) OnTransferSuccess ¶
func (r *WebhookRouter) OnTransferSuccess(fn func(context.Context, *WebhookTransferBody) error) *WebhookRouter
OnTransferSuccess registers a handler for transfer.success events.
func (*WebhookRouter) OnUnknown ¶
func (r *WebhookRouter) OnUnknown(fn func(context.Context, *WebhookEvent) error) *WebhookRouter
OnUnknown registers a fallback handler for unrecognised or future event types. The raw *WebhookEvent is passed so the caller can inspect event.Body directly.
func (*WebhookRouter) OnVirtualAccountCredit ¶
func (r *WebhookRouter) OnVirtualAccountCredit(fn func(context.Context, *WebhookVirtualAccountBody) error) *WebhookRouter
OnVirtualAccountCredit registers a handler for virtual-account.credit events.
func (*WebhookRouter) ServeHTTP ¶
func (r *WebhookRouter) ServeHTTP(w http.ResponseWriter, req *http.Request)
ServeHTTP implements http.Handler. It reads the request body, validates the x-squad-signature header, parses the event, and dispatches to the registered handler. Returns 403 on invalid signature, 400 on parse errors, 500 if a handler returns an error, and 200 on success.
type WebhookTransactionBody ¶
type WebhookTransactionBody struct {
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
Status string `json:"transaction_status"`
Channel string `json:"channel"`
CustomerEmail string `json:"customer_email"`
CustomerName string `json:"customer_name"`
Meta map[string]any `json:"meta,omitempty"`
GatewayRef string `json:"gateway_ref"`
IsRecurring bool `json:"is_recurring"`
ChargeToken *ChargeToken `json:"charge_token,omitempty"`
CreatedAt string `json:"created_at"`
}
WebhookTransactionBody holds the body payload for charge.success and charge.failed events.
type WebhookTransferBody ¶
type WebhookTransferBody struct {
TransactionRef string `json:"transaction_ref"`
Amount int64 `json:"amount"`
Status string `json:"status"`
AccountName string `json:"account_name"`
AccountNumber string `json:"account_number"`
BankCode string `json:"bank_code"`
CreatedAt string `json:"created_at"`
}
WebhookTransferBody holds the body payload for transfer events.
type WebhookVirtualAccountBody ¶
type WebhookVirtualAccountBody struct {
VirtualAccountNumber string `json:"virtual_account_number"`
Amount int64 `json:"amount"`
Currency string `json:"currency"`
SenderName string `json:"sender_name"`
SenderBank string `json:"sender_bank"`
TransactionRef string `json:"transaction_ref"`
CustomerIdentifier string `json:"customer_identifier"`
CreatedAt string `json:"created_at"`
}
WebhookVirtualAccountBody holds the body payload for virtual-account.credit events.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
payment
command
|
|
|
virtualaccount
command
|
|
|
webhook
command
|
|
|
Package squadtest provides a mock Squad API server for use in tests.
|
Package squadtest provides a mock Squad API server for use in tests. |