Documentation
¶
Index ¶
- Variables
- func PreparePaymentEvent(event *PaymentEvent)
- func PrepareRefundEvent(event *RefundEvent)
- func SendOnce(ctx context.Context, cfg config.CallbacksConfig, event PaymentEvent) error
- type DLQStore
- type FailedWebhook
- type FileDLQStore
- func (f *FileDLQStore) Close() error
- func (f *FileDLQStore) DeleteFailedWebhook(ctx context.Context, id string) error
- func (f *FileDLQStore) ListFailedWebhooks(ctx context.Context, limit int) ([]FailedWebhook, error)
- func (f *FileDLQStore) SaveFailedWebhook(ctx context.Context, webhook FailedWebhook) error
- type MemoryDLQStore
- type NoopDLQStore
- type NoopNotifier
- type Notifier
- type PaymentEvent
- type PersistentCallbackClient
- type PersistentCallbackOptions
- type RefundEvent
- type RetryConfig
- type RetryOption
- type RetryableClient
- type WebhookQueueWorker
- type WebhookQueueWorkerOptions
Constants ¶
This section is empty.
Variables ¶
var ErrCallbackDisabled = errors.New("callbacks: disabled")
ErrCallbackDisabled is returned when callbacks are not configured.
Functions ¶
func PreparePaymentEvent ¶
func PreparePaymentEvent(event *PaymentEvent)
PreparePaymentEvent ensures PaymentEvent has required idempotency fields set. If EventID is already set, it's preserved (for retries). If not, a new one is generated.
func PrepareRefundEvent ¶
func PrepareRefundEvent(event *RefundEvent)
PrepareRefundEvent ensures RefundEvent has required idempotency fields set. If EventID is already set, it's preserved (for retries). If not, a new one is generated.
func SendOnce ¶
func SendOnce(ctx context.Context, cfg config.CallbacksConfig, event PaymentEvent) error
SendOnce sends a payment event webhook without retry logic (for testing/CLI tools).
Types ¶
type DLQStore ¶
type DLQStore interface {
SaveFailedWebhook(ctx context.Context, webhook FailedWebhook) error
ListFailedWebhooks(ctx context.Context, limit int) ([]FailedWebhook, error)
DeleteFailedWebhook(ctx context.Context, id string) error
}
DLQStore persists failed webhook attempts for manual retry or analysis.
type FailedWebhook ¶
type FailedWebhook struct {
ID string `json:"id"`
URL string `json:"url"`
Payload json.RawMessage `json:"payload"`
Headers map[string]string `json:"headers"`
EventType string `json:"eventType"` // "payment" or "refund"
Attempts int `json:"attempts"`
LastError string `json:"lastError"`
LastAttempt time.Time `json:"lastAttempt"`
CreatedAt time.Time `json:"createdAt"`
}
FailedWebhook represents a webhook that exhausted all retry attempts.
type FileDLQStore ¶
type FileDLQStore struct {
// contains filtered or unexported fields
}
FileDLQStore stores failed webhooks in a JSON file.
func NewFileDLQStore ¶
func NewFileDLQStore(filePath string) (*FileDLQStore, error)
NewFileDLQStore creates a file-based DLQ store.
func (*FileDLQStore) Close ¶
func (f *FileDLQStore) Close() error
Close ensures all data is persisted (no-op for file store).
func (*FileDLQStore) DeleteFailedWebhook ¶
func (f *FileDLQStore) DeleteFailedWebhook(ctx context.Context, id string) error
func (*FileDLQStore) ListFailedWebhooks ¶
func (f *FileDLQStore) ListFailedWebhooks(ctx context.Context, limit int) ([]FailedWebhook, error)
func (*FileDLQStore) SaveFailedWebhook ¶
func (f *FileDLQStore) SaveFailedWebhook(ctx context.Context, webhook FailedWebhook) error
type MemoryDLQStore ¶
type MemoryDLQStore struct {
// contains filtered or unexported fields
}
MemoryDLQStore stores failed webhooks in memory (for testing/development).
func NewMemoryDLQStore ¶
func NewMemoryDLQStore() *MemoryDLQStore
NewMemoryDLQStore creates an in-memory DLQ store.
func (*MemoryDLQStore) DeleteFailedWebhook ¶
func (m *MemoryDLQStore) DeleteFailedWebhook(ctx context.Context, id string) error
func (*MemoryDLQStore) ListFailedWebhooks ¶
func (m *MemoryDLQStore) ListFailedWebhooks(ctx context.Context, limit int) ([]FailedWebhook, error)
func (*MemoryDLQStore) SaveFailedWebhook ¶
func (m *MemoryDLQStore) SaveFailedWebhook(ctx context.Context, webhook FailedWebhook) error
type NoopDLQStore ¶
type NoopDLQStore struct{}
NoopDLQStore is a DLQ store that discards all failed webhooks.
func (NoopDLQStore) DeleteFailedWebhook ¶
func (NoopDLQStore) DeleteFailedWebhook(context.Context, string) error
func (NoopDLQStore) ListFailedWebhooks ¶
func (NoopDLQStore) ListFailedWebhooks(context.Context, int) ([]FailedWebhook, error)
func (NoopDLQStore) SaveFailedWebhook ¶
func (NoopDLQStore) SaveFailedWebhook(context.Context, FailedWebhook) error
type NoopNotifier ¶
type NoopNotifier struct{}
NoopNotifier ignores all events.
func (NoopNotifier) PaymentSucceeded ¶
func (NoopNotifier) PaymentSucceeded(context.Context, PaymentEvent)
func (NoopNotifier) RefundSucceeded ¶
func (NoopNotifier) RefundSucceeded(context.Context, RefundEvent)
type Notifier ¶
type Notifier interface {
PaymentSucceeded(ctx context.Context, event PaymentEvent)
RefundSucceeded(ctx context.Context, event RefundEvent)
}
Notifier delivers payment events to user-defined callbacks.
func NewRetryableClient ¶
func NewRetryableClient(cfg config.CallbacksConfig, opts ...RetryOption) Notifier
NewRetryableClient constructs a callback client with retry support.
type PaymentEvent ¶
type PaymentEvent struct {
// Idempotency and event metadata (ALWAYS present)
EventID string `json:"eventId"` // Unique event identifier for idempotency (e.g., "evt_abc123")
EventType string `json:"eventType"` // Always "payment.succeeded" for this event
EventTimestamp time.Time `json:"eventTimestamp"` // ISO8601 timestamp when event was created (UTC)
// Payment details
ResourceID string `json:"resource"`
Method string `json:"method"` // "stripe" or "x402"
StripeSessionID string `json:"stripeSessionId,omitempty"`
StripeCustomer string `json:"stripeCustomer,omitempty"`
FiatAmountCents int64 `json:"fiatAmountCents,omitempty"`
FiatCurrency string `json:"fiatCurrency,omitempty"`
CryptoAtomicAmount int64 `json:"cryptoAtomicAmount,omitempty"`
CryptoToken string `json:"cryptoToken,omitempty"`
Wallet string `json:"wallet,omitempty"`
ProofSignature string `json:"proofSignature,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
PaidAt time.Time `json:"paidAt"`
}
PaymentEvent encapsulates the essential information about a completed payment. IMPORTANT: EventID is the idempotency key - webhook consumers MUST use this to prevent duplicate processing.
type PersistentCallbackClient ¶
type PersistentCallbackClient struct {
// contains filtered or unexported fields
}
PersistentCallbackClient delivers webhooks via a persistent queue. Unlike RetryableClient which uses goroutines (lost on restart), this client persists webhooks to the database for guaranteed delivery across server restarts.
func NewPersistentCallbackClient ¶
func NewPersistentCallbackClient(opts PersistentCallbackOptions) *PersistentCallbackClient
NewPersistentCallbackClient creates a callback client with persistent queue backing.
func (*PersistentCallbackClient) Close ¶
func (c *PersistentCallbackClient) Close() error
Close gracefully stops the webhook worker.
func (*PersistentCallbackClient) PaymentSucceeded ¶
func (c *PersistentCallbackClient) PaymentSucceeded(ctx context.Context, event PaymentEvent)
PaymentSucceeded queues a payment success webhook for persistent delivery.
func (*PersistentCallbackClient) RefundSucceeded ¶
func (c *PersistentCallbackClient) RefundSucceeded(ctx context.Context, event RefundEvent)
RefundSucceeded queues a refund success webhook for persistent delivery.
type PersistentCallbackOptions ¶
type PersistentCallbackOptions struct {
Store storage.Store
Config config.CallbacksConfig
RetryConfig RetryConfig
Logger zerolog.Logger
Metrics *metrics.Metrics
}
PersistentCallbackOptions configures the persistent callback client.
type RefundEvent ¶
type RefundEvent struct {
// Idempotency and event metadata (ALWAYS present)
EventID string `json:"eventId"` // Unique event identifier for idempotency (e.g., "evt_refund_xyz")
EventType string `json:"eventType"` // Always "refund.succeeded" for this event
EventTimestamp time.Time `json:"eventTimestamp"` // ISO8601 timestamp when event was created (UTC)
// Refund details
RefundID string `json:"refundId"`
OriginalPurchaseID string `json:"originalPurchaseId"`
RecipientWallet string `json:"recipientWallet"`
AtomicAmount int64 `json:"atomicAmount"` // Amount in atomic units (e.g., 10500000 for 10.5 USDC with 6 decimals)
Token string `json:"token"`
ProcessedBy string `json:"processedBy"` // Server wallet that executed refund
Signature string `json:"signature"`
Reason string `json:"reason,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
RefundedAt time.Time `json:"refundedAt"`
}
RefundEvent encapsulates the essential information about a completed refund. IMPORTANT: EventID is the idempotency key - webhook consumers MUST use this to prevent duplicate processing.
type RetryConfig ¶
type RetryConfig struct {
MaxAttempts int // Maximum retry attempts (default: 5)
InitialInterval time.Duration // Initial backoff interval (default: 1s)
MaxInterval time.Duration // Maximum backoff interval (default: 5m)
Multiplier float64 // Backoff multiplier (default: 2.0)
Timeout time.Duration // Per-attempt timeout (default: 10s)
}
RetryConfig holds webhook retry configuration.
func DefaultRetryConfig ¶
func DefaultRetryConfig() RetryConfig
DefaultRetryConfig returns sensible defaults for webhook retries.
type RetryOption ¶
type RetryOption func(*RetryableClient)
RetryOption customizes the retry client behavior.
func WithDLQStore ¶
func WithDLQStore(store DLQStore) RetryOption
WithDLQStore enables dead letter queue for failed webhooks.
func WithMetrics ¶
func WithMetrics(metrics *metrics.Metrics) RetryOption
WithMetrics sets the metrics collector for webhook observability.
func WithRetryConfig ¶
func WithRetryConfig(cfg RetryConfig) RetryOption
WithRetryConfig sets custom retry configuration.
func WithRetryLogger ¶
func WithRetryLogger(logger zerolog.Logger) RetryOption
WithRetryLogger sets a custom logger for retry operations.
type RetryableClient ¶
type RetryableClient struct {
// contains filtered or unexported fields
}
RetryableClient posts payment events with exponential backoff retry logic.
func (*RetryableClient) PaymentSucceeded ¶
func (c *RetryableClient) PaymentSucceeded(ctx context.Context, event PaymentEvent)
PaymentSucceeded dispatches the payment event asynchronously with retry logic. IMPORTANT: EventID is generated once and preserved across all retry attempts for idempotency.
func (*RetryableClient) RefundSucceeded ¶
func (c *RetryableClient) RefundSucceeded(ctx context.Context, event RefundEvent)
RefundSucceeded dispatches the refund event asynchronously with retry logic. IMPORTANT: EventID is generated once and preserved across all retry attempts for idempotency.
type WebhookQueueWorker ¶
type WebhookQueueWorker struct {
// contains filtered or unexported fields
}
WebhookQueueWorker processes webhooks from the persistent queue.
func NewWebhookQueueWorker ¶
func NewWebhookQueueWorker(opts WebhookQueueWorkerOptions) *WebhookQueueWorker
NewWebhookQueueWorker creates a new webhook queue worker.
func (*WebhookQueueWorker) EnqueuePaymentWebhook ¶
func (w *WebhookQueueWorker) EnqueuePaymentWebhook(ctx context.Context, event PaymentEvent) error
EnqueuePaymentWebhook adds a payment webhook to the persistent queue.
func (*WebhookQueueWorker) EnqueueRefundWebhook ¶
func (w *WebhookQueueWorker) EnqueueRefundWebhook(ctx context.Context, event RefundEvent) error
EnqueueRefundWebhook adds a refund webhook to the persistent queue.
func (*WebhookQueueWorker) Start ¶
func (w *WebhookQueueWorker) Start(ctx context.Context)
Start begins processing webhooks from the queue.
func (*WebhookQueueWorker) Stop ¶
func (w *WebhookQueueWorker) Stop()
Stop gracefully stops the worker.
type WebhookQueueWorkerOptions ¶
type WebhookQueueWorkerOptions struct {
Store storage.Store
Config config.CallbacksConfig
RetryConfig RetryConfig
Logger zerolog.Logger
Metrics *metrics.Metrics
PollInterval time.Duration // How often to poll for pending webhooks (default: 5s)
}
WebhookQueueWorkerOptions configures the webhook queue worker.