Merchants can enforce 3-D Secure (3DS) authentication for payments made using a saved card token. This flow also supports token enablement on a new gateway (for example: BAFL → HBL token migration). This integration is used for:
- 3DS authentication on saved token payments
- Token enablement on a new gateway
- Token migration between gateways
Integration Flow
Follow these steps to integrate Token 3DS payments:
- Create a Payment Intent on your backend by passing the saved token ID.
- Return the
client_secretfrom your backend - Initialize the SDK on the client side
- Load the Token 3DS payment element
- Enable the Pay button when SDK is ready
- Call
confirmPayment()to trigger 3DS authentication
Step 1: Create Payment Intent (Server Side)
Before confirming a tokenized 3DS payment, your backend must first create a Payment Intent (PI).
There are two supported use cases depending on the payment flow.
Case 1: Standard Token 3DS Authentication
Use this flow when you only want to perform 3DS authentication for an existing saved token.
Pass the token ID in the request payload:
{
"token":"xpay_tok_xxxxxxxxxxxxxxxx"
}Case 2: Token Enablement on New Gateway (Migration)
Use this flow when the same token is being used on a different/new gateway (for example: BAFL → HBL) and the token needs to be re-enabled.
Pass the metadata.reason = "token" key-value pair along with the token ID in the payload:
{
"token":"xpay_tok_xxxxxxxxxxxxxxxx",
"metadata": {
"reason":"token"
}
}Step 2: SDK Integration (Client Side)
After creating the Payment Intent:
- Return the
client_secretfrom your backend - Initialize the SDK
- Load the Token 3DS payment element
- Call
confirmPayment()to start the 3DS authentication flow
Web SDK
For Token 3DS payments, set the paymentMethods value to ["token_3ds"] while initializing the SDK.
Use Web SDK v4.
SDK URLs
Production: https://js.xstak.com/v4/xpay.js
Staging: https://js.xstak.com/v4/xpay-stage.jsThe SDK will:
- Display only the CVC field for saved cards
- Automatically handle the 3DS authentication flow
- Complete payment confirmation after successful authentication
Initialize SDK
const options = {
override: true,
paymentMethods: ["token_3ds"],
fields: {
cvc: {
placeholder: "CVC",
},
},
style: {
".input": {
"border": "1px solid black",
"border-radius": "15px"
},
".invalid": {},
".label": {
"font-size": "18px"
},
".input:focus":{},
":focus": {},
":hover": {},
"::placeholder": {},
"::selection": {},
},
};
Enable your Pay button using the SDK ready event.
Confirm Payment
Call confirmPayment() when the user submits the payment form.
Pass:
- Payment method type
client_secretreturned from backend- Customer object
- Encryption key
const { error, message }=await xpay.confirmPayment(
"card",
"clientSecret",
{ name:"" },
"encryptionKey"
);The SDK automatically performs the 3DS challenge and completes the payment if authentication succeeds.
Use "token_3ds" only when you want to force 3DS authentication for tokenized payments.
React Native SDK
Import the Package
// for production
import { XPayProvider, Token3dsPaymentElement } from '@xstak/xpay-element-react-native';
// for stagging
import { XPayProvider, Token3dsPaymentElement} from '@xstak/xpay-element-react-native-stage';Load Token 3DS Element
To enable token 3DS payments, wrap the Token3dsPaymentElement inside the XPayProvider. Use the required credentials from your XPay Dashboard, By this , the SDK will display only the CVC field for the saved card and automatically handle the 3DS authentication flow during payment confirmation.
Wrap Token3dsPaymentElement inside XPayProvider.
<XPayProvider xpay={{ publishableKey: '', hmacSecret: '', accountId: '' }}>
<Token3dsPaymentElement onReady={(data) => { setEnabled(data.complete); }} />
</XPayProvider>The SDK will:
- Display only the CVC field for saved cards
- Handle 3DS authentication automatically
- Enable payment confirmation after validation
Enable your Pay button using the onReady event value.
Confirm Payment
Call confirmPayment() when the user submits the payment form.
Pass:
client_secretreturned from backend
const confirmPayment = async () => {
try {
const { message, error } = await Token3dsPaymentElement.confirmPayment("client_secret_from_intent_api");
if (error) {
// Handle payment failure
console.log("Payment failed: ", message);
} else {
// Handle payment success
console.log("Payment successful: ", message);
}
} catch (e) {
// Handle unexpected exceptions
console.log("Payment Error: ", e);
}
};
The SDK automatically performs the 3DS challenge and completes the payment flow after successful authentication.
Flutter SDK
The SDK:
- Collects CVC for saved cards
- Triggers 3DS authentication automatically
- Handles the full payment confirmation flow
Install / Import SDK
Production
import'package:xpay_element_flutter/xpay_element_flutter.dart';Staging
import'package:xpay_element_flutter/xpay_element_flutter_stage.dart';Initialize Controller
final XPayElementController _controller= XPayElementController(
publicKey:'your_publishable_key',
hmacSecret:'your_hmac_secret',
accountId:'your_account_id',
);Render Token 3DS Widget
XPayToken3DSElementWidget(
controller: _controller,
onReady: (isReady) {
setState(() {
_isPayEnabled=isReady;
});
},
)Notes
- Only the CVC field is displayed for saved cards
onReadycontrols the Pay button state- Enable the Pay button only when
isReady == true
Confirm Payment
Call confirmPayment() using:
client_secretreturned from backend- Encryption keys returned from backend
finalresult = await _controller.confirmPayment(
clientSecret:'pi_client_secret_from_your_server',
encryptionsKeys: 'encryptionKeysFromServer',
);This step:
- Initiates payment confirmation
- Triggers the 3DS authentication flow
- Completes the tokenized payment flow automatically
Confirm Payment Response
The confirmPayment() response contains: