Welcome to the Jose Madrid Salsa developer docs — explore features, APIs, and deployment guides.
Jose Madrid SalsaJMS Docs

Payment Processing

Multi-provider payment system with Stripe, PayPal, and Square adapters behind a unified provider interface

Payment Processing

The platform uses a provider-agnostic payment architecture. All payment operations (create, confirm, refund) go through a common PaymentProviderAdapter interface, with a registry that routes requests to the correct provider based on payment method type.

Architecture

index.ts
types.ts
registry.ts
stripe.ts
paypal.ts
square.ts

Provider Registry

The registry (lib/payments/registry.ts) maps payment method types to providers:

const METHOD_PROVIDER_MAP: Record<PaymentMethodType, PaymentProvider> = {
  CARD: 'STRIPE',
  ACH: 'STRIPE',
  APPLE_PAY: 'STRIPE',
  GOOGLE_PAY: 'STRIPE',
  PAYPAL: 'PAYPAL',
  SQUARE_TERMINAL: 'SQUARE',
}

Providers are auto-registered on import based on available environment variables:

// Always available
registerProvider(new StripeAdapter())

// Conditional registration
if (process.env.PAYPAL_CLIENT_ID && process.env.PAYPAL_CLIENT_SECRET) {
  registerProvider(new PayPalAdapter())
}
if (process.env.SQUARE_ACCESS_TOKEN) {
  registerProvider(new SquareAdapter())
}

PaymentProviderAdapter Interface

Every provider adapter implements this interface:

interface PaymentProviderAdapter {
  readonly provider: PaymentProvider

  createPayment(request: CreatePaymentRequest): Promise<PaymentResult>
  confirmPayment(providerPaymentId: string): Promise<PaymentResult>
  refund(request: RefundRequest): Promise<RefundResult>
  createCustomer(email: string, name: string): Promise<CustomerResult>
  listPaymentMethods(customerId: string): Promise<SavedPaymentMethod[]>
  detachPaymentMethod(paymentMethodId: string): Promise<void>
  verifyWebhookSignature(request: WebhookVerificationRequest): Promise<boolean>
}

Core Types

CreatePaymentRequest

FieldTypeDescription
amountnumberAmount in cents (e.g., 4299 = $42.99)
currencystringISO 4217 code (e.g., usd)
orderIdstringInternal order CUID
orderNumberstringHuman-readable (e.g., JMS-20260331-1234)
customerEmailstringFor receipts
methodTypePaymentMethodTypeRoutes to correct provider
channelPaymentChannelONLINE or POS
setupFutureUsageboolean?Save payment method for reuse

PaymentResult

FieldTypeDescription
successbooleanOperation completed without error
providerPaymentProviderWhich provider processed it
providerPaymentIdstringProvider-specific ID
clientSecretstring?For Stripe client-side confirmation
approvalUrlstring?For PayPal redirect flow
statusenumREQUIRES_ACTION, PROCESSING, SUCCEEDED, FAILED

Usage

import { getProvider, getProviderForMethod } from '@/lib/payments'

// Get adapter by provider name
const stripe = getProvider('STRIPE')

// Get adapter by payment method (auto-routes)
const adapter = getProviderForMethod('PAYPAL')

// Create a payment
const result = await adapter.createPayment({
  amount: 4299,
  currency: 'usd',
  orderId: 'clx...',
  orderNumber: 'JMS-20260408-1234',
  customerEmail: 'customer@example.com',
  customerName: 'Jane Doe',
})

For provider-specific details, see the Stripe, PayPal, and Square pages.

How is this guide?

Edit on GitHub

Last updated on

On this page