deepvue-aadhaar-ekyc-digilocker-switch
Version:
A SDK powered by DeepVue.Tech for Aadhaar eKYC and DigiLocker authentication flows
1,383 lines (1,380 loc) • 70.8 kB
JavaScript
import { useState, useEffect, useCallback } from 'react';
import { TextField, Button, Paper, Box, useTheme, Fade, Typography, CircularProgress, Stack, Chip, Divider, useMediaQuery, Stepper, Step, StepLabel, InputAdornment, IconButton, FormControlLabel, Checkbox, Alert, alpha as alpha$1 } from '@mui/material';
import { createSvgIcon } from '@mui/material/utils';
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import axios from 'axios';
import { useFormik } from 'formik';
import { styled, alpha } from '@mui/material/styles';
// src/components/FlowSelector.tsx
var AccountBox_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2m-7 3c1.93 0 3.5 1.57 3.5 3.5S13.93 13 12 13s-3.5-1.57-3.5-3.5S10.07 6 12 6m7 13H5v-.23c0-.62.28-1.2.76-1.58C7.47 15.82 9.64 15 12 15s4.53.82 6.24 2.19c.48.38.76.97.76 1.58z"
}), "AccountBox");
var Cloud_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96"
}), "Cloud");
var CloudQueue_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96M19 18H6c-2.21 0-4-1.79-4-4s1.79-4 4-4h.71C7.37 7.69 9.48 6 12 6c3.04 0 5.5 2.46 5.5 5.5v.5H19c1.66 0 3 1.34 3 3s-1.34 3-3 3"
}), "CloudQueue");
var client = axios.create({
baseURL: import.meta.env.VITE_API_URL || "https://production.deepvue.tech",
headers: { "Content-Type": "application/json" }
});
async function generateOtp(aadhaarNumber, apiKey, clientId, purpose) {
const res = await client.post(
"/v2/ekyc/aadhaar/generate-otp",
null,
{
params: {
aadhaar_number: aadhaarNumber,
consent: "Y",
purpose
},
headers: { "x-api-key": apiKey, "client-id": clientId }
}
);
return res.data;
}
async function verifyOtp(referenceId, otp, apiKey, clientId, generate_pdf) {
const res = await client.post(
"/v2/ekyc/aadhaar/verify-otp",
null,
{
params: {
reference_id: referenceId,
otp,
consent: "Y",
purpose: "For KYC",
generate_pdf
},
headers: { "x-api-key": apiKey, "client-id": clientId },
responseType: "json"
}
);
return res.data;
}
async function initiateDigiLockerSession(apiKey, clientId, redirectUrl) {
const res = await client.post(
"/v1/kyc/digilocker/initiate-session",
{ consent: "Y", purpose: "KYC", redirect_url: redirectUrl },
{ headers: { "x-api-key": apiKey, "client-id": clientId } }
);
return res.data;
}
async function getDigiLockerAccessToken(transactionId, code, apiKey, clientId) {
const res = await client.post(
"/v1/kyc/digilocker/access-token",
{ consent: "Y", purpose: "KYC", initial_deepvue_transaction_id: transactionId, digilocker_code: code },
{ headers: { "x-api-key": apiKey, "client-id": clientId } }
);
return res.data;
}
async function getEAadhaarData(transactionId, apiKey, clientId) {
const res = await client.post(
"/v1/kyc/digilocker/eaadhaar",
{ consent: "Y", purpose: "KYC", initial_deepvue_transaction_id: transactionId },
{ headers: { "x-api-key": apiKey, "client-id": clientId } }
);
return res.data;
}
async function initiateSession(apiKey, clientId) {
const res = await client.get(
"/v2/ekyc/aadhaar/sdk/initiate-session",
{ headers: { "x-api-key": apiKey, "client-id": clientId } }
);
return res.data;
}
async function updateSessionStatus(sessionId, status, apiKey, clientId, aadhaar_reference_id) {
const params = {
session_id: sessionId,
status
};
if (aadhaar_reference_id) {
params.aadhaar_reference_id = aadhaar_reference_id;
}
const res = await client.get(
`/v2/ekyc/aadhaar/sdk/update-session`,
{
params,
headers: { "x-api-key": apiKey, "client-id": clientId }
}
);
return res.data;
}
async function getSessionStatus(sessionId, apiKey, clientId) {
const res = await client.get(
`/v2/ekyc/aadhaar/sdk/session-status`,
{
params: { session_id: sessionId },
headers: { "x-api-key": apiKey, "client-id": clientId }
}
);
return res.data;
}
// src/assets/Logo.svg?base64
var Logo_default = 'data:image/svg+xml,<svg width="77" height="90" viewBox="0 0 77 90" fill="none" xmlns="http://www.w3.org/2000/svg">%0A<path d="M19.5312 12.0884L38.3566 0.972656V23.2307L19.5312 12.0884Z" fill="%23EA637D"/>%0A<path d="M0.679688 23.2302L19.5311 12.0879V34.3459L0.679688 23.2302Z" fill="%23E84278"/>%0A<path d="M0.679688 45.4885V23.2305L19.5311 34.3462L0.679688 45.4885Z" fill="%23EA637D"/>%0A<path d="M57.2029 12.0879V34.3459L38.3516 23.2302L57.2029 12.0879Z" fill="%23CE78C2"/>%0A<path d="M38.3516 0.972656L57.2029 12.0884L38.3516 23.2307V0.972656Z" fill="%23E84278"/>%0A<path d="M76.0623 23.2305V45.4885L57.2109 34.3462L76.0623 23.2305Z" fill="%23CE78C2"/>%0A<path d="M57.2109 12.0879L76.0623 23.2302L57.2109 34.3459V12.0879Z" fill="%236B2B80"/>%0A<path d="M76.0623 45.4863V67.7178L57.2109 56.602L76.0623 45.4863Z" fill="%23CE78C2"/>%0A<path d="M57.2109 56.6035L76.0623 67.7192L57.2109 78.8615V56.6035Z" fill="%236B2B80"/>%0A<path d="M38.3566 89.9787L19.5312 78.863L38.3566 67.7207V89.9787Z" fill="%23EA637D"/>%0A<path d="M38.3516 67.7207L57.4818 78.8239L38.3516 89.9787V67.7207Z" fill="%23E84278"/>%0A<path d="M0.679688 45.488L19.5311 34.3457V56.6037L0.679688 45.488Z" fill="%23FF83B0"/>%0A<path d="M0.679688 67.7178V45.4863L19.5311 56.602L0.679688 67.7178Z" fill="%23CE78C2"/>%0A<path d="M19.5311 78.8615L0.679688 67.7192L19.5311 56.6035V78.8615Z" fill="%236B2B80"/>%0A<path d="M38.3906 67.7996L57.4942 56.7461V78.8232L38.3906 67.7996Z" fill="%23CE78C2"/>%0A<path d="M76.1687 45.4177L57.6864 34.3984L57.5 56.7467L76.1687 45.4177Z" fill="%23FF83B0"/>%0A</svg>%0A';
var Logo = () => /* @__PURE__ */ jsx(
Box,
{
component: "img",
src: Logo_default,
alt: "DeepVue Logo",
sx: {
height: 30,
width: "auto",
filter: "drop-shadow(0px 2px 4px rgba(0,0,0,0.1))",
transition: "transform 0.2s ease",
"&:hover": {
transform: "scale(1.05)"
}
}
}
);
var FlowSelector = ({
apiKey,
clientId,
onSelectAadhaar,
onAutoSelectDigiLocker,
autoDetectCallback = true
}) => {
const theme = useTheme();
const sdkCallbackUrl = `${window.location.origin}/callback.html`;
const [isRedirecting, setIsRedirecting] = useState(false);
const [sessionId, setSessionId] = useState(null);
useEffect(() => {
const initializeSession = async () => {
try {
const existingSessionId = localStorage.getItem("deepvue_session_id");
if (existingSessionId) {
try {
const sessionStatus = await getSessionStatus(
existingSessionId,
apiKey,
clientId
);
if (sessionStatus.status === "aadhaar_otp_send_success" && sessionStatus.aadhaar_reference_id) {
const nowMs = Date.now();
const expMs = sessionStatus.aadhaar_reference_id_exp;
if (expMs && nowMs < expMs) {
setSessionId(existingSessionId);
return;
} else {
localStorage.removeItem("deepvue_session_id");
}
} else if (sessionStatus.status === "aadhaar_otp_verification_success" || sessionStatus.status === "digilocker_success") {
localStorage.removeItem("deepvue_session_id");
}
} catch (statusError) {
console.error("Failed to check session status:", statusError);
localStorage.removeItem("deepvue_session_id");
}
}
const response = await initiateSession(apiKey, clientId);
if (response?.session_id) {
localStorage.setItem("deepvue_session_id", response.session_id);
setSessionId(response.session_id);
} else {
console.error("No session_id in response:", response);
}
} catch (error) {
console.error("Failed to initialize session:", error);
if (error instanceof Error && error.message.includes("already in the required status")) {
const existing = localStorage.getItem("deepvue_session_id");
if (existing) {
setSessionId(existing);
return;
}
}
localStorage.removeItem("deepvue_session_id");
setSessionId(null);
}
};
initializeSession();
}, [apiKey, clientId]);
useEffect(() => {
if (!autoDetectCallback) return;
const checkDigiLockerCallback = () => {
const callbackReceived = sessionStorage.getItem(
"digilocker_callback_received"
);
const flowActive = sessionStorage.getItem("digilocker_flow_active");
if (callbackReceived === "true" && flowActive === "true") {
onAutoSelectDigiLocker();
return;
}
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get("code");
const state = urlParams.get("state");
if (code && state) {
sessionStorage.setItem("digilocker_callback_code", code);
sessionStorage.setItem("digilocker_callback_state", state);
sessionStorage.setItem("digilocker_callback_received", "true");
sessionStorage.setItem("digilocker_flow_active", "true");
sessionStorage.setItem("digilocker_api_key", apiKey);
sessionStorage.setItem("digilocker_client_id", clientId);
window.history.replaceState(
{},
document.title,
window.location.pathname
);
onAutoSelectDigiLocker();
return;
}
};
checkDigiLockerCallback();
}, [autoDetectCallback, onAutoSelectDigiLocker, apiKey, clientId]);
const handleDigilocker = async () => {
if (!sessionId) {
const existing = localStorage.getItem("deepvue_session_id");
if (existing) {
setSessionId(existing);
setTimeout(() => handleDigilocker(), 100);
return;
}
alert(
"Session initialization failed. Please refresh the page and try again."
);
return;
}
try {
setIsRedirecting(true);
await updateSessionStatus(
sessionId,
"method_digilocker_selected",
apiKey,
clientId
);
sessionStorage.setItem("digilocker_flow_active", "true");
sessionStorage.setItem("digilocker_api_key", apiKey);
sessionStorage.setItem("digilocker_client_id", clientId);
const response = await initiateDigiLockerSession(
apiKey,
clientId,
sdkCallbackUrl
);
if (!response.data.authorization_url) {
throw new Error("No authorization URL received from DigiLocker");
}
const authUrl = new URL(response.data.authorization_url);
setTimeout(() => {
window.location.replace(authUrl.toString());
}, 3e3);
} catch (error) {
console.error("DigiLocker error:", error);
alert("Failed to start DigiLocker session. Please try again.");
setIsRedirecting(false);
sessionStorage.removeItem("digilocker_flow_active");
sessionStorage.removeItem("digilocker_api_key");
sessionStorage.removeItem("digilocker_client_id");
}
};
const handleAadhaar = async () => {
if (!sessionId) {
const existing = localStorage.getItem("deepvue_session_id");
if (existing) {
setSessionId(existing);
setTimeout(() => handleAadhaar(), 100);
return;
}
alert(
"Session initialization failed. Please refresh the page and try again."
);
return;
}
try {
const sessionStatus = await getSessionStatus(sessionId, apiKey, clientId);
if (sessionStatus.status === "aadhaar_otp_send_success" && sessionStatus.aadhaar_reference_id) {
const nowMs = Date.now();
const expMs = sessionStatus.aadhaar_reference_id_exp;
if (expMs && nowMs < expMs) {
onSelectAadhaar();
return;
} else {
localStorage.removeItem("deepvue_session_id");
const newSession = await initiateSession(apiKey, clientId);
if (newSession?.session_id) {
localStorage.setItem("deepvue_session_id", newSession.session_id);
setSessionId(newSession.session_id);
}
}
}
await updateSessionStatus(
sessionId,
"method_aadhaar_selected",
apiKey,
clientId
);
onSelectAadhaar();
} catch (error) {
console.error("Failed to check/update session status:", error);
try {
const newSession = await initiateSession(apiKey, clientId);
if (newSession?.session_id) {
localStorage.setItem("deepvue_session_id", newSession.session_id);
setSessionId(newSession.session_id);
await updateSessionStatus(
newSession.session_id,
"method_aadhaar_selected",
apiKey,
clientId
);
}
} catch {
}
onSelectAadhaar();
}
};
if (isRedirecting) {
return /* @__PURE__ */ jsx(
Box,
{
sx: {
display: "flex",
justifyContent: "center",
alignItems: "center",
minHeight: "100vh",
backgroundColor: theme.palette.background.default
},
children: /* @__PURE__ */ jsx(Fade, { in: true, timeout: 500, children: /* @__PURE__ */ jsxs(
Paper,
{
elevation: 4,
sx: {
width: "100%",
maxWidth: 450,
p: theme.spacing(5),
borderRadius: theme.spacing(2),
backgroundColor: "#ffffff",
textAlign: "center"
},
children: [
/* @__PURE__ */ jsx(
CloudQueue_default,
{
sx: {
fontSize: 64,
color: theme.palette.primary.main,
mb: 2
}
}
),
/* @__PURE__ */ jsx(Typography, { variant: "h5", fontWeight: "bold", gutterBottom: true, children: "Connecting to DigiLocker" }),
/* @__PURE__ */ jsx(Typography, { variant: "body1", color: "text.secondary", sx: { mb: 4 }, children: "Please wait while we securely connect you to DigiLocker..." }),
/* @__PURE__ */ jsx(
CircularProgress,
{
size: 40,
thickness: 4,
sx: { color: theme.palette.primary.main }
}
)
]
}
) })
}
);
}
return /* @__PURE__ */ jsx(
Box,
{
sx: {
display: "flex",
justifyContent: "center",
alignItems: "center",
p: { xs: 1.5, sm: 3 },
backgroundColor: theme.palette.grey[50]
},
children: /* @__PURE__ */ jsxs(
Paper,
{
elevation: 4,
sx: {
width: "100%",
maxWidth: 420,
p: { xs: theme.spacing(2), sm: theme.spacing(4) },
borderRadius: theme.spacing(2),
backgroundColor: "#ffffff",
textAlign: "center",
boxShadow: "0 8px 24px rgba(0,0,0,0.08)"
},
children: [
/* @__PURE__ */ jsx(
Typography,
{
variant: "h6",
fontWeight: "bold",
gutterBottom: true,
sx: {
color: theme.palette.primary.main,
mb: 0.5
},
children: "Choose Your Verification Method"
}
),
/* @__PURE__ */ jsx(
Typography,
{
variant: "body2",
color: "text.secondary",
sx: {
mb: 3,
maxWidth: "420px",
mx: "auto",
lineHeight: 1.5
},
children: "Select your preferred secure eKYC method to verify your identity"
}
),
/* @__PURE__ */ jsxs(Stack, { spacing: 2, children: [
/* @__PURE__ */ jsxs(
Box,
{
sx: {
p: 2,
borderRadius: theme.spacing(1.5),
border: `1px solid ${theme.palette.primary.main}`,
backgroundColor: theme.palette.primary.light + "08",
transition: "all 0.2s ease",
position: "relative",
overflow: "visible",
"&:hover": {
backgroundColor: theme.palette.primary.light + "12",
transform: "translateY(-2px)",
boxShadow: "0 4px 12px rgba(0,0,0,0.05)"
},
cursor: "pointer"
},
children: [
/* @__PURE__ */ jsx(
Chip,
{
label: "Recommended",
size: "small",
sx: {
position: "absolute",
top: 2,
right: 2,
background: theme.palette.success.light + "15",
color: theme.palette.success.main,
fontWeight: 500,
fontSize: "0.7rem",
height: "22px",
boxShadow: "none",
border: `1px solid ${theme.palette.success.light + "40"}`,
backdropFilter: "blur(4px)",
zIndex: 1,
"& .MuiChip-label": {
px: 1.2,
py: 0.3
},
"& .MuiChip-icon": {
color: theme.palette.success.light,
marginLeft: "4px",
marginRight: "-4px"
},
"&:hover": {
background: theme.palette.success.light + "25"
}
}
}
),
/* @__PURE__ */ jsx(
Cloud_default,
{
sx: {
fontSize: 32,
color: theme.palette.info.main,
mb: 1
}
}
),
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", fontWeight: "600", gutterBottom: true, children: "DigiLocker" }),
/* @__PURE__ */ jsx(
Typography,
{
variant: "body2",
color: "text.secondary",
sx: {
mb: 1.5,
fontSize: "0.875rem"
},
children: "Verify your identity using your Digilocker E-Aadhaar"
}
),
/* @__PURE__ */ jsx(
Button,
{
fullWidth: true,
variant: "contained",
size: "medium",
sx: {
textTransform: "none",
fontWeight: 600,
py: 1,
borderRadius: theme.spacing(1),
fontSize: "0.875rem",
"&:hover": {
backgroundColor: theme.palette.primary.dark
}
},
onClick: handleDigilocker,
children: "Continue with DigiLocker"
}
)
]
}
),
/* @__PURE__ */ jsx(
Typography,
{
variant: "caption",
color: "text.secondary",
sx: {
position: "relative",
display: "block",
my: 1,
"&::before, &::after": {
content: '""',
position: "absolute",
top: "50%",
width: "25%",
height: "1px",
backgroundColor: theme.palette.divider
},
"&::before": {
left: 0
},
"&::after": {
right: 0
}
},
children: "OR"
}
),
/* @__PURE__ */ jsxs(
Box,
{
sx: {
p: 2,
borderRadius: theme.spacing(1.5),
border: `1px solid ${theme.palette.grey[300]}`,
backgroundColor: theme.palette.grey[50],
transition: "all 0.2s ease",
"&:hover": {
backgroundColor: theme.palette.grey[100],
transform: "translateY(-2px)",
boxShadow: "0 4px 12px rgba(0,0,0,0.05)"
},
cursor: "pointer"
},
children: [
/* @__PURE__ */ jsx(
AccountBox_default,
{
sx: {
fontSize: 32,
color: theme.palette.primary.main,
mb: 1
}
}
),
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", fontWeight: "600", gutterBottom: true, children: "Aadhaar eKYC" }),
/* @__PURE__ */ jsx(
Typography,
{
variant: "body2",
color: "text.secondary",
sx: {
mb: 1.5,
fontSize: "0.875rem"
},
children: "Verify your identity using your Aadhaar number and OTP"
}
),
/* @__PURE__ */ jsx(
Button,
{
fullWidth: true,
variant: "outlined",
size: "medium",
sx: {
textTransform: "none",
fontWeight: 600,
py: 1,
borderRadius: theme.spacing(1),
fontSize: "0.875rem",
borderColor: theme.palette.info.main,
color: theme.palette.info.main,
"&:hover": {
borderColor: theme.palette.info.dark,
backgroundColor: theme.palette.info.light + "12"
}
},
onClick: handleAadhaar,
children: "Continue with Aadhaar"
}
)
]
}
)
] }),
/* @__PURE__ */ jsx(Divider, { sx: { my: 4, opacity: 0.6 } }),
/* @__PURE__ */ jsxs(
Box,
{
sx: {
display: "flex",
alignItems: "center",
justifyContent: "center",
gap: 1.5
},
children: [
/* @__PURE__ */ jsx(
Typography,
{
variant: "caption",
sx: {
color: theme.palette.text.secondary,
fontSize: "0.75rem",
letterSpacing: "0.5px",
fontWeight: 500
},
children: "Powered By"
}
),
/* @__PURE__ */ jsx(Logo, {})
]
}
)
]
}
)
}
);
};
function useCountdown(seconds) {
const [count, setCount] = useState(0);
useEffect(() => {
let timer;
if (count > 0) {
timer = setTimeout(() => setCount(count - 1), 1e3);
}
return () => clearTimeout(timer);
}, [count]);
const start = useCallback(() => setCount(seconds), [seconds]);
return { count, start };
}
// src/hooks/useAadhaarEkyc.ts
function useAadhaarEkyc(apiKey, clientId, generate_pdf, purpose) {
const [referenceId, setReferenceId] = useState();
const [data, setData] = useState();
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
const [hasActiveSession, setHasActiveSession] = useState(false);
const { count, start } = useCountdown(30);
useEffect(() => {
const checkActiveSession = async () => {
const sessionId = localStorage.getItem("deepvue_session_id");
if (!sessionId) return false;
try {
const sessionStatus = await getSessionStatus(sessionId, apiKey, clientId);
if (sessionStatus.status === "aadhaar_otp_send_success" && sessionStatus.aadhaar_reference_id) {
const currentTimeMs = Date.now();
const expirationTimeMs = sessionStatus.aadhaar_reference_id_exp;
if (expirationTimeMs && currentTimeMs < expirationTimeMs) {
setReferenceId(sessionStatus.aadhaar_reference_id);
setHasActiveSession(true);
start();
return true;
} else {
localStorage.removeItem("deepvue_session_id");
}
}
if (sessionStatus.status === "aadhaar_otp_verification_success" || sessionStatus.status === "digilocker_success") {
localStorage.removeItem("deepvue_session_id");
}
} catch (err) {
console.error("Failed to check session status:", err);
localStorage.removeItem("deepvue_session_id");
}
return false;
};
checkActiveSession();
}, [apiKey, clientId, start]);
const requestOtp = async (aadhaarNumber) => {
setLoading(true);
setError(void 0);
const sessionId = localStorage.getItem("deepvue_session_id");
try {
const res = await generateOtp(aadhaarNumber, apiKey, clientId, purpose);
setReferenceId(res.reference_id);
if (sessionId) {
await updateSessionStatus(
sessionId,
"aadhaar_otp_send_success",
apiKey,
clientId,
res.reference_id
);
}
start();
return res;
} catch (e) {
if (sessionId) {
try {
await updateSessionStatus(
sessionId,
"aadhaar_otp_send_failure",
apiKey,
clientId
);
} catch {
}
}
setError(e.message);
throw e;
} finally {
setLoading(false);
}
};
const confirmOtp = async (otp) => {
if (!referenceId) {
const msg = "No OTP session. Please resend.";
setError(msg);
return { code: 0, message: msg };
}
setLoading(true);
setError(void 0);
try {
const res = await verifyOtp(
referenceId,
otp,
apiKey,
clientId,
generate_pdf
);
if (res.code === 200 && res.data) {
setData(res.data);
}
const sessionId = localStorage.getItem("deepvue_session_id");
if (sessionId) {
if (res.code === 200) {
await updateSessionStatus(
sessionId,
"aadhaar_otp_verification_success",
apiKey,
clientId
);
setHasActiveSession(false);
} else {
await updateSessionStatus(
sessionId,
"aadhaar_otp_verification_failure",
apiKey,
clientId
);
setError(res.message);
}
}
return res;
} catch (e) {
const errorMessage = e.response?.data?.message || e.message;
setError(errorMessage);
const sessionId = localStorage.getItem("deepvue_session_id");
if (sessionId) {
try {
await updateSessionStatus(
sessionId,
"aadhaar_otp_verification_failure",
apiKey,
clientId
);
} catch {
}
}
return { code: 0, message: errorMessage };
} finally {
setLoading(false);
}
};
const clearOtpSession = () => {
setReferenceId(void 0);
setHasActiveSession(false);
};
return {
requestOtp,
confirmOtp,
data,
loading,
error,
count,
hasActiveSession,
clearOtpSession
};
}
var StyledTextField = styled(TextField)(({ theme }) => ({
width: "100%",
"& .MuiOutlinedInput-root": {
borderRadius: theme.spacing(1.5),
transition: "all 0.2s ease-in-out",
backgroundColor: alpha(theme.palette.background.paper, 0.8),
"&:hover": {
backgroundColor: alpha(theme.palette.background.paper, 0.9),
transform: "translateY(-1px)",
boxShadow: theme.shadows[2]
},
"&.Mui-focused": {
boxShadow: theme.shadows[3],
backgroundColor: theme.palette.background.paper
},
"& fieldset": {
borderColor: alpha(theme.palette.primary.main, 0.2)
},
"&:hover fieldset": {
borderColor: theme.palette.primary.main
}
}
}));
var ResendButton = styled(Button)(({ theme }) => ({
borderRadius: theme.spacing(1.5),
textTransform: "none",
transition: "all 0.2s ease-in-out",
"&:hover": {
transform: "translateY(-1px)",
boxShadow: theme.shadows[2]
}
}));
var VerifyButton = styled(Button)(({ theme }) => ({
maxWidth: "220px",
borderRadius: theme.spacing(1.5),
textTransform: "none",
transition: "all 0.2s ease-in-out",
background: `linear-gradient(45deg, ${theme.palette.primary.main} 30%, ${theme.palette.primary.dark} 90%)`,
"&:hover": {
transform: "translateY(-1px)",
boxShadow: theme.shadows[4]
},
"&:disabled": {
background: theme.palette.action.disabledBackground
}
}));
var OtpForm = ({
onVerify,
loading: verifyLoading,
countdown,
onResend,
error
}) => {
const [otp, setOtp] = useState("");
const [resendLoading, setResendLoading] = useState(false);
const handleResend = async () => {
setResendLoading(true);
try {
await onResend();
} finally {
setResendLoading(false);
}
};
const handleKeyPress = (e) => {
if (e.key === "Enter") {
e.preventDefault();
if (otp.length === 6 && !verifyLoading && !resendLoading) {
onVerify(otp);
}
}
};
return /* @__PURE__ */ jsx(Fade, { in: true, timeout: 500, children: /* @__PURE__ */ jsxs(
Box,
{
component: "form",
onSubmit: (e) => e.preventDefault(),
sx: {
display: "flex",
flexDirection: "column",
gap: 2,
alignItems: "center",
width: "100%",
py: 1
},
children: [
/* @__PURE__ */ jsxs(
Box,
{
sx: {
display: "flex",
flexDirection: { xs: "column", sm: "row" },
gap: 2,
width: "100%",
alignItems: "center"
},
children: [
/* @__PURE__ */ jsx(
StyledTextField,
{
placeholder: "Enter 6-digit OTP",
value: otp,
onChange: (e) => setOtp(e.target.value.replace(/\D/g, "").slice(0, 6)),
onKeyDown: handleKeyPress,
disabled: verifyLoading || resendLoading,
slotProps: {
input: {
inputProps: {
maxLength: 6,
pattern: "[0-9]*",
inputMode: "numeric"
}
}
}
}
),
/* @__PURE__ */ jsx(
ResendButton,
{
variant: "outlined",
disabled: countdown !== 0 || resendLoading || verifyLoading,
onClick: handleResend,
sx: {
width: { xs: "100%", sm: "120px" },
height: "40px",
whiteSpace: "nowrap",
flexShrink: 0
},
children: resendLoading ? "Sending..." : countdown > 0 ? `Resend (${countdown}s)` : "Resend OTP"
}
)
]
}
),
/* @__PURE__ */ jsx(
Box,
{
sx: {
display: "flex",
justifyContent: "center",
width: "100%"
},
children: /* @__PURE__ */ jsx(
VerifyButton,
{
variant: "contained",
onClick: () => onVerify(otp),
disabled: verifyLoading || resendLoading || !otp || otp.length !== 6,
sx: {
py: 1,
px: 2,
mt: 2,
fontSize: "1.1rem",
width: "100%",
height: "48px"
},
children: verifyLoading ? "Verifying..." : "Verify OTP"
}
)
}
),
/* @__PURE__ */ jsx(Fade, { in: !!error, timeout: 300, children: /* @__PURE__ */ jsx(Box, { sx: { width: "100%" }, children: error && /* @__PURE__ */ jsx(
Alert,
{
severity: "error",
variant: "filled",
sx: {
borderRadius: 2,
boxShadow: 2
},
children: error
}
) }) })
]
}
) });
};
var OtpForm_default = OtpForm;
var CheckCircle_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2m-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8z"
}), "CheckCircle");
var Fingerprint_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28M3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7s-.54.11-.7-.12c-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21m6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39s-4.66 1.97-4.66 4.39c0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15m7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12M14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94s3.08 1.32 3.08 2.94c0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38"
}), "Fingerprint");
var Message_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M20 2H4c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2m-2 12H6v-2h12zm0-3H6V9h12zm0-3H6V6h12z"
}), "Message");
var ArrowBack_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20z"
}), "ArrowBack");
var Visibility_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5M12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5m0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3"
}), "Visibility");
var VisibilityOff_default = createSvgIcon(/* @__PURE__ */ jsx("path", {
d: "M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7M2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2m4.31-.78 3.15 3.15.02-.16c0-1.66-1.34-3-3-3z"
}), "VisibilityOff");
var StyledPaper = styled(Paper)(({ theme }) => ({
padding: theme.spacing(4),
maxWidth: 450,
margin: "2rem auto",
borderRadius: theme.spacing(2),
boxShadow: theme.shadows[4],
[theme.breakpoints.down("sm")]: {
padding: theme.spacing(1.5),
margin: "1rem"
}
}));
var StyledTextField2 = styled(TextField)(({ theme }) => ({
"& .MuiOutlinedInput-root": {
borderRadius: theme.spacing(1),
"&:hover fieldset": {
borderColor: theme.palette.primary.main
}
}
}));
var ResultRow = styled(Box)(({ theme }) => ({
display: "flex",
alignItems: "center",
padding: theme.spacing(1.5, 0),
"&:last-child": {
borderBottom: "none"
},
[theme.breakpoints.down("sm")]: {
flexDirection: "column",
alignItems: "flex-start",
gap: theme.spacing(1)
}
}));
var AadhaarFlow = ({
apiKey,
clientId,
generatePdf,
redirectUrl,
onBack,
companyName,
purpose
}) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down("sm"));
const {
requestOtp,
confirmOtp,
data,
loading,
error,
count,
hasActiveSession,
clearOtpSession
} = useAadhaarEkyc(apiKey, clientId, generatePdf, purpose);
const [stage, setStage] = useState(hasActiveSession ? "otp" : "init");
const [redirectCount, setRedirectCount] = useState(5);
const [apiError, setApiError] = useState("");
const [showAadhaar, setShowAadhaar] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const [showError, setShowError] = useState(false);
const [showInitError, setShowInitError] = useState(false);
const [consentChecked, setConsentChecked] = useState(false);
const cleanupSession = () => {
if (stage === "result" || showSuccess) {
localStorage.removeItem("deepvue_session_id");
}
};
useEffect(() => {
return () => {
cleanupSession();
};
}, [stage, showSuccess]);
useEffect(() => {
if (hasActiveSession && stage !== "result" && !data) {
setStage("otp");
setShowSuccess(true);
const timer = setTimeout(() => {
setShowSuccess(false);
}, 5e3);
return () => clearTimeout(timer);
}
}, [hasActiveSession, stage, data]);
const handleBack = () => {
if (stage === "init") {
cleanupSession();
onBack();
} else {
clearOtpSession();
setStage("init");
setShowSuccess(false);
setShowError(false);
setApiError("");
}
};
const handleVerify = async (otp) => {
try {
const res = await confirmOtp(otp);
if (res.code === 200) {
setStage("result");
} else {
setApiError(res.message || "Verification failed");
setShowError(true);
setTimeout(() => {
setShowError(false);
setApiError("");
}, 5e3);
}
} catch (error2) {
const errorMessage = error2.response?.data?.message || (error2.response?.data?.sub_code === "INVALID_OTP" ? "Invalid OTP" : "An error occurred while verifying OTP");
setApiError(errorMessage);
setShowError(true);
setTimeout(() => {
setShowError(false);
setApiError("");
}, 5e3);
}
};
useEffect(() => {
if (data && stage === "result") {
const timer = setInterval(() => {
setRedirectCount((prev) => {
if (prev <= 1) {
clearInterval(timer);
cleanupSession();
window.location.href = redirectUrl;
return 0;
}
return prev - 1;
});
}, 1e3);
return () => {
clearInterval(timer);
cleanupSession();
};
}
}, [data, stage, redirectUrl]);
const formik = useFormik({
initialValues: { aadhaar: "", consent: false },
validate: (values) => {
const errs = {};
if (!values.aadhaar) {
errs.aadhaar = "Aadhaar number is required";
} else if (!/^\d{12}$/.test(values.aadhaar)) {
errs.aadhaar = "Enter a valid 12-digit Aadhaar number";
}
if (!values.consent) {
errs.consent = "Please provide consent to proceed";
}
return errs;
},
onSubmit: async ({ aadhaar }) => {
if (!consentChecked) return;
try {
setApiError("");
setShowInitError(false);
await requestOtp(aadhaar);
setStage("otp");
} catch (error2) {
const errorMessage = error2.response?.data?.message || "An error occurred while requesting OTP";
setApiError(errorMessage);
setShowInitError(true);
setTimeout(() => setShowInitError(false), 5e3);
}
}
});
const steps = ["Verify Aadhaar", "Verify OTP", "Fetch Details"];
const getActiveStep = () => {
switch (stage) {
case "init":
return 0;
case "otp":
return 1;
case "result":
return 2;
default:
return 0;
}
};
const transformValue = (val) => {
if (val == null) return "";
if (typeof val === "boolean") return val ? "Yes" : "No";
return val;
};
const renderData = (obj) => {
if (!obj || typeof obj !== "object") {
return [];
}
const fieldsToShow = [
{ key: "maskedNumber", label: "Aadhaar Number" },
{ key: "name", label: "Name" },
{ key: "dateOfBirth", label: "Date Of Birth" },
{ key: "gender", label: "Gender" },
{ key: "address", label: "Address" },
{ key: "photo", label: "Photo" }
];
return fieldsToShow.flatMap(({ key, label }, idx) => {
const value = obj[key];
if (key === "photo" && typeof value === "string") {
return [
/* @__PURE__ */ jsxs(ResultRow, { children: [
/* @__PURE__ */ jsx(
Typography,
{
variant: "subtitle2",
sx: { width: "180px", fontWeight: 600 },
children: label
}
),
/* @__PURE__ */ jsx(
Box,
{
component: "img",
src: `data:image/jpeg;base64,${value}`,
alt: "Aadhaar Photo",
sx: { width: 100, height: "auto", borderRadius: 1 }
}
)
] }, key),
idx < fieldsToShow.length - 1 && /* @__PURE__ */ jsx(Divider, {}, `${key}-div`)
];
}
if (key === "address" && value && typeof value === "object") {
const address = value;
const addressParts = [
address.house,
address.street,
address.locality,
address.landmark,
address.vtc,
address.subDistrict,
address.district,
address.state,
address.pin,
address.country
].filter(Boolean).join(", ");
return [
/* @__PURE__ */ jsxs(ResultRow, { children: [
/* @__PURE__ */ jsx(
Typography,
{
variant: "subtitle2",
sx: { width: "180px", fontWeight: 600 },
children: label
}
),
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: addressParts })
] }, key),
idx < fieldsToShow.length - 1 && /* @__PURE__ */ jsx(Divider, {}, `${key}-div`)
];
}
return [
/* @__PURE__ */ jsxs(ResultRow, { children: [
/* @__PURE__ */ jsx(
Typography,
{
variant: "subtitle2",
sx: { width: "180px", fontWeight: 600 },
children: label
}
),
/* @__PURE__ */ jsx(Typography, { variant: "body2", children: transformValue(value) })
] }, key),
idx < fieldsToShow.length - 1 && /* @__PURE__ */ jsx(Divider, {}, `${key}-div`)
];
});
};
const handleAadhaarChange = (e) => {
const inputValue = e.target.value;
if (!showAadhaar) {
const inputLength = inputValue.length;
const currentLength = formik.values.aadhaar.length;
if (inputLength > currentLength) {
const newChar = inputValue.slice(-1);
if (/^\d$/.test(newChar)) {
const newValue = formik.values.aadhaar + newChar;
if (newValue.length <= 12) {
formik.setFieldValue("aadhaar", newValue);
}
}
} else if (inputLength < currentLength) {
const newValue = formik.values.aadhaar.slice(0, inputLength);
formik.setFieldValue("aadhaar", newValue);
}
} else {
if (/^\d*$/.test(inputValue) && inputValue.length <= 12) {
formik.setFieldValue("aadhaar", inputValue);
}
}
};
const getDisplayValue = () => {
if (showAadhaar) {
return formik.values.aadhaar;
} else {
return formik.values.aadhaar.replace(/./g, "x");
}
};
const toggleAadhaarVisibility = () => {
setShowAadhaar(!showAadhaar);
};
return /* @__PURE__ */ jsx(Fade, { in: true, timeout: 500, children: /* @__PURE__ */ jsxs(StyledPaper, { elevation: 4, children: [
/* @__PURE__ */ jsx(
Stepper,
{
activeStep: getActiveStep(),
alternativeLabel: true,
sx: { mb: 4, display: { xs: "none", sm: "flex" } },
children: steps.map((label) => /* @__PURE__ */ jsx(Step, { children: /* @__PURE__ */ jsx(StepLabel, { children: label }) }, label))
}
),
stage !== "result" ? /* @__PURE__ */ jsxs(Box, { children: [
/* @__PURE__ */ jsxs(
Box,
{
sx: {
display: "flex",
flexDirection: "column",
gap: 2,
mb: 4
},
children: [
/* @__PURE__ */ jsxs(
Box,
{
sx: {
display: "flex",
justifyContent: "space-between",
alignItems: "center"
},
children: [
/* @__PURE__ */ jsx(
Typography,
{
variant: "h5",
fontWeight: 600,
sx: { display: "flex", alignItems: "center", gap: 1 },
children: stage === "init" ? /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Fingerprint_default, { color: "primary" }),
"Verify Aadhaar"
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(Message_default, { color: "primary" }),
"Verify OTP"
] })
}
),
/* @__PURE__ */ jsx(
Button,
{
variant: "outlined",
onClick: handleBack,
sx: { borderRadius: 2, lineHeight: "15px" },
startIcon: /* @__PURE__ */ jsx(ArrowBack_default, { sx: { width: "16px" } }),
children: "Back"
}
)
]
}
),
/* @__PURE__ */ jsx(Typography, { variant: "body1", color: "text.secondary", children: stage === "init" ? "Enter your 12-digit aadhaar number to get an OTP on your aadhaar-linked mobile" : hasActiveSession ? "Resuming your verification. Enter the OTP sent to your aadhaar-linked mobile number" : "Enter the OTP sent to your aadhaar-linked mobile number" })
]
}
),
/* @__PURE__ */ jsxs(Box, { component: "div", sx: { mt: 3 }, children: [
stage === "init" ? /* @__PURE__ */ jsxs(Box, { sx: { mb: 3 }, children: [
/* @__PURE__ */ jsx(Typography, { variant: "subtitle1", sx: { mb: 1 }, children: "Aadhaar Number" }),
/* @__PURE__ */ jsx(
StyledTextField2,
{
fullWidth: true,
required: true,
placeholder: "Enter Aadhaar Number",
value: getDisplayValue(),
onChange: handleAadhaarChange,
helperText: formik.touched.aadhaar && formik.errors.aad