Skip to main content

threeDSChallenge

const threeDSChallenge: (options) => Promise<ThreeDSFrameResult>;

Renders a 3DS challenge in an iframe inside your checkout and resolves when the cardholder is done.

The challenge is shown in-context: the iframe goes into the container you provide, sized per the EMVCo challengeWindowSize the authentication response echoed back. The SDK adds no overlay, no dialog and no styling of its own — the surrounding UI is yours.

Completion is a postMessage from the page the flow lands on, which is why completion.origins is required: only those exact origins can end the wait. A message from anywhere else is ignored.

Note the challenge outcome is authoritative server-side. Whatever this resolves with, confirm the payment through your backend before fulfilling: an abandoned or timed-out challenge is settled server-side too, so status: 'timeout' does not mean the payment failed.

Parameters

ParameterType
optionsThreeDSChallengeOptions

Returns

Promise<ThreeDSFrameResult>

Always resolves. status is completed, timeout or aborted.

Throws

SdkError If the input is invalid. Possible errors include:

Error Code
THREEDS_INVALID_URL
THREEDS_INVALID_INPUT
CONTAINER_NOT_FOUND

Examples

EMVCo challenge, from the authentication response

const { status, data } = await threeDSChallenge({
acsUrl,
creq,
challengeWindowSize, // pass through — EMVCo requires the announced size
container: 'checkout-3ds-slot',
completion: { origins: ['https://api.purse.tech'] },
});

A provider posting the result back through your own return page

await threeDSChallenge({
url: stepUpUrl,
fields: { JWT: accessToken, MD: merchantData },
container: challengeSlot,
size: { width: '100%', height: '600px' },
completion: {
origins: [window.location.origin],
match: (data) => (data as { MessageType?: string }).MessageType === 'stepUpComplete',
},
});

See

SecureFieldsErrors