PayFanout API reference
    Preparing search index...

    Implements

    Index
    pspName: "payzen" = PAYZEN_PSP_NAME
    • Stops PSP-side billing via Subscription/Cancel (immediate termination — installments already in flight are NOT cancelled; use cancelPayment on the individual transaction for those). The composite key rule of retrieveNativeSubscription applies: savedPaymentMethodToken is required.

      The Cancel answer is a bare Common/ResponseCodeAnswer (0 terminated, 30 token not found, 32 subscription not found, 99 undefined error), so the returned record always comes from a follow-up Subscription/Get. Verified-idempotent: on ANY rejection — nonzero responseCode or an ERROR envelope such as PSP_033/PSP_564 (already cancelled) — the adapter re-reads the subscription and resolves successfully when it is already terminated; only a subscription that is genuinely still billing surfaces the rejection. Replaying this call is therefore always safe, which is also why it is the one mutating PayZen call that keeps automatic transport retries. idempotencyKey has no PayZen channel to ride; replay safety comes from this verification, not from dedupe.

      Returns Promise<NativeSubscriptionRecord>

    • Manual capture = Transaction/Validate: it confirms an AUTHORISED_TO_VALIDATE transaction for capture on its expected date. Transaction/Capture is NOT this operation — it is a Brazil-specific batch WS and must never be used here. Validation releases the full authorized amount; PayZen has no partial validate, so a differing amount is rejected. The required idempotencyKey cannot be delegated — PayZen has no idempotency channel — but replays are naturally safe: validating twice yields a status error, never a duplicate capture.

      Parameters

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

      Returns Promise<PaymentInfo>

    • Creates a PSP-native subscription via Charge/CreateSubscription: the gateway itself schedules, charges, and retries every installment against the vaulted savedPaymentMethodToken (a PayZen paymentMethodToken; for SEPA direct debits the mandate reference, which PayZen requires to start

      = 14 days out). Installment outcomes arrive as ordinary transaction IPNs on the existing webhook path — enable the Back Office rule "Notification URL when creating a recurring payment".

      Cadence: interval/intervalCount synthesize an RFC 5545 RRULE (day/week/month/year are all accepted — PayZen rejects only sub-daily periods); schedule passes a host RRULE through after validation and is sent in PayZen's documented RRULE:-prefixed form. startAt becomes effectDate (normalized to PayZen's 25-character ISO 8601 UTC shape); when omitted the adapter's clock supplies "now" because effectDate is a REQUIRED field. merchantRefNum rides the dedicated orderId field. pspCustomerId is withheld (PayZen keys subscriptions by token, not by a customer object) and planId is rejected — the platform has no plan/price model to bill from.

      Replay safety: PayZen has no idempotency channel and creation applies IMMEDIATELY (unlike a formToken, a subscription is a live billing schedule), so this call is never transport-retried and a replayed create CAN create a second active subscription. The deterministic orderId (derived from idempotencyKey unless merchantRefNum is set) and the payfanout_key metadata stamp make duplicates visible in the Back Office and on installment IPNs, but there is no API to look a subscription up by orderId — never blind-retry this call; reconcile first. RETAIN the returned record's id together with the token: they form the composite key every later retrieve/cancel needs.

      Returns Promise<NativeSubscriptionRecord>

    • Two session shapes, routed by the requested payment method types:

      • Embedded (default, card/wallet types): Charge/CreatePayment → formToken (the client secret the krypton form mounts with). No transaction exists until the shopper pays, and the formToken expires after ~15 minutes — sessions are cheap to re-create.
      • Hosted redirect (any bank-rail type): Charge/CreatePaymentOrder → paymentURL (the client secret the client adapter redirects to). See createHostedPaymentSession.

      PayZen has no idempotency mechanism, so the adapter synthesizes traceable replays: orderId derives deterministically from the idempotencyKey and the key is stamped into metadata. A replayed call mints another formToken (or payment order) for the SAME orderId — harmless (no money moves until the shopper completes) and reconcilable via Order/Get.

      Parameters

      Returns Promise<PaymentSession>

    • PayZen has NO refund idempotency: a replayed Transaction/Refund creates a SECOND credit while the total stays within the original, and the refund request carries no metadata/reference field the adapter could pre-check against (idempotencyKey cannot be delegated OR reliably synthesized). Consequences, deliberately encoded here:

      • refund calls are never transport-retried, and their transport failures surface retryable: false (a lost response may mean the credit exists);
      • hosts must not blind-retry refunds — re-read the payment (amountRefunded) before trying again.

      Partial refunds go to Transaction/Refund (requires a captured source). Full refunds go through Transaction/CancelOrRefund AUTO, which cancels a not-yet-captured transaction instead — the result is mapped honestly (a cancellation releases the authorization; the shopper was never charged, so the refund "succeeded").

      Parameters

      Returns Promise<RefundResult>

    • Accepts either a transaction uuid (32-hex, from webhooks/refunds) or a PayFanout pspSessionId (= the derived orderId): the krypton form creates the transaction in-browser, so right after checkout the host may only hold the orderId. The orderId path reads the order and reports its most recent payment (DEBIT) attempt.

      Parameters

      • pspPaymentId: string

      Returns Promise<PaymentInfo>

    • "Test connection" probe: one single-shot, side-effect-free Charge/SDKTest call — PayZen's purpose-built connection test, which just echoes the submitted value back on valid credentials. Transport retries are disabled so a transient failure surfaces promptly instead of replaying (a "Test connection" click must not hang for multiples of the timeout). PayZen selects TEST vs LIVE by the key set, so the probe body carries no mode. The outcome is classified so a host UI can tell a wrong shopId/password (auth) from a transient outage (network); it resolves on every path instead of throwing, and never surfaces the credential.

      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>