PayFanout API reference
    Preparing search index...

    Implements

    Index
    pspName: "worldline" = WORLDLINE_PSP_NAME
    • Resolves "canceled" only when the PSP confirms it. Under getCapabilities().modificationOutcome "asynchronous" the PSP merely acknowledges the request and the outcome arrives by webhook, so the returned status is "processing" — never an unconfirmed terminal state.

      Parameters

      • pspPaymentId: string
      • idempotencyKey: string

      Returns Promise<PaymentInfo>

    • Only present if getCapabilities().supportsManualCapture. Capture is the canonical double-charge operation — the idempotency key is REQUIRED, and under supportsMultiCapture each partial capture is its own charge with its own key.

      Parameters

      • pspPaymentId: string
      • amount: number | undefined
      • idempotencyKey: string

      Returns Promise<PaymentInfo>

    • Tokenize-first completion: create the payment from the clientToken confirm() produced, the hostedTokenizationId plus the browser's device data (see decodeWorldlineClientToken; a bare hostedTokenizationId is accepted too). The signed context is the only trusted source of amount/currency/capture-method. The session's metadata, when it has entries, is sent JSON-encoded as order.references.merchantParameters; a context signed before metadata was carried sends none.

      Every payment carries the mandatory 3-D Secure properties the adapter can supply: the return URL in both documented forms, threeDSecure.skipAuthentication: false, the device data as order.customer.device, and the use case Cartes Bancaires requires, paymentProduct130SpecificInput.threeDSecure.usecase: "single-amount", whatever the card's brand. acceptHeader and ipAddress are observed on the customer's HTTP request and CompletePaymentInput carries neither, so they are not sent. The cardholder name is entered in the Hosted Tokenization iframe. sca.challenge: "force" requests challengeIndicator: "challenge-required". sca.exemption: "moto" sends transactionChannel: "MOTO", Worldline's mail order / telephone order channel, with the 3-D Secure data unchanged; without it no channel is sent, which Worldline reads as ECOMMERCE.

      A REDIRECT merchantAction (3-D Secure challenge) surfaces as requires_action with the redirect URL on raw; the customer completes it and the host reconciles with retrievePayment. Its metadata is the answer's merchantParameters echo when it carries one. The API contract documents that echo on GET calls and webhooks only, so without one it is the metadata the payment's request carried: this call's for the call's own payment, and for an earlier attempt's, the metadata that payment reads back with. A decline rejects with the same error code whether Worldline answers it with a 402 or with a 2xx carrying a REJECTED payment (see mapWorldlineError); raw is the error body in the first case and the whole CreatePayment response in the second.

      Worldline answers a key it has seen with that key's first outcome for at least 24 hours, so on its own a key whose attempt failed would answer every later card with that failure. When a key answers with a replay of a failed attempt, the payment goes out again under a key derived from idempotencyKey and that attempt, and so on until an attempt that did not fail, past which nothing is sent: a completion repeated after a success returns that payment. An attempt failed once its payment was declined or cancelled, as its answer shows or, for a 3-D Secure challenge or a payment still pending when answered, as it reads back now. A payment authorised or captured when created never counts as failed, nor does one that reads Authorised and cancelled (6); a challenge still open is returned as requires_action, and a refusal whose payment may still go through is thrown marked outcomeUnknown, as is a payment that cannot be read back. An earlier attempt's payment that did not end unpaid is returned only when it was made for the session's amount and currency; otherwise the completion is refused with a non-retryable invalid_request marked outcomeUnknown (raw.reason: "another_sessions_payment").

      A replay is recognised by its X-GCS-Idempotence-Request-Timestamp header on the key's first send in the call. On a re-send, after a timeout or a lost connection, only a timestamp that reads as the documented milliseconds, less than 23 hours old and more than 15 minutes before that first send, names an earlier completion's attempt. Any other replayed answer may be the call's own: it is read like a replay, but a failed attempt among them is thrown marked outcomeUnknown instead of walked past. That margin assumes this server's clock runs less than 15 minutes ahead of Worldline's. A 409, a 429 and a 5xx never lead to a new attempt. The completion is refused with a non-retryable invalid_request after 20 attempts under one key (raw.reason: "attempt_limit"), and, marked outcomeUnknown, when Worldline could forget the key's first attempt before the session expires (raw.reason: "first_attempt_may_expire").

      Parameters

      Returns Promise<PaymentInfo>

    • Creates the Hosted Tokenization session (POST /hostedtokenizations — no amount at this step) and encodes amount/currency/capture-method, the return URL, the SCA preference, the metadata and the returned hostedTokenizationId into a signed, self-contained context that completePayment later verifies and trusts. The client mounts the iframe from the returned hostedTokenizationUrl (the session's clientSecret).

      metadata goes to Worldline JSON-encoded, as the payment's order.references.merchantParameters, which Worldline echoes on reads and in webhooks: retrievePayment reports it as PaymentInfo.metadata, and readWorldlineWebhookMetadata reads it from a webhook. Worldline's API contract says of that field: "This field must not contain any personal data." Keep personal data out of a Worldline session's metadata; the adapter sends what it is given. The context is signed, not encrypted: whoever holds pspSessionId can read it, the metadata included.

      Refused with invalid_request before anything reaches Worldline when the session has no return URL (neither a non-empty returnUrl nor the adapter's defaultReturnUrl) or one Worldline rejects (over 200 characters, or without a protocol such as https:// or an app scheme), when id is longer than the 40 characters order.references.merchantReference accepts, when statementDescriptor is longer than the 256 characters order.references.softDescriptor accepts, or when the JSON sent for metadata is not an object of string values or is longer than the 1000 characters order.references.merchantParameters accepts (UTF-16 code units, so an emoji counts two).

      Parameters

      Returns Promise<PaymentSession>

    • Reads the payment, its captures and its refunds. metadata is the session's as Worldline echoes it in merchantParameters (see createPaymentSession). createdAt is the payment's paymentOutput.transactionDate, which Worldline describes as "the server-side processing date and time of the transaction" without saying whether a later capture or refund moves it. It is read only with a time zone: Z, ±HH:MM or ±HH. Without a readable one, a value without a zone included, it is 1970-01-01T00:00:00.000Z.

      Parameters

      • pspPaymentId: string
      • OptionalpayfanoutId: string

      Returns Promise<PaymentInfo>

    • "Test connection" probe: one side-effect-free GET against the account's test-connection service, /v2/{merchantId}/services/testconnection. It reads the RAW HTTP status, so an auth rejection (401/403; Worldline answers a key, secret or PSPID it cannot match, or keys of the other environment, with a 403) is told apart from an outage (429/5xx) from the status line alone. Only a 2xx carrying the service's OK answer, "result": "OK", passes: "If you receive an OK result you know that your connection with us is working correctly" (Connect S2S API reference, Test connection). Any other answer that is neither an auth rejection nor an outage means the probe did not get that answer: a baseUrl override is wrong (Worldline answers a wrong endpoint with an empty body), names a host that answers 2xx with something else, or the service answered a result other than OK, which no Worldline page documents. It reports internal, naming the HTTP status and, on a non-2xx, the first error's id when it reads as one. A single call, never retried; never mutates PSP state, never puts a credential in the result.

      Returns Promise<VerifyCredentialsResult>

    • Webhook handling — same adapter, separate concerns. Both async: future PSPs may need remote key retrieval; the contract stays uniform. MUST operate on the RAW request body bytes/string — re-serializing a parsed body breaks signatures (the conformance suite tests this).

      Parameters

      • rawBody: string
      • headers: Record<string, string>

      Returns Promise<boolean>