Agora
Patterns

Patterns

A cookbook of the flows this library exists for — Pix and subscriptions per gateway, where business logic lives, metered billing, marketplace splits, recovery, chargebacks, and reading the billing data without the bundled console.

Each page below is a complete flow you can adapt, with the gateway differences shown side by side rather than averaged into a generic example — because the differences are the part that costs you an afternoon.

The two habits every pattern assumes

Set externalReference on everything. It is the string the gateway echoes back, and it is the only thing tying a confirmation to your own row. A charge created without one produces a webhook your handler cannot route, and the failure is a silent return. See The payment lifecycle.

Put business logic in a handler, not next to the charge() call. The charge returns PENDING; nothing has been paid. Granting anything there gives the product away to whoever starts a checkout and walks off. See Reacting to payments.

Every example is integer cents

1990 is R$ 19,90. Never a float, never a decimal — see Money.

The patterns

Picking a gateway per flow

The routing table is where these decisions land. A common Brazilian setup splits by what each gateway is actually best at:

config/payments.ts
export default defineConfig({
  default: 'asaas',
  providers: {
    woovi: payments.woovi({ appId: env.get('WOOVI_APP_ID') }),
    stripe: payments.stripe({ apiKey: env.get('STRIPE_KEY'), currency: 'brl' }),
    asaas: payments.asaas({ apiKey: env.get('ASAAS_API_KEY') }),
  },
  methods: {
    pix: 'woovi',           // best Pix rates
    credit_card: 'stripe',  // best card tooling
    boleto: 'asaas',
    debit_card: 'asaas',
    undefined: 'asaas',
  },
})

Your services then name the method, never the gateway — so moving Pix from Woovi to Asaas is one line of config. See Routing.

On this page