@sanctum-key/react-native-sdk 1.0.51 → 1.0.53
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/android/build/intermediates/compiled_local_resources/debug/compileDebugLibraryResources/out/xml_file_paths.xml.flat +0 -0
- package/android/build/intermediates/incremental/debug/packageDebugResources/compile-file-map.properties +2 -2
- package/android/build/intermediates/incremental/debug/packageDebugResources/merger.xml +1 -1
- package/android/build/intermediates/incremental/mergeDebugJniLibFolders/merger.xml +1 -1
- package/android/build/intermediates/incremental/mergeDebugShaders/merger.xml +1 -1
- package/android/build/intermediates/incremental/packageDebugAssets/merger.xml +1 -1
- package/android/build/intermediates/manifest_merge_blame_file/debug/processDebugManifest/manifest-merger-blame-debug-report.txt +41 -41
- package/android/build/kotlin/compileDebugKotlin/cacheable/last-build.bin +0 -0
- package/android/build/kotlin/compileDebugKotlin/local-state/build-history.bin +0 -0
- package/android/build/outputs/logs/manifest-merger-debug-report.txt +52 -52
- package/build/package.json +1 -1
- package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.js +73 -66
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/components/TemplateKYCExample.d.ts +2 -1
- package/build/src/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/src/components/TemplateKYCExample.js +20 -18
- package/build/src/components/TemplateKYCExample.js.map +1 -1
- package/build/src/components/TemplateKYCFlowRefactored.d.ts +1 -0
- package/build/src/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/src/components/TemplateKYCFlowRefactored.js +20 -20
- package/build/src/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/src/config/KYCConfig.d.ts.map +1 -1
- package/build/src/config/KYCConfig.js +4 -2
- package/build/src/config/KYCConfig.js.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.d.ts +1 -0
- package/build/src/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/src/hooks/useTemplateLoader.d.ts.map +1 -1
- package/build/src/hooks/useTemplateLoader.js +0 -2
- package/build/src/hooks/useTemplateLoader.js.map +1 -1
- package/build/src/modules/api/CardAuthentification.d.ts +0 -23
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +46 -83
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +96 -38
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/modules/api/SelfieVerification.d.ts.map +1 -1
- package/build/src/modules/api/SelfieVerification.js +12 -19
- package/build/src/modules/api/SelfieVerification.js.map +1 -1
- package/build/src/modules/api/TemplateService.d.ts.map +1 -1
- package/build/src/modules/api/TemplateService.js +2 -1
- package/build/src/modules/api/TemplateService.js.map +1 -1
- package/build/src/modules/api/types.d.ts +34 -27
- package/build/src/modules/api/types.d.ts.map +1 -1
- package/build/src/modules/api/types.js.map +1 -1
- package/package.json +1 -1
- package/src/components/KYCElements/IDCardCapture.tsx +192 -191
- package/src/components/TemplateKYCExample.tsx +29 -20
- package/src/components/TemplateKYCFlowRefactored.tsx +33 -31
- package/src/config/KYCConfig.ts +7 -5
- package/src/hooks/useTemplateKYCFlow.tsx +1 -0
- package/src/hooks/useTemplateLoader.ts +0 -2
- package/src/modules/api/CardAuthentification.ts +409 -445
- package/src/modules/api/KYCService.ts +599 -449
- package/src/modules/api/SelfieVerification.ts +22 -29
- package/src/modules/api/TemplateService.ts +3 -2
- package/src/modules/api/types.ts +36 -29
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TemplateService.js","sourceRoot":"","sources":["../../../../src/modules/api/TemplateService.ts"],"names":[],"mappings":"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","sourcesContent":["import axios from 'axios';\nimport { BackendKYCTemplate, TemplateAPIResponse } from '../../types/KYC.types';\nimport { logger } from '../../utils/logger';\nimport { errorMessage } from './KYCService';\nimport KYCConfig from '../../config/KYCConfig';\n\nexport class TemplateServiceClass {\n private cache: Map<string, { template: BackendKYCTemplate; timestamp: number }> = new Map();\n private cacheTimeout = 5 * 60 * 1000; // 5 minutes\n\n /**\n * Get headers for API requests\n */\n private getHeaders(apiKey?: string, token?: string) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `ApiKey ${apiKey}`;\n } else if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n return headers;\n }\n\n /**\n * Fetch a template from the backend API\n * @param templateId - The ID of the template to fetch\n * @param apiKey - Optional API key for authentication\n * @param token - Optional Bearer token for authentication\n * @param useCache - Whether to use cached version if available (default: true)\n * @returns The backend template\n */\n async fetchTemplate(\n templateId: string,\n apiKey?: string,\n token?: string,\n useCache: boolean = true\n ): Promise<BackendKYCTemplate> {\n // Check cache first\n if (useCache) {\n const cached = this.cache.get(templateId);\n if (cached) {\n const age = Date.now() - cached.timestamp;\n if (age < this.cacheTimeout) {\n logger.log(`Template ${templateId} loaded from cache`);\n return cached.template;\n } else {\n // Cache expired, remove it\n this.cache.delete(templateId);\n }\n }\n }\n\n try {\n const url = `${KYCConfig.getBackendUrl()}/templates/kyc/template/${templateId}/`;\n logger.log(templateId)\n logger.log(`Fetching template from: ${url} with apiKey: ${apiKey} and token: ${token}`, {\n headers: this.getHeaders(apiKey, token)\n });\n\n const response = await axios.get<TemplateAPIResponse>(url, {\n headers: this.getHeaders(apiKey, token),\n timeout: 30000, // 30 seconds timeout\n });\n\n const template: BackendKYCTemplate = response.data;\n\n // Validate template structure\n if (!template.id || !template.name || !Array.isArray(template.components)) {\n throw new Error('Invalid template structure received from API');\n }\n\n // Store in cache\n this.cache.set(templateId, {\n template,\n timestamp: Date.now(),\n });\n\n logger.log(`Template ${templateId} fetched successfully`);\n return template;\n } catch (error: any) {\n logger.error(`Error fetching template ${templateId}:`, JSON.stringify(errorMessage(error), null, 2));\n\n // Extract backend error message if available\n const backendMessage = errorMessage(error);\n\n if (error.response?.status === 404) {\n throw new Error(`Template not found: ${templateId}`);\n }\n\n if (error.response?.status === 401 || error.response?.status === 403) {\n throw new Error(`Unauthorized: Invalid API key or token`);\n }\n\n if (backendMessage) {\n throw new Error(`Failed to fetch template: ${JSON.stringify(backendMessage)}`);\n }\n\n throw new Error(`Failed to fetch template: ${error.message || 'Unknown error'}`);\n }\n }\n\n /**\n * Clear the template cache\n * @param templateId - Optional template ID to clear. If not provided, clears all cache.\n */\n clearCache(templateId?: string): void {\n if (templateId) {\n this.cache.delete(templateId);\n logger.log(`Cache cleared for template: ${templateId}`);\n } else {\n this.cache.clear();\n logger.log('All template cache cleared');\n }\n }\n\n /**\n * Get cached template if available\n * @param templateId - The template ID\n * @returns The cached template or null if not found/expired\n */\n getCachedTemplate(templateId: string): BackendKYCTemplate | null {\n const cached = this.cache.get(templateId);\n if (cached) {\n const age = Date.now() - cached.timestamp;\n if (age < this.cacheTimeout) {\n return cached.template;\n } else {\n this.cache.delete(templateId);\n }\n }\n return null;\n }\n\n /**\n * Fetch list of available templates (optional feature)\n * @param apiKey - Optional API key for authentication\n * @param token - Optional Bearer token for authentication\n * @returns Array of template metadata\n */\n async fetchTemplateList(apiKey?: string, token?: string): Promise<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>> {\n try {\n const url = `${KYCConfig.getBackendUrl()}/templates/kyc/templates`;\n logger.log(`Fetching template list from: ${url}`);\n\n const response = await axios.get<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>>(url, {\n headers: this.getHeaders(apiKey, token),\n timeout: 30000,\n });\n\n logger.log(`Fetched ${response.data.length} templates`);\n return response.data;\n } catch (error: any) {\n logger.error('Error fetching template list:', JSON.stringify(errorMessage(error), null, 2));\n throw new Error(`Failed to fetch template list: ${error.message || 'Unknown error'}`);\n }\n }\n}\n\n// Export singleton instance as default\nconst templateService = new TemplateServiceClass();\nexport default templateService;\n\n// Also export the class for advanced usage\n// export { TemplateServiceClass };"]}
|
|
1
|
+
{"version":3,"file":"TemplateService.js","sourceRoot":"","sources":["../../../../src/modules/api/TemplateService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAE/C,MAAM,OAAO,oBAAoB;IACvB,KAAK,GAAqE,IAAI,GAAG,EAAE,CAAC;IACpF,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,YAAY;IAElD;;OAEG;IACK,UAAU,CAAC,MAAe,EAAE,KAAc;QAChD,MAAM,OAAO,GAA2B;YACtC,cAAc,EAAE,kBAAkB;SACnC,CAAC;QAEF,IAAI,MAAM,EAAE,CAAC;YACX,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,EAAE,CAAC;QAChD,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;QAC/C,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,aAAa,CACjB,UAAkB,EAClB,MAAe,EACf,KAAc,EACd,WAAoB,IAAI;QAExB,oBAAoB;QACpB,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAC1C,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;gBAC1C,IAAI,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;oBAC5B,MAAM,CAAC,GAAG,CAAC,YAAY,UAAU,oBAAoB,CAAC,CAAC;oBACvD,OAAO,MAAM,CAAC,QAAQ,CAAC;gBACzB,CAAC;qBAAM,CAAC;oBACN,2BAA2B;oBAC3B,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,aAAa,EAAE,2BAA2B,UAAU,GAAG,CAAC;YACjF,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,CAAA;YACtB,MAAM,CAAC,GAAG,CAAC,2BAA2B,GAAG,iBAAiB,MAAM,eAAe,KAAK,EAAE,EAAE;gBACtF,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC;aACxC,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAsB,GAAG,EAAE;gBACzD,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC;gBACvC,OAAO,EAAE,KAAK,EAAE,qBAAqB;aACtC,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAuB,QAAQ,CAAC,IAAI,CAAC;YAEnD,8BAA8B;YAC9B,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC1E,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAClE,CAAC;YAED,iBAAiB;YACjB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE;gBACzB,QAAQ;gBACR,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;aACtB,CAAC,CAAC;YAEH,MAAM,CAAC,GAAG,CAAC,YAAY,UAAU,uBAAuB,CAAC,CAAC;YAC1D,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,2BAA2B,UAAU,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;YACpG,SAAS,CAAC,KAAK,CAAC,2BAA2B,UAAU,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAExG,6CAA6C;YAC7C,MAAM,cAAc,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;YAE3C,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnC,MAAM,IAAI,KAAK,CAAC,uBAAuB,UAAU,EAAE,CAAC,CAAC;YACvD,CAAC;YAED,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,CAAC;gBACrE,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;YAC5D,CAAC;YAED,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;YACjF,CAAC;YAED,MAAM,IAAI,KAAK,CAAC,6BAA6B,KAAK,CAAC,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,UAAmB;QAC5B,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,CAAC,GAAG,CAAC,+BAA+B,UAAU,EAAE,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,iBAAiB,CAAC,UAAkB;QAClC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC;YAC1C,IAAI,GAAG,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC5B,OAAO,MAAM,CAAC,QAAQ,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,iBAAiB,CAAC,MAAe,EAAE,KAAc;QACrD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,aAAa,EAAE,0BAA0B,CAAC;YACnE,MAAM,CAAC,GAAG,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;YAElD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAyF,GAAG,EAAE;gBAC5H,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC;gBACvC,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YAEH,MAAM,CAAC,GAAG,CAAC,WAAW,QAAQ,CAAC,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC;YACxD,OAAO,QAAQ,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC5F,MAAM,IAAI,KAAK,CAAC,kCAAkC,KAAK,CAAC,OAAO,IAAI,eAAe,EAAE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;CACF;AAED,uCAAuC;AACvC,MAAM,eAAe,GAAG,IAAI,oBAAoB,EAAE,CAAC;AACnD,eAAe,eAAe,CAAC;AAE/B,2CAA2C;AAC3C,mCAAmC","sourcesContent":["import axios from 'axios';\nimport { BackendKYCTemplate, TemplateAPIResponse } from '../../types/KYC.types';\nimport { logger, sdkLogger } from '../../utils/logger';\nimport { errorMessage } from './KYCService';\nimport KYCConfig from '../../config/KYCConfig';\n\nexport class TemplateServiceClass {\n private cache: Map<string, { template: BackendKYCTemplate; timestamp: number }> = new Map();\n private cacheTimeout = 5 * 60 * 1000; // 5 minutes\n\n /**\n * Get headers for API requests\n */\n private getHeaders(apiKey?: string, token?: string) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n\n if (apiKey) {\n headers['Authorization'] = `ApiKey ${apiKey}`;\n } else if (token) {\n headers['Authorization'] = `Bearer ${token}`;\n }\n\n return headers;\n }\n\n /**\n * Fetch a template from the backend API\n * @param templateId - The ID of the template to fetch\n * @param apiKey - Optional API key for authentication\n * @param token - Optional Bearer token for authentication\n * @param useCache - Whether to use cached version if available (default: true)\n * @returns The backend template\n */\n async fetchTemplate(\n templateId: string,\n apiKey?: string,\n token?: string,\n useCache: boolean = true\n ): Promise<BackendKYCTemplate> {\n // Check cache first\n if (useCache) {\n const cached = this.cache.get(templateId);\n if (cached) {\n const age = Date.now() - cached.timestamp;\n if (age < this.cacheTimeout) {\n logger.log(`Template ${templateId} loaded from cache`);\n return cached.template;\n } else {\n // Cache expired, remove it\n this.cache.delete(templateId);\n }\n }\n }\n\n try {\n const url = `${KYCConfig.getBackendUrl()}/templates/kyc/template/${templateId}/`;\n logger.log(templateId)\n logger.log(`Fetching template from: ${url} with apiKey: ${apiKey} and token: ${token}`, {\n headers: this.getHeaders(apiKey, token)\n });\n\n const response = await axios.get<TemplateAPIResponse>(url, {\n headers: this.getHeaders(apiKey, token),\n timeout: 30000, // 30 seconds timeout\n });\n\n const template: BackendKYCTemplate = response.data;\n\n // Validate template structure\n if (!template.id || !template.name || !Array.isArray(template.components)) {\n throw new Error('Invalid template structure received from API');\n }\n\n // Store in cache\n this.cache.set(templateId, {\n template,\n timestamp: Date.now(),\n });\n\n logger.log(`Template ${templateId} fetched successfully`);\n return template;\n } catch (error: any) {\n logger.error(`Error fetching template ${templateId}:`, JSON.stringify(errorMessage(error), null, 2))\n sdkLogger.error(`Error fetching template ${templateId}:`, JSON.stringify(errorMessage(error), null, 2));\n\n // Extract backend error message if available\n const backendMessage = errorMessage(error);\n\n if (error.response?.status === 404) {\n throw new Error(`Template not found: ${templateId}`);\n }\n\n if (error.response?.status === 401 || error.response?.status === 403) {\n throw new Error(`Unauthorized: Invalid API key or token`);\n }\n\n if (backendMessage) {\n throw new Error(`Failed to fetch template: ${JSON.stringify(backendMessage)}`);\n }\n\n throw new Error(`Failed to fetch template: ${error.message || 'Unknown error'}`);\n }\n }\n\n /**\n * Clear the template cache\n * @param templateId - Optional template ID to clear. If not provided, clears all cache.\n */\n clearCache(templateId?: string): void {\n if (templateId) {\n this.cache.delete(templateId);\n logger.log(`Cache cleared for template: ${templateId}`);\n } else {\n this.cache.clear();\n logger.log('All template cache cleared');\n }\n }\n\n /**\n * Get cached template if available\n * @param templateId - The template ID\n * @returns The cached template or null if not found/expired\n */\n getCachedTemplate(templateId: string): BackendKYCTemplate | null {\n const cached = this.cache.get(templateId);\n if (cached) {\n const age = Date.now() - cached.timestamp;\n if (age < this.cacheTimeout) {\n return cached.template;\n } else {\n this.cache.delete(templateId);\n }\n }\n return null;\n }\n\n /**\n * Fetch list of available templates (optional feature)\n * @param apiKey - Optional API key for authentication\n * @param token - Optional Bearer token for authentication\n * @returns Array of template metadata\n */\n async fetchTemplateList(apiKey?: string, token?: string): Promise<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>> {\n try {\n const url = `${KYCConfig.getBackendUrl()}/templates/kyc/templates`;\n logger.log(`Fetching template list from: ${url}`);\n\n const response = await axios.get<Array<{ id: string; name: Record<string, string>; version?: string; status?: string }>>(url, {\n headers: this.getHeaders(apiKey, token),\n timeout: 30000,\n });\n\n logger.log(`Fetched ${response.data.length} templates`);\n return response.data;\n } catch (error: any) {\n logger.error('Error fetching template list:', JSON.stringify(errorMessage(error), null, 2));\n throw new Error(`Failed to fetch template list: ${error.message || 'Unknown error'}`);\n }\n }\n}\n\n// Export singleton instance as default\nconst templateService = new TemplateServiceClass();\nexport default templateService;\n\n// Also export the class for advanced usage\n// export { TemplateServiceClass };"]}
|
|
@@ -19,35 +19,42 @@ export interface VerificationSessionRequest {
|
|
|
19
19
|
}
|
|
20
20
|
export type VerificationSessionData = Record<string, any>;
|
|
21
21
|
export interface VerificationResult {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
22
|
+
message?: string;
|
|
23
|
+
status?: string;
|
|
24
|
+
referenceId?: string;
|
|
25
|
+
issues?: string[];
|
|
26
|
+
data?: {
|
|
27
|
+
session_id?: string;
|
|
28
|
+
verification_id?: string;
|
|
29
|
+
verification_status?: string;
|
|
30
|
+
completion_timestamp?: string;
|
|
31
|
+
user_data?: {
|
|
32
|
+
personal_information?: {
|
|
33
|
+
full_name?: string | null;
|
|
34
|
+
first_name?: string | null;
|
|
35
|
+
last_name?: string | null;
|
|
36
|
+
given_name?: string | null;
|
|
37
|
+
surname?: string | null;
|
|
38
|
+
date_of_birth?: string | null;
|
|
39
|
+
birth_date?: string | null;
|
|
40
|
+
sex?: string | null;
|
|
41
|
+
expiry_date?: string | null;
|
|
42
|
+
issue_date?: string | null;
|
|
43
|
+
issue_place?: string | null;
|
|
44
|
+
place_of_birth?: string | null;
|
|
45
|
+
address?: string | null;
|
|
46
|
+
city?: string | null;
|
|
47
|
+
postal_code?: string | null;
|
|
48
|
+
country?: string | null;
|
|
49
|
+
nationality?: string | null;
|
|
50
|
+
document_number?: string | null;
|
|
49
51
|
};
|
|
50
52
|
};
|
|
53
|
+
selfie_info?: {
|
|
54
|
+
is_match?: boolean;
|
|
55
|
+
similarity?: number;
|
|
56
|
+
image?: string;
|
|
57
|
+
};
|
|
51
58
|
};
|
|
52
59
|
}
|
|
53
60
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/api/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,0BAA0B;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,uBAAuB,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IAC/B,CAAC,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/modules/api/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,0BAA0B;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,uBAAuB,CAAC;IAC9B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,MAAM,MAAM,uBAAuB,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAG1D,MAAM,WAAW,kBAAkB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,CAAC,EAAE;QACL,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,SAAS,CAAC,EAAE;YACV,oBAAoB,CAAC,EAAE;gBACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBACxB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC9B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBACpB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC3B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC5B,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBACxB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBACxB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;gBAC5B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;aACjC,CAAC;SACH,CAAC;QACF,WAAW,CAAC,EAAE;YACZ,QAAQ,CAAC,EAAE,OAAO,CAAC;YACnB,UAAU,CAAC,EAAE,MAAM,CAAC;YACpB,KAAK,CAAC,EAAE,MAAM,CAAC;SAChB,CAAC;KACH,CAAC;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/modules/api/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface SessionResponse {\n id: number;\n session_id: string;\n status: string;\n created_at: string;\n updated_at: string;\n metadata: string;\n user: number;\n module: number;\n}\n\n\nexport interface VerificationSessionRequest {\n step: number;\n data: VerificationSessionData;\n templateId: string | null;\n session_id: string;\n token: string;\n action: string\n apiKey?: string;\n}\n\n\n// dynamic type\nexport type VerificationSessionData = Record<string, any>;\n\n\nexport interface VerificationResult {\n
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/modules/api/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface SessionResponse {\n id: number;\n session_id: string;\n status: string;\n created_at: string;\n updated_at: string;\n metadata: string;\n user: number;\n module: number;\n}\n\n\nexport interface VerificationSessionRequest {\n step: number;\n data: VerificationSessionData;\n templateId: string | null;\n session_id: string;\n token: string;\n action: string\n apiKey?: string;\n}\n\n\n// dynamic type\nexport type VerificationSessionData = Record<string, any>;\n\n\nexport interface VerificationResult {\n message?: string;\n status?: string;\n referenceId?: string;\n issues?: string[];\n data?: {\n session_id?: string;\n verification_id?: string;\n verification_status?: string;\n completion_timestamp?: string;\n user_data?: {\n personal_information?: {\n full_name?: string | null;\n first_name?: string | null;\n last_name?: string | null;\n given_name?: string | null;\n surname?: string | null;\n date_of_birth?: string | null;\n birth_date?: string | null;\n sex?: string | null;\n expiry_date?: string | null;\n issue_date?: string | null;\n issue_place?: string | null;\n place_of_birth?: string | null;\n address?: string | null;\n city?: string | null;\n postal_code?: string | null;\n country?: string | null;\n nationality?: string | null;\n document_number?: string | null;\n };\n };\n selfie_info?: {\n is_match?: boolean;\n similarity?: number;\n image?: string;\n };\n };\n }"]}
|
package/package.json
CHANGED
|
@@ -525,217 +525,218 @@ export const IDCardCapture: React.FC<IDCardCaptureProps> = ({ component, value =
|
|
|
525
525
|
}
|
|
526
526
|
};
|
|
527
527
|
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
528
|
+
const handleSilentCapture = async (result: { success: boolean; path?: string; error?: string; barcode?: unknown }) => {
|
|
529
|
+
if (isProcessingCaptureRef.current) return;
|
|
530
|
+
if (scanPhaseRef.current === 'barcode') return;
|
|
531
|
+
if (isAnalyzingRef.current) return;
|
|
532
|
+
|
|
533
|
+
// 🚨 SYNCHRONOUS LOCK: Block all subsequent camera frames immediately
|
|
534
|
+
isAnalyzingRef.current = true;
|
|
535
|
+
|
|
536
|
+
const side = currentSideRef.current;
|
|
537
|
+
const captured = capturedImagesRef.current;
|
|
538
|
+
const docType = selectedDocTypeRef.current;
|
|
539
|
+
const cData = countryDataRef.current;
|
|
540
|
+
|
|
541
|
+
if (result.success && result.path) {
|
|
542
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: true, success: false, error: '' }));
|
|
543
|
+
const safeCapturePath = Platform.OS === 'ios' && !result.path.startsWith('file://') ? `file://${result.path}` : result.path;
|
|
544
|
+
|
|
545
|
+
let templatePath = captured[side]?.templatePath || '';
|
|
546
|
+
let templateBbox: IBbox | undefined;
|
|
547
|
+
let templateResponse: any;
|
|
538
548
|
|
|
539
|
-
if (
|
|
540
|
-
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing:
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
let templateBbox: IBbox | undefined;
|
|
545
|
-
let templateResponse: any;
|
|
549
|
+
if (!docType) {
|
|
550
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: 'Document type not selected' }));
|
|
551
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
546
554
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
555
|
+
const issuingSubdivision = docType.region !== 'root' ? docType.region : undefined;
|
|
556
|
+
|
|
557
|
+
const watchdog = setTimeout(() => {
|
|
558
|
+
if (isAnalyzingRef.current) {
|
|
559
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK inside watchdog
|
|
560
|
+
setSilentCaptureResult((prev) => ({
|
|
561
|
+
...prev,
|
|
562
|
+
isAnalyzing: false,
|
|
563
|
+
success: false,
|
|
564
|
+
error: state.currentLanguage === 'en' ? 'Taking longer than expected. Hold steady.' : 'Traitement long. Veuillez rester immobile.'
|
|
565
|
+
}));
|
|
550
566
|
}
|
|
567
|
+
}, 20000);
|
|
551
568
|
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
try { const crop = await cropByObb(safeCapturePath, (templateType as any).card_obb); templateBbox = crop.bbox; } catch {}
|
|
569
|
+
try {
|
|
570
|
+
if (!templatePath) {
|
|
571
|
+
const templateType = await checkTemplateType({
|
|
572
|
+
path: safeCapturePath,
|
|
573
|
+
docType: docType.type as GovernmentDocumentType,
|
|
574
|
+
docRegion: cData?.code || "",
|
|
575
|
+
postfix: side,
|
|
576
|
+
issuingSubdivision: issuingSubdivision
|
|
577
|
+
}, env);
|
|
578
|
+
|
|
579
|
+
templateResponse = templateType;
|
|
580
|
+
if (templateType.template_path) templatePath = templateType.template_path;
|
|
581
|
+
|
|
582
|
+
if (templateType.card_obb) {
|
|
583
|
+
const obbConfidence = getObbConfidence((templateType as any).card_obb);
|
|
584
|
+
if (obbConfidence !== null && obbConfidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
585
|
+
clearTimeout(watchdog);
|
|
586
|
+
setSilentCaptureResult((prev) => ({ ...prev, isAnalyzing: false, success: false, error: t('kyc.idCardCapture.cardNotFullyInFrame') }));
|
|
587
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK
|
|
588
|
+
return;
|
|
573
589
|
}
|
|
590
|
+
try {
|
|
591
|
+
const crop = await cropByObb(safeCapturePath, (templateType as any).card_obb);
|
|
592
|
+
templateBbox = crop.bbox;
|
|
593
|
+
} catch {}
|
|
574
594
|
}
|
|
595
|
+
}
|
|
575
596
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
597
|
+
sdkLogger.info(`Template check passed for ${side}`, { templatePath });
|
|
598
|
+
|
|
599
|
+
const extractedCountryKey = templatePath ? templatePath.split('/')[0] : (ISO_TO_COUNTRY_NAME[cData?.code || ''] || 'root');
|
|
600
|
+
const regionMappings = getCurrentSideVerification(side, extractedCountryKey, cData);
|
|
601
|
+
|
|
602
|
+
let verificationRes: any;
|
|
603
|
+
if (side === 'front') {
|
|
604
|
+
const matchedAuthMethod = getCorrespondingAuthMethod(templatePath, regionMappings.regionMapping, regionMappings.key || '', 'front');
|
|
605
|
+
const mrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || 'TD1';
|
|
606
|
+
|
|
607
|
+
verificationRes = await frontVerification({
|
|
608
|
+
path: safeCapturePath,
|
|
609
|
+
regionMapping: { authMethod: matchedAuthMethod ? [matchedAuthMethod] : [], mrzTypes: mrzType ? [mrzType] : [] },
|
|
610
|
+
selectedDocumentType: GovernmentDocumentTypeShorted[docType.type as keyof typeof GovernmentDocumentTypeShorted] || '',
|
|
611
|
+
code: cData?.code || '',
|
|
612
|
+
currentSide: side,
|
|
613
|
+
templatePath,
|
|
614
|
+
mrzType,
|
|
615
|
+
issuingSubdivision: issuingSubdivision,
|
|
616
|
+
clientSideBarcodeData: silentCaptureResult.barcode
|
|
617
|
+
}, env);
|
|
618
|
+
} else {
|
|
619
|
+
const matchedBackAuthMethod = getCorrespondingAuthMethod(templatePath, regionMappings.regionMapping, regionMappings.key || '', 'back');
|
|
620
|
+
const backMrzType = getCorrespondingMrzType(templatePath, regionMappings.regionMapping, regionMappings.key || '') || '';
|
|
621
|
+
const frontTemplatePath = captured['front']?.templatePath || '';
|
|
622
|
+
|
|
623
|
+
verificationRes = await backVerification({
|
|
624
|
+
path: safeCapturePath,
|
|
625
|
+
regionMapping: { authMethod: matchedBackAuthMethod ? [matchedBackAuthMethod] : [], mrzTypes: backMrzType ? [backMrzType] : [] },
|
|
626
|
+
selectedDocumentType: GovernmentDocumentTypeShorted[docType.type as keyof typeof GovernmentDocumentTypeShorted] || '',
|
|
627
|
+
code: cData?.code || '',
|
|
628
|
+
currentSide: side,
|
|
629
|
+
templatePath,
|
|
630
|
+
mrzType: backMrzType,
|
|
631
|
+
templateResponse,
|
|
632
|
+
issuingSubdivision: issuingSubdivision,
|
|
633
|
+
frontTemplatePath: frontTemplatePath
|
|
634
|
+
}, env);
|
|
635
|
+
}
|
|
591
636
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
}
|
|
608
|
-
const verifiedResult: ISilentCaptureResult & { region?: string } = { path: safeCapturePath, templatePath: templatePath, bbox: bbox, success: true, mrz: JSON.stringify(parsedDictionary), barcode: barcodeData, isAnalyzing: false, country: cData?.code, documentType: docType.type, region: docType.region !== 'root' ? docType.region : undefined };
|
|
609
|
-
|
|
610
|
-
clearTimeout(watchdog); setSilentCaptureResult(verifiedResult);
|
|
611
|
-
if (bbox) setBboxBySide(prev => ({ ...prev, ['back']: bbox as IBbox }));
|
|
612
|
-
await autoCapture(safeCapturePath!, verifiedResult);
|
|
613
|
-
return;
|
|
637
|
+
const bbox = verificationRes?.bbox || templateBbox;
|
|
638
|
+
const verifiedMrz = verificationRes?.mrz ? JSON.stringify(verificationRes.mrz) : "";
|
|
639
|
+
|
|
640
|
+
if (isBarcodeRequired(side, cData, docType)) {
|
|
641
|
+
const barcodeData = scannedBarcodeRef.current;
|
|
642
|
+
const isHIC = docType.type === 'health_insurance_card';
|
|
643
|
+
const isValidScan = typeof barcodeData === 'string' && ((isHIC && barcodeData.length > 0) || barcodeData.length > 50);
|
|
644
|
+
|
|
645
|
+
if (isValidScan) {
|
|
646
|
+
let parsedDictionary;
|
|
647
|
+
if (isHIC && barcodeData.length < 50) {
|
|
648
|
+
parsedDictionary = { data: { card_number: barcodeData, barcode_type: "1D" } };
|
|
649
|
+
} else {
|
|
650
|
+
const token = await authentification();
|
|
651
|
+
parsedDictionary = await kycService.formatBarcodeData({ textInput: barcodeData, token }, env);
|
|
614
652
|
}
|
|
615
|
-
|
|
653
|
+
const verifiedResult: ISilentCaptureResult & { region?: string } = {
|
|
654
|
+
path: safeCapturePath, templatePath: templatePath, bbox: bbox, success: true,
|
|
655
|
+
mrz: JSON.stringify(parsedDictionary), barcode: barcodeData, isAnalyzing: false,
|
|
656
|
+
country: cData?.code, documentType: docType.type, region: docType.region !== 'root' ? docType.region : undefined
|
|
657
|
+
};
|
|
658
|
+
|
|
616
659
|
clearTimeout(watchdog);
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
660
|
+
setSilentCaptureResult(verifiedResult);
|
|
661
|
+
if (bbox) setBboxBySide(prev => ({ ...prev, ['back']: bbox as IBbox }));
|
|
662
|
+
|
|
663
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK on success
|
|
664
|
+
await autoCapture(safeCapturePath!, verifiedResult);
|
|
620
665
|
return;
|
|
621
666
|
}
|
|
622
667
|
|
|
623
|
-
|
|
668
|
+
sdkLogger.info(`Verification passed. Waiting for barcode scan phase.`);
|
|
624
669
|
clearTimeout(watchdog);
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
670
|
+
setPendingCAImage({ path: safeCapturePath!, templateResponse, templatePath, bbox });
|
|
671
|
+
setScanPhase('barcode');
|
|
672
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false }));
|
|
673
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK before phase shift
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
628
676
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
rawMessage.includes('token') ||
|
|
641
|
-
rawMessage.includes('unauthenticated')
|
|
642
|
-
) {
|
|
643
|
-
sdkLogger.error(`Secure API Session Expired during AI extraction`);
|
|
644
|
-
setShowCamera(false);
|
|
645
|
-
setIsProcessingCapture(false);
|
|
646
|
-
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: '' }));
|
|
647
|
-
|
|
648
|
-
// Use React Native's native Alert to wait for the user's tap
|
|
649
|
-
Alert.alert(
|
|
650
|
-
state.currentLanguage === 'en' ? 'Session Expired' : 'Session Expirée',
|
|
651
|
-
state.currentLanguage === 'en'
|
|
652
|
-
? 'Your secure session has expired. Please restart the process.'
|
|
653
|
-
: 'Votre session sécurisée a expiré. Veuillez recommencer.',
|
|
654
|
-
[
|
|
655
|
-
{
|
|
656
|
-
text: state.currentLanguage === 'en' ? 'Restart' : 'Recommencer',
|
|
657
|
-
onPress: () => handleExitKYCFlow() // Redirects ONLY when they click the button
|
|
658
|
-
}
|
|
659
|
-
],
|
|
660
|
-
{ cancelable: false } // Forces them to click the button
|
|
661
|
-
);
|
|
662
|
-
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
677
|
+
const verifiedResult: ISilentCaptureResult & { region?: string } = {
|
|
678
|
+
path: safeCapturePath, templatePath, bbox, success: true, mrz: verifiedMrz, isAnalyzing: false,
|
|
679
|
+
country: cData?.code, documentType: docType.type, region: issuingSubdivision
|
|
680
|
+
};
|
|
681
|
+
|
|
682
|
+
clearTimeout(watchdog);
|
|
683
|
+
setSilentCaptureResult(verifiedResult);
|
|
684
|
+
if (bbox) setBboxBySide(prev => ({ ...prev, [side]: bbox }));
|
|
685
|
+
|
|
686
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK on final success
|
|
687
|
+
await autoCapture(safeCapturePath, verifiedResult);
|
|
665
688
|
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
)
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
// 2. Document/Country Mismatch
|
|
681
|
-
// Catches: 'pays sélectionné', 'LPIPS'
|
|
682
|
-
else if (rawMessage.includes('pays sélectionné')) {
|
|
683
|
-
hintMessage = state.currentLanguage === 'en'
|
|
684
|
-
? 'This document does not match the selected country.'
|
|
685
|
-
: 'Ce document ne correspond pas au pays sélectionné.';
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// 3. Front/Back Document Mismatch
|
|
689
|
-
// Catches: 'ne correspond pas au recto', 'document différent'
|
|
690
|
-
else if (rawMessage.includes('ne correspond pas au recto') || rawMessage.includes('document différent')) {
|
|
691
|
-
hintMessage = state.currentLanguage === 'en'
|
|
692
|
-
? 'Please scan the back of the exact same ID.'
|
|
693
|
-
: 'Veuillez scanner le verso de la même pièce d\'identité.';
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
// 4. Data Extraction Failures (OCR & MRZ)
|
|
697
|
-
// Catches: 'impossible de lire', 'impossible d'extraire', 'mrz illisible', 'lecture mrz invalide'
|
|
698
|
-
else if (
|
|
699
|
-
rawMessage.includes('impossible de lire') ||
|
|
700
|
-
rawMessage.includes('impossible d\'extraire') ||
|
|
701
|
-
rawMessage.includes('mrz') ||
|
|
702
|
-
rawMessage.includes('extraction') ||
|
|
703
|
-
rawMessage.includes('illisible') ||
|
|
704
|
-
rawMessage.includes('invalide')
|
|
705
|
-
) {
|
|
706
|
-
hintMessage = state.currentLanguage === 'en'
|
|
707
|
-
? 'Cannot read document text. Avoid glare, improve lighting, and hold steady.'
|
|
708
|
-
: 'Impossible de lire le texte. Évitez les reflets, améliorez l\'éclairage et restez immobile.';
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// 5. Server Infrastructure & Downtime
|
|
712
|
-
// Catches: Cloudflare tunnel errors, 502/503 Gateway timeouts
|
|
713
|
-
else if (
|
|
714
|
-
rawMessage.includes('cloudflare') ||
|
|
715
|
-
rawMessage.includes('tunnel') ||
|
|
716
|
-
rawMessage.includes('502') ||
|
|
717
|
-
rawMessage.includes('503')
|
|
718
|
-
) {
|
|
719
|
-
hintMessage = state.currentLanguage === 'en'
|
|
720
|
-
? 'Server is temporarily offline. Please try again in a few minutes.'
|
|
721
|
-
: 'Le serveur est temporairement hors ligne. Veuillez réessayer dans quelques minutes.';
|
|
722
|
-
}
|
|
689
|
+
} catch (error: any) {
|
|
690
|
+
clearTimeout(watchdog);
|
|
691
|
+
const rawMessage = (typeof error === 'string' ? error : (error?.message || '')).toLowerCase();
|
|
692
|
+
const statusCode = error?.response?.status || error?.status;
|
|
693
|
+
|
|
694
|
+
if (
|
|
695
|
+
statusCode === 401 || statusCode === 403 ||
|
|
696
|
+
rawMessage.includes('401') || rawMessage.includes('unauthorized') ||
|
|
697
|
+
rawMessage.includes('token') || rawMessage.includes('unauthenticated')
|
|
698
|
+
) {
|
|
699
|
+
sdkLogger.error(`Secure API Session Expired during AI extraction`);
|
|
700
|
+
setShowCamera(false);
|
|
701
|
+
setIsProcessingCapture(false);
|
|
702
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: '' }));
|
|
723
703
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
704
|
+
Alert.alert(
|
|
705
|
+
state.currentLanguage === 'en' ? 'Session Expired' : 'Session Expirée',
|
|
706
|
+
state.currentLanguage === 'en' ? 'Your secure session has expired. Please restart the process.' : 'Votre session sécurisée a expiré. Veuillez recommencer.',
|
|
707
|
+
[{ text: state.currentLanguage === 'en' ? 'Restart' : 'Recommencer', onPress: () => handleExitKYCFlow() }],
|
|
708
|
+
{ cancelable: false }
|
|
709
|
+
);
|
|
710
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK on session expiry
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
let hintMessage = '';
|
|
715
|
+
if (rawMessage.includes('card_not_fully_in_frame') || rawMessage.includes('non entièrement visible') || rawMessage.includes('aucun visage détecté') || rawMessage.includes('stabiliser la caméra')) {
|
|
716
|
+
hintMessage = state.currentLanguage === 'en' ? 'Ensure the entire card and your face are clearly inside the frame.' : 'Assurez-vous que toute la carte et le visage sont clairement dans le cadre.';
|
|
717
|
+
} else if (rawMessage.includes('pays sélectionné')) {
|
|
718
|
+
hintMessage = state.currentLanguage === 'en' ? 'This document does not match the selected country.' : 'Ce document ne correspond pas au pays sélectionné.';
|
|
719
|
+
} else if (rawMessage.includes('ne correspond pas au recto') || rawMessage.includes('document différent')) {
|
|
720
|
+
hintMessage = state.currentLanguage === 'en' ? 'Please scan the back of the exact same ID.' : 'Veuillez scanner le verso de la même pièce d\'identité.';
|
|
721
|
+
} else if (rawMessage.includes('impossible de lire') || rawMessage.includes('impossible d\'extraire') || rawMessage.includes('mrz') || rawMessage.includes('extraction') || rawMessage.includes('illisible') || rawMessage.includes('invalide')) {
|
|
722
|
+
hintMessage = state.currentLanguage === 'en' ? 'Cannot read document text. Avoid glare, improve lighting, and hold steady.' : 'Impossible de lire le texte. Évitez les reflets, améliorez l\'éclairage et restez immobile.';
|
|
723
|
+
} else if (rawMessage.includes('cloudflare') || rawMessage.includes('tunnel') || rawMessage.includes('502') || rawMessage.includes('503')) {
|
|
724
|
+
hintMessage = state.currentLanguage === 'en' ? 'Server is temporarily offline. Please try again in a few minutes.' : 'Le serveur est temporairement hors ligne. Veuillez réessayer dans quelques minutes.';
|
|
725
|
+
} else {
|
|
726
|
+
const isNetworkError = error?.isAxiosError || rawMessage === 'network error' || error?.code === 'econnaborted' || rawMessage.includes('network');
|
|
727
|
+
if (isNetworkError) {
|
|
728
|
+
hintMessage = state.currentLanguage === 'en' ? 'Poor connection. Please check your internet.' : 'Connexion faible. Veuillez vérifier votre internet.';
|
|
734
729
|
}
|
|
735
|
-
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: hintMessage }));
|
|
736
730
|
}
|
|
731
|
+
|
|
732
|
+
setSilentCaptureResult(prev => ({ ...prev, isAnalyzing: false, success: false, error: hintMessage }));
|
|
733
|
+
isAnalyzingRef.current = false; // 🚨 UNLOCK at end of catch block
|
|
737
734
|
}
|
|
738
|
-
}
|
|
735
|
+
} else {
|
|
736
|
+
// 🚨 UNLOCK if the camera frame was invalid or empty
|
|
737
|
+
isAnalyzingRef.current = false;
|
|
738
|
+
}
|
|
739
|
+
};
|
|
739
740
|
|
|
740
741
|
useEffect(() => {
|
|
741
742
|
if (scanPhase === 'barcode' && pendingCAImage && silentCaptureResult.barcode) {
|