Prood
Packages

@prood/checkout

Framework-agnostic checkout state machine managing the payment lifecycle.

@prood/checkout provides the CheckoutSession class — a finite state machine that orchestrates the complete checkout flow from customer info to payment confirmation.

Installation

pnpm add @prood/checkout

Depends on @prood/types for PaymentProvider interface.

Basic usage

import { CheckoutSession } from '@prood/checkout'
import { StripePaymentProvider } from '@prood/payment-stripe'

const provider = new StripePaymentProvider({ secretKey: 'sk_...' })

const session = new CheckoutSession({
  provider,
  amount: 9999,
  currency: 'EUR',
  orderId: 'ord_123',
  returnUrl: 'https://store.example.com/order-confirmation',
  fulfillment: 'shipping',
})

State machine API

Set customer info (idle → info)

session.setCustomerInfo({
  email: 'customer@example.com',
  firstName: 'Maria',
  lastName: 'Silva',
  phone: '+351912345678',
})

Set shipping address (info → shipping)

Required for shipping and local_delivery fulfillment:

session.setShippingAddress({
  street: 'Rua Augusta 123',
  city: 'Lisboa',
  country: 'PT',
  postalCode: '1100-053',
  street2: null,
  state: null,
  district: null,
  nationalAddress: null,
})

Submit payment (→ payment)

const paymentSession = await session.submitPayment({
  sourceToken: 'pm_xxx',
})

if (paymentSession.redirectUrl) {
  // Redirect for 3DS
}

Confirm payment (payment → complete)

const confirmed = await session.confirmPayment(chargeId)
// session.state === 'complete' | 'failed'

Webhook update

session.handleWebhookUpdate({
  id: event.id,
  providerId: 'stripe',
  status: 'captured',
  amount: 9999,
  currency: 'EUR',
  redirectUrl: null,
  createdAt: new Date().toISOString(),
})

Events

session.on('stateChange', ({ from, to }) => { ... })
session.on('complete', ({ paymentSession }) => { ... })
session.on('error', ({ error, state }) => { ... })
session.on('expired', () => { ... })

Snapshots

const snapshot = session.toSnapshot()
// Serializable — used by @prood/checkout-host for Redis persistence

CheckoutSession.fromSnapshot(snapshot, provider)
// Rehydrate from saved state

Fulfillment types

TypeFlow
shippinginfo → shipping → payment → complete
local_deliveryinfo → shipping → payment → complete
pickupinfo → payment → complete
noneinfo → payment → complete

Exports

export { CheckoutSession } from '@prood/checkout'
export { buildTransitions } from '@prood/checkout'
export type { CheckoutState, CheckoutSnapshot, CheckoutChannel } from '@prood/checkout'

On this page