SDK-SPEC-GO — Go SDK Specification¶
Status: Draft
Owner: Platform Engineering
Module: github.com/simpaisa/simpaisa-go
Runtime: Go 1.22+
Last Updated: 2026-04-03
1. Overview¶
Official Go SDK for the Simpaisa Payment Gateway. Provides idiomatic, context-aware access to Pay-Ins, Pay-Outs, Remittances, and Cards across PK, BD, NP, and IQ corridors. Handles 270M+ annual transactions at $1B+ volume. Used internally by Simpaisa platform services and offered to merchant integrators. Published via go.dev.
2. Module Path¶
module github.com/simpaisa/simpaisa-go
Import: import "github.com/simpaisa/simpaisa-go/payin"
3. Package Structure¶
simpaisa-go/
├── client.go # Client struct, constructor, options
├── config.go # Config type and defaults
├── payin/
│ ├── client.go # PayIn operations (Initiate, Verify, Status, List)
│ ├── request.go # PayInRequest struct
│ └── response.go # PayInResponse struct
├── payout/
│ ├── client.go # PayOut operations (Initiate, Status, Batch, Cancel)
│ ├── request.go
│ └── response.go
├── remittance/
│ ├── client.go # Remittance operations (Quote, Initiate, Status, Beneficiaries)
│ ├── request.go
│ └── response.go
├── cards/
│ ├── client.go # Cards operations (Pay, Capture, Void, Refund, Tokenise)
│ ├── request.go
│ └── response.go
├── webhook/
│ ├── verifier.go # HMAC-SHA256 webhook verification
│ └── event.go # WebhookEvent type
├── auth/
│ ├── rsa.go # RSAAuthProvider — PEM loading, request signing
│ └── auth.go # AuthProvider interface
├── errors.go # Error types and sentinel values
├── retry/
│ └── policy.go # Exponential backoff with jitter
├── idempotency/
│ └── generator.go # UUID v7 key generation
├── internal/
│ ├── transport.go # HTTP transport with auth, retry, idempotency
│ └── json.go # JSON helpers
├── go.mod
├── go.sum
└── Makefile
4. Authentication — RSAAuthProvider¶
- Load merchant private key from PEM file via
crypto/x509.ParsePKCS8PrivateKey - Sign request body with
crypto/rsa.SignPKCS1v15using SHA-256 - Attach
X-Simpaisa-SignatureandX-Simpaisa-Merchant-Idheaders - Implement
AuthProviderinterface for extensibility - Support key rotation via slice of key paths
auth, err := auth.NewRSAProvider(
auth.WithMerchantID("MCH-001"),
auth.WithPrivateKeyFile("./keys/merchant.pem"),
)
5. Context-Aware Design¶
- ALL public methods SHALL accept
context.Contextas first parameter - Respect context cancellation and deadlines
- Propagate trace context via
go.opentelemetry.io/otelwhen available - No background goroutines without explicit lifecycle management
result, err := client.PayIn.Initiate(ctx, &payin.Request{
Amount: 5000,
Currency: "PKR",
Channel: "EASYPAISA",
})
6. WebhookVerifier¶
- Verify
X-Simpaisa-Webhook-Signatureusingcrypto/hmacwith SHA-256 Verify(payload []byte, signature string) error- Constant-time comparison via
hmac.Equal() - Replay protection: validate timestamp header within tolerance (default 300s)
- Return
ErrWebhookVerificationon failure
7. Retry with Backoff¶
- Exponential backoff with jitter (base 200ms, max 30s)
- Configurable max retries (default 3)
- Retry on: 429, 502, 503, 504,
net.Error(temporary) - Never retry: 400, 401, 403, 404, 409, 422
- Respect
Retry-Afterheader OnRetrycallback function for observability- Context cancellation stops retries immediately
8. Idiomatic Go Patterns¶
- Functional options pattern for configuration:
WithTimeout(),WithRetries() - Error values (not exceptions): return
errorfrom all fallible operations - Sentinel errors:
ErrAuthentication,ErrValidation,ErrRateLimit,ErrTimeout errors.Is()anderrors.As()compatible- No generics abuse — use concrete types
io.Reader/io.Writerwhere appropriate- Struct embedding for composition
9. Error Handling¶
var (
ErrAuthentication // 401/403 responses
ErrValidation // 400/422 with field details
ErrRateLimit // 429 with RetryAfter
ErrTimeout // request/connection timeout
ErrIdempotency // conflicting idempotency key
ErrNetwork // connection/DNS failures
ErrWebhookVerification // signature mismatch
)
// SimPaisaError wraps all errors with metadata
type SimPaisaError struct {
Code string
Message string
StatusCode int
RequestID string
Retryable bool
Err error // wrapped error for errors.Is/As
}
10. Configuration¶
client, err := simpaisa.NewClient(
simpaisa.WithEnvironment(simpaisa.Sandbox), // Sandbox or Production
simpaisa.WithMerchantID("MCH-001"),
simpaisa.WithPrivateKeyFile("./keys/merchant.pem"),
simpaisa.WithTimeout(30 * time.Second), // default 30s
simpaisa.WithMaxRetries(3), // default 3
simpaisa.WithHTTPClient(customClient), // optional
simpaisa.WithLogger(slog.Default()), // optional, log/slog
)
11. Example Usage¶
package main
import (
"context"
"log"
"github.com/simpaisa/simpaisa-go"
"github.com/simpaisa/simpaisa-go/payin"
"github.com/simpaisa/simpaisa-go/webhook"
)
func main() {
client, err := simpaisa.NewClient(
simpaisa.WithEnvironment(simpaisa.Sandbox),
simpaisa.WithMerchantID("MCH-001"),
simpaisa.WithPrivateKeyFile("./keys/merchant.pem"),
)
if err != nil {
log.Fatal(err)
}
// Pay-In
result, err := client.PayIn.Initiate(context.Background(), &payin.Request{
Amount: 5000,
Currency: "PKR",
Channel: "EASYPAISA",
CustomerMSISDN: "03001234567",
CallbackURL: "https://merchant.com/webhook",
})
// Webhook verification
verifier := webhook.NewVerifier("whsec_...")
err = verifier.Verify(rawBody, signatureHeader)
}
12. Build and Publish¶
- Test:
go test ./...with race detector (-race) - Linting: golangci-lint (golint, govet, staticcheck, errcheck, gosec)
- CI: Bitbucket Pipelines — lint → test → vet → build
- Publish: Tag-based releases; go.dev indexes automatically
- Versioning: Semantic versioning via git tags (
v1.x.x) - Go compatibility: Tested on latest two Go releases
13. Dependencies¶
- Standard library only for core functionality (
net/http,crypto/*,encoding/json) - Optional:
go.opentelemetry.io/otelfor tracing - Zero required third-party dependencies for the base SDK
log/slogfor structured logging (Go 1.21+)
14. Testing Requirements¶
- Unit tests for every exported function (>90% coverage)
- Integration tests against sandbox environment (build-tagged)
- Table-driven tests following Go conventions
- Webhook verification round-trip tests
- Retry behaviour tests with
httptest.Server - Race condition tests (
-raceflag in CI) - Fuzz tests for webhook verification and JSON parsing
15. Documentation¶
- GoDoc comments on all exported types, functions, and methods
- Package-level doc.go in each package
- README with quickstart and corridor-specific examples
- Examples as
Example*test functions (appear on go.dev) - CHANGELOG following Keep a Changelog format