Payment providers, set up a PSP
PayFanout installs every PSP the same shape: a server adapter that holds your secret credentials, a client adapter that holds only a browser-safe key, and (optionally) a webhook endpoint. Application code never learns which PSP is active, so "install a PSP" is the same job whether it is one we ship or one you write yourself.
Pick the PSP you're wiring up:
| PSP | Set-up guide | Server package | Client package | Completion shape |
|---|---|---|---|---|
| Stripe | Set up Stripe | @payfanout/adapter-stripe-server | @payfanout/adapter-stripe | Confirm-on-client |
| Paysafe | Set up Paysafe | @payfanout/adapter-paysafe-server | @payfanout/adapter-paysafe | Tokenize-first (needs a server-completion route) |
| GoCardless | Set up GoCardless | @payfanout/adapter-gocardless-server | @payfanout/adapter-gocardless | Confirm-on-client (redirect to hosted bank authorisation) |
| PayPal | Set up PayPal | @payfanout/adapter-paypal-server | @payfanout/adapter-paypal | Tokenize-first (needs a server-completion route) |
| PayZen (Lyra) | Set up PayZen | @payfanout/adapter-payzen-server | @payfanout/adapter-payzen | Confirm-on-client |
| Worldline (Direct) | Set up Worldline | @payfanout/adapter-worldline-server | @payfanout/adapter-worldline | Tokenize-first (needs a server-completion route) |
New to the packages themselves? Installation covers prerequisites, which packages to add, and the env-var mechanics first. This page and the guides below are about wiring a specific PSP end to end.
The four steps, for every PSP
The guides follow the identical arc, only the credential names and a few quirks differ:
- Get credentials. Every PSP has a sandbox and a live set. PayFanout never infers which you're using from a key prefix, you pass
environment: "sandbox" | "live"explicitly, and the adapter throws if you don't. - Wire the server adapter. Construct it from environment variables and register it on a
PaymentService. The constructor validates its config and throws at startup on a missing required field, a misconfiguration can never reach checkout. - Wire the client adapter. Construct it with the browser-safe key and hand it to
<PayFanoutProvider>. The PSP's browser SDK loads lazily from the PSP's CDN, there is nothing extra topnpm add. - Register the webhook endpoint. Point the PSP at your
/webhooks/<psp>route and give the adapter the signing secret. Signature verification hashes the exact raw request bytes, see Webhooks for the raw-body requirement that every framework fights you on.
Which side do I need?
Server-only backend? Steps 1, 2, 4. Adding the embedded card fields? Also step 3. You do not have to install both PSPs, add only the one(s) you use.
Sandbox first, always
Do the whole integration against the PSP's sandbox, environment: "sandbox", test keys, test cards. Nothing about going live changes your PayFanout code except the credentials and the environment string; each set-up guide ends with a Go live checklist that spells out exactly what swaps. Because PayFanout is stateless, there is no data migration between sandbox and live, the switch is credentials only.
Installing a PSP we don't ship yet
A third, fourth, or fifth PSP is a new adapter package, not a fork. You implement the ServerPaymentAdapter / ClientPaymentAdapter contracts from @payfanout/core, prove the adapter against @payfanout/conformance, the same suite Stripe and Paysafe pass, and it drops into the exact four steps above with zero changes to core, server, React, or your application code. The step-by-step build is Writing an adapter, and Conformance is how "extensible" stays a guarantee rather than a hope.