PayFanout API reference
    Preparing search index...

    Adyen is a PUSH-ONLY provider: its pspReference is a write target, there is no read for a payment or a refund, and every modification answers with a bare acknowledgement whose outcome arrives by webhook. Two consequences shape this adapter:

    • Capabilities declare supportsPaymentRetrieval: false, supportsRefundRetrieval: false and modificationOutcome: "asynchronous"; capture and cancel resolve "processing" and refunds "pending", never a terminal state Adyen has not confirmed.
    • PaymentInfo.pspPaymentId is the composite "{pspReference}:{value}:{currency}". A capture or refund needs the payment's currency (and, when no amount is given, its value); with no read and no persistence, the money facts ride the reference. The part before the first ":" is Adyen's own pspReference — the one webhooks report — and cancels accept it bare.

    Implements

    Index
    pspName: "adyen" = ADYEN_PSP_NAME
    • Requests a cancel. Accepts the bare pspReference: no money facts are needed. Adyen documents only that a captured payment can no longer be cancelled; a cancel after the capture is assumed to be acknowledged and to fail in the CANCELLATION webhook, and a rejection in the answer surfaces as an error.

      Parameters

      • pspPaymentId: string
      • idempotencyKey: string

      Returns Promise<PaymentInfo>

    • Requests a capture. Adyen answers { status: "received" }, so the reported status is "processing" and no amountCaptured is invented — the settled amount is knowable only from the CAPTURE webhook. An acknowledgement echoing a different amount or currency is rejected, and one echoing none is accepted (see readAcknowledgement).

      Parameters

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

      Returns Promise<PaymentInfo>

    • Tokenize-first completion. clientToken is the JSON the client adapter produced (see parseClientToken):

      • confirm()'s envelope — the encrypted card paymentMethod plus the browser data 3-D Secure uses — or the bare paymentMethod earlier client adapters send, which creates the payment (POST /payments), or
      • { details } from a finished action (handleAction(), or the redirectResult of a 3-D Secure redirect return), which finishes it (POST /payments/details).

      The signed context is the only trusted source of amount, currency, reference and capture method. A refusal is raised as a mapped PayFanoutError rather than folded into a "failed" PaymentInfo. An action surfaces as requires_action with Adyen's answer on raw. Adyen can answer an action without a pspReference (its native 3-D Secure 2 example does); pspPaymentId is then the empty string, which capturePayment, cancelPayment and refundPayment refuse.

      Every answer is compared with the session it completes. A /payments answer naming another merchant reference or amount is refused: the request named the session's own, so the answer belongs to another request (an idempotencyKey reused across sessions replays the first answer), and unless it is Refused, Error or Cancelled the refusal carries outcomeUnknown (see anotherRequestsAnswer). A /payments/details answer stands for the session only when it names the session's merchant reference and amount (see detailsBelongToSession); one that does not carries no pspPaymentId and reads "processing". The AUTHORISATION webhook, whose merchantReference is one of the signed values, then supplies the reference (encodeAdyenPaymentRef(event.pspPaymentId, event.amount, event.currency)).

      Parameters

      Returns Promise<PaymentInfo>

    • Creates NO Adyen object: the payment only exists once completePayment posts /payments. Amount, currency, reference, capture method and the checkout fields are signed into the returned pspSessionId, which is also the session's clientSecret — the browser reads the payload half to drive Adyen Web's own copy and cannot tamper with the amount.

      The shopper email Adyen asks for on Visa and JCB 3-D Secure 2 payments is receiptEmail, or billingDetails.email when there is none; both ride the signed context, whose payload half the browser can read. Refused with invalid_request, before the shopper enters a card, when the return URL is missing or malformed (see assertReturnUrl) or receiptEmail is not an address of at most 256 characters. A billingDetails.email like that is left out instead: billing details are optional data, withheld rather than failing the session.

      Parameters

      Returns Promise<PaymentSession>

    • 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>