astra-sdk-web 1.1.27 → 1.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/astra-sdk.cjs.js +126 -23
- package/dist/astra-sdk.cjs.js.map +1 -1
- package/dist/astra-sdk.es.js +126 -23
- package/dist/astra-sdk.es.js.map +1 -1
- package/dist/components.cjs.js +126 -23
- package/dist/components.cjs.js.map +1 -1
- package/dist/components.es.js +126 -23
- package/dist/components.es.js.map +1 -1
- package/package.json +1 -1
- package/src/pages/MobileRoute.tsx +51 -15
- package/src/pages/QRCodePage.tsx +18 -17
- package/src/utils/kycConfigStorage.ts +125 -0
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useState } from 'react';
|
|
2
2
|
import { isMobileDevice } from '../utils/deviceDetection';
|
|
3
|
+
import { getKycConfig, clearExpiredConfigs } from '../utils/kycConfigStorage';
|
|
3
4
|
import FaceScanModal from './FaceScanModal';
|
|
4
5
|
import { KycProvider } from '../contexts/KycContext';
|
|
5
6
|
import '../index.css';
|
|
@@ -22,27 +23,62 @@ function MobileRoute({ onClose, onNavigate }: MobileRouteProps = {}) {
|
|
|
22
23
|
} | null>(null);
|
|
23
24
|
|
|
24
25
|
useEffect(() => {
|
|
26
|
+
// Clear expired configs on mount
|
|
27
|
+
clearExpiredConfigs();
|
|
28
|
+
|
|
25
29
|
if (!isMobileDevice() && onNavigate) {
|
|
26
30
|
onNavigate('qr');
|
|
27
31
|
return;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
//
|
|
34
|
+
// Get sessionId from URL params
|
|
31
35
|
const searchParams = new URLSearchParams(window.location.search);
|
|
32
36
|
const sessionId = searchParams.get('sessionId');
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
37
|
+
|
|
38
|
+
if (sessionId) {
|
|
39
|
+
let apiBaseUrl = '';
|
|
40
|
+
let serverKey = '';
|
|
41
|
+
|
|
42
|
+
// First, try to decode config from URL (for cross-device QR scanning)
|
|
43
|
+
const encodedConfig = searchParams.get('config');
|
|
44
|
+
if (encodedConfig) {
|
|
45
|
+
try {
|
|
46
|
+
const decodedConfig = JSON.parse(atob(encodedConfig));
|
|
47
|
+
if (decodedConfig.apiBaseUrl && decodedConfig.serverKey) {
|
|
48
|
+
apiBaseUrl = decodedConfig.apiBaseUrl;
|
|
49
|
+
serverKey = decodedConfig.serverKey;
|
|
50
|
+
}
|
|
51
|
+
} catch (error) {
|
|
52
|
+
console.error('Failed to decode config from URL:', error);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// If not found in encoded config, try localStorage (for same-device scenarios)
|
|
57
|
+
if (!apiBaseUrl || !serverKey) {
|
|
58
|
+
const storedConfig = getKycConfig(sessionId);
|
|
59
|
+
if (storedConfig) {
|
|
60
|
+
apiBaseUrl = storedConfig.apiBaseUrl;
|
|
61
|
+
serverKey = storedConfig.serverKey;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Fallback: try to get from URL params directly (for backward compatibility)
|
|
66
|
+
if (!apiBaseUrl || !serverKey) {
|
|
67
|
+
apiBaseUrl = searchParams.get('apiBaseUrl') || searchParams.get('apiUrl') || '';
|
|
68
|
+
serverKey = searchParams.get('serverKey') || '';
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (apiBaseUrl && serverKey) {
|
|
72
|
+
setConfig({
|
|
73
|
+
apiBaseUrl,
|
|
74
|
+
sessionId,
|
|
75
|
+
serverKey,
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
console.error('Missing required parameters: apiBaseUrl and serverKey not found in URL config, localStorage, or URL params');
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
console.error('Missing required parameter: sessionId must be in URL');
|
|
46
82
|
}
|
|
47
83
|
}, [onNavigate]);
|
|
48
84
|
|
|
@@ -90,7 +126,7 @@ function MobileRoute({ onClose, onNavigate }: MobileRouteProps = {}) {
|
|
|
90
126
|
<div className="bg-white p-6 rounded-lg text-center max-w-md mx-4">
|
|
91
127
|
<p className="text-red-600 mb-2">Missing Configuration</p>
|
|
92
128
|
<p className="text-sm text-gray-600">
|
|
93
|
-
Please ensure the URL includes sessionId
|
|
129
|
+
Please ensure the URL includes sessionId parameter. The configuration should be stored automatically when scanning the QR code.
|
|
94
130
|
</p>
|
|
95
131
|
</div>
|
|
96
132
|
</div>
|
package/src/pages/QRCodePage.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useState, useEffect } from 'react';
|
|
2
2
|
import { QRCodeSVG } from 'qrcode.react';
|
|
3
3
|
import { KycApiService } from '../services/kycApiService';
|
|
4
|
+
import { storeKycConfig } from '../utils/kycConfigStorage';
|
|
4
5
|
// @ts-ignore - optional dependency, may not be installed in some consumers
|
|
5
6
|
import { toast, ToastContainer } from 'react-toastify';
|
|
6
7
|
// @ts-ignore - import styles only when package is present
|
|
@@ -21,25 +22,25 @@ function QRCodePage({ onClose, mobileBaseUrl = 'https://kyc-sdk.astraprotocol.co
|
|
|
21
22
|
const [copied, setCopied] = useState<boolean>(false);
|
|
22
23
|
|
|
23
24
|
useEffect(() => {
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
// Add required params to query string for mobile route
|
|
28
|
-
if (sessionId) {
|
|
29
|
-
searchParams.set('sessionId', sessionId);
|
|
30
|
-
}
|
|
31
|
-
if (apiBaseUrl) {
|
|
32
|
-
searchParams.set('apiBaseUrl', apiBaseUrl);
|
|
25
|
+
// Store config in localStorage for mobile route to retrieve (for same-device scenarios)
|
|
26
|
+
if (sessionId && apiBaseUrl && serverKey) {
|
|
27
|
+
storeKycConfig(sessionId, apiBaseUrl, serverKey);
|
|
33
28
|
}
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
|
|
30
|
+
// Encode config in URL for cross-device scenarios (when QR is scanned on different device)
|
|
31
|
+
if (sessionId && apiBaseUrl && serverKey) {
|
|
32
|
+
const mobileRoute = '/mobileroute';
|
|
33
|
+
// Encode config as base64 to include in URL (needed for cross-device QR scanning)
|
|
34
|
+
const config = JSON.stringify({ apiBaseUrl, serverKey });
|
|
35
|
+
const encodedConfig = btoa(config);
|
|
36
|
+
const fullUrl = `${mobileBaseUrl}${mobileRoute}?sessionId=${sessionId}&config=${encodedConfig}`;
|
|
37
|
+
setQrUrl(fullUrl);
|
|
38
|
+
} else if (sessionId) {
|
|
39
|
+
// Fallback: just sessionId if config not available
|
|
40
|
+
const mobileRoute = '/mobileroute';
|
|
41
|
+
const fullUrl = `${mobileBaseUrl}${mobileRoute}?sessionId=${sessionId}`;
|
|
42
|
+
setQrUrl(fullUrl);
|
|
36
43
|
}
|
|
37
|
-
|
|
38
|
-
const mobileRoute = '/mobileroute';
|
|
39
|
-
const queryString = searchParams.toString();
|
|
40
|
-
const fullUrl = `${mobileBaseUrl}${mobileRoute}${queryString ? `?${queryString}` : ''}`;
|
|
41
|
-
|
|
42
|
-
setQrUrl(fullUrl);
|
|
43
44
|
}, [mobileBaseUrl, sessionId, apiBaseUrl, serverKey]);
|
|
44
45
|
|
|
45
46
|
const handleCopyUrl = async () => {
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for storing and retrieving KYC configuration
|
|
3
|
+
* Uses localStorage to store apiBaseUrl and serverKey associated with sessionId
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
interface KycConfig {
|
|
7
|
+
apiBaseUrl: string;
|
|
8
|
+
serverKey: string;
|
|
9
|
+
sessionId: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const STORAGE_PREFIX = 'kyc_config_';
|
|
13
|
+
const STORAGE_EXPIRY_MS = 24 * 60 * 60 * 1000; // 24 hours
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Store KYC configuration in localStorage
|
|
17
|
+
*/
|
|
18
|
+
export function storeKycConfig(sessionId: string, apiBaseUrl: string, serverKey: string): void {
|
|
19
|
+
if (!sessionId || !apiBaseUrl || !serverKey) {
|
|
20
|
+
console.warn('Cannot store KYC config: missing required parameters');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const config: KycConfig = {
|
|
26
|
+
apiBaseUrl,
|
|
27
|
+
serverKey,
|
|
28
|
+
sessionId,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const storageKey = `${STORAGE_PREFIX}${sessionId}`;
|
|
32
|
+
const data = {
|
|
33
|
+
config,
|
|
34
|
+
timestamp: Date.now(),
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
localStorage.setItem(storageKey, JSON.stringify(data));
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.error('Failed to store KYC config:', error);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Retrieve KYC configuration from localStorage
|
|
45
|
+
*/
|
|
46
|
+
export function getKycConfig(sessionId: string): { apiBaseUrl: string; serverKey: string } | null {
|
|
47
|
+
if (!sessionId) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const storageKey = `${STORAGE_PREFIX}${sessionId}`;
|
|
53
|
+
const stored = localStorage.getItem(storageKey);
|
|
54
|
+
|
|
55
|
+
if (!stored) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const data = JSON.parse(stored);
|
|
60
|
+
|
|
61
|
+
// Check if config is expired
|
|
62
|
+
if (data.timestamp && Date.now() - data.timestamp > STORAGE_EXPIRY_MS) {
|
|
63
|
+
localStorage.removeItem(storageKey);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (data.config && data.config.apiBaseUrl && data.config.serverKey) {
|
|
68
|
+
return {
|
|
69
|
+
apiBaseUrl: data.config.apiBaseUrl,
|
|
70
|
+
serverKey: data.config.serverKey,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return null;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
console.error('Failed to retrieve KYC config:', error);
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Clear KYC configuration from localStorage
|
|
83
|
+
*/
|
|
84
|
+
export function clearKycConfig(sessionId: string): void {
|
|
85
|
+
if (!sessionId) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const storageKey = `${STORAGE_PREFIX}${sessionId}`;
|
|
91
|
+
localStorage.removeItem(storageKey);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error('Failed to clear KYC config:', error);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Clear all expired KYC configurations
|
|
99
|
+
*/
|
|
100
|
+
export function clearExpiredConfigs(): void {
|
|
101
|
+
try {
|
|
102
|
+
const keys = Object.keys(localStorage);
|
|
103
|
+
const now = Date.now();
|
|
104
|
+
|
|
105
|
+
keys.forEach((key) => {
|
|
106
|
+
if (key.startsWith(STORAGE_PREFIX)) {
|
|
107
|
+
try {
|
|
108
|
+
const stored = localStorage.getItem(key);
|
|
109
|
+
if (stored) {
|
|
110
|
+
const data = JSON.parse(stored);
|
|
111
|
+
if (data.timestamp && now - data.timestamp > STORAGE_EXPIRY_MS) {
|
|
112
|
+
localStorage.removeItem(key);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
} catch (error) {
|
|
116
|
+
// If parsing fails, remove the key
|
|
117
|
+
localStorage.removeItem(key);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
} catch (error) {
|
|
122
|
+
console.error('Failed to clear expired configs:', error);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|