https://github.com/pcriv/go-payoneer
A high-quality, type-safe, and observable Go SDK for the Payoneer API
https://github.com/pcriv/go-payoneer
Last synced: 3 months ago
JSON representation
A high-quality, type-safe, and observable Go SDK for the Payoneer API
- Host: GitHub
- URL: https://github.com/pcriv/go-payoneer
- Owner: pcriv
- License: mit
- Created: 2026-03-16T20:27:21.000Z (4 months ago)
- Default Branch: main
- Last Pushed: 2026-04-14T07:56:43.000Z (3 months ago)
- Last Synced: 2026-04-14T09:34:23.859Z (3 months ago)
- Language: Go
- Size: 137 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# go-payoneer
A high-quality, type-safe, and observable Go SDK for the Payoneer API.
[](https://pkg.go.dev/github.com/pcriv/go-payoneer)
[](https://goreportcard.com/report/github.com/pcriv/go-payoneer)
[](https://codecov.io/gh/pcriv/go-payoneer)
## Features
- **Full Service Coverage**: Accounts, Payouts, Webhooks, and Payee Management.
- **Robust Authentication**: Secure OAuth 2.0 with eager credential validation and automatic token refreshing.
- **Observability**: First-class support for `slog` structured logging and OpenTelemetry (Tracing/Metrics).
- **Resiliency**: Built-in exponential backoff retries and rate-limit handling (429s).
- **Type-Safety**: Clean Go structs for all API resources, using generics for optional/nullable fields.
- **Secure Webhooks**: Mandatory HMAC SHA-256 signature validation with an easy-to-use middleware.
## Installation
```bash
go get github.com/pcriv/go-payoneer
```
## Quick Start
### 1. Initialize the Client
The SDK uses functional options for clean and flexible configuration.
```go
import "github.com/pcriv/go-payoneer/pkg/payoneer"
client := payoneer.NewClient(
payoneer.WithSandbox(), // Use Sandbox for development
payoneer.WithProgramID("your-program-id"),
payoneer.WithClientCredentials("your-client-id", "your-client-secret"),
payoneer.WithRetries(3),
)
```
### 2. Authenticate
`Authenticate` eagerly fetches a token to validate your credentials. If the credentials or token endpoint are invalid, it fails immediately with a clear error.
```go
ctx := context.Background()
err := client.Authenticate(ctx)
if err != nil {
// errors.Is(err, payoneer.ErrAuthenticationFailed) can be used
// to programmatically detect auth failures.
log.Fatal(err)
}
```
## Usage Examples
### Submit a Mass Payout
```go
request := &payoneer.MassPayoutRequest{
Payments: []payoneer.PayoutItem{
{
ClientReferenceID: "unique-payout-ref-123",
PayeeID: "payee-456",
Amount: 15000, // $150.00 (in cents, converted to 150.00 on the wire)
Currency: "USD",
Description: "March payout",
},
},
}
result, err := client.Payouts.SubmitMany(ctx, request)
// result.Result — e.g. "Payments Created"
```
### Handle Webhooks (IPCN)
Protect your webhook endpoint using the built-in middleware.
```go
cfg := payoneer.WebhookConfig{
Secret: "your-shared-secret",
ExpectedAppName: payoneer.AppNameProduction, // or AppNameSandbox
// MaxClockSkew defaults to 5m; set to -1 to disable the timestamp check.
// NonceStore: yourStore, // optional replay protection
}
mux := http.NewServeMux()
// Middleware parses `Authorization: hmacauth :::`,
// verifies the HMAC-SHA256 over payload+nonce+timestamp, and restores the body.
// Each Payoneer webhook type is delivered to its own endpoint — the event
// type is implied by the URL, not carried in the body. Unmarshal into the
// struct that matches the endpoint: PaymentRequestAcceptedEvent,
// CancelPayoutEvent, PayeeApprovedEvent, PayeeDeclinedEvent.
mux.Handle("/webhooks/cancel-payout", payoneer.WebhookValidator(cfg)(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
wh, err := payoneer.ParseWebhook(r, cfg)
if err != nil {
http.Error(w, err.Error(), http.StatusUnauthorized)
return
}
var ev payoneer.CancelPayoutEvent
if err := wh.Decode(&ev); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
fmt.Printf("Payout %s cancelled for payee %s: %s\n",
ev.IntPaymentID, ev.PayeeID, ev.ReasonDescription)
w.WriteHeader(http.StatusOK)
}),
))
```
### Payee Onboarding
```go
// Generate a link for a new payee to register
result, err := client.Payees.CreateRegistrationLink(ctx, "payee-789",
payoneer.WithRedirectURL("https://myapp.com/onboarded"),
payoneer.WithLanguage("en"),
)
// result.RegistrationLink — the URL to redirect the payee to
// result.Token — unique token for this registration session
```
## Configuration
### Environments
`WithSandbox()` configures both the API base URL (`api.sandbox.payoneer.com`) and the OAuth2 base URL (`login.sandbox.payoneer.com`) in one call. For production, the defaults point to `api.payoneer.com` and `login.payoneer.com` respectively.
You can override them independently if needed:
```go
client := payoneer.NewClient(
payoneer.WithBaseURL("https://api.payoneer.com"),
payoneer.WithAuthBaseURL("https://login.payoneer.com"),
)
```
## Advanced Patterns
### Optional Fields
The SDK uses a generic `Optional[T]` type to distinguish between empty values and fields omitted by the API.
```go
if val, ok := payee.FirstName.Get(); ok {
fmt.Println("First Name:", val)
}
```
### Redacting Logs
Sensitive information is automatically redacted in logs.
```go
client := payoneer.NewClient(
payoneer.WithLogger(slog.Default()), // Integrated with transport redaction
)
```
## License
MIT