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,paypalormanualinfeatures/integrations/payment; - an external HTTP app, chosen by storing a URL in an operation field on the
PaymentProviderrecord.
How dispatch works
features/keystone/utils/paymentProviderAdapter.ts reads the field for the requested operation:
createPaymentFunctioncapturePaymentFunctionrefundPaymentFunctiongetPaymentStatusFunctiongeneratePaymentLinkFunctionhandleWebhookFunction
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
- Deploy the adapter, or add a module under
features/integrations/payment. - Create a
PaymentProviderwith a name, acode,isInstalledon, credentials or metadata, and the six operation fields. The dashboard drawer at/dashboard/platform/payment-providersonly offers Stripe, PayPal and Manual presets, so set custom fields on the generic/dashboard/payment-providerseditor. - Link the provider to each region it serves.
- Point the provider's webhook at
/api/payment-webhooks/<providerId>. - 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.
generatePaymentLinkFunctionexists 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.