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
| Parameter | Type |
|---|---|
options | ThreeDSChallengeOptions |
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',
},
});