Add a payment adapter

Connect a local payment module or an independently deployed HTTP adapter.

The payment dispatcher supports two modes:

  • a local module such as stripe, paypal or manual in features/integrations/payment;
  • an external HTTP app, chosen by storing a URL in an operation field on the PaymentProvider record.

How dispatch works

features/keystone/utils/paymentProviderAdapter.ts reads the field for the requested operation:

  • createPaymentFunction
  • capturePaymentFunction
  • refundPaymentFunction
  • getPaymentStatusFunction
  • generatePaymentLinkFunction
  • handleWebhookFunction

If the value starts with http, Openfront sends a JSON POST to that URL. Otherwise it imports features/integrations/payment/<value>.ts and calls the export named after the field.

Payment creation sends a body like:

{
  "provider": "the PaymentProvider record",
  "cart": "the cart projection",
  "amount": 2500,
  "currency": "usd"
}

Other operations send provider plus paymentId, amount, currency, idempotencyKey, event or headers. See Implement a payment adapter for the expected replies.

Configure a provider

  1. Deploy the adapter, or add a module under features/integrations/payment.
  2. Create a PaymentProvider with a name, a code, isInstalled on, credentials or metadata, and the six operation fields. The dashboard drawer at /dashboard/platform/payment-providers only offers Stripe, PayPal and Manual presets, so set custom fields on the generic /dashboard/payment-providers editor.
  3. Link the provider to each region it serves.
  4. Point the provider's webhook at /api/payment-webhooks/<providerId>.
  5. Test in a sandbox before taking real payments.

The code decides whether checkout will show the provider. Only codes starting with pp_stripe (needs Stripe env vars), pp_paypal (needs PayPal env vars), pp_manual or pp_system_default pass the configuration check. Codes containing manual cannot complete checkout or refunds. Any other code is hidden from checkout until you extend features/keystone/utils/paymentProviderConfig.ts.

Current source limits

  • The HTTP bridge sends only a JSON content-type header. It has no timeout, request signature, destination allowlist or response schema.
  • The provider record, including credentials, is sent to the HTTP adapter on every call.
  • Webhook processing only recognizes Stripe and PayPal event types and amount formats.
  • generatePaymentLinkFunction exists in the adapter, but no checkout or invoice path calls it.

Required checks

  • Only trusted operators can create providers or change their fields.
  • Each operation reaches only its configured destination.
  • The adapter authenticates calls from Openfront.
  • Duplicate capture or refund requests have one provider effect.
  • Malformed or slow adapter replies fail without changing orders.
  • Credentials do not appear in logs or browser responses.
  • Bad and replayed webhooks change nothing.

See Payment providers.

On this page