Skip to main content
Version: 0.8

Errors

Every provider translates its SDK's own errors into gopay's sentinel errors, so callers write one errors.Is check that works across Stripe, PayPal, and Razorpay instead of branching on each SDK's error types.

p, err := client.CreatePayment(ctx, req)
if errors.Is(err, payment.ErrCardDeclined) {
// handle declined card
} else if errors.Is(err, payment.ErrInsufficientFunds) {
// handle insufficient funds
} else if errors.Is(err, payment.ErrInvalidAmount) {
// handle invalid amount
}

Errors returned by Client methods are wrapped with fmt.Errorf("...: %w", err) (e.g. "create payment: gopay: card declined"), so errors.Is still matches through the wrapping.

Sentinel errors

ErrorMeaning
ErrInvalidConfigProvider configuration is invalid (e.g. missing API key)
ErrInvalidAmountAmount is negative or fails validation
ErrInvalidCurrencyCurrency is empty or not in the accepted ISO 4217 set
ErrInvalidCardCard details are invalid
ErrCardDeclinedThe card was declined
ErrInsufficientFundsThe card had insufficient funds
ErrExpiredCardThe card has expired
ErrPaymentFailedThe payment failed for another reason
ErrRefundFailedThe refund failed
ErrSetupFailedThe setup intent failed
ErrSubscriptionFailedThe subscription operation failed
ErrNotFoundThe requested resource doesn't exist (also returned for an empty ID)
ErrAlreadyRefundedThe payment was already fully refunded
ErrAlreadyCapturedThe payment was already captured
ErrAuthenticationRequiredAdditional authentication (e.g. 3DS) is required
ErrProviderErrorAn unmapped provider-side error
ErrUnsupportedThe provider doesn't implement the optional capability called

ErrUnsupported is the one to check across providers

Because optional capabilities (customers, subscriptions, listing, ...) are gated per-provider (see Client), ErrUnsupported is the error you'll see most often when writing provider-agnostic code:

_, err := client.ListPayments(ctx, params)
if errors.Is(err, payment.ErrUnsupported) {
// this provider (e.g. PayPal) has no list endpoint
}

The error-translation pattern

Each provider package implements its own unexported error-translation method — mapError in Stripe, parseError in PayPal and Razorpay — that inspects the underlying SDK error (HTTP status code, decline code, provider-specific error type) and returns the matching gopay sentinel, falling back to ErrProviderError for anything it doesn't recognize. Every provider method funnels its SDK error through that function before returning, so no raw provider error type ever reaches a caller through the Client.