Dependencies
react: provides state and context management.react-native: provides native UI components used to build the screens.uuid: creates unique identifiers.jose: used for cryptographic operations.react-native-device-info: retrieves device metadata.react-native-webview: displays the 3DS web view.react-native-localize: provides localization support.react-native-network-info: retrieves the device's IP address.react-native-quick-crypto: used for cryptographic operations.react-native-get-random-values: provides random value generation for crypto.@react-native-async-storage/async-storage: persistent storage for app identifiers.@react-native-community/checkbox: renders checkboxes for the UI.@react-native-picker/picker: renders dropdown lists for form fields.react-native-device-info-bridge: bridge for collecting device information.react-native-ecdh-bridge: bridge for generating ephemeral key pairs and encryption.
NuveiProvider
Overview
Purpose - NuveiProvider is a context provider that manages and shares payment state and callbacks across the SDK.
It centralizes data such as the current nvPaymentMerchantSettings, merchant settings, card details, internationalization (i18n) preferences, and navigation handlers for web views.
Where it is used - NuveiProvider wraps the main part of the application that requires access to Nuvei payment configuration and state.
Behavior
- Stores the active
nvPaymentMerchantSettingsand merchant configuration. - Manages the success and failure callbacks for Simply Connect.
- Holds i18n fields for localization.
- Provides a navigation handler to open web views dynamically.
- Shares default card details for convenience and auto-fill behavior.
- Configures the SDK environment (STAGING or PROD).
- Manages global card blocking rules via
blockCards. - Wraps and integrates additional providers:
_3DS2ServiceContextProvider,PayServiceContextProvider, andPaymentScreenContextProvider.
What the context does
NuveiProvider serves as a central controller for the payment SDK’s state management and callbacks.
Responsibilities
- Manage global state for:
nvPaymentMerchantSettings: current merchant transaction information.merchantSettings: merchant’s checkout and payment configuration.defaultCardDetails: card info.simplyConnectI18NSettings: localization data for Simply Connect screens.
- Store callback references for:
simplyConnectOnSuccess: executed when a Simply Connect operation succeeds.simplyConnectOnFail: executed when a Simply Connect operation fails.navigateToWebview: handles custom navigation to web views.
- Provide setter functions for all of the above.
- Configure global SDK settings:
environment: sets the API environment (STAGING or PROD).blockCards: array af string arrays ([string[]]), where each inner array combination of values to be checked in getCardDetails() and blocked if all exist.
- Ensure that payment and UI-related contexts (
_3DS2ServiceContextProvider,PayServiceContextProvider,PaymentScreenContextProvider) are properly nested and have access to shared data.
Data structure
Request
type ContextType = {
nvPaymentMerchantSettings: NvPaymentMerchantSettings | null;
setNvPaymentMerchantSettings: (value: NvPaymentMerchantSettings) => void;
simplyConnectOnSuccess: (response?: unknown) => void;
setSimplyConnectOnFail: (callback: (error: any) => void) => void;
simplyConnectOnFail: (error: any) => void;
setSimplyConnectOnSuccess: (callback: () => void) => void;
simplyConnectI18NSettings: i18NFieldsType | null;
setSimplyConnectI18NSettings: (value: i18NFieldsType) => void;
setNavigateToWebView: (callback: (webViewParams: any) => void) => void;
navigateToWebview: (webViewParams: any) => void;
merchantSettings: useCheckoutSettingsType | null;
setMerchantSettings: (value: useCheckoutSettingsType) => void;
defaultCardDetails: DefaultCardDetails;
setDefaultCardDetails: (value: DefaultCardDetails) => void;
environment: EnvironmentEnum;
blockCards: BlockCardsType[] | null;
};
NuveiProvider Props
type NuveiProviderPropsType = {
children: ReactNode;
environment?: EnvironmentEnum;
blockCards?: BlockCardsType[];
};
Key functions
nvPaymentMerchantSettings, setNvPaymentMerchantSettings(value)
- Stores and updates the current active merchant and transaction settings data.
- The
NvPaymentMerchantSettingscontains amount, currency, sessionToken, and merchant identifiers.
simplyConnectOnSuccess, setSimplyConnectOnSuccess(callback)
simplyConnectOnSuccessholds the callback executed after a successful Simply Connect eventsetSimplyConnectOnSuccessregisters a new callback function dynamically.
simplyConnectOnFail, setSimplyConnectOnFail(callback)
simplyConnectOnFailholds the callback executed when Simply Connect fails.- Accepts an error object with optional
errorCodeand areasonmessage.
simplyConnectI18NSettings, setSimplyConnectI18NSettings(value)
- Manages the localization fields (labels, text, and translations) used by Simply Connect.
- Can be updated to change the current language dynamically.
navigateToWebview, setNavigateToWebView(callback)
navigateToWebviewstores a callback for handling navigation to a web view.setNavigateToWebViewreplaces the current navigation function.
merchantSettings, setMerchantSettings(value)
- Holds the merchant’s configuration.
defaultCardDetails, setDefaultCardDetails(value)
- Stores default cardholder data:
cardHolderNamecardNumberCVVexpirationYearexpirationMonth
environment
- Sets the SDK environment. Available values are
EnvironmentEnum.STAGINGandEnvironmentEnum.PROD. - When set, it automatically calls
setGlobalEnvironmentto update the base URL for API requests.
blockCards
- An optional array of card BINs or identifiers that should be blocked across the SDK.
- These rules are respected by validation hooks and components like
NuveiFieldsto prevent users from proceeding with blocked cards.
Integration
All components that Context contains are exported in index.ts
export * from './Context'
Error handling
- Callback setters (
setSimplyConnectOnFail,setSimplyConnectOnSuccess, etc.) should always be initialized before triggering their corresponding actions. - Components using the context should validate data before use:
const simplyConnectOnFail = useRef<
(error: { errorCode?: number; reason: string }) => void
>(() => { });
Diagram and description
flowchart TD
id1[Create global state] ==> id2[Expose callbacks]
id2 ==> id3[Provide context]
id3 ==> id4[Wrap children]
id4 -.-> id5([3DS2ServiceContext]) & id6([PayServiceContext])
classDef bold font-weight:bold;
class id1,id2,id3,id4,id5,id6 bold;
Context (NuveiProvider) is the root provider for thе SimplyConnect payment. It stores global payment configuration such as:
- The current merchant and transaction settings.
- Merchant settings.
- Internationalization (i18N).
- Default card form values.
- Merchant callbacks (onSuccess / onFail).
- Custom error messages.
It also wraps all children with:
- 3DS2ServiceContextProvider;
- PayServiceContextProvider;
This ensures all payment logic — 3DS2 validation, authentication, card flow, and errors — is available everywhere.
⭐ Simple explanation:
Context is the “global storage” for the entire payment. Everything depends on it.
- Initialize the global payment state
The provider initializes multiple values:
const [nvPaymentMerchantSettings, setNvPaymentMerchantSettings] = useState<NvPaymentMerchantSettings | null>(null);
const [merchantSettings, setMerchantSettings] = useState(null);
const [defaultCardDetails, setDefaultCardDetails] = useState({...});
const [customNuveiFieldsCardNumberError, setCustomNuveiFieldsCardNumberError] = useState('');
const [simplyConnectI18NSettings, setSimplyConnectI18NSettings] = useState(null);
📌 Important:
All payment screens rely on the objectnvPaymentMerchantSettings. If it is not set, the payment UI cannot function.
- Store success/failure callbacks using useRef
const simplyConnectOnSuccess = useRef<() => void>(() => {});
const simplyConnectOnFail = useRef<(error) => void>(() => {});
useRef ensures the callback always points to the latest merchant-provided handler.
These callbacks allow the merchant to react to:
- Successful payments.
- Failed / declined payments.
💡 Useful:
Using useRef avoids re-rendering the entire payment UI when callbacks change.
- Expose setter functions for callbacks
const setSimplyConnectOnSuccess = (callback: () => void) => {
simplyConnectOnSuccess.current = callback;
};
const setSimplyConnectOnFail = (
callback: (error: { errorCode?: number; reason: string }) => void
) => {
simplyConnectOnFail.current = callback;
};
This helps to configure:
- What happens on payment success.
- What happens on payment failure.
- Provide all values through Context.Provider
<Context.Provider value={{
nvPaymentMerchantSettings,
setNvPaymentMerchantSettings,
setSimplyConnectOnFail,
setSimplyConnectOnSuccess,
simplyConnectOnSuccess: simplyConnectOnSuccess.current,
simplyConnectOnFail: simplyConnectOnFail.current,
simplyConnectI18NSettings,
setSimplyConnectI18NSettings,
merchantSettings,
setMerchantSettings,
defaultCardDetails,
setDefaultCardDetails,
customNuveiFieldsCardNumberError,
setCustomNuveiFieldsCardNumberError,
}}>
All nested components can now access this state using:
useNuveiContext();
📌 Important:
This is the global data source for the whole payment flow. Missing it breaks everything.
- Wrap children with additional providers
<3DS2ServiceContextProvider>
<PayServiceContextProvider>{props.children}</PayServiceContextProvider>
</3DS2ServiceContextProvider>
This setup creates a nested provider hierarchy:
- Context – global configuration;
- 3DS2ServiceContext – handles 3DS2 flows;
- PayServiceContext – handles initAuth3D, payload, and payment responses;
⭐ Recommendation:
Provider nesting should be kept in this order — payment logic depends on the upper layers.
⚠️ Warning:
Reordering these providers may cause 3DS2 flows or authentication to break unexpectedly.
3DS2ServiceContext
Overview
Purpose - _3DS2ServiceContextProvider manages and shares the 3D Secure v2 (3DS2) helper functions and data across the app.
It creates 3DS2 transactions that include device data and ephemeral keys.
Where it is used - Wraps the parts of the app that need 3DS2 transactions. Other components/hooks read the shared service context with use3DS2ServiceContext().
Behavior
-
Stores a service object (
_3DS2Service) with initialization state, public keys, UI customization and config parameters. -
Uses
initialize(configParams, uiCustomization)to register directory server info and mark the service as ready. -
Exposes
createTransaction(directoryServerID, messageVersion)to:- collect device info,
- encrypt device info for the directory server,
- generate an ephemeral EC key pair,
- return a
Transactionobject ready for the next 3DS step.
-
Keeps an app ID in persistent storage (AsyncStorage) and generates it once per device.
What the context does
_3DS2ServiceContextProvider is a shared layer for 3DS2 flows.
Responsibilities
-
Accepts and stores configuration about the Directory Server (DS) such as DS id, public key, algorithm via
initialize(). -
Keeps
isInitializedflag and adsPublicKeysmap. -
Provides the following functions:
initialize(configParams, uiCustomization)— registers DS info and UI customization.createTransaction(directoryServerID, messageVersion)— builds a transaction object.use3DS2ServiceContext()— hook to access service and functions.
Data structure
Request
Service type
export type _3DS2Service = {
isInitialized: boolean;
dsPublicKeys: Map<String, any>;
uiCustomization?: any;
configParams?: ServiceConfigParams;
};
Transaction
export type Transaction = {
directoryServerID: string;
dsPublicKey: any;
deviceData: string | undefined;
appId: string;
sdkReferenceNumber: string;
messageVersion: string;
uiCustomization: any;
configParameters: ServiceConfigParams | undefined;
sdkEphemeralPublicKey: string;
transactionID: string;
counterStoA: number;
challengeKeys: {
sdkJwk: JWK;
sdkReferenceNumber: string;
};
};
Key functions
initialize(configParams, uiCustomization)
- Checks for current service and if the service is initialized, logs error and returns undefined
- What it does:
- Reads keys from
configParamslikeDS@@@ID,DS@@@KEY,DS@@@ALG,DS@@@ROOT_CA,DS@@@ROOT_CA_ALG. - Determines algorithm type (RSA or EC).
- Stores a
dsPublicKeyobject inservice.current.dsPublicKeys. - Stores
uiCustomizationandconfigParamsin the service. - Sets
service.current.isInitialized = true.
- Reads keys from
getOrGenerateAppId()
- Ensures a unique app id exists for the app.
- What it does:
- Tries to read
APP_ID_KEYfrom AsyncStorage. - If the id is missing, generates a new id using UUID (
uuidv4()), stores it and returns it.
- Tries to read
- Used by
createTransaction()to get appId.
createTransaction(directoryServerID, messageVersion)
- Creates a 3DS2 transaction object.
- Steps:
- Checks if service is initialized.
- Validates
directoryServerIDandmessageVersion. - Checks if
messageVersionis supported (fromsupportedVersions). - Verifies DS public key info using
service.current.dsPublicKeys. - Collects device info via
getDeviceInfo(sdkVersion). - Encrypts device info using
encrypt(deviceData, dsPublicKey, directoryServerID) - Generates an ephemeral key pair with
generateECKeyPair(). - Builds and returns a
Transactionobject with:sdkEphemeralPublicKey=sdkEphemeralKeyPair.publicchallengeKeys.sdkJwk=sdkEphemeralKeyPair.private- a new
transactionID(UUID)
- On error: logs an error and returns
undefined.
Integration
This context provider is imported in Context
import { _3DS2ServiceContextProvider } from './3DS2ServiceContext';
Error handling
initialize():- If called twice, it logs an error and returns without changing state.
- If required config is missing (like
DS@@@ID) it logs and returns.
createTransaction():- If the service is not initialized it logs:
"You must call initialize() first."and returnsundefined. - If
directoryServerIDormessageVersionis null or unsupported it logs and returnsundefined. - If DS public key cannot be found it logs and returns
undefined. - If device info encryption fails it logs the error and returns
undefined. - If generating ephemeral keys fails it logs the error and returns
undefined.
- If the service is not initialized it logs:
Diagram and description
flowchart TD
id1[Load service object] ==> id2["initialize(configParams, uiCustomization)"]
id2 ==> id3[Store]
id3 -.-> id4([DS public keys]) & id5([config]) & id6([uiCustomization])
id2 ===> id7[Call createTransaction]
id7 ==> id8[Validate input]
id8 ==> id9[Fetch or generate app Id]
id9 ==> id10[Collect device info and encrypt it]
id10 ==> id11[Generate EC ephemeral key pair]
id11 ==> id12[Create and return transaction object]
classDef bold font-weight:bold;
class id1,id2,id3,id4,id5,id6,id7,id8,id9,id10,id11,id12 bold;
3DS2ServiceContext manages the 3D Secure v2 (3DS2) setup and transaction creation. It is responsible for:
- Merchant configuration.
- Storing Directory Server (DS) public keys and settings.
- Managing the constant App ID.
- Collecting and encrypting device information.
- Generating EC ephemeral keys.
- Producing a Transaction object for the 3DS2 authentication flow.
This context is the 3DS2 logic layer used internally by the payment flow.
- The Provider is mounted
3DS2ServiceContextProvider is a wrapper for the app.
It creates a shared service instance:
const initialValue: _3DS2Service = {
isInitialized: false,
dsPublicKeys: new Map(),
};
First is created initialValue which is assigned to the service instance
const service = useRef<_3DS2Service>(initialValue);
💡 Info:
The service is stored inside useRef, so it never resets between renders.
- initialize(configParams, uiCustomization) is called
This is the entry point for loading 3DS2 configuration.
What the function does:
- Prevents double initialization.
- Reads the merchant’s DS configuration.
- Detects used algorithm.
- Saves the DS public key configuration into dsPublicKeys.
- Stores UI customization and config parameters.
⚠️ Important:
Initialization must happen before creating any transaction.
- App ID is created or retrieved
When creating a transaction, the app first ensures there is an App ID:
Checks AsyncStorage for App ID. If missing -> generates a unique ID (UUID) and saves it.
💡 Info:
The App ID uniquely identifies the device across 3DS2 flows.
- createTransaction(directoryServerID, messageVersion)
This is the main method used by the payment flow.
The method performs several steps:
-
Validate inputs:
- service must be initialized.
- Directory server ID must be provided.
- Version must be supported (2.1.0 or 2.2.0).
-
Collect device info:
- getDeviceInfo(sdkVersion) - gathers encrypted hardware & OS metadata required by the 3DS2.
-
Encrypt device info using DS public key:
- encrypt(deviceData, dsPublicKey, directoryServerID) - this returns encrypted device data.
⚠️ Warning:
If encryption fails the transaction cannot continue.
- Generate ephemeral EC key pair
A EC key pair is created and is sent to the server.
💡 Tip:
These keys exist only for the current transaction.
- Build the Transaction object:
export type Transaction = {
directoryServerID: string;
dsPublicKey: any;
deviceData: string | undefined;
appId: string;
sdkReferenceNumber: string;
messageVersion: string;
uiCustomization: any;
configParameters: ServiceConfigParams | undefined;
sdkEphemeralPublicKey: string;
transactionID: string;
counterStoA: number;
challengeKeys: {
sdkJwk: JWK;
sdkReferenceNumber: string;
};
};
This object is returned to the caller and used in the 3DS process.
PayServiceContext
Overview
Purpose - PayServiceContextProvider manages and shares the payment data and methods.
It provides a place to initialize the 3D Secure authentication (initAuth3D) and store the responses.
Where it is used - It wraps parts of the application that need access to payment and authentication data — the hooks useAuth3D and useNuveiFields.
Behavior
- Calls
sendInitAuth3D()to start a 3D Secure initialization. - Stores the response and payload for later use.
- Shares its data so that other hooks and components can easily access or update it.
What the context does
PayServiceContextProvider acts as a shared data layer for all payment logic.
Responsibilities
- Initialize 3D Secure authorization by calling
sendInitAuth3D(). - Store and update:
initAuth3DResponse— the result after starting 3DS.initAuth3DPayload— the request body that was sent.clientPaymentResponse— the result of the client payment.transaction— holds a transaction object.
- Provide setter functions to update all of the above.
- Make this data accessible to other parts of the SDK using
usePayServiceContext().
Data structure
Request
export type InitPaymentBody = {
currencyCode?: string;
amount?: string;
billingAddress?: {
country: string;
email: string;
address?: string;
city?: string;
state?: string;
zip?: string;
};
clientRequestId?: string;
countryCode?: string;
currency?: string;
googlePayGateway?: string;
googlePayGatewayMerchantId?: string;
googlePayMerchantId?: string;
googlePayMerchantName?: string;
merchantId?: string | number;
merchantSiteId?: string;
paymentOption: InitPaymentOptions;
requestTimeout?: number;
sessionToken: string;
timeout?: number;
userTokenId?: string;
webMasterId?: string;
deviceDetails?: DeviceDetails;
sourceApplication?: SourceApplication;
relatedTransactionId?: string;
};
Response
export type InitPaymentResponse = {
internalRequestId: number;
status: string;
errCode: number;
reason: string;
merchantId: string;
merchantSiteId: string;
version: string;
clientRequestId: string;
sessionToken: string;
orderId: string;
userTokenId: string;
transactionId: string;
transactionType: string;
transactionStatus: string;
gwErrorCode: number;
gwExtendedErrorCode: number;
paymentOption: {
card: {
ccCardNumber: string;
bin: string;
last4Digits: string;
ccExpMonth: string;
ccExpYear: string;
acquirerId: string;
ccTempToken: string;
threeD: ThreeD;
processedBrand: string;
};
};
customData: string;
result: string;
paymentMethodErrorCode?: number;
gwErrorReason?: string;
paymentMethodErrorReason?: string;
};
Key functions and variables
initAuth3D(paymentSettings, source, nvPaymentMerchantSettings)
- Asynchronously calls
sendInitAuth3D()to begin the 3D Secure process. - Parameters:
paymentSettings: contains merchant and payment configuration data.source: the request source (CHECKOUT,DIRECT,FIELDS).nvPaymentMerchantSettings: the merchant settings (containing amount, currency, sessionToken).
- On success:
- Stores both the
responseandpayloadreturned by the API. - Returns an object with
{ response, payload }.
- Stores both the
- On failure:
- Returns
undefined.
- Returns
initAuth3DResponse
- Holds the last response from the
initAuth3D()request. - Can be updated by calling
setInit3DResponse(response).
initAuth3DPayload
- Stores the payload that was sent during
initAuth3D()initialization.
clientPaymentResponse
- Keeps track of the client payment’s result after 3D Secure completion.
- Accessible to other components that need to check payment status.
Integration
import { PayServiceContextProvider } from './PayServiceContext';
return (
<Context.Provider
value={{
setNvPaymentMerchantSettings,
nvPaymentMerchantSettings,
setSimplyConnectOnFail,
setSimplyConnectOnSuccess,
simplyConnectOnSuccess: simplyConnectOnSuccess.current,
simplyConnectOnFail: simplyConnectOnFail.current,
simplyConnectI18NSettings,
setSimplyConnectI18NSettings,
setNavigateToWebView,
navigateToWebview: navigateToWebview.current,
merchantSettings,
setMerchantSettings,
defaultCardDetails,
setDefaultCardDetails
}}
>
<_3DS2ServiceContextProvider>
<PayServiceContextProvider>
<PaymentScreenContextProvider>
{props.children}
</PaymentScreenContextProvider>
</PayServiceContextProvider>
</_3DS2ServiceContextProvider>
</Context.Provider>
);
Error handling
- If
sendInitAuth3D()fails or returnsnull, the function stops and returnsundefined. - Components using this context should always check for a valid response before proceeding:
const result = await sendInitAuth3D(paymentSettings, nvPaymentMerchantSettings, source);
if (!result) {
return;
}
Diagram and description
flowchart TD
id1[initAuth3D] ==> id2[Call sendInitAuth3D]
id2 ==> id3[Receive response and payload]
id3 ==> id6[Store]
id6 -.-> id7([initAuth3DResponse])
id7 -.-> id8([initAuth3DPayload])
id3 ===> id9[Expose]
id9 -.-> id10([clientPaymentResponse])
id10 -.-> id11([transaction reference])
classDef bold font-weight:bold;
class id1,id2,id3,id4,id5,id6,id7,id8,id9,id10,id11 bold;
PayServiceContext manages the initialization phase of the 3D Secure flow. It sends the authentication request to the backend (initAuth3D), stores both the request payload and the backend response, keeps track of the client-side payment result, and exposes a shared transaction reference used later in the 3DS flow.
It is also responsible for storing the result of the backend request (response + payload) in a state so other components can read them at any time.
⭐ Simple explanation:
PayServiceContext is the starting point of the payment authentication process — it prepares and stores everything required before 3DS challenge can begin.
- Wrap payment-related screens inside PayServiceContextProvider
This makes the following data available everywhere in the payment flow:
- The InitAuth3D response from the backend.
- The InitAuth3D request payload/
- The client payment response after authentication.
- The transaction reference, used for 3DS operations.
- The initAuth3D() function that starts the backend request.
⚠️ Important:
Without this provider, no payment component can start 3DS — the authentication data won’t exist.
- Access global PayServiceContext data through the hook
export const usePayServiceContext = () => useContext(payServiceContext);
Where payServiceContext contains:
- initAuth3DResponse;
- setInit3DResponse;
- initAuth3D;
- clientPaymentResponse;
- setClientPaymentResponse;
- initAuth3DPayload;
- setInit3DPayload;
- transaction;
Each field provides part of the 3DS initialization.
💡 Tip:
initAuth3D() it's triggered automatically when the user selects a payment method.
- Calling initAuth3D() to start the backend authentication request
initAuth3D(paymentSettings, nvPaymentMerchantSettings, source) sends the first request to the backend to begin the 3D Secure flow.
const result = await sendInitAuth3D(paymentSettings, nvPaymentMerchantSettings, source);
The arguments used in sendInitAuth3D contain the following values:
- paymentSettings -> merchant configuration;
- nvPaymentMerchantSettings -> total amount, currency, sessionToken;
- source -> where the request came from;
⚠️ Important:
If this request fails, the entire 3DS2 payment flow stops immediately.
- Validate backend response
If the backend returns nothing:
if (!result) return;
Nothing is stored and the payment cannot continue.
- Store InitAuth3D response and payload
When the backend returns data:
setInit3DResponse(result.response); setInit3DPayload(result.payload);
This data includes:
- Transaction info.
- Fields needed for challenge.
💡 Useful:
Storing both the response and the payload ensures that nested components always have the exact data the backend sent.
- Expose and update clientPaymentResponse
The context exposes:
clientPaymentResponse setClientPaymentResponse(...)
This value is set after WebView payment completes and the final result is known.
⭐ Recommendation:
clientPaymentResponse is used to determine if the user should be navigated to a “success”, “fail”, or “loading” page.
- Shared transaction reference
const transaction = useRef(null);
This is used to store transaction-specific data that must be contained across in other components.
💡 Tip: Because it’s a useRef, the value is a constant even if the component re-renders multiple times.
- The context provides everything to all children
<payServiceContext.Provider value={{ ... }}>
{children}
</payServiceContext.Provider>
Any nested payment component can now:
- Start 3DS initialization.
- Access the backend data.
- Access the transaction reference.
- Store client responses.
3D Secure
Description
3D Secure provides the full logic and tools required to run 3D Secure v2 (3DS2) and 3D Secure v1 (3DS1) authentication in a checkout. It ensures a secure verification process.
This module consists of two primary parts:
useAuth3D- this hook organises the complete 3D authentication for a card payment. It is typically used inside checkout screens or anywhere a card payment needs to be confirmed.useGetAuth3DPayload- this hook is responsible for preparing and constructing the 3DS2 payload required for the authentication request. It is used before triggering a client payment that requires a 3DS2 challenge.
3DAuth
Overview
Purpose - useGetAuth3DPayload and its related functions manage the initialization and preparation of the 3D Secure v2 (3DS2) authentication flow for card payments.
It is responsible for:
- Preparing and structuring the 3DS2 payload
- Initializing a 3DS2 transaction through the SDK service.
- Building and returning a fully configured payload
useGetAuth3DPayload is typically used before initiating a client payment or challenge flow.
Where it is used - Inside payment and checkout flows where a card payment requires 3DS2 authentication.
The returned payload is passed to the payment API call (doClientPayment or doClientAuth3D), which then either completes frictionless or initiates a challenge.
Behavior
- Reads
threeDconfiguration from theInitPaymentResponse. - Checks if 3DS2 is supported (
v2Supported). - If not supported -> falls back to 3DS v1 flow.
- If supported:
- Parses the Directory Server (DS) public key and algorithm.
- Initializes a 3DS2 transaction using the SDK service.
- Builds the object required for the authentication request.
- Adds to the request browser details and challenge window size.
- Returns the final payload and server transaction ID for the next step in the payment process.
What the hook does
- Retrieves 3DS2 directory server data (ID, public key, algorithm).
- Initializes a 3DS2 transaction through
use3DS2ServiceContext. - Gathers browser and device information (screen size, locale, user agent, IP address, timezone).
- Constructs and returns the final 3DS2 payload to be sent with the payment request.
- Supports force web challenge mode (used when the merchant wants to handle challenges in a webview).
Data structure
Request
export type ChallengeParameters = {
threeDSServerTransactionID: string;
acsTransactionID: string;
acsRefNumber: string;
acsSignedContent: string;
threeDSRequestorAppURL: string;
};
export type CReq = {
threeDSRequestorAppURL: string;
threeDSServerTransID: string;
acsTransID: string;
challengeCancel: string;
challengeDataEntry: string;
challengeHTMLDataEntry: string;
challengeNoEntry: string;
challengeWindowSize: string;
messageExtension: string;
messageType: string;
messageVersion: string;
oobContinue: string;
resendChallenge: string;
sdkTransID: string;
sdkCounterStoA: string;
whitelistingDataEntry: string;
};
export type InitPaymentBody = {
currencyCode?: string;
amount?: string;
billingAddress?: {
country: string;
email: string;
address?: string;
city?: string;
state?: string;
zip?: string;
};
clientRequestId?: string;
countryCode?: string;
currency?: string;
googlePayGateway?: string;
googlePayGatewayMerchantId?: string;
googlePayMerchantId?: string;
googlePayMerchantName?: string;
merchantId?: string | number;
merchantSiteId?: string;
paymentOption: InitPaymentOptions;
requestTimeout?: number;
sessionToken: string;
timeout?: number;
userTokenId?: string;
webMasterId?: string;
deviceDetails?: DeviceDetails;
sourceApplication?: SourceApplication;
relatedTransactionId?: string;
};
Response
export async function doClientPayment(body: InitPaymentBody) {
if (body.paymentOption.card?.cardNumber) {
body.paymentOption.card.cardNumber = body.paymentOption.card.cardNumber
.split(' ')
.join('');
}
try {
const response = await fetch(`${API_BASE_URL_V1}websdk/clientPayment.do`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
return await response.json();
} catch (error: any) {
return error;
}
}
export async function doClientAuth3D(body: InitPaymentBody) {
try {
const response = await fetch(`${API_BASE_URL_V1}clientAuthorize3d.do`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
return await response.json();
} catch (error: any) {
return error;
}
}
export type InitPaymentResponse = {
internalRequestId: number;
status: string;
errCode?: number;
reason: string;
merchantId: string;
merchantSiteId: string;
version: string;
clientRequestId: string;
sessionToken: string;
orderId: string;
userTokenId: string;
transactionId: string;
transactionType: string;
transactionStatus: string;
gwErrorCode?: number;
gwExtendedErrorCode: number;
paymentOption: {
card: {
ccCardNumber: string;
bin: string;
last4Digits: string;
ccExpMonth: string;
ccExpYear: string;
acquirerId: string;
ccTempToken: string;
threeD: ThreeD;
processedBrand: string;
};
};
customData: string;
result: string;
paymentMethodErrorCode?: number;
gwErrorReason?: string;
paymentMethodErrorReason?: string;
};
Key functions
getNotificationURL(sessionToken: string, isCreatePayment: boolean)
- Builds the notification URL for 3DS2 callbacks after challenge completion.
- Used when
forceWebChallengeis enabled.
useInit3DS2Transaction()
- Initializes a new transaction with the 3DS2 SDK.
- Returns both
transactionandsdkmetadata required for the authentication request.
getDirectoryServerPublicKeyAlg(directoryServerPublicKeyAndAlg: string[])
- Validates and extracts the algorithm from the directory server public key.
getAuthRequestParams(transaction: Transaction)
- Builds SDK authentication parameters (ephemeral key, reference number, transaction ID, ..).
filterClientAuthorize3d(threeD: ThreeD)
- Lists only the fields required by the backend during client authorization to keep the payload minimal and secure.
getScreenSizeLabel(width: number, height: number)
- Maps screen dimensions to one of the standard 3DS2 challenge window size labels:
01: 250x40002: 390x40003: 500x60004: 600x40005: Full screen
getTimezoneOffsetInHours()
- Calculates the client timezone offset
Integration
import { useGetAuth3DPayload } from '../utils/3DAuth.ts';
Error handling
- If
payServiceContextor_3DSContextisnull-> returns nothing (log error). - If directory server public key or algorithm is missing / invalid -> returns
ERROR_CODES.INTERNAL_ERROR. - If transaction initialization fails -> returns
ERROR_CODES.INTERNAL_ERROR. - If 3DS2 is not supported (
v2Supported === false) -> returns original payment body for v1 fallback. - If required SDK fields are missing -> challenge flow will not start and an error is returned.
Diagram and description
flowchart TD
id1[Init 3DS2 Service] ==> id2[Create transaction]
id2[Build Auth3D Payload] ==> id3[Send Challenge Req]
id3 ==> id4[Handle ASC Challenge]
id4 ==> id5[Recieve Challenge Res]
id5 ==> id6[Compplete Payment/Verify]
classDef bold font-weight:bold;
class id1,id2,id3,id4,id5,id6 bold;
The 3DAuth component is responsible for the 3D Secure v2 (3DS2) authentication inside the payment flow. It handles:
- Initializing 3DS2.
- Creating a 3DS transaction.
- Preparing the Auth3D payload.
- Launching the Challenge (CReq).
- Decrypting ACS responses.
- Running the challenge loop until completion.
- Finishing the payment or verification.
⭐ Explanation:
This component is a bridge between the app, the cardholder device, the Directory Server (DS), and the ACS (bank).
- Initializing the 3DS2 Service
The function useInit3DS2Transaction() performs:
- Loading Directory Server (DS) IDs.
- Loading the DS public key.
- Preparing configuration.
- Creating UI customizations for the challenge screens.
⚠️ Warning:
If the DS public key or algorithm is not valid, the entire 3DS2 process will stop — this is required for security.
💡 Tip: The public key and algorithm always should be passed together. Missing fields cause errors.
- Creating a Transaction
After initialization, it is generated:
- transactionID.
- sdkEphemeralPublicKey.
- Device metadata.
- Message version.
- Building the Auth3DPayload
The function useGetAuth3DPayload():
- Reads the card’s 3D configuration.
- Detects if 3DS2 is supported.
- Merges payloads from:
- The backend (server data).
- The SDK (device data).
- The app (screen size, language)
- Sending CReq (Challenge Request)
The function useDoChallenge() prepares the CReq message:
- Builds the JSON payload.
- Encrypts it using the ephemeral public key.
Sends it to the ACS URL
- Handling the ACS Challenge
The ACS responds with CRes:
- May request user interaction (OTP, PIN, biometrics).
- May be automatic (frictionless).
💬 Tip:
The component retries challenge steps and updates transaction counters (sdkCounterStoA) automatically.
- Receiving the Challenge Result (CRes)
The ACS response may indicate:
- Finalized challenge (success/failure).
- More challenge steps required.
- Protocol error.
- Runtime errors.
executeChallenge() validates:
- Message type.
- Challenge completion indicator.
- Completing the Payment / Verification
After challenge completion, useHandle3d2Challenge() decides:
- If the flow is a payment, call doClientPayment.
- If it's a card verification, call doClientAuth3D.
Finally, the backend processes:
- Transaction status.
- Authentication indicators.
useAuth3D
Overview
Purpose - useAuth3D manages the 3D Secure authentication flow for card payments. It coordinates:
- calling the payment service to start an auth3D flow (
initAuth3D). - performing the client-side payment call (
useClientPayment). - handling 3DS v2 and 3DS v1.
- invoking success/error callbacks.
Where it is used - Inside checkout screens (or anywhere an app needs to create/confirm a card payment) to run the full 3D authentication step.
Behavior
- Calls
payServiceContext.initAuth3D(paymentSettings, nvPaymentMerchantSettings)to obtain initialresponseandpayload. - Uses
clientPayment(payload, response, forceWebChallenge, isCreatePayment)to perform the client payment step. - Inspects the client payment response:
- If frictionless (APPROVED) — resolves success or passes response to
onSuccess. - If REDIRECT (3DS v2) — triggers either internal
handle3d2ChallengeorforceWebChallengepath returningwebViewParams. - If v1 — constructs
webViewParamsfor 3DS v1.
- If frictionless (APPROVED) — resolves success or passes response to
What the hook does
- Starts the authorization flow via
payServiceContext.initAuth3D(paymentSettings, nvPaymentMerchantSettings). - Calls the client payment function with the returned payload and response.
- Sets
payServiceContext.setClientPaymentResponse(clientPaymentResponse). - Delegates the 3DS outcome handling to
handleClientPaymentResponse:- For v2
APPROVED: returns the response (frictionless). - For v2
REDIRECT:- If
forceWebChallengeChecked === true→ returnswebViewParamsproduced byforceWebChallengePaymentFrame. - Else → calls
handle3d2Challenge(...)(the 3DS v2 challenge handler).
- If
- For non-v2 flows, if
threeDcontainsacsUrl+paRequest+sessionToken→ returns 3DS v1webViewParams(viainit3D1PaymentFrame).
- For v2
- If
webViewParamsare produced, the hook callsnavigateToWebview(webViewParams)so the host app can present the ACS web page.
Data structure
Request
export const useAuth3D: (isDirect?: boolean) => (props: {
isCreatePayment: boolean;
paymentSettings: PaymentSettings;
forceWebChallengeChecked: boolean;
navigateToWebview: (webViewParams: WebViewParams) => void;
onSuccess?: (res: any) => void;
onError?: (res: any) => void;
source: RequestSource;
nvPaymentMerchantSettings: NvPaymentMerchantSettings;
}) => Promise<void>
Parameters
isCreatePayment: booleantruewhen creating a new paymentpaymentSettings: PaymentSettingsPayment configuration object passed toinitAuth3D.forceWebChallengeChecked: booleanWhentrue, forces the SDK to open a webview for 3DS v2 challenges instead of the normal 3DS v2 challenge.nvPaymentMerchantSettings: NvPaymentMerchantSettings | nullOrder data used byinitAuth3D.navigateToWebview: (webViewParams: unknown) => voidRequired callback when a webview must be shownonSuccess?: (res:any) => voidOptional callback invoked when final payment status isAPPROVED(after client payment).onError?: (res:any) => voidOptional callback invoked on errors orDECLINEDstatuses.
Key functions
forceWebChallengePaymentFrame(acsUrl, creq, sessionToken, isCreatePayment, toolbarBgColor?)
- Builds
webViewParamsfor forcing a 3DS v2 web challenge frame
Where webViewParams contains:
const webViewParams = {
challengeType: CHALLENGE_TYPE.THREE_D2_FORCE_WEB,
acsUrl: acsUrl,
creq: creq,
termUrl: notificationURL,
toolbarBgColor: toolbarBgColor,
isCreatePayment: isCreatePayment,
};
handleForceWebChallenge({ clientPaymentInput, clientPaymentOutput, isCreatePayment, threeD })
- Wrapper to extract details from threeD and call
forceWebChallengePaymentFrame
init3D1PaymentFrame({ acsUrl, paRequest, sessionToken, isCreatePayment })
- Builds
webViewParamsfor a 3DS v1 web challenge frame
Where webViewParams contains:
const webViewParams = {
challengeType: CHALLENGE_TYPE.THREE_D1,
acsUrl: acsUrl,
paRequest: paRequest,
termUrl,
toolbarBgColor: '#40c1ac',
isCreatePayment: isCreatePayment,
};
useHandleClientPaymentResponse()
- Returns a function that handles the
clientPaymentresult:- if the
statusfrom a transaction is 'APPROVED' returns frictionless response - if the
statusis 'REDIRECT' returns force web challenge - otherwise (DECLINED, CANCELLED, ERROR) returns errors
- if the
Integration
import { useAuth3D } from './src/hooks/useAuth3d.tsx';
Error handling
- If
nvPaymentMerchantSettingsisnull-> nothing happens. - If
payServiceContext?.initAuth3D(...)returns falsy -> returns nothing. - If
response.status === 'ERROR'->onErroris called withresponse - If
clientPaymentResultis missing orclientPaymentResult.response.status !== 'SUCCESS'ortransactionStatus === 'DECLINED'->onErrormay be invoked. - If required fields for webview construction are missing (
acsUrl,creq/notificationUrl) -> return{ error: ERROR_CODES.INTERNAL_ERROR }.
Diagram and description
graph TD
id1["initAuth3D()"] ==> id2[clientPayment]
id2 ==> id3[Process clientPaymentResponse]
id3 ==> id4[Force Web Challenge] & id5[3DS2 Challenge]
id4 ==> id6[WebView redirect]
id4 ===> id8[Completion]
id5 ==> id7[Handle Challenge]
id5 ===> id8
id8 -.-> id9([Success]) & id10([Error])
classDef bold font-weight:bold;
class id1,id2,id3,id4,id5,id6,id7,id8,id9,id10 bold;
useAuth3D is part of the 3D Secure authentication flow. It coordinates:
- Initialization of the 3DS process via the server.
- Execution of the initial payment call.
- Detection of 3DS version (3DS1, 3DS2).
- Routing to the correct challenge method (challenge or forced web challenge).
- Handling success, errors, and WebView redirection.
- Notifying other layers through onSuccess or onError.
It acts as the controller for all 3DS operations in the payment flow.
- Initialize Auth3D on the Server (initAuth3D)
The first action is calling:
payServiceContext.initAuth3D(paymentSettings, nvPaymentMerchantSettings, source);
This prepares the backend for 3D authentication and returns:
- response (server result).
- payload (data needed for clientPayment).
⚠️ Warning:
If the server response is ERROR, the component immediately triggers onError.
- Execute the initial client payment (clientPayment)
This sends the first authentication payload to the server.
Returns:
- response – contains transactionStatus.
- payload – used for the next step.
- serverTransId – used in 3DS2.
- v2Supported – whether the card supports 3DS2.
💡 Tip:
If isError(clientPaymentResult), this means the card or network blocked the payment.
⚠️ Warning:
If this step fails, the flow stops completely.
- Process the client payment response
Handled by handleClientPaymentResponse()
This step decides the actual 3DS path:
It checks:
- Is this 3DS2?
- Is the flow frictionless?
- Does the ACS require a challenge?
- Do we need to redirect to WebView?
- Should we force a Web Challenge?
Possible transaction statuses:
- APPROVED → frictionless
- REDIRECT → challenge needed
- DECLINED → stop, call onError
- ERROR → stop, call onError
4A. Force Web Challenge (THREE_D2_FORCE_WEB)
Triggered only when:
Merchant enforces WebView challenge or forceWebChallengeChecked is true
It is used forceWebChallengePaymentFrame() which builds webViewParams
4B. 3DS2 Challenge (handle3d2Challenge)
Runs only if 3DS2 is supported and forceWebChallenge is false
- WebView or Challenge execution
Depending on Step 4:
If Web Challenge:
- The app navigates to WebView:
- navigateToWebview(webViewParams)
This opens the ACS page where the user completes the challenge.
If Challenge:
Automatically handling authentication screens.
⚠️ Warning:
If both WebView and Challenge fail, the final result is treated as an authentication error.
- Completion (Success / Error)
After challenge execution:
- If APPROVED → call onSuccess
- If DECLINED or ERROR → call onError
- If no response → treat as fatal error
💡 Tip:
Success requires both:
status: "SUCCESS";
transactionStatus: "APPROVED";
Otherwise the payment is not authenticated.
Public Utilities and Hooks
The Nuvei SDK provides several utility hooks and API functions that can be used for custom integrations or to enhance the payment flow.
Public API Functions
These functions are available in httpService.ts and can be used to interact directly with the Nuvei backend.
getCardDetails(payload: GetCardDetailPayload)
Retrieves metadata about a card based on its number or a saved payment method ID (UPO).
Usage:
import { getCardDetails } from 'react-native-nuvei';
const details = await getCardDetails({
cardNumber: '4111...',
merchantId: '...',
merchantSiteId: '...',
sessionToken: '...',
});
Returns: A CardDetails object containing:
brand: Card brand (e.g., 'visa', 'mastercard').cardType: 'Credit' or 'Debit'.isPrepaid: Boolean indicating if it's a prepaid card.issuerCountry: Country code of the issuing bank.issuerBankName: Name of the issuing bank.bin: The first 6 digits of the card.last4Digits: The last 4 digits of the card.
checkPaymentStatus(sessionToken: string)
Checks the final status of a payment for a specific session.
Usage:
import { checkPaymentStatus } from 'react-native-nuvei';
const status = await checkPaymentStatus(sessionToken);
setGlobalEnvironment(env: EnvironmentEnum)
Sets the SDK environment globally (STAGING or PROD).
Usage:
import { setGlobalEnvironment, EnvironmentEnum } from 'react-native-nuvei';
setGlobalEnvironment(EnvironmentEnum.PROD);
Utility Hooks
These hooks provide pre-built logic for common UI and validation tasks.
useGetCardDetails()
A SimplyConnect helper hook that returns a function to fetch details for the currently selected card in the context.
Usage:
import { useGetCardDetails } from 'react-native-nuvei';
const getDetails = useGetCardDetails();
try {
const details = await getDetails();
console.log(details.brand);
} catch (error) {
console.error(error.message);
}
useGetCreditCardFieldsErrors()
A utility hook that validates credit card fields using the current SimplyConnect i18n settings and validation rules.
Usage:
import { useGetCreditCardFieldsErrors } from 'react-native-nuvei';
const getErrors = useGetCreditCardFieldsErrors();
const { cvvError, dateError, nameError, numberError } = getErrors(
cardHolder,
cvv,
cardNumber,
expiry,
isValidCardType,
cvvLengthArray
);
useShowCardNumberError()
Returns the current custom card number error message from the Nuvei context. Useful for custom UI components that need to react to card block errors.
Usage:
import { useShowCardNumberError } from 'react-native-nuvei';
const cardNumberError = useShowCardNumberError();
Data Structures
GetCardDetailPayload
type GetCardDetailPayload = {
cardNumber?: string;
userPaymentOptionId?: number;
merchantId: string;
merchantSiteId: string;
sessionToken: string;
clientRequestId?: string;
};
CardDetails
type CardDetails = {
brand: string;
cardType: string;
isPrepaid: boolean;
issuerCountry: string;
issuerBankName: string;
bin: string;
last4Digits: string;
ccExpMonth: string;
ccExpYear: string;
secondaryBrand: string;
status: string;
// ... other metadata fields
};