# OpenSpec Change: enterprise-payment-providers - **Change ID**: enterprise-payment-providers - **Package**: `@suaveplan/payment-providers` - **Category**: universal - **Target path**: `universal/commerce/payment-providers` - **Status**: IN PROGRESS - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/payment-providers.md` --- ## Summary Deliver `@suaveplan/payment-providers` on the genesis branch from scratch at enterprise quality. The package provides concrete `PaymentAdapter` implementations for Stripe, PayPal, Square, Mollie, and Adyen. Each adapter wraps the provider's REST API using injectable fetch (no provider SDK dependency), implements the full `PaymentAdapter` interface from `@suaveplan/payment`, handles provider-specific webhook signature verification, and normalises provider error codes to the canonical `PAYMENT.*` code registry. The main-branch version sat at 100% coverage. Genesis adds structured errors, Zod schemas, OTel instrumentation, retry with circuit breaker, and integration-test harnesses. --- ## Current-state audit (genesis) The package does not exist on genesis yet — this is a fresh build. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/error` (`workspace:^`) | `PaymentProviderError`; extends `PAYMENT.*` code set | | `@suaveplan/types` (`workspace:^`) | `LoggerLike`, `Clock` | | `@suaveplan/payment` (`workspace:^`) | `PaymentAdapter` interface; `PaymentIntent`, `PaymentWebhookEvent` types | | `@suaveplan/retry` (`workspace:^`) | Retry + circuit breaker for provider API calls | | `@suaveplan/crypto` (`workspace:^`) | HMAC webhook signature verification | | `zod` (`catalog:forms`) | Provider response schema validation | | `@opentelemetry/api` (`catalog:observability`) | Spans + counters | Dev deps: `vitest`, `@vitest/coverage-istanbul` (all `catalog:testing`). --- ## Public API surface ### Provider factories ```ts function createStripeAdapter(options: StripeAdapterOptions): PaymentAdapter function createPayPalAdapter(options: PayPalAdapterOptions): PaymentAdapter function createSquareAdapter(options: SquareAdapterOptions): PaymentAdapter function createMollieAdapter(options: MollieAdapterOptions): PaymentAdapter function createAdyenAdapter(options: AdyenAdapterOptions): PaymentAdapter ``` All option types share a common base: ```ts interface BaseAdapterOptions { apiKey: string webhookSecret?: string environment?: 'sandbox' | 'production' // default 'production' retryOptions?: RetryOptions fetch?: typeof globalThis.fetch clock?: Clock logger?: LoggerLike } interface StripeAdapterOptions extends BaseAdapterOptions { apiVersion?: string // default 'latest' } interface PayPalAdapterOptions extends BaseAdapterOptions { clientId: string clientSecret: string } interface AdyenAdapterOptions extends BaseAdapterOptions { merchantAccount: string liveUrlPrefix?: string } ``` ### Provider-normalised types Each provider's raw response is normalised to `PaymentIntent` via a per-provider mapper; these mappers are exported for testing: ```ts function normalizeStripePaymentIntent(raw: unknown): PaymentIntent function normalizePayPalOrder(raw: unknown): PaymentIntent function normalizeSquarePayment(raw: unknown): PaymentIntent function normalizeMolliePayment(raw: unknown): PaymentIntent function normalizeAdyenPayment(raw: unknown): PaymentIntent ``` ### Error codes Provider errors are wrapped in `PaymentError` with existing `PAYMENT_PROVIDER_ERROR` code plus an added detail field: ```ts interface PaymentProviderErrorDetail { provider: string providerCode?: string providerMessage?: string } ``` --- ## Genesis additions 1. **Zod schemas** for all provider-specific option types and raw response shapes. 2. **Sandbox/production switching** — `environment: 'sandbox'` routes to provider test endpoints automatically. 3. **Idempotency key passthrough** — all create/capture/refund calls forward the caller-supplied idempotency key as the provider-specific header (`Idempotency-Key` for Stripe, etc.). 4. **Circuit breaker** — wraps all provider API calls via `@suaveplan/retry`; opens after 5 consecutive provider errors. 5. **OTel instrumentation** — span `payment_provider.api_call` with attributes `payment_provider.name`, `payment_provider.method`; counter `payment_provider.api_total`; histogram `payment_provider.api_duration_ms`. 6. **Provider error normalisation** — 4xx/5xx provider responses are mapped to the closest `PAYMENT.*` error code with provider details preserved in the error context. --- ## File layout ```text universal/commerce/payment-providers/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/ index.ts types/ common.ts common.md providers/ stripe/ stripe.ts stripe.md stripe.types.ts stripe.test.ts index.ts paypal/ paypal.ts paypal.md paypal.types.ts paypal.test.ts index.ts square/ square.ts square.md square.types.ts square.test.ts index.ts mollie/ mollie.ts mollie.md mollie.types.ts mollie.test.ts index.ts adyen/ adyen.ts adyen.md adyen.types.ts adyen.test.ts index.ts __benchmarks__/ payment-providers.bench.ts tests/ integration.test.ts ``` --- ## Impact **Downstream consumers**: `@suaveplan/booking`, any server-side checkout flow. **Workspace dep prerequisites**: `@suaveplan/error`, `@suaveplan/types`, `@suaveplan/payment`, `@suaveplan/retry`, `@suaveplan/crypto`.