Help us shape the future of Go! Take the 2026 Go Developer Survey

lunixi

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 26 Imported by: 0

README

Lunixi

Lunixi Go SDK

Current source release: 0.1.1. The earlier 0.1.0 registry version below remains the verified published version; the new source patch is not yet claimed as published there.

The source patch adds a concrete merchant-site presentation example. Embedded checkout is the default: load only the official Lunixi bundle and mount the existing form; methods and multi-card choices stay in the Lunixi panel. Optional hosted mode uses the backend paymentPageUrl after exact HTTPS pay.lunixi.com/payment/ validation. Its token may differ from the embedded token. Missing URLs keep embedded available and hosted on hold/reconciliation with the original attempt/key. Never derive a URL from the browser token. Authorize the customer/order and native browser CSRF before rendering, send Cache-Control: private, no-store, preserve the merchant CSP nonce and keep tokens/HTML/redirect URLs out of logs. Generic response data preserves paymentPageUrl; no new typed product parity is claimed.

CI Go reference

Documentation · Türkçe · Changelog · Security

Server-side Go client for Lunixi payments. Works with net/http, Gin, Echo, Fiber and other Go frameworks without a framework dependency. The SDK uses the Go standard library only. Go 1.26 or newer is required.

Install

go get github.com/Lunixi-Payment/lunixi-go@v0.1.0

Create one client per merchant

import (
    "os"
    "time"
    lunixi "github.com/Lunixi-Payment/lunixi-go"
)

client, err := lunixi.New(lunixi.Config{
    BaseURL:    "https://api-gateway.lunixi.com",
    KeyID:      os.Getenv("LUNIXI_KEY_ID"),
    PrivateKey: os.Getenv("LUNIXI_PRIVATE_KEY_PEM"),
    Timeout:    30 * time.Second,
    MaxRetries: 2,
})
if err != nil { return err }

Register the public key in your Lunixi dashboard. Keep its Ed25519 private key on your server or secret manager. PKCS8 PEM, base64 PKCS8 DER, base64 32-byte seed and a validated base64 64-byte Ed25519 private key are accepted. The merchant key selects TEST/LIVE; there is no client-side environment switch. Never put a LIVE key in a sample application.

The client is safe to share between goroutines. Token acquisition is lazy, cached with an expiry margin and coalesced during concurrent refresh. All merchant requests are signed, including GET requests. Canonicalization matches the gateway's JSON.stringify numeric-key order, compact UTF-8 and number format; unsafe JSON integers and duplicate keys are rejected.

Setting Default Bounds / behavior
Timeout 30 seconds Up to 2 minutes per HTTP request; pass an overall context deadline
MaxRetries 0 0–5; GET or a supplied stable idempotency key only
MaxResponseBytes 8 MiB Up to 32 MiB; request JSON is limited to 8 MiB
HTTPClient Standard client Copied; redirects always disabled; never use insecure TLS in production
AllowInsecureLocalhost false HTTP allowed only for explicit localhost / literal loopback testing

BaseURL must be a trusted HTTPS origin, without credentials, path or query. Merchant API paths cannot change origin, traverse directories or call the token endpoint through Do.

Start hosted checkout

Load the basket and order from your server-side records. Persist the attempt key before calling, then reuse that key and body after a timeout.

ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
defer cancel()

response, err := client.Payments.CreateIntent(ctx, lunixi.IntentRequest{
    Amount:      10050, // 100.50 TRY, integer minor units
    Currency:    "TRY",
    OrderID:     "ORD-1001",
    CallbackURL: "https://merchant.example/payment/return",
    BasketItems: []lunixi.BasketItem{
        {ID: "line-1", Name: "Example product", ItemType: "PHYSICAL", Price: 10050},
    },
}, persistedAttemptKey)
if err != nil { return err }

var checkout struct { Token string `json:"token"` }
if err := response.DecodeData(&checkout); err != nil { return err }
if checkout.Token == "" { return errors.New("missing checkout token") }
// Send Token only to this order's authenticated customer, with
// Cache-Control: no-store. Initialize the existing Lunixi checkout form.

Amounts are int64 minor units, positive and no greater than 9007199254740991. Basket Price is the line total; line totals must equal Amount. Do not send the removed root fields price, paidPrice, autoCapture. Installment selection and fees belong to the Lunixi form. Buyer/address and documented insurance basket details can be supplied on IntentRequest; optional method restrictions can narrow the methods already enabled in the Lunixi panel.

The existing Lunixi form handles cards and enabled alternative methods; this SDK does not build another form or collect PAN/CVV. A checkout token, a browser return, HTTP 200 or an authorization is not proof of capture. Finalize only from an authenticated gateway result after checking your stored order ID, merchant, payment ID, expected amount/currency and final capture/reconciliation state. Apply corresponding refund, void and dispute transitions separately.

Payment lifecycle

payment, err := client.Payments.Get(ctx, paymentID)
partial := int64(2500)
refund, err := client.Payments.Refund(ctx, paymentID, &partial, "Customer return", persistedRefundKey)
// nil amount requests the full capture/refund; Void releases an authorization.
Helper Coverage
Payments CreateIntent, Get, List, Methods, Capture, Refund, Void
Payments split Split, GetSplit, RefundSplit
Fraud Evaluate, RecordEvent, Decisions, Decision
Client.Do Signed requests to other documented /api/v1/ merchant endpoints
WebhookVerifier, SQLInbox Raw v2 verification and durable transactional deduplication

Split accepts the documented gateway map and locally checks safe total/leg amounts, 1–5 legs and the leg sum. Method-specific fields remain governed by the API schema. A pending split may return a Response with HTTP 400; inspect StatusCode and signed gateway status. AUTHORIZED, AWAITING_*, COMPENSATING, partial refunds and reconciliation-required states do not imply a fulfilled order. Root SDK responses preserve the original envelope, Data, PageInfo and binary Bytes; DecodeData uses json.Number for interface values.

Wallet, bank-connect, payment links, insurance, marketplace, subscription, identity, reference and other services currently use Do with their documented schema. Version 0.1.0 does not claim typed helper parity for these services. For example:

response, err := client.Do(ctx, lunixi.Request{
    Method: "GET",
    Path: "/api/v1/payments",
    Query: url.Values{"limit": {"20"}},
})

Retries keep the exact body and idempotency key and use a new signature nonce. Mutation helpers require 16–128 non-space printable ASCII characters as the key. GET and keyed calls can retry transient network failures / 429 / 500 / 502 / 503 / 504 within the configured bound, with capped exponential delay; safe operations can refresh a rejected token once. Unkeyed mutations never automatically retry. Reconcile an unknown payment outcome before creating another attempt.

APIError provides StatusCode, Code and RequestID. Error strings omit upstream messages and request/response bodies. Responses can contain customer data or tokens; do not log Response, headers, raw webhook bytes or credentials.

Verify webhooks and consume them transactionally

verifier, err := lunixi.NewWebhookVerifier(lunixi.WebhookConfig{
    Secrets: []string{os.Getenv("LUNIXI_WEBHOOK_SECRET")},
})
if err != nil { return err }
event, err := verifier.VerifyRequest(ctx, request)
if err != nil { return err } // return a non-2xx response

inbox, err := lunixi.NewSQLInbox(db, "lunixi_webhook_inbox", merchantScope)
if err != nil { return err }
// Apply inbox.EnsureSchema(ctx) during migrations / startup, not per request.
applied, err := inbox.Process(ctx, event, func(tx *sql.Tx) error {
    // Validate the authenticated event against your stored order and payment.
    // Apply the order transition AND any outbox rows using this same tx.
    return applyVerifiedOrderTransition(ctx, tx, event)
})

The signature is HMAC-SHA256 over eventId + "." + exactTimestamp + "." + rawBody. Verification uses constant-time comparison, checks timestamp freshness (default 5 minutes, configurable up to 15 minutes), rejects duplicate headers/JSON keys and matches the signed body ID/type against the headers. The event body must contain type; an unsigned type header cannot authorize a financial action. Raw bytes must reach the verifier before any JSON middleware. Secrets can include up to three active/previous secrets during rotation. Use a fresh delivery/replay from the dashboard for an old event; do not disable timestamp checks.

SQLInbox supports PostgreSQL and SQLite through database/sql; supply your own driver. Each merchant/integration gets a separate scope. The callback and event marker commit together. A duplicate skips the callback; a different payload reusing the ID fails closed. Callback/database failure rolls back the marker, allowing safe provider retry. Retain markers for your event replay policy; do not prune within the provider's delivery/replay horizon. External effects require a transactional outbox.

The runnable SQLite receipt server includes actual rollback, crash/restart, duplicate, collision, concurrent replay and HTTP tests. It records verified notifications only; it does not fulfill orders. Add your order state adapter after matching all financial fields. The database contains no webhook body, card data or customer details. Place the loopback HTTP listener behind your trusted HTTPS reverse proxy.

Examples and checks

# Main SDK and TEST checkout example
go test -race ./...
go vet ./...
go build ./...
go run ./examples/checkout

# Standalone durable receipt server; the SQLite example requires CGO/C compiler.
cd examples/webhook
go test -race ./...
go vet ./...
go run .

The checkout example requires LUNIXI_BASE_URL, LUNIXI_KEY_ID (TEST only), LUNIXI_PRIVATE_KEY_PEM, and persisted LUNIXI_ORDER_ID / LUNIXI_ATTEMPT_KEY. The receipt server requires LUNIXI_WEBHOOK_SECRET. Supply secrets from your shell/secret manager without committing them. .env files are ignored and are not loaded automatically.

go run golang.org/x/vuln/cmd/govulncheck@v1.9.0 ./...

Run that audit in both modules. CI checks Go 1.26/1.27, formatting, vet, the race detector, builds and vulnerability reachability. Tests use real TLS test servers and independently produced Node.js Ed25519/JSON/HMAC fixtures. All fixture keys/secrets are synthetic and unusable for merchant access. Tests require no merchant credentials or network payment calls.

Security policy · Contributing · MIT license

Merchant-page integration example

The source example defines RenderCheckoutHTML(token, nonce) and HostedCheckoutURL(paymentPageUrl) in presentation.go. Copy/adapt these helpers inside your existing authorized, CSRF-protected merchant controller. The CLI defaults to LUNIXI_CHECKOUT_MODE=embedded; hosted validates the backend URL. It renders/validates internally and intentionally prints neither HTML, token nor URL. These example functions are not new SDK client methods.

Documentation

Overview

Package lunixi is a server-side client for Lunixi's signed merchant APIs.

The client signs requests with Ed25519, caches short-lived access tokens, preserves integer minor-unit money, and verifies raw-body v2 webhooks. Secret keys belong on the merchant server; browser checkout uses the short-lived token returned by Payments.CreateIntent.

Index

Constants

View Source
const MaxSafeInteger int64 = 9007199254740991

MaxSafeInteger is the largest integer JSON.stringify preserves exactly.

View Source
const Version = "0.1.1"

Version is the SDK semantic version.

Variables

View Source
var (
	// ErrConfiguration indicates invalid configuration or a rejected request.
	ErrConfiguration = errors.New("lunixi: invalid configuration or request")
	// ErrWebhook indicates an invalid, stale, or mismatched webhook.
	ErrWebhook = errors.New("lunixi: webhook verification failed")
)
View Source
var ErrInbox = errors.New("lunixi: webhook inbox persistence failed")

ErrInbox indicates a durable database failure. Return a retryable HTTP status, not a successful webhook acknowledgement, when it occurs.

Functions

func CanonicalJSON

func CanonicalJSON(value any) ([]byte, error)

CanonicalJSON produces compact JSON with JavaScript's numeric-index key ordering, UTF-8 strings, and number formatting. Unsafe integer numbers and duplicate object keys are rejected; use strings where an API specifies them.

func CanonicalRequest

func CanonicalRequest(method, path, date, nonce, digest string) string

CanonicalRequest returns the exact string signed by the gateway protocol.

func Digest

func Digest(body []byte) string

Digest returns the gateway's SHA-256 digest header value.

Types

type APIError

type APIError struct {
	StatusCode int
	Code       string
	RequestID  string
}

APIError exposes safe diagnostics without including a request body, access token, private key, customer information, or an upstream error message.

func (*APIError) Error

func (e *APIError) Error() string

type Address

type Address struct {
	ContactName string `json:"contactName,omitempty"`
	Address     string `json:"address,omitempty"`
	City        string `json:"city,omitempty"`
	Country     string `json:"country,omitempty"`
	ZipCode     string `json:"zipCode,omitempty"`
}

Address is a billing or shipping address accepted by the payment API.

type BasketItem

type BasketItem struct {
	ID                string         `json:"id"`
	Name              string         `json:"name"`
	ItemType          string         `json:"itemType"`
	Price             int64          `json:"price"`
	Category1         string         `json:"category1,omitempty"`
	Category2         string         `json:"category2,omitempty"`
	InsuranceData     map[string]any `json:"insuranceData,omitempty"`
	InsuranceCategory string         `json:"insuranceCategory,omitempty"`
	InsuranceTypes    []string       `json:"insuranceTypes,omitempty"`
}

BasketItem is a checkout basket line; Price is an integer minor-unit line total, not a per-unit float. Additional insurance data follows the gateway schema and is passed without guessing insurance-specific field rules.

type Buyer

type Buyer struct {
	ID                  string `json:"id,omitempty"`
	Name                string `json:"name,omitempty"`
	Surname             string `json:"surname,omitempty"`
	IdentityNumber      string `json:"identityNumber,omitempty"`
	Email               string `json:"email,omitempty"`
	GSMNumber           string `json:"gsmNumber,omitempty"`
	IP                  string `json:"ip,omitempty"`
	City                string `json:"city,omitempty"`
	Country             string `json:"country,omitempty"`
	ZipCode             string `json:"zipCode,omitempty"`
	RegistrationDate    string `json:"registrationDate,omitempty"`
	LastLoginDate       string `json:"lastLoginDate,omitempty"`
	RegistrationAddress string `json:"registrationAddress,omitempty"`
}

Buyer holds the documented buyer details used by hosted checkout. Values are sent to Lunixi only and must never be copied to application logs.

type Client

type Client struct {
	Payments *PaymentClient
	Fraud    *FraudClient
	// contains filtered or unexported fields
}

Client is safe for concurrent use. Create one client per merchant key.

func New

func New(config Config) (*Client, error)

New validates configuration without making a network request.

func (*Client) Do

func (c *Client) Do(ctx context.Context, in Request) (*Response, error)

Do calls a documented merchant endpoint through the same signed transport as the high-level clients. It does not invent service-specific validation; callers using this escape hatch must follow the endpoint's public schema.

func (*Client) InvalidateToken

func (c *Client) InvalidateToken()

InvalidateToken clears the in-memory token cache, for example after key permissions change. Key rotation itself requires constructing a new client.

type Config

type Config struct {
	BaseURL          string
	KeyID            string `json:"-"`
	PrivateKey       string `json:"-"`
	HTTPClient       *http.Client
	Timeout          time.Duration
	MaxRetries       int
	MaxResponseBytes int64
	// AllowInsecureLocalhost permits HTTP only for literal loopback addresses
	// and localhost. It is intended for local test servers, never production.
	AllowInsecureLocalhost bool
	// Now provides a deterministic clock for tests. Nil uses time.Now.
	Now func() time.Time
}

Config configures one merchant's client. Do not reuse a client across keys or merchants. HTTPClient is copied and redirects are always disabled.

func (Config) GoString

func (c Config) GoString() string

func (Config) MarshalJSON

func (c Config) MarshalJSON() ([]byte, error)

MarshalJSON intentionally excludes configuration secrets from structured logs.

func (Config) String

func (c Config) String() string

String and GoString keep routine configuration logging from exposing keys.

type FraudClient

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

FraudClient exposes transaction evaluation and event ingestion. Results remain gateway decisions; callers must enforce their own business policy.

func (*FraudClient) Decision

func (f *FraudClient) Decision(ctx context.Context, traceID string) (*Response, error)

Decision reads one fraud decision by trace ID.

func (*FraudClient) Decisions

func (f *FraudClient) Decisions(ctx context.Context, filters url.Values) (*Response, error)

Decisions lists fraud decisions without discarding sibling pageInfo.

func (*FraudClient) Evaluate

func (f *FraudClient) Evaluate(ctx context.Context, body map[string]any) (*Response, error)

Evaluate rejects unknown top-level fields, including tenantId, before authentication. Tenant identity always comes from the merchant credential.

func (*FraudClient) RecordEvent

func (f *FraudClient) RecordEvent(ctx context.Context, event map[string]any, key string) (*Response, error)

RecordEvent ingests one transaction event. A stable eventId and caller key are required by this helper for durable application-level idempotency.

type IntentRequest

type IntentRequest struct {
	Amount          int64          `json:"amount"`
	Currency        string         `json:"currency"`
	OrderID         string         `json:"orderId"`
	CallbackURL     string         `json:"callbackUrl"`
	Buyer           *Buyer         `json:"buyer,omitempty"`
	BillingAddress  *Address       `json:"billingAddress,omitempty"`
	ShippingAddress *Address       `json:"shippingAddress,omitempty"`
	BasketItems     []BasketItem   `json:"basketItems,omitempty"`
	Metadata        map[string]any `json:"metadata,omitempty"`
	Preauth         bool           `json:"preauth,omitempty"`
	Locale          string         `json:"locale,omitempty"`
	Description     string         `json:"description,omitempty"`
	CustomerID      string         `json:"customerId,omitempty"`
	CardUserKey     string         `json:"cardUserKey,omitempty"`
	PaymentMethod   string         `json:"paymentMethod,omitempty"`
	WalletProvider  string         `json:"walletProvider,omitempty"`
	PaymentChannel  string         `json:"paymentChannel,omitempty"`
	PaymentGroup    string         `json:"paymentGroup,omitempty"`
	Force3D         *bool          `json:"force3D,omitempty"`
	Settings        map[string]any `json:"settings,omitempty"`
}

IntentRequest creates a checkout form token. Amount is the basket total before a provider-calculated installment fee. Installments are selected in the shared form, not prescribed in the intent request.

type PaymentClient

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

PaymentClient implements checkout forms, payment lifecycle and split payment merchant endpoints. It never determines an order's paid state.

func (*PaymentClient) Capture

func (p *PaymentClient) Capture(ctx context.Context, id string, amount *int64, key string) (*Response, error)

Capture captures the full authorization when amount is nil, or a specified positive integer amount. It must reference the original payment account.

func (*PaymentClient) CreateIntent

func (p *PaymentClient) CreateIntent(ctx context.Context, r IntentRequest, key string) (*Response, error)

CreateIntent creates a hosted checkout session. Persist key per payment attempt before calling; reuse it after a timeout instead of charging again.

func (*PaymentClient) Get

func (p *PaymentClient) Get(ctx context.Context, id string) (*Response, error)

Get reads the authoritative gateway payment state.

func (*PaymentClient) GetSplit

func (p *PaymentClient) GetSplit(ctx context.Context, id string) (*Response, error)

GetSplit returns all legs and aggregate amounts; COMPLETED alone should not replace amount/currency/balancing/reconciliation checks in the order adapter.

func (*PaymentClient) List

func (p *PaymentClient) List(ctx context.Context, filters url.Values) (*Response, error)

List returns the original gateway envelope including pagination metadata.

func (*PaymentClient) Methods

func (p *PaymentClient) Methods(ctx context.Context) (*Response, error)

Methods reads the merchant's enabled method/provider capabilities.

func (*PaymentClient) Refund

func (p *PaymentClient) Refund(ctx context.Context, id string, amount *int64, reason, key string) (*Response, error)

Refund refunds the full refundable payment when amount is nil, or a partial amount. Unknown outcomes must be reconciled with the same key.

func (*PaymentClient) RefundSplit

func (p *PaymentClient) RefundSplit(ctx context.Context, id string, amount int64, reason, key string) (*Response, error)

RefundSplit asks the gateway to distribute a refund across refundable legs. Partial or failed allocations return an APIError and require review.

func (*PaymentClient) Split

func (p *PaymentClient) Split(ctx context.Context, body map[string]any, key string) (*Response, error)

Split validates the documented split amount/leg contract and starts or continues it. Supply the same body and key for every continuation. Pending split states can be returned on HTTP 400 and remain explicitly unpaid.

func (*PaymentClient) Void

func (p *PaymentClient) Void(ctx context.Context, id, key string) (*Response, error)

Void releases an authorization; it does not refund a captured payment.

type ReplayStore

type ReplayStore interface {
	Process(context.Context, *WebhookEvent, func(*sql.Tx) error) (bool, error)
}

ReplayStore applies a verified event and its event-ID marker in the SAME transaction. The callback must use the supplied transaction for business state. Network requests and other nontransactional effects belong in a durable application outbox, not inside this callback.

type Request

type Request struct {
	Method         string
	Path           string
	Query          url.Values
	Body           any
	IdempotencyKey string
}

Request is a signed merchant API request. Path must be an unescaped path under /api/v1/; use Query for query parameters. A stable IdempotencyKey is required by financial mutation helpers and controls safe automatic retries.

type Response

type Response struct {
	StatusCode  int
	RequestID   string
	Envelope    json.RawMessage
	Data        json.RawMessage
	PageInfo    json.RawMessage
	ContentType string
	Bytes       []byte
}

Response preserves the gateway envelope, including pageInfo and pending financial states. Inspect verified amount, currency and status before order fulfillment. A successful HTTP response alone is not proof of payment.

func (*Response) DecodeData

func (r *Response) DecodeData(target any) error

DecodeData decodes data without converting integer amounts to float64. A map/interface target receives json.Number values.

type SQLInbox

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

SQLInbox is a durable ReplayStore for PostgreSQL and SQLite. Database drivers are supplied by the application; the SDK has no runtime dependency. Its table stores IDs, timestamp and a payload hash, never webhook raw data.

func NewSQLInbox

func NewSQLInbox(db *sql.DB, table, scope string) (*SQLInbox, error)

NewSQLInbox validates a separate deduplication scope for each merchant or integration. table must be a trusted migration-time SQL identifier.

func (*SQLInbox) EnsureSchema

func (s *SQLInbox) EnsureSchema(ctx context.Context) error

EnsureSchema explicitly creates the inbox table. Production applications can apply the equivalent DDL in their normal migration process instead.

func (*SQLInbox) Process

func (s *SQLInbox) Process(ctx context.Context, event *WebhookEvent, apply func(*sql.Tx) error) (bool, error)

Process returns true only when the callback and event marker are committed. A duplicate returns false without running callback. An event-ID collision with different signed content fails closed. Callback failure rolls back its marker so the provider can safely retry after an application crash/error.

type WebhookConfig

type WebhookConfig struct {
	Secrets   []string
	Tolerance time.Duration
	Now       func() time.Time
}

WebhookConfig verifies current and previous rotation secrets. Tolerance defaults to five minutes and cannot be disabled in production verification.

type WebhookEvent

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

WebhookEvent is an authenticated immutable event. Accessors return copies; unverified events cannot be constructed through exported fields.

func (*WebhookEvent) Data

func (e *WebhookEvent) Data() json.RawMessage

Data returns an independent copy of the signed data object.

func (*WebhookEvent) DecodeData

func (e *WebhookEvent) DecodeData(target any) error

DecodeData decodes the signed data using json.Number for interface values.

func (*WebhookEvent) ID

func (e *WebhookEvent) ID() string

ID is the event ID bound to the raw-body signature.

func (*WebhookEvent) Raw

func (e *WebhookEvent) Raw() []byte

Raw returns an independent copy of the signed body. It can contain customer data: do not log it or persist it outside your data-retention policy.

func (*WebhookEvent) Timestamp

func (e *WebhookEvent) Timestamp() time.Time

Timestamp is the verified signature timestamp.

func (*WebhookEvent) Type

func (e *WebhookEvent) Type() string

Type is read from the signed JSON body, never an unsigned header fallback.

type WebhookVerifier

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

WebhookVerifier authenticates raw request bytes. Verification does not consume an event ID: use a durable transactional ReplayStore before applying financial state, so a crash cannot lose a previously claimed event.

func NewWebhookVerifier

func NewWebhookVerifier(config WebhookConfig) (*WebhookVerifier, error)

NewWebhookVerifier validates webhook configuration without handling data.

func (*WebhookVerifier) Verify

func (v *WebhookVerifier) Verify(raw []byte, headers http.Header) (*WebhookEvent, error)

Verify checks the exact raw bytes, event ID, ISO timestamp, body/header ID agreement, type and rotated v2 signatures. Unknown schemes do not authorize a request. Read the body with an application-level size limit before calling.

func (*WebhookVerifier) VerifyRequest

func (v *WebhookVerifier) VerifyRequest(ctx context.Context, request *http.Request) (*WebhookEvent, error)

VerifyRequest reads an HTTP request with a fixed limit before verification. The caller remains responsible for applying ReplayStore transactionally.

Directories

Path Synopsis
examples
checkout command
This example creates a TEST checkout intent from trusted merchant values.
This example creates a TEST checkout intent from trusted merchant values.

Jump to

Keyboard shortcuts

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