Go SDK
Integrate Seev payments into your Go application. Build checkouts, handle callbacks, process webhooks, and manage transactions with the seevpay package.
The Seev Go SDK (seevcashplus/pkg/seevpay) provides a type-safe, idiomatic Go interface to the Seev payment API. It works with any Go web framework — Gin, Echo, Chi, net/http, and more.
Installation
go get github.com/seev/sdk/pkg/seevpayOr if working inside the same workspace, import directly:
import "seevcashplus/pkg/seevpay"Initialise the SDK
Call seevpay.Init() once at startup — in init() or your application bootstrap — before making any API calls.
package main
import (
"log"
"seevcashplus/pkg/seevpay"
)
func init() {
err := seevpay.Init(seevpay.Config{
PublicKey: "pk_your_public_key",
PrivateKey: "sk_your_secret_key",
})
if err != nil {
log.Fatal("Failed to initialise Seev SDK:", err)
}
}Create a charge
seevpay.Charge(req ChargeRequest)
Create a checkout session and redirect the customer to the returned CheckoutURL.
Returns: (*Charge, error)
With a fixed amount:
charge, err := seevpay.Charge(seevpay.ChargeRequest{
Type: "checkout",
Recipient: seevpay.CheckoutRecipient{
Name: "Jane Doe",
Email: "jane@example.com",
Phone: "+233501234567",
Address: "123 Main St",
City: "Accra",
},
Amount: seevpay.Int64Ptr(10000), // 10000 = GHS 100.00
Currency: "GHS",
Channels: []string{"card", "mobile_money"},
Discount: seevpay.Float64Ptr(5),
Tax: seevpay.Float64Ptr(2.5),
RedirectURL: "https://myapp.com/callback",
})
if err != nil {
log.Fatalf("Charge failed: %v", err)
}
// Redirect the customer
fmt.Println(charge.CheckoutURL)With line items (amount calculated server-side):
charge, err := seevpay.Charge(seevpay.ChargeRequest{
Type: "checkout",
Recipient: seevpay.CheckoutRecipient{
Name: "John Doe",
Email: "john@example.com",
},
Items: []seevpay.CheckoutItem{
{
Name: "Product A",
Description: "A great product",
Quantity: seevpay.Int64Ptr(2),
Price: 5000,
Image: "https://example.com/product-a.jpg",
},
{
Name: "Product B",
Quantity: seevpay.Int64Ptr(1),
Price: 3000,
},
},
Currency: "GHS",
RedirectURL: "https://myapp.com/callback",
})Charge fields:
| Field | Type | Description |
|---|---|---|
charge.ID | string | Checkout session ID |
charge.CheckoutURL | string | URL to redirect the customer to |
charge.Status | string | Initial session status |
charge.Amount | int64 | Resolved charge amount |
charge.Currency | string | Charge currency |
charge.GetResponse() | map[string]interface{} | Full API response |
charge.GetRaw(key) | interface{} | Access any field from the raw response |
Handle the callback
seevpay.Callback(sessionID string)
Verify the session after the customer returns from the checkout page.
Returns: (*Callback, error)
// Gin example
func handleCallback(c *gin.Context) {
sessionID := c.Query("session_id")
session, err := seevpay.Callback(sessionID)
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if session.IsSuccessful() {
log.Printf("Payment successful — session: %s", session.ID)
c.JSON(200, gin.H{"status": "success"})
} else {
c.JSON(200, gin.H{"status": session.Status})
}
}Callback fields:
| Field / Method | Type | Description |
|---|---|---|
session.ID | string | Session ID |
session.Status | string | Payment status |
session.Reference | string | Transaction reference |
session.IsSuccessful() | bool | true if payment completed |
session.GetSession() | map[string]interface{} | Full session object |
Handle webhooks
seevpay.Webhook(body map[string]interface{}, user interface{})
Parse incoming Seev webhook events. Always return 200 quickly and process asynchronously.
Returns: (*Webhook, error)
func handleWebhook(c *gin.Context) {
var body map[string]interface{}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, gin.H{"error": "Invalid request"})
return
}
event, err := seevpay.Webhook(body, nil)
if err != nil {
c.JSON(400, gin.H{"error": "Invalid webhook"})
return
}
switch {
case event.Is("checkout.completed"):
data := event.GetData()
log.Printf("Payment completed: %v %v %v",
data["checkoutId"], data["amount"], data["currency"])
case event.Is("checkout.failed"):
data := event.GetData()
log.Printf("Payment failed: %v — %v", data["checkoutId"], data["reason"])
case event.Is("refund.issued"):
log.Printf("Refund issued: %v", event.GetData())
default:
log.Printf("Unhandled event: %s", event.Type())
}
c.JSON(200, gin.H{"received": true})
}Webhook fields:
| Field / Method | Description |
|---|---|
event.Type() | Event type string, e.g. "checkout.completed" |
event.Is(type) | true if the event matches the given type |
event.GetData() | Event payload as map[string]interface{} |
event.User() | Associated user (passed as second arg to Webhook()) |
event.GetRawEvent() | Full raw event object |
Common webhook events:
| Event | Description |
|---|---|
checkout.completed | Payment succeeded |
checkout.failed | Payment failed |
checkout.pending | Payment is pending confirmation |
refund.issued | A refund was issued |
invoice.created | Invoice was created |
invoice.paid | Invoice was paid |
Fetch a transaction
seevpay.Transaction(transactionID string)
Retrieve details about a specific transaction. Use this server-side to confirm payment status.
Returns: (*Transaction, error)
txn, err := seevpay.Transaction("txn_abc123xyz")
if err != nil {
log.Fatalf("Failed to fetch transaction: %v", err)
}
log.Printf("Status: %s — Amount: %d %s", txn.Status, txn.Amount, txn.Currency)Transaction fields:
| Field | Type | Description |
|---|---|---|
txn.ID | string | Transaction ID |
txn.Status | string | "completed", "pending", "failed" |
txn.Amount | int64 | Transaction amount |
txn.Currency | string | Transaction currency |
txn.Reference | string | Optional reference |
Type reference
Config
type Config struct {
PublicKey string // Your Seev public key
PrivateKey string // Your Seev private key
BaseURL string // Optional — defaults to production URL
Timeout time.Duration // Optional — defaults to 30s
}ChargeRequest
type ChargeRequest struct {
Type string // "checkout" | "invoice" | "payment_link"
Recipient CheckoutRecipient
Currency string // GHS | USD | EUR | GBP | NGN | USDC | USDT | ETH | BTC | XRP
Channels []string // card | mobile_money | bank_transfer | seev | crypto
Amount *int64 // Omit if using Items
Items []CheckoutItem // Omit if using Amount
Discount *float64
Tax *float64
RedirectURL string // Required
}CheckoutRecipient
type CheckoutRecipient struct {
Name string // Required
Email string // Required
Address string // Optional
City string // Optional
Phone string // Optional
}CheckoutItem
type CheckoutItem struct {
Name string
Description string // Optional
Quantity *int64 // Optional — defaults to 1
Price int64 // Required
Image string // Optional
}Helper functions
The SDK provides pointer helpers for optional numeric fields:
amount := seevpay.Int64Ptr(10000)
discount := seevpay.Float64Ptr(5.0)Error handling
All SDK functions return Go errors. Use errors.As to inspect SDK-specific errors:
charge, err := seevpay.Charge(seevpay.ChargeRequest{ /* ... */ })
if err != nil {
var sdkErr *seevpay.SDKError
if errors.As(err, &sdkErr) {
log.Printf("SDK error [%s]: %s", sdkErr.Code, sdkErr.Message)
} else {
log.Printf("Unexpected error: %v", err)
}
}Common errors:
| Error | Cause |
|---|---|
"Seev SDK not initialized. Call Init() first." | Init() was not called before making a request |
"Failed to create checkout session: ..." | Bad request data or invalid API keys |
"Failed to verify checkout session: session not found or invalid" | Expired or invalid session ID |
"Invalid webhook payload: missing event type" | Malformed webhook body |
"Network error: ..." | Connectivity issue or unreachable endpoint |
Full integration example
package main
import (
"log"
"github.com/gin-gonic/gin"
"seevcashplus/pkg/seevpay"
)
func init() {
if err := seevpay.Init(seevpay.Config{
PublicKey: "pk_test_123",
PrivateKey: "sk_test_456",
}); err != nil {
log.Fatal(err)
}
}
func main() {
r := gin.Default()
r.POST("/checkout", func(c *gin.Context) {
charge, err := seevpay.Charge(seevpay.ChargeRequest{
Type: "checkout",
Recipient: seevpay.CheckoutRecipient{Name: "Jane Doe", Email: "jane@example.com"},
Items: []seevpay.CheckoutItem{
{Name: "Widget", Price: 2500, Quantity: seevpay.Int64Ptr(1)},
},
Currency: "GHS",
RedirectURL: "https://myapp.com/callback",
})
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"checkoutUrl": charge.CheckoutURL})
})
r.GET("/callback", func(c *gin.Context) {
result, err := seevpay.Callback(c.Query("session_id"))
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
if result.IsSuccessful() {
c.JSON(200, gin.H{"status": "success", "sessionId": result.ID})
} else {
c.JSON(200, gin.H{"status": result.Status})
}
})
r.POST("/webhooks/seev", func(c *gin.Context) {
var body map[string]interface{}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, gin.H{"error": "Invalid request"})
return
}
event, err := seevpay.Webhook(body, nil)
if err != nil {
c.JSON(400, gin.H{"error": "Invalid webhook"})
return
}
if event.Is("checkout.completed") {
log.Printf("Payment completed: %v", event.GetData())
}
c.JSON(200, gin.H{"received": true})
})
r.GET("/transaction/:id", func(c *gin.Context) {
txn, err := seevpay.Transaction(c.Param("id"))
if err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, txn)
})
r.Run(":8080")
}Advanced configuration
// Custom base URL (e.g. sandbox) and timeout
seevpay.Init(seevpay.Config{
PublicKey: "pk_test_123",
PrivateKey: "sk_test_456",
BaseURL: "https://sandbox-api.seevpay.com",
Timeout: 45 * time.Second,
})