worldpay

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 16 Imported by: 0

README

worldpay-go

A production-grade, dependency-free Go client for Worldpay's payment platforms, structured with Domain-Driven Design.

import worldpay "github.com/iamkanishka/worldpay-go"

Architecture

worldpay-go/
├── worldpay.go, config.go, errors.go, doc.go   composition root (facade Client, Config)
├── shared/                                      shared kernel: value objects, Error, telemetry, call options
├── internal/
│   ├── transport/                               Doer port + HTTP adapter (retry, circuit breaker, telemetry)
│   └── auth/                                    Basic Auth + idempotency/correlation key generation
├── domain/                                      one package per bounded context
│   ├── payments/       authorize → settle/cancel/refund lifecycle
│   ├── payouts/         card payouts, account payouts
│   ├── transfers/       money transfers, account transfers, FX
│   ├── accounts/        balances, statements
│   ├── queries/         historical payment queries
│   ├── risk/            FraudSight, 3DS, exemptions, card BIN lookup
│   ├── tokenization/     network tokens, customer events, security tokens, forward API, token import
│   ├── apm/              alternative payment methods
│   ├── partner/          partner notifications, terminal lease
│   ├── marketplace/      parties, split payments
│   └── webhooks/         webhook parsing/dispatch
├── gateway/                                     anti-corruption layer to non-Access protocols
│   ├── wpg/       WPG Direct (XML)
│   ├── cnp/       cnpAPI / Vantiv (XML)
│   ├── raft/      RAFT 610 (ISO 8583 over TCP/TLS)
│   ├── express/   Element Express (JSON)
│   └── reporting/ eMAF flat files + cnpAPI batch XML
└── examples/basic/

Dependency rule: every domain/* package depends only on shared and internal/transport — never on another domain package. internal/transport defines the Doer port (an interface); domain services depend on that abstraction, not on net/http directly, so internal/transport.Client is the only concrete adapter that talks to the wire. gateway/* packages are a separate anti-corruption layer for Worldpay's non-Access protocols and depend on shared (for Error) and the composition root (for Config). This keeps the import graph acyclic and each bounded context testable in isolation — see domain/payments/payments_test.go for an example that exercises a Service against an httptest.Server with no dependency on the facade Client at all.

Quick start

import (
	worldpay "github.com/iamkanishka/worldpay-go"
	"github.com/iamkanishka/worldpay-go/domain/payments"
	"github.com/iamkanishka/worldpay-go/shared"
)

cfg := worldpay.NewConfig(
	worldpay.WithCredentials("username", "password"),
	worldpay.WithEnvironment(worldpay.Live),
)
client := worldpay.NewClient(cfg)

resp, err := client.Payments.Authorize(ctx, payments.AuthorizeRequest{
	Merchant: shared.Merchant{Entity: "default"},
	Instruction: payments.AuthorizeInstruction{
		Narrative: shared.Narrative{Line1: "My Store"},
		Value:     shared.Amount{Amount: 1999, Currency: "GBP"},
		PaymentInstrument: shared.PaymentInstrument{
			Type:           "card/plain",
			CardNumber:     "4444333322221111",
			CardExpiryDate: &shared.CardExpiryDate{Month: 5, Year: 2035},
			CVC:            "123",
		},
	},
})
if err != nil {
	var werr *worldpay.Error
	if errors.As(err, &werr) {
		// werr.Status, werr.Code, werr.Message, werr.ValidationErrors
	}
	return err
}

if href, ok := resp.HrefOf("payments:settle"); ok {
	err = client.Payments.Settle(ctx, href)
}

The facade Client groups bounded contexts by field: client.Payments, client.Payouts.Card / .Account, client.Transfers.Money / .Account / .FX, client.Accounts.Balances / .Statements, client.Queries, client.Risk.FraudSight / .ThreeDS / .Exemptions / .CardBIN, client.Tokenization.*, client.APM, client.Partner.*, client.Marketplace.*, client.Webhooks. Request/response types live in each domain/* package (e.g. payments.AuthorizeRequest), and shared value objects (Amount, Merchant, PaymentInstrument, ...) live in shared.

See examples/basic for a complete runnable program.

Design

  • Every call takes a context.Context and is safe for concurrent use. A Client (or Config, for the XML/TCP gateway packages) holds no per-request mutable state and can be shared across goroutines.
  • Structured errors. Every failure is a *worldpay.Error (a type alias for shared.Error) with a Type (api_error, network_error, decode_error, validation_error, circuit_open, timeout_error), and — for API errors — Status, Code, and field-level ValidationErrors. Unwrap() is implemented so errors.As/errors.Is work uniformly across every domain and gateway package.
  • Retry with backoff + jitter. Network errors, timeouts, 429, and 5xx responses are retried with full-jitter exponential backoff, honoring a server Retry-After header when present. Configurable via WithRetryCount.
  • Circuit breaker. Optional, per-API circuit breaking (WithCircuitBreaker) so a failing endpoint fails fast instead of being hammered, without affecting unrelated APIs.
  • Telemetry hooks. WithTelemetry installs a shared.TelemetryHook invoked around every request (Start/End).
  • Idempotency. Mutating calls generate an Idempotency-Key header automatically (via crypto/rand, not math/rand); override per-call with shared.WithIdempotencyKey.
  • Functional options throughout (Option for Config, shared.CallOption for individual requests).

Gateway packages

Each gateway package takes the shared *worldpay.Config so credentials, environment, and TLS settings stay in one place:

cfg := worldpay.NewConfig(worldpay.WithWPGCredentials("MERCHANTCODE", "user", "pass"))

wpgClient := wpg.New(cfg, "MERCHANTCODE", "user", "pass")
result, err := wpgClient.Authorize(ctx, "order-1", "My Order", 1999, "GBP", wpg.CardDetails{
	CardNumber: "4444333322221111", ExpiryMonth: 5, ExpiryYear: 2035, CVC: "123",
})

WPG and cnpAPI responses are XML, decoded via a generic, schema-less XML→map flattener (internal/xmlutil) so you get typed request builders without hand-writing a struct per response shape; use Result.Find / Result.LastEvent / Result.AsInt to read fields out of the response tree.

RAFT's actual ISO 8583 bitmap encoding is proprietary to RAFT and supplied by Worldpay's Implementation Manager during onboarding — this package provides fully-typed message builders for every RAFT transaction type (auth, sale, capture, reversal, refund, balance inquiry, EBT, gift card, fleet, check/ACH, WIC, batch/reconciliation, network management) plus a Serialize/Deserialize integration point you swap for your certified codec; everything else (connection handling, response helpers) works as-is.

Quality

  • Zero external dependencies — standard library only.
  • go vet and golangci-lint run (govet, staticcheck, errcheck, gosec, gocritic, revive, exhaustive, gocyclo, and more) both clean.
  • Race-detector-clean test suite (go test -race ./...), with each bounded context's tests living alongside its own package — e.g. domain/payments is tested purely against the transport.Doer abstraction via httptest, with no dependency on the facade Client.
  • No import cycles; every domain/* package depends only on shared and internal/transport (verified with go list -deps).

License

Add your license of choice here.

Documentation

Index

Constants

View Source
const (
	ErrorTypeAPI         = shared.ErrorTypeAPI
	ErrorTypeNetwork     = shared.ErrorTypeNetwork
	ErrorTypeDecode      = shared.ErrorTypeDecode
	ErrorTypeValidation  = shared.ErrorTypeValidation
	ErrorTypeCircuitOpen = shared.ErrorTypeCircuitOpen
	ErrorTypeTimeout     = shared.ErrorTypeTimeout
)

Re-exported ErrorType values for convenience at the facade level.

Variables

View Source
var ErrCircuitOpen = shared.ErrCircuitOpen

ErrCircuitOpen is wrapped inside an *Error with Type ErrorTypeCircuitOpen when a circuit breaker rejects a call outright.

Functions

This section is empty.

Types

type AccountsClient

type AccountsClient struct {
	Balances   *accounts.BalancesService
	Statements *accounts.StatementsService
}

AccountsClient groups the Accounts bounded context's services.

type CircuitBreakerConfig

type CircuitBreakerConfig = transport.CircuitBreakerConfig

CircuitBreakerConfig configures the failure threshold and cool-down for the Access API circuit breaker. See WithCircuitBreaker.

type Client

type Client struct {
	Payments     *payments.Service
	Payouts      PayoutsClient
	Transfers    TransfersClient
	Accounts     AccountsClient
	Queries      *queries.PaymentsService
	Risk         RiskClient
	Tokenization TokenizationClient
	APM          *apm.Service
	Partner      PartnerClient
	Marketplace  MarketplaceClient
	Webhooks     WebhooksClient
	// contains filtered or unexported fields
}

Client is the Access Worldpay facade: the composition root that wires the shared transport.Doer into every bounded-context domain service. Construct one with NewClient. A Client is safe for concurrent use and holds no per-request mutable state.

Each field groups a bounded context, matching the module layout under domain/: Payments handles the full authorize→settle/cancel/refund lifecycle, Payouts covers card and account payouts, Transfers covers money/account transfers and FX, Accounts covers balances and statements, Risk covers FraudSight/3DS/exemptions/BIN lookup, Tokenization covers network tokens and related services, and so on.

func NewClient

func NewClient(cfg *Config) *Client

NewClient builds an Access Worldpay Client from cfg.

func (*Client) Config

func (c *Client) Config() *Config

Config returns the Config this Client was built from.

type Config

type Config struct {
	// contains filtered or unexported fields
}

Config carries credentials, environment selection, and cross-cutting HTTP behavior for Access Worldpay, and the shared settings (TLS, WPG credentials) consumed by the gateway packages (wpg, cnp, raft, express, reporting). Config is immutable after construction and safe for concurrent use — build one with NewConfig and share it across the facade Client and any gateway clients.

func NewConfig

func NewConfig(opts ...Option) *Config

NewConfig builds a Config from the given options.

func (*Config) AccessBaseURL

func (c *Config) AccessBaseURL() string

AccessBaseURL returns the Access Worldpay base URL in use.

func (*Config) Environment

func (c *Config) Environment() Environment

Environment returns the configured Environment.

func (*Config) WPGBaseURL

func (c *Config) WPGBaseURL() string

WPGBaseURL returns the WPG endpoint URL in use.

type Environment

type Environment int

Environment selects which Worldpay environment a Config talks to.

const (
	// Try is Worldpay's sandbox / test environment.
	Try Environment = iota
	// Live is Worldpay's production environment.
	Live
)

func (Environment) String

func (e Environment) String() string

type Error

type Error = shared.Error

Error is an alias for shared.Error, the error type returned by every Worldpay SDK call regardless of which bounded context issued it. Using errors.As(err, &werr) with *worldpay.Error works transparently across domain and gateway package boundaries since this is a true type alias.

type ErrorType

type ErrorType = shared.ErrorType

ErrorType classifies an Error for programmatic handling. See shared.ErrorType for the full set of values (ErrorTypeAPI/Network/Decode/Validation/CircuitOpen/Timeout).

type MarketplaceClient

type MarketplaceClient struct {
	Parties       *marketplace.PartiesService
	SplitPayments *marketplace.SplitPaymentsService
}

MarketplaceClient groups the Marketplace bounded context's services.

type Option

type Option func(*Config)

Option configures a Config. Options are applied in order, so later options override earlier ones.

func WithAPIVersion

func WithAPIVersion(version string) Option

WithAPIVersion overrides the WP-Api-Version header sent on Access requests.

func WithAccessBaseURL

func WithAccessBaseURL(url string) Option

WithAccessBaseURL overrides the Access Worldpay base URL (useful for testing against a local mock server).

func WithCircuitBreaker

func WithCircuitBreaker(cfg CircuitBreakerConfig) Option

WithCircuitBreaker enables a per-API circuit breaker: after repeated failures it fails fast for a cool-down period instead of hammering a downed endpoint. Disabled by default.

func WithCredentials

func WithCredentials(username, password string) Option

WithCredentials sets the Access Worldpay Basic Auth credentials.

func WithEnvironment

func WithEnvironment(env Environment) Option

WithEnvironment selects Try (sandbox) or Live.

func WithHTTPClient

func WithHTTPClient(hc *http.Client) Option

WithHTTPClient overrides the underlying *http.Client. The client's Timeout, if zero, is set to the Config's timeout.

func WithRetryCount

func WithRetryCount(n int) Option

WithRetryCount sets how many times a failed request is retried for retryable errors (network errors, 429, and 5xx). Default is 2.

func WithTLSConfig

func WithTLSConfig(tc *tls.Config) Option

WithTLSConfig overrides the TLS configuration used for RAFT's raw TCP/TLS socket and the HTTP transport's TLS settings.

func WithTelemetry

func WithTelemetry(hook shared.TelemetryHook) Option

WithTelemetry installs a hook invoked around every outbound request. See shared.TelemetryHook.

func WithTimeout

func WithTimeout(d time.Duration) Option

WithTimeout sets the per-request timeout (default 30s).

func WithWPGBaseURL

func WithWPGBaseURL(url string) Option

WithWPGBaseURL overrides the WPG endpoint URL.

func WithWPGCredentials

func WithWPGCredentials(merchantCode, username, password string) Option

WithWPGCredentials sets the WPG merchant code and XML admin credentials.

type PartnerClient

type PartnerClient struct {
	Notifications *partner.NotificationsService
	TerminalLease *partner.TerminalLeaseService
}

PartnerClient groups the Partner bounded context's services.

type PayoutsClient

type PayoutsClient struct {
	Card    *payouts.CardService
	Account *payouts.AccountService
}

PayoutsClient groups the Payouts bounded context's services.

type RiskClient

type RiskClient struct {
	FraudSight *risk.FraudSightService
	ThreeDS    *risk.ThreeDSService
	Exemptions *risk.ExemptionsService
	CardBIN    *risk.CardBINService
}

RiskClient groups the Risk bounded context's services.

type TokenizationClient

type TokenizationClient struct {
	Tokens         *tokenization.TokensService
	CustomerEvents *tokenization.CustomerEventsService
	SecurityTokens *tokenization.SecurityTokenService
	ForwardAPI     *tokenization.ForwardAPIService
	TokenImport    *tokenization.TokenImportService
}

TokenizationClient groups the Tokenization bounded context's services.

type TransfersClient

type TransfersClient struct {
	Money   *transfers.MoneyService
	Account *transfers.AccountService
	FX      *transfers.FXService
}

TransfersClient groups the Transfers bounded context's services.

type WebhooksClient

type WebhooksClient struct{}

WebhooksClient exposes webhook parsing/dispatch. It performs no I/O.

func (WebhooksClient) Handle

func (WebhooksClient) Handle(body []byte, handler webhooks.Handler) error

Handle parses body and dispatches it to handler.

func (WebhooksClient) Parse

func (WebhooksClient) Parse(body []byte) (*webhooks.Event, error)

Parse decodes a raw webhook request body into a webhooks.Event.

Directories

Path Synopsis
domain
accounts
Package accounts is the Accounts bounded context: balance and statement visibility for embedded-finance accounts.
Package accounts is the Accounts bounded context: balance and statement visibility for embedded-finance accounts.
apm
Package apm is the Alternative Payment Methods bounded context (PayPal, Klarna, iDEAL, Sofort, Alipay, WeChat Pay, and others).
Package apm is the Alternative Payment Methods bounded context (PayPal, Klarna, iDEAL, Sofort, Alipay, WeChat Pay, and others).
marketplace
Package marketplace is the Marketplace bounded context: onboarding sub-merchant "parties" and distributing a single payment's funds across them (split payments).
Package marketplace is the Marketplace bounded context: onboarding sub-merchant "parties" and distributing a single payment's funds across them (split payments).
partner
Package partner is the Partner bounded context: parsing partner transaction notifications and terminal lease notifications pushed by Worldpay to ISO/reseller partner endpoints.
Package partner is the Partner bounded context: parsing partner transaction notifications and terminal lease notifications pushed by Worldpay to ISO/reseller partner endpoints.
payments
Package payments is the Payments bounded context: card payment authorization and the settle/cancel/refund actions that follow it.
Package payments is the Payments bounded context: card payment authorization and the settle/cancel/refund actions that follow it.
payouts
Package payouts is the Payouts bounded context: pushing funds to a card (Original Credit Transaction) or bank account.
Package payouts is the Payouts bounded context: pushing funds to a card (Original Credit Transaction) or bank account.
queries
Package queries is the Queries bounded context: historical payment status lookups.
Package queries is the Queries bounded context: historical payment status lookups.
risk
Package risk is the Risk bounded context: fraud scoring, Strong Customer Authentication (3DS), SCA exemptions, and card BIN lookup.
Package risk is the Risk bounded context: fraud scoring, Strong Customer Authentication (3DS), SCA exemptions, and card BIN lookup.
tokenization
Package tokenization is the Tokenization bounded context: network payment tokens, customer/account update events, short-lived security tokens, PCI-scope-reducing request forwarding, and bulk token import.
Package tokenization is the Tokenization bounded context: network payment tokens, customer/account update events, short-lived security tokens, PCI-scope-reducing request forwarding, and bulk token import.
transfers
Package transfers is the Transfers bounded context: moving funds between Worldpay-held accounts (money transfers), a merchant's own accounts (account transfers), and currency conversion (FX).
Package transfers is the Transfers bounded context: moving funds between Worldpay-held accounts (money transfers), a merchant's own accounts (account transfers), and currency conversion (FX).
webhooks
Package webhooks is the Webhooks bounded context: parsing and dispatching Access Worldpay webhook notifications.
Package webhooks is the Webhooks bounded context: parsing and dispatching Access Worldpay webhook notifications.
examples
basic command
Command basic demonstrates authorizing and settling a card payment against Worldpay's Try (sandbox) environment.
Command basic demonstrates authorizing and settling a card payment against Worldpay's Try (sandbox) environment.
gateway
cnp
Package cnp implements Worldpay's cnpAPI (Vantiv) XML integration: sale, authorization, capture, credit, and void, plus response parsing.
Package cnp implements Worldpay's cnpAPI (Vantiv) XML integration: sale, authorization, capture, credit, and void, plus response parsing.
express
Package express implements Worldpay's Element Express JSON API: credit-card and check authorization, capture, reversal, and recurring transactions.
Package express implements Worldpay's Element Express JSON API: credit-card and check authorization, capture, reversal, and recurring transactions.
raft
Package raft implements Worldpay's RAFT 610 interface: ISO 8583 card-present processing (credit, debit, EBT, gift card, fleet, check/ACH, WIC) over TCP/TLS.
Package raft implements Worldpay's RAFT 610 interface: ISO 8583 card-present processing (credit, debit, EBT, gift card, fleet, check/ACH, WIC) over TCP/TLS.
reporting
Package reporting parses Worldpay's offline report formats: eMAF (electronic Merchant Activity File) fixed-format records, and cnpAPI account-updater / funding-report XML batches.
Package reporting parses Worldpay's offline report formats: eMAF (electronic Merchant Activity File) fixed-format records, and cnpAPI account-updater / funding-report XML batches.
wpg
Package wpg implements Worldpay's WPG (Worldpay Payment Gateway) XML Direct integration: order authorization, capture, cancel, refund, and inquiry over HTTPS with a hand-rolled XML envelope.
Package wpg implements Worldpay's WPG (Worldpay Payment Gateway) XML Direct integration: order authorization, capture, cancel, refund, and inquiry over HTTPS with a hand-rolled XML envelope.
internal
auth
Package auth builds Access Worldpay's Basic Auth header and generates the random keys used for Idempotency-Key / WP-CorrelationId headers.
Package auth builds Access Worldpay's Basic Auth header and generates the random keys used for Idempotency-Key / WP-CorrelationId headers.
transport
Package transport is the infrastructure adapter that every domain package depends on through the Doer port, instead of talking to net/http directly.
Package transport is the infrastructure adapter that every domain package depends on through the Doer port, instead of talking to net/http directly.
xmlutil
Package xmlutil provides a generic, schema-less XML→map decoder used by the wpg and cnp packages to flatten Worldpay's XML responses into string-keyed maps without hand-writing a struct per response shape.
Package xmlutil provides a generic, schema-less XML→map decoder used by the wpg and cnp packages to flatten Worldpay's XML responses into string-keyed maps without hand-writing a struct per response shape.
Package shared is the shared kernel: value objects, error types, and cross-cutting contracts (telemetry, call options) used by every bounded context in this module.
Package shared is the shared kernel: value objects, error types, and cross-cutting contracts (telemetry, call options) used by every bounded context in this module.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL