@payfanout/adapter-worldline
v1.1.3
Published
Client-side Worldline Direct adapter for PayFanout (Hosted Tokenization Page iframe, tokenize-first). No secrets, no server code.
Readme
@payfanout/adapter-worldline
Client-side Worldline Direct adapter for PayFanout: the Hosted Tokenization Page iframe (card data captured inside Worldline's iframe, SAQ-A eligible), tokenize-first.
No secrets. This package ships to the browser and holds no API credentials. The tokenization iframe is addressed entirely by the
hostedTokenizationUrlthe server session hands it.
It implements the ClientPaymentAdapter contract from @payfanout/core, so
@payfanout/react renders it through the same <PaymentFields> / <PayButton> as every
other PSP.
📖 Documentation: https://donapulse.github.io/payfanout/ · Set up Worldline · React usage
Installation
pnpm add @payfanout/react @payfanout/adapter-worldline react react-domThe Worldline Tokenizer script is not an npm dependency; the adapter injects it lazily
from Worldline's host on first mount.
Usage
import { PayFanoutProvider, PaymentFields, PayButton } from "@payfanout/react";
import { WorldlineClientAdapter } from "@payfanout/adapter-worldline";
const worldline = new WorldlineClientAdapter({ environment: "sandbox" });
<PayFanoutProvider adapters={[worldline]} initialPsp="worldline" completionEndpoint="/api/complete">
{/* onChange fires { complete: false } on mount, then { complete: true | false } each time
the Tokenizer reports a validity change. */}
<PaymentFields clientSecret={session.clientSecret} onChange={({ complete }) => setPayEnabled(complete)} />
{/* completionEndpoint finishes the tokenize-first flow automatically — no onServerCompletion. */}
<PayButton onResult={(result) => showOutcome(result)}>Pay</PayButton>
</PayFanoutProvider>environmentselects the Worldline host the Hosted Tokenization script loads from (sandbox → payment.preprod.direct.worldline-solutions.com,live → payment.direct.worldline-solutions.com). Nothing is inferred.- The session's
clientSecretis thehostedTokenizationUrlreturned bycreatePaymentSession; the adapter builds theTokenizerfrom it. No client key is needed. confirm()tokenizes the card and resolves{ status: "requires_confirmation", clientToken }whereclientTokencarries thehostedTokenizationIdand the browser's 3-D Secure data (see below). The host passes it to the server'scompletePayment—<PayButton>/completionEndpointwire this automatically.
3-D Secure and card storage
- Worldline lists browser device data among the mandatory 3-D Secure properties of every card
payment, and only the browser can read it.
confirm()collects it (language, time zone offset, user agent, screen height, width and color depth, the Java and JavaScript flags) and sends it with thehostedTokenizationIdas a JSONclientToken:{"hostedTokenizationId":"…","device":{…}}. Browser characteristics only, never card data; a value the browser does not expose is left out rather than failing the payment. @payfanout/adapter-worldline-serverdecodes the envelope and forwards the device data asorder.customer.device. Deploy the server adapter release that understands it before this package: an earlier server adapter would send the whole envelope as thehostedTokenizationId.- The card is tokenized with
storePermanently: false, so Worldline keeps no token for later payments. The adapter has no saved-card surface, so a stored token could never be used.
Notes
- Card data is captured only inside Worldline's Hosted Tokenization iframe; there is no raw card input, and no PAN/CVV ever touches your DOM.
onChangeis driven by the Tokenizer'svalidationCallback: it fires{ complete: false, empty: true }on mount, then{ complete }carrying each validity report'svalidflag. The adapter owns that callback; one passed infieldOptionsstill runs, afteronChange, with the same result. Validity only means the form is correctly filled in: the decline outcome surfaces server-side atcompletePayment.- The cardholder-name field is shown by default (
hideCardholderName: false), because Worldline requires the cardholder name and hides that field unless told otherwise. AhideCardholderName: trueinfieldOptionsstill wins, but then the name has to reach Worldline through itsuseCardholderNamecall, which the adapter neither makes nor exposes, so keep the field visible.
Documentation
License
MIT
