@transfergratis/react-native-sdk 0.1.25 → 0.1.26
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/src/main/AndroidManifest.xml +12 -0
- package/build/components/EnhancedCameraView.web.d.ts.map +1 -1
- package/build/components/EnhancedCameraView.web.js +76 -21
- package/build/components/EnhancedCameraView.web.js.map +1 -1
- package/build/components/KYCElements/EmailVerificationTemplate.d.ts.map +1 -1
- package/build/components/KYCElements/EmailVerificationTemplate.js +48 -29
- package/build/components/KYCElements/EmailVerificationTemplate.js.map +1 -1
- package/build/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/components/KYCElements/IDCardCapture.js +40 -11
- package/build/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/components/KYCElements/WelcomeTemplate.js +2 -1
- package/build/components/KYCElements/WelcomeTemplate.js.map +1 -1
- package/build/components/OverLay/type.d.ts +2 -0
- package/build/components/OverLay/type.d.ts.map +1 -1
- package/build/components/OverLay/type.js.map +1 -1
- package/build/components/TemplateKYCExample.d.ts +8 -2
- package/build/components/TemplateKYCExample.d.ts.map +1 -1
- package/build/components/TemplateKYCExample.js +2 -2
- package/build/components/TemplateKYCExample.js.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.d.ts +10 -2
- package/build/components/TemplateKYCFlowRefactored.d.ts.map +1 -1
- package/build/components/TemplateKYCFlowRefactored.js +13 -3
- package/build/components/TemplateKYCFlowRefactored.js.map +1 -1
- package/build/config/KYCConfig.js +1 -1
- package/build/config/KYCConfig.js.map +1 -1
- package/build/hooks/useTemplateKYCFlow.d.ts +14 -2
- package/build/hooks/useTemplateKYCFlow.d.ts.map +1 -1
- package/build/hooks/useTemplateKYCFlow.js +175 -84
- package/build/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/i18n/en/index.d.ts +2 -0
- package/build/i18n/en/index.d.ts.map +1 -1
- package/build/i18n/en/index.js +3 -1
- package/build/i18n/en/index.js.map +1 -1
- package/build/i18n/fr/index.d.ts +2 -0
- package/build/i18n/fr/index.d.ts.map +1 -1
- package/build/i18n/fr/index.js +3 -1
- package/build/i18n/fr/index.js.map +1 -1
- package/build/i18n/types.d.ts +2 -0
- package/build/i18n/types.d.ts.map +1 -1
- package/build/i18n/types.js.map +1 -1
- package/build/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/modules/api/CardAuthentification.js +22 -2
- package/build/modules/api/CardAuthentification.js.map +1 -1
- package/build/modules/api/KYCService.d.ts +10 -0
- package/build/modules/api/KYCService.d.ts.map +1 -1
- package/build/modules/api/KYCService.js +24 -0
- package/build/modules/api/KYCService.js.map +1 -1
- package/build/modules/camera/VisionCameraModule.web.d.ts.map +1 -1
- package/build/modules/camera/VisionCameraModule.web.js +27 -8
- package/build/modules/camera/VisionCameraModule.web.js.map +1 -1
- package/build/types/KYC.types.d.ts +6 -2
- package/build/types/KYC.types.d.ts.map +1 -1
- package/build/types/KYC.types.js.map +1 -1
- package/build/utils/cropByObb.d.ts +7 -0
- package/build/utils/cropByObb.d.ts.map +1 -1
- package/build/utils/cropByObb.js +20 -1
- package/build/utils/cropByObb.js.map +1 -1
- package/build/web/WebKYCEntry.d.ts.map +1 -1
- package/build/web/WebKYCEntry.js +11 -5
- package/build/web/WebKYCEntry.js.map +1 -1
- package/package.json +1 -1
- package/plugin/build/index.d.ts +1 -0
- package/plugin/build/index.js +3 -1
- package/plugin/build/withRemovePermissions.d.ts +3 -0
- package/plugin/build/withRemovePermissions.js +67 -0
- package/plugin/src/index.ts +2 -1
- package/plugin/src/withRemovePermissions.js +85 -0
- package/plugin/src/withRemovePermissions.ts +83 -0
- package/plugin/tsconfig.tsbuildinfo +1 -1
- package/plugin.js +6 -1
- package/src/components/EnhancedCameraView.web.tsx +76 -21
- package/src/components/KYCElements/EmailVerificationTemplate.tsx +47 -33
- package/src/components/KYCElements/IDCardCapture.tsx +41 -10
- package/src/components/KYCElements/WelcomeTemplate.tsx +2 -1
- package/src/components/OverLay/type.ts +2 -0
- package/src/components/TemplateKYCExample.tsx +9 -5
- package/src/components/TemplateKYCFlowRefactored.tsx +24 -6
- package/src/config/KYCConfig.ts +1 -1
- package/src/hooks/useTemplateKYCFlow.tsx +189 -95
- package/src/i18n/en/index.ts +3 -1
- package/src/i18n/fr/index.ts +3 -1
- package/src/i18n/types.ts +2 -0
- package/src/modules/api/CardAuthentification.ts +23 -2
- package/src/modules/api/KYCService.ts +41 -0
- package/src/modules/camera/VisionCameraModule.web.ts +30 -12
- package/src/types/KYC.types.ts +7 -3
- package/src/utils/cropByObb.ts +20 -1
- package/src/web/WebKYCEntry.tsx +17 -6
|
@@ -524,6 +524,47 @@ export class KYCService {
|
|
|
524
524
|
throw new Error(errorMessage(error));
|
|
525
525
|
}
|
|
526
526
|
}
|
|
527
|
+
|
|
528
|
+
/** Send email verification code. POST /api/v1/accounts/email/send/ */
|
|
529
|
+
async sendEmailVerificationCode(
|
|
530
|
+
email: string,
|
|
531
|
+
auth?: { apiKey?: string; token?: string }
|
|
532
|
+
): Promise<unknown> {
|
|
533
|
+
const url = `${KYCConfig.getBackendUrl()}/accounts/email/send/`;
|
|
534
|
+
const token = auth?.apiKey ? undefined : (auth?.token ?? await authentification());
|
|
535
|
+
const res = await axios.post(
|
|
536
|
+
url,
|
|
537
|
+
{ email },
|
|
538
|
+
{
|
|
539
|
+
headers: {
|
|
540
|
+
'Content-Type': 'application/json',
|
|
541
|
+
...(auth?.apiKey ? { 'Authorization': `ApiKey ${auth.apiKey}` } : { 'Authorization': `Bearer ${token}` }),
|
|
542
|
+
},
|
|
543
|
+
}
|
|
544
|
+
);
|
|
545
|
+
return res.data;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/** Verify email with OTP. POST /api/v1/accounts/email/verify/ */
|
|
549
|
+
async verifyEmailCode(
|
|
550
|
+
otp: string,
|
|
551
|
+
auth?: { apiKey?: string; token?: string }
|
|
552
|
+
): Promise<unknown> {
|
|
553
|
+
const url = `${KYCConfig.getBackendUrl()}/accounts/email/verify/`;
|
|
554
|
+
const token = auth?.apiKey ? undefined : (auth?.token ?? await authentification());
|
|
555
|
+
const res = await axios.post(
|
|
556
|
+
url,
|
|
557
|
+
{ otp },
|
|
558
|
+
{
|
|
559
|
+
headers: {
|
|
560
|
+
'Content-Type': 'application/json',
|
|
561
|
+
...(auth?.apiKey ? { 'Authorization': `ApiKey ${auth.apiKey}` } : { 'Authorization': `Bearer ${token}` }),
|
|
562
|
+
},
|
|
563
|
+
}
|
|
564
|
+
);
|
|
565
|
+
return res.data;
|
|
566
|
+
}
|
|
567
|
+
|
|
527
568
|
// reultat de la verification
|
|
528
569
|
async getVerificationResult(session_id: string): Promise<VerificationResult> {
|
|
529
570
|
try {
|
|
@@ -151,17 +151,18 @@ export class VisionCameraModule {
|
|
|
151
151
|
return false;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
|
|
155
|
-
|
|
154
|
+
// Use min + ideal so Android Chrome doesn't cache low resolution (e.g. 640x480)
|
|
155
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
156
|
+
video: {
|
|
156
157
|
facingMode: 'user',
|
|
157
|
-
width: {
|
|
158
|
-
height: {
|
|
159
|
-
}
|
|
158
|
+
width: { min: 1280, ideal: 1920 },
|
|
159
|
+
height: { min: 720, ideal: 1080 },
|
|
160
|
+
},
|
|
160
161
|
});
|
|
161
|
-
|
|
162
|
+
|
|
162
163
|
// Libérer le stream de test
|
|
163
164
|
stream.getTracks().forEach(track => track.stop());
|
|
164
|
-
|
|
165
|
+
|
|
165
166
|
return true;
|
|
166
167
|
} catch (error) {
|
|
167
168
|
console.error('Error requesting camera permission:', error);
|
|
@@ -330,13 +331,30 @@ export class VisionCameraModule {
|
|
|
330
331
|
return;
|
|
331
332
|
}
|
|
332
333
|
|
|
333
|
-
|
|
334
|
+
const constraints: MediaStreamConstraints = {
|
|
334
335
|
video: {
|
|
335
336
|
facingMode: 'user',
|
|
336
|
-
width: {
|
|
337
|
-
height: {
|
|
337
|
+
width: { min: 1280, ideal: 1920 },
|
|
338
|
+
height: { min: 720, ideal: 1080 },
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
try {
|
|
343
|
+
this.stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
344
|
+
} catch (err) {
|
|
345
|
+
const name = err instanceof Error ? err.name : '';
|
|
346
|
+
if (name === 'OverconstrainedError') {
|
|
347
|
+
this.stream = await navigator.mediaDevices.getUserMedia({
|
|
348
|
+
video: {
|
|
349
|
+
facingMode: 'user',
|
|
350
|
+
width: { ideal: 1920 },
|
|
351
|
+
height: { ideal: 1080 },
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
} else {
|
|
355
|
+
throw err;
|
|
338
356
|
}
|
|
339
|
-
}
|
|
357
|
+
}
|
|
340
358
|
|
|
341
359
|
if (this.videoElement) {
|
|
342
360
|
this.videoElement.srcObject = this.stream;
|
|
@@ -531,7 +549,7 @@ export class VisionCameraModule {
|
|
|
531
549
|
context.drawImage(this.videoElement, 0, 0);
|
|
532
550
|
|
|
533
551
|
// Convertir en base64
|
|
534
|
-
const imageDataUrl = this.canvasElement.toDataURL('image/jpeg', 0.
|
|
552
|
+
const imageDataUrl = this.canvasElement.toDataURL('image/jpeg', 0.95);
|
|
535
553
|
|
|
536
554
|
// Créer un nom de fichier unique
|
|
537
555
|
const timestamp = new Date().getTime();
|
package/src/types/KYC.types.ts
CHANGED
|
@@ -455,6 +455,8 @@ export interface SessionState {
|
|
|
455
455
|
isInitialized: boolean;
|
|
456
456
|
isProcessing: boolean;
|
|
457
457
|
error: string | null;
|
|
458
|
+
/** True once loadSessionData has run (for resume flow); allows UI to show loading until country/data restored */
|
|
459
|
+
sessionDataRestored?: boolean;
|
|
458
460
|
}
|
|
459
461
|
|
|
460
462
|
export type VerificationStatus = 'idle' | 'in_progress' | 'success' | 'failed';
|
|
@@ -469,11 +471,11 @@ export interface VerificationState {
|
|
|
469
471
|
// Actions pour le template KYC
|
|
470
472
|
export interface TemplateActions {
|
|
471
473
|
initializeTemplate: (template: KYCTemplate) => void;
|
|
472
|
-
nextComponent: () => void;
|
|
474
|
+
nextComponent: (overrideData?: any) => void;
|
|
473
475
|
previousComponent: () => void;
|
|
474
476
|
goToComponent: (componentId: number) => void;
|
|
475
477
|
updateComponentData: (componentId: number, data: any) => void;
|
|
476
|
-
validateComponent: (componentId: number) => boolean;
|
|
478
|
+
validateComponent: (componentId: number, dataOverride?: any) => boolean;
|
|
477
479
|
submitTemplate: () => Promise<void>;
|
|
478
480
|
resetTemplate: () => void;
|
|
479
481
|
setLanguage: (language: string) => void;
|
|
@@ -482,7 +484,7 @@ export interface TemplateActions {
|
|
|
482
484
|
submitVerification: () => Promise<void>;
|
|
483
485
|
}
|
|
484
486
|
|
|
485
|
-
// Hook pour le template KYC
|
|
487
|
+
// Hook pour le template KYC (return type of useTemplateKYCFlow)
|
|
486
488
|
export interface UseTemplateReturn {
|
|
487
489
|
state: TemplateState;
|
|
488
490
|
actions: TemplateActions;
|
|
@@ -494,6 +496,8 @@ export interface UseTemplateReturn {
|
|
|
494
496
|
getLocalizedText: (text: LocalizedText) => string;
|
|
495
497
|
initializeSession: () => Promise<void>;
|
|
496
498
|
env: 'PRODUCTION' | 'SANDBOX';
|
|
499
|
+
/** Optional API key for backend auth (e.g. email verification endpoints). */
|
|
500
|
+
apiKey?: string;
|
|
497
501
|
}
|
|
498
502
|
|
|
499
503
|
|
package/src/utils/cropByObb.ts
CHANGED
|
@@ -5,6 +5,21 @@ import { logger } from './logger';
|
|
|
5
5
|
|
|
6
6
|
type Point = [number, number];
|
|
7
7
|
|
|
8
|
+
/** OBB confidence below this = card not fully in frame; don't crop, give user feedback. */
|
|
9
|
+
export const OBB_CONFIDENCE_THRESHOLD = 0.85;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* card_obb format from API: [ [ [p1,p2,p3,p4], confidence ] ]
|
|
13
|
+
* Returns confidence in [0,1] or null if not present.
|
|
14
|
+
*/
|
|
15
|
+
export function getObbConfidence(cardObb: any): number | null {
|
|
16
|
+
if (!cardObb || !Array.isArray(cardObb) || cardObb.length === 0) return null;
|
|
17
|
+
const first = cardObb[0];
|
|
18
|
+
if (!Array.isArray(first) || first.length < 2) return null;
|
|
19
|
+
const score = first[1];
|
|
20
|
+
return typeof score === 'number' ? score : null;
|
|
21
|
+
}
|
|
22
|
+
|
|
8
23
|
// Compute axis-aligned bounding box from oriented quadrilateral
|
|
9
24
|
function computeAabb(points: Point[]) {
|
|
10
25
|
const xs = points.map(p => p[0]);
|
|
@@ -49,7 +64,11 @@ async function cropWeb(uri: string, points: Point[]): Promise<string> {
|
|
|
49
64
|
// Fallback: return original for native (no dependency added); caller can still use bbox to draw overlay
|
|
50
65
|
export async function cropByObb(uri: string, cardObb: any): Promise<{ base64?: string; bbox?: { minX: number; minY: number; width: number; height: number } }> {
|
|
51
66
|
try {
|
|
52
|
-
// card_obb format: [ [ [p1,p2,p3,p4], score ] ]
|
|
67
|
+
// card_obb format: [ [ [p1,p2,p3,p4], score ] ] — if confidence too low, don't crop (send full image)
|
|
68
|
+
const confidence = getObbConfidence(cardObb);
|
|
69
|
+
if (confidence !== null && confidence < OBB_CONFIDENCE_THRESHOLD) {
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
53
72
|
const first = Array.isArray(cardObb) ? cardObb[0] : null;
|
|
54
73
|
const points = Array.isArray(first?.[0]) ? (first[0] as Point[]) : null;
|
|
55
74
|
if (!points || points.length !== 4) return {};
|
package/src/web/WebKYCEntry.tsx
CHANGED
|
@@ -25,7 +25,11 @@ interface URLParams {
|
|
|
25
25
|
env?: 'PRODUCTION' | 'SANDBOX'; // Environment mode
|
|
26
26
|
template_id?: string; // Template ID for dynamic template loading
|
|
27
27
|
server_env?: BackendEnvironment; // Backend environment mode
|
|
28
|
-
step?: string; //
|
|
28
|
+
step?: string; // Deprecated: use component_index.
|
|
29
|
+
component_index?: string; // Index in template.components (0-based) to resume at
|
|
30
|
+
country?: string; // Code pays pour restaurer la sélection (reprise multi-appareil)
|
|
31
|
+
document_type?: string; // Type de document (national_id, passport, etc.)
|
|
32
|
+
region?: string; // Région si applicable
|
|
29
33
|
}
|
|
30
34
|
|
|
31
35
|
interface VerificationSteps {
|
|
@@ -70,6 +74,10 @@ const WebKYCEntry: React.FC<WebKYCEntryProps> = ({
|
|
|
70
74
|
template_id: urlParams.get('template_id') || undefined,
|
|
71
75
|
server_env: validServerEnv,
|
|
72
76
|
step: urlParams.get('step') || undefined,
|
|
77
|
+
component_index: urlParams.get('component_index') || undefined,
|
|
78
|
+
country: urlParams.get('country') || undefined,
|
|
79
|
+
document_type: urlParams.get('document_type') || undefined,
|
|
80
|
+
region: urlParams.get('region') || undefined,
|
|
73
81
|
};
|
|
74
82
|
}, []);
|
|
75
83
|
|
|
@@ -294,12 +302,15 @@ const WebKYCEntry: React.FC<WebKYCEntryProps> = ({
|
|
|
294
302
|
API_KEY={urlParams.token}
|
|
295
303
|
templateId={urlParams.template_id}
|
|
296
304
|
env={urlParams.env || 'PRODUCTION'}
|
|
305
|
+
serverEnv={urlParams.server_env}
|
|
297
306
|
existingSessionId={urlParams.kyc_id}
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
307
|
+
initialComponentIndex={(() => {
|
|
308
|
+
const raw = urlParams.component_index ?? urlParams.step;
|
|
309
|
+
if (raw == null || raw === '') return undefined;
|
|
310
|
+
const index = parseInt(raw, 10);
|
|
311
|
+
return Number.isNaN(index) ? undefined : index;
|
|
312
|
+
})()}
|
|
313
|
+
initialCountryResume={urlParams.country && urlParams.document_type ? { code: urlParams.country, documentType: urlParams.document_type, region: urlParams.region || undefined } : undefined}
|
|
303
314
|
/>
|
|
304
315
|
</SafeAreaView>
|
|
305
316
|
);
|