3DS Challenge Element
Mount the issuer 3DS challenge returned by a card operation and resolve the flow on its outcome.
Before You Start
Read the following guides before proceeding:
| Guide | Why |
|---|---|
| PCI Compliant SDK | Isolation model and package map |
| SDK Setup | CSP entry for the 3DS orchestrator origin |
| Top-Up Transfer | The operation that returns three_ds_state |
Overview
@wirexapp/card-3ds-web mounts the 3DS step-up challenge an issuer demands during a card operation. The
challenge is a Wirex-hosted orchestrator page rendered in an iframe; the package owns the message handling
around it — origin verification, protocol parsing and once-only resolution.
No cardholder data passes through your page at any point of the 3DS step. The package depends on nothing
else in the SDK and does not use the frame origin.
This element runs the issuer challenge for an operation your application initiated, such as a card
top-up debit. It is not the in-app approval flow for transactions made on an issued Wirex card — that
flow is webhook-driven and documented in 3DS Authentication.
When You Need It
API operations that can require a step-up return a challenge URL when the issuer demands one. Card top-up
execute returns it as three_ds_state.url:
{
"id": "d4e5f6a7-b8c9-0123-def4-567890123456",
"status": "Pending",
"three_ds_state": {
"flow": "challenge",
"provider": "checkout",
"status": "pending",
"status_reason": "authentication_required",
"url": "https://3ds.example/challenge?session_token=abc123"
}
}Run the challenge when three_ds_state.url is present. When three_ds_state is absent, no step-up is
required and the operation proceeds.
Mount the Challenge
import { createThreeDsChallenge } from '@wirexapp/card-3ds-web';
const challenge = createThreeDsChallenge({
url: execute.three_ds_state.url,
onComplete: status => finishTopUp(status),
onError: message => {
showToast(message);
finishTopUp('Failed');
},
onLoad: () => hideSpinner(),
title: '3DS Verification',
});
challenge.mount(document.querySelector('#threeds-container'));
// When the user cancels from your own UI:
challenge.destroy();| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Challenge URL from the API response. Must be https:// |
onComplete | (status: string) => void | Yes | The orchestrator finished with a status |
onError | (message: string) => void | Yes | The step-up failed before producing a status. The message is safe to display |
onLoad | () => void | No | The iframe document finished loading |
title | string | No | Accessible iframe title. Default 3DS Verification |
onComplete and onError fire exactly once. Mounting an element twice throws
ThreeDsChallenge is already mounted.
Outcome Statuses
onComplete receives the backend's status string, matched case-insensitively.
| Status | Meaning | Action |
|---|---|---|
Completed | The step-up succeeded | Continue the flow to its settled outcome |
Pending | The outcome is not yet known | Reconcile from the activity feed or webhooks |
Failed | The step-up failed | Report the failure to the user |
Treat any other value as unknown and direct the user to their activity feed. A step-up outcome is not the
final state of the operation — the operation's own status and its webhooks own that.
Sizing and Cancellation
- The iframe fills its container at 100% width and height. Give the container explicit dimensions; issuer
challenge pages are commonly designed for 500×480 pixels or larger. - Render a light background behind the iframe. Many issuer pages assume a light container.
- Cancel and back navigation are yours. Render your own control and call
destroy().
Treat a user-cancelled challenge as
Pending, notFailed. The operation can still complete after
the challenge iframe is removed. Reconcile from your activity feed or webhooks rather than reporting a
failure to the user.
What the Element Enforces
- Messages are accepted only from the challenge URL's HTTPS origin and only from the exact iframe the
element created. Messages from any other frame or origin are ignored. - A challenge URL that is not parseable or not
https://fails throughonErrorwith
3DS verification URL is invalid, and no message listener is attached. - A
stepUp.completemessage carrying no status fails throughonErrorwith
3DS verification returned no status. - An enrollment error riding inside an otherwise-successful message is detected and surfaced through
onErrorwith the backend's reason.
Content Security Policy
The orchestrator page is served by a Wirex backend origin, not by the card-frame origin. Add that origin —
named in your onboarding pack — to frame-src alongside the frame origin. See
SDK Setup.
Updated 15 days ago

