@test-web/react-native-sdk 2.1.0 → 2.2.0
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/README.md +284 -3
- package/package.json +12 -3
- package/src/config/apiConfig.ts +1 -1
- package/src/screens/BarcodeCapture.tsx +119 -41
- package/src/screens/MrzCapture.tsx +147 -23
- package/src/services/getUserData.ts +31 -11
package/README.md
CHANGED
|
@@ -9,7 +9,8 @@ A fully dynamic, production-ready React Native SDK for identity verification wit
|
|
|
9
9
|
- ✅ **18 Verification Screens** - Complete identity verification flow
|
|
10
10
|
- ✅ **Document Scanning** - Support for ID cards, passports, driver licenses
|
|
11
11
|
- ✅ **Selfie Capture** - Live selfie verification with camera integration
|
|
12
|
-
- ✅ **MRZ & Barcode Scanning** - Machine-readable zone and barcode support
|
|
12
|
+
- ✅ **MRZ & Barcode Scanning** - Machine-readable zone and barcode support with Dynamsoft & ML Kit
|
|
13
|
+
- ✅ **Advanced Scanning** - Optional Dynamsoft barcode scanner and ML Kit text recognition
|
|
13
14
|
- ✅ **10 Pre-built Themes** - Customizable UI themes
|
|
14
15
|
- ✅ **Camera & Location Permissions** - Built-in permission handling
|
|
15
16
|
- ✅ **TypeScript Support** - Full type definitions included
|
|
@@ -55,13 +56,27 @@ npm install react-native-vision-camera react-native-image-resizer react-native-f
|
|
|
55
56
|
npm install react-native-device-info react-native-geolocation-service
|
|
56
57
|
```
|
|
57
58
|
|
|
58
|
-
### Step 4: Install
|
|
59
|
+
### Step 4: Install Scanning Libraries (Optional but Recommended)
|
|
60
|
+
|
|
61
|
+
For enhanced barcode and MRZ scanning capabilities:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Dynamsoft Capture Vision for barcode scanning
|
|
65
|
+
npm install dynamsoft-capture-vision-react-native
|
|
66
|
+
|
|
67
|
+
# ML Kit for MRZ text recognition
|
|
68
|
+
npm install @react-native-ml-kit/text-recognition
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Note:** Without these libraries, the SDK will use fallback simulation for barcode and MRZ scanning. For production use, we strongly recommend installing these libraries for accurate scanning.
|
|
72
|
+
|
|
73
|
+
### Step 5: Install iOS Pods (iOS only)
|
|
59
74
|
|
|
60
75
|
```bash
|
|
61
76
|
cd ios && pod install && cd ..
|
|
62
77
|
```
|
|
63
78
|
|
|
64
|
-
### Step
|
|
79
|
+
### Step 6: Rebuild Your App
|
|
65
80
|
|
|
66
81
|
```bash
|
|
67
82
|
# For Android
|
|
@@ -155,6 +170,95 @@ platform :ios, '11.0'
|
|
|
155
170
|
|
|
156
171
|
---
|
|
157
172
|
|
|
173
|
+
### Dynamsoft Barcode Scanner Setup (Optional)
|
|
174
|
+
|
|
175
|
+
If you installed `dynamsoft-capture-vision-react-native`, follow these additional steps:
|
|
176
|
+
|
|
177
|
+
#### Android Configuration
|
|
178
|
+
|
|
179
|
+
1. Add to `android/app/build.gradle`:
|
|
180
|
+
|
|
181
|
+
```gradle
|
|
182
|
+
android {
|
|
183
|
+
defaultConfig {
|
|
184
|
+
minSdkVersion 21
|
|
185
|
+
// Add this for Dynamsoft
|
|
186
|
+
ndk {
|
|
187
|
+
abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
2. Get your Dynamsoft license key from [Dynamsoft Customer Portal](https://www.dynamsoft.com/customer/license/trialLicense)
|
|
194
|
+
|
|
195
|
+
3. Initialize the license in your app (before using the SDK):
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
import { DCVBarcodeReader } from 'dynamsoft-capture-vision-react-native';
|
|
199
|
+
|
|
200
|
+
// Initialize Dynamsoft license (do this once at app startup)
|
|
201
|
+
await DCVBarcodeReader.initLicense('YOUR_DYNAMSOFT_LICENSE_KEY');
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
#### iOS Configuration
|
|
205
|
+
|
|
206
|
+
1. Add to `ios/Podfile`:
|
|
207
|
+
|
|
208
|
+
```ruby
|
|
209
|
+
platform :ios, '11.0'
|
|
210
|
+
|
|
211
|
+
target 'YourApp' do
|
|
212
|
+
# ... other pods
|
|
213
|
+
|
|
214
|
+
# Add this for Dynamsoft
|
|
215
|
+
pod 'DynamsoftCaptureVisionRouter', '~> 2.0'
|
|
216
|
+
pod 'DynamsoftBarcodeReader', '~> 10.0'
|
|
217
|
+
end
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
2. Run `pod install`:
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
cd ios && pod install && cd ..
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
**Note:** The SDK will automatically detect if Dynamsoft is available and use it for barcode scanning. If not installed, it will fall back to simulation mode.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
### ML Kit Text Recognition Setup (Optional)
|
|
231
|
+
|
|
232
|
+
If you installed `@react-native-ml-kit/text-recognition`, follow these additional steps:
|
|
233
|
+
|
|
234
|
+
#### Android Configuration
|
|
235
|
+
|
|
236
|
+
ML Kit will be automatically configured on Android. No additional setup required.
|
|
237
|
+
|
|
238
|
+
#### iOS Configuration
|
|
239
|
+
|
|
240
|
+
1. Add to `ios/Podfile`:
|
|
241
|
+
|
|
242
|
+
```ruby
|
|
243
|
+
platform :ios, '11.0'
|
|
244
|
+
|
|
245
|
+
target 'YourApp' do
|
|
246
|
+
# ... other pods
|
|
247
|
+
|
|
248
|
+
# ML Kit is automatically linked
|
|
249
|
+
end
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
2. Run `pod install`:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
cd ios && pod install && cd ..
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Note:** The SDK will automatically detect if ML Kit is available and use it for MRZ text recognition. If not installed, it will fall back to simulation mode.
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
158
262
|
## 🚀 Usage
|
|
159
263
|
|
|
160
264
|
### Basic Implementation
|
|
@@ -257,6 +361,95 @@ export default function App() {
|
|
|
257
361
|
|
|
258
362
|
---
|
|
259
363
|
|
|
364
|
+
## 📸 Scanning Capabilities
|
|
365
|
+
|
|
366
|
+
### Barcode Scanning
|
|
367
|
+
|
|
368
|
+
The SDK supports barcode scanning with two modes:
|
|
369
|
+
|
|
370
|
+
#### 1. Production Mode (Recommended)
|
|
371
|
+
|
|
372
|
+
Install Dynamsoft Capture Vision for accurate barcode scanning:
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
npm install dynamsoft-capture-vision-react-native
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Supported Barcode Types:**
|
|
379
|
+
- PDF417 (Driver's License, ID Cards)
|
|
380
|
+
- QR Code
|
|
381
|
+
- Code 128
|
|
382
|
+
- Code 39
|
|
383
|
+
- EAN-13
|
|
384
|
+
- UPC-A
|
|
385
|
+
- And more...
|
|
386
|
+
|
|
387
|
+
**Initialize License:**
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
import { DCVBarcodeReader } from 'dynamsoft-capture-vision-react-native';
|
|
391
|
+
|
|
392
|
+
// At app startup
|
|
393
|
+
await DCVBarcodeReader.initLicense('YOUR_LICENSE_KEY');
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Get your free trial license from [Dynamsoft Customer Portal](https://www.dynamsoft.com/customer/license/trialLicense).
|
|
397
|
+
|
|
398
|
+
#### 2. Fallback Mode
|
|
399
|
+
|
|
400
|
+
Without Dynamsoft installed, the SDK will use simulation mode for testing purposes. This is useful for development but not recommended for production.
|
|
401
|
+
|
|
402
|
+
### MRZ Scanning
|
|
403
|
+
|
|
404
|
+
The SDK supports MRZ (Machine Readable Zone) scanning with two modes:
|
|
405
|
+
|
|
406
|
+
#### 1. Production Mode (Recommended)
|
|
407
|
+
|
|
408
|
+
Install ML Kit Text Recognition for accurate MRZ scanning:
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
npm install @react-native-ml-kit/text-recognition
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**Supported MRZ Types:**
|
|
415
|
+
- TD1 (ID Cards)
|
|
416
|
+
- TD2 (Travel Documents)
|
|
417
|
+
- TD3 (Passports)
|
|
418
|
+
- MRVA (Visa Type A)
|
|
419
|
+
- MRVB (Visa Type B)
|
|
420
|
+
|
|
421
|
+
The SDK automatically detects the MRZ type based on document metadata.
|
|
422
|
+
|
|
423
|
+
#### 2. Fallback Mode
|
|
424
|
+
|
|
425
|
+
Without ML Kit installed, the SDK will use simulation mode for testing purposes. This is useful for development but not recommended for production.
|
|
426
|
+
|
|
427
|
+
### Scanning Flow
|
|
428
|
+
|
|
429
|
+
The SDK automatically determines which scanning methods are required based on document metadata:
|
|
430
|
+
|
|
431
|
+
```typescript
|
|
432
|
+
// Example metadata from API
|
|
433
|
+
{
|
|
434
|
+
"document_flow": ["F", "B"], // Front and Back required
|
|
435
|
+
"barcode": "PDF417 B" // Barcode on back side
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
**Flow:** Selfie → Front → Back → Barcode Scan → Complete
|
|
440
|
+
|
|
441
|
+
```typescript
|
|
442
|
+
// Example metadata for passport
|
|
443
|
+
{
|
|
444
|
+
"document_flow": ["F"], // Front only
|
|
445
|
+
"barcode": "TD3" // MRZ scanning required
|
|
446
|
+
}
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
**Flow:** Selfie → Front → MRZ Scan → Complete
|
|
450
|
+
|
|
451
|
+
---
|
|
452
|
+
|
|
260
453
|
## 🔄 Dynamic Flow
|
|
261
454
|
|
|
262
455
|
The SDK automatically determines the verification flow based on document metadata:
|
|
@@ -449,6 +642,86 @@ cd android && ./gradlew clean && cd ..
|
|
|
449
642
|
- Ensure react-native-fs is installed
|
|
450
643
|
- Check storage permissions
|
|
451
644
|
|
|
645
|
+
#### 7. Barcode Scanning Not Working
|
|
646
|
+
|
|
647
|
+
**Problem:** Barcode scanning shows simulation or doesn't detect barcodes.
|
|
648
|
+
|
|
649
|
+
**Solution:**
|
|
650
|
+
- Install `dynamsoft-capture-vision-react-native` for real barcode scanning
|
|
651
|
+
- Initialize Dynamsoft license key before using the SDK
|
|
652
|
+
- Ensure camera permissions are granted
|
|
653
|
+
- Test with a real PDF417 barcode (driver's license back)
|
|
654
|
+
- Check console logs for Dynamsoft initialization errors
|
|
655
|
+
|
|
656
|
+
#### 8. MRZ Scanning Not Working
|
|
657
|
+
|
|
658
|
+
**Problem:** MRZ scanning shows simulation or doesn't detect MRZ codes.
|
|
659
|
+
|
|
660
|
+
**Solution:**
|
|
661
|
+
- Install `@react-native-ml-kit/text-recognition` for real MRZ scanning
|
|
662
|
+
- Ensure camera permissions are granted
|
|
663
|
+
- Test with a real passport or ID card with MRZ
|
|
664
|
+
- Ensure good lighting and steady camera position
|
|
665
|
+
- Check console logs for ML Kit errors
|
|
666
|
+
|
|
667
|
+
---
|
|
668
|
+
|
|
669
|
+
## 🧪 Testing Scanning Features
|
|
670
|
+
|
|
671
|
+
### Testing Barcode Scanning
|
|
672
|
+
|
|
673
|
+
#### With Dynamsoft (Production)
|
|
674
|
+
|
|
675
|
+
1. Install Dynamsoft:
|
|
676
|
+
```bash
|
|
677
|
+
npm install dynamsoft-capture-vision-react-native
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
2. Get a trial license from [Dynamsoft](https://www.dynamsoft.com/customer/license/trialLicense)
|
|
681
|
+
|
|
682
|
+
3. Initialize in your app:
|
|
683
|
+
```typescript
|
|
684
|
+
import { DCVBarcodeReader } from 'dynamsoft-capture-vision-react-native';
|
|
685
|
+
|
|
686
|
+
await DCVBarcodeReader.initLicense('YOUR_LICENSE_KEY');
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
4. Test with a real driver's license or ID card with PDF417 barcode
|
|
690
|
+
|
|
691
|
+
#### Without Dynamsoft (Development)
|
|
692
|
+
|
|
693
|
+
The SDK will automatically use simulation mode. After 3 seconds, it will generate a simulated barcode result.
|
|
694
|
+
|
|
695
|
+
### Testing MRZ Scanning
|
|
696
|
+
|
|
697
|
+
#### With ML Kit (Production)
|
|
698
|
+
|
|
699
|
+
1. Install ML Kit:
|
|
700
|
+
```bash
|
|
701
|
+
npm install @react-native-ml-kit/text-recognition
|
|
702
|
+
```
|
|
703
|
+
|
|
704
|
+
2. Test with a real passport or ID card with MRZ zone
|
|
705
|
+
|
|
706
|
+
3. Ensure good lighting and hold the document steady
|
|
707
|
+
|
|
708
|
+
#### Without ML Kit (Development)
|
|
709
|
+
|
|
710
|
+
The SDK will automatically use simulation mode. After 3 seconds, it will generate a simulated MRZ result.
|
|
711
|
+
|
|
712
|
+
### Checking Scanner Status
|
|
713
|
+
|
|
714
|
+
The SDK logs which scanning mode is being used:
|
|
715
|
+
|
|
716
|
+
```
|
|
717
|
+
// Console output examples:
|
|
718
|
+
"Dynamsoft Barcode Scanner initialized" // Production mode
|
|
719
|
+
"Dynamsoft not available, using fallback" // Simulation mode
|
|
720
|
+
|
|
721
|
+
"ML Kit text recognition initialized" // Production mode
|
|
722
|
+
"ML Kit not available, using fallback" // Simulation mode
|
|
723
|
+
```
|
|
724
|
+
|
|
452
725
|
---
|
|
453
726
|
|
|
454
727
|
## 🎯 Advanced Usage
|
|
@@ -557,6 +830,14 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
557
830
|
- ✅ **Flow Manager** - Smart navigation based on document type
|
|
558
831
|
- ✅ **Better Error Handling** - Comprehensive error management
|
|
559
832
|
- ✅ **Loading States** - User feedback throughout the flow
|
|
833
|
+
- ✅ **Dynamsoft Integration** - Professional barcode scanning (optional)
|
|
834
|
+
- ✅ **ML Kit Integration** - Accurate MRZ text recognition (optional)
|
|
835
|
+
|
|
836
|
+
### Scanning Features
|
|
837
|
+
- **Dynamsoft Capture Vision** - Industry-leading barcode scanning for PDF417, QR codes, and more
|
|
838
|
+
- **ML Kit Text Recognition** - Google's ML Kit for accurate MRZ detection on passports and ID cards
|
|
839
|
+
- **Fallback Mode** - Simulation mode for development without external libraries
|
|
840
|
+
- **Auto-Detection** - SDK automatically uses available scanning libraries
|
|
560
841
|
|
|
561
842
|
### Breaking Changes from v1.x
|
|
562
843
|
- `clientID`, `clientSecret`, `environment`, and `requestData` are now required
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@test-web/react-native-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Dynamic React Native SDK for document verification with API-driven configuration",
|
|
5
5
|
"main": "src/index.tsx",
|
|
6
6
|
"types": "src/index.tsx",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"barcode",
|
|
26
26
|
"mrz",
|
|
27
27
|
"dynamic",
|
|
28
|
-
"api-driven"
|
|
28
|
+
"api-driven",
|
|
29
|
+
"dynamsoft"
|
|
29
30
|
],
|
|
30
31
|
"repository": "https://github.com/yourcompany/react-native-sdk",
|
|
31
32
|
"author": "Your Company <hello@yourcompany.com>",
|
|
@@ -41,7 +42,9 @@
|
|
|
41
42
|
"react-native-image-resizer": ">=1.0.0",
|
|
42
43
|
"react-native-fs": ">=2.0.0",
|
|
43
44
|
"react-native-device-info": ">=10.0.0",
|
|
44
|
-
"react-native-geolocation-service": ">=5.0.0"
|
|
45
|
+
"react-native-geolocation-service": ">=5.0.0",
|
|
46
|
+
"dynamsoft-capture-vision-react-native": ">=3.0.0",
|
|
47
|
+
"@react-native-ml-kit/text-recognition": ">=1.1.0"
|
|
45
48
|
},
|
|
46
49
|
"peerDependenciesMeta": {
|
|
47
50
|
"react-native-image-resizer": {
|
|
@@ -55,6 +58,12 @@
|
|
|
55
58
|
},
|
|
56
59
|
"react-native-geolocation-service": {
|
|
57
60
|
"optional": true
|
|
61
|
+
},
|
|
62
|
+
"dynamsoft-capture-vision-react-native": {
|
|
63
|
+
"optional": true
|
|
64
|
+
},
|
|
65
|
+
"@react-native-ml-kit/text-recognition": {
|
|
66
|
+
"optional": true
|
|
58
67
|
}
|
|
59
68
|
},
|
|
60
69
|
"devDependencies": {
|
package/src/config/apiConfig.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const SANDBOX_BASE_URL = 'https://sandbox
|
|
1
|
+
export const SANDBOX_BASE_URL = 'https://sandbox.idmvalidate.com';
|
|
2
2
|
export const PRODUCTION_BASE_URL = 'https://api.idmerit.com';
|
|
3
3
|
|
|
4
4
|
export const getBaseURL = (environment: 'sandbox' | 'production'): string => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { View, Text, StyleSheet, Alert } from 'react-native';
|
|
3
3
|
import { useNavigation } from '@react-navigation/native';
|
|
4
4
|
import { useTheme } from '../context/ThemeContext';
|
|
@@ -16,10 +16,46 @@ export default function BarcodeCapture() {
|
|
|
16
16
|
const navigation = useNavigation();
|
|
17
17
|
const [loading, setLoading] = useState(false);
|
|
18
18
|
const [scannedData, setScannedData] = useState<string | null>(null);
|
|
19
|
+
const [isScanning, setIsScanning] = useState(true);
|
|
20
|
+
const scannerRef = useRef<any>(null);
|
|
19
21
|
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
// Initialize Dynamsoft Barcode Scanner
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
let isMounted = true;
|
|
25
|
+
|
|
26
|
+
const initializeScanner = async () => {
|
|
27
|
+
try {
|
|
28
|
+
// Try to import Dynamsoft Capture Vision
|
|
29
|
+
const { DCVCameraView, DBRRuntimeSettings } = require('dynamsoft-capture-vision-react-native');
|
|
30
|
+
|
|
31
|
+
// License initialization would go here
|
|
32
|
+
// await DCVBarcodeReader.initLicense('YOUR_LICENSE_KEY');
|
|
33
|
+
|
|
34
|
+
console.log('Dynamsoft Barcode Scanner initialized');
|
|
35
|
+
} catch (error) {
|
|
36
|
+
console.warn('Dynamsoft not available, using fallback:', error);
|
|
37
|
+
// Fallback to simulation if Dynamsoft not installed
|
|
38
|
+
if (isMounted) {
|
|
39
|
+
simulateBarcodeScan();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
initializeScanner();
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
isMounted = false;
|
|
48
|
+
setIsScanning(false);
|
|
49
|
+
};
|
|
50
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
// Handle barcode scan result
|
|
54
|
+
const handleBarcodeScanned = async (barcodeText: string) => {
|
|
55
|
+
if (loading || !barcodeText || !isScanning) return;
|
|
56
|
+
|
|
57
|
+
setIsScanning(false);
|
|
58
|
+
setScannedData(barcodeText);
|
|
23
59
|
|
|
24
60
|
try {
|
|
25
61
|
setLoading(true);
|
|
@@ -42,61 +78,103 @@ export default function BarcodeCapture() {
|
|
|
42
78
|
// Navigate to ThankYou
|
|
43
79
|
navigation.navigate('ThankYou' as never);
|
|
44
80
|
} else {
|
|
45
|
-
Alert.alert('Error', result.errorMessage || 'Failed to process barcode'
|
|
46
|
-
|
|
81
|
+
Alert.alert('Error', result.errorMessage || 'Failed to process barcode', [
|
|
82
|
+
{
|
|
83
|
+
text: 'Retry',
|
|
84
|
+
onPress: () => {
|
|
85
|
+
setIsScanning(true);
|
|
86
|
+
setScannedData(null);
|
|
87
|
+
setLoading(false);
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
]);
|
|
47
91
|
}
|
|
48
92
|
} catch (error: any) {
|
|
49
93
|
console.error('Error processing barcode:', error);
|
|
50
|
-
Alert.alert('Error', 'Failed to process barcode'
|
|
51
|
-
|
|
94
|
+
Alert.alert('Error', 'Failed to process barcode', [
|
|
95
|
+
{
|
|
96
|
+
text: 'Retry',
|
|
97
|
+
onPress: () => {
|
|
98
|
+
setIsScanning(true);
|
|
99
|
+
setScannedData(null);
|
|
100
|
+
setLoading(false);
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
]);
|
|
52
104
|
}
|
|
53
105
|
};
|
|
54
106
|
|
|
55
|
-
//
|
|
56
|
-
|
|
57
|
-
// TODO: Integrate actual barcode scanning library (e.g., react-native-vision-camera with barcode plugin)
|
|
58
|
-
// For now, simulate scanning after 3 seconds
|
|
107
|
+
// Fallback simulation if Dynamsoft not available
|
|
108
|
+
const simulateBarcodeScan = () => {
|
|
59
109
|
const timer = setTimeout(() => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
110
|
+
if (isScanning) {
|
|
111
|
+
const simulatedBarcode = 'SIMULATED_PDF417_' + Date.now();
|
|
112
|
+
handleBarcodeScanned(simulatedBarcode);
|
|
113
|
+
}
|
|
63
114
|
}, 3000);
|
|
64
115
|
|
|
65
116
|
return () => clearTimeout(timer);
|
|
66
|
-
|
|
67
|
-
}, []);
|
|
117
|
+
};
|
|
68
118
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
</Text>
|
|
119
|
+
// Render Dynamsoft Camera View
|
|
120
|
+
const renderBarcodeScanner = () => {
|
|
121
|
+
try {
|
|
122
|
+
const { DCVCameraView } = require('dynamsoft-capture-vision-react-native');
|
|
74
123
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
style={
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
124
|
+
return (
|
|
125
|
+
<DCVCameraView
|
|
126
|
+
ref={scannerRef}
|
|
127
|
+
style={StyleSheet.absoluteFill}
|
|
128
|
+
scanRegionVisible={true}
|
|
129
|
+
overlayVisible={true}
|
|
130
|
+
onBarcodeScanned={(results: any) => {
|
|
131
|
+
if (results && results.length > 0 && isScanning) {
|
|
132
|
+
const barcodeText = results[0].barcodeText || results[0].text;
|
|
133
|
+
handleBarcodeScanned(barcodeText);
|
|
134
|
+
}
|
|
83
135
|
}}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
console.warn('Dynamsoft camera view not available:', error);
|
|
140
|
+
|
|
141
|
+
// Fallback UI
|
|
142
|
+
return (
|
|
143
|
+
<View style={[StyleSheet.absoluteFill, { backgroundColor: '#000' }]}>
|
|
88
144
|
<Text
|
|
89
145
|
style={{
|
|
90
|
-
color: '#
|
|
146
|
+
color: '#fff',
|
|
91
147
|
textAlign: 'center',
|
|
92
|
-
marginTop:
|
|
93
|
-
fontSize:
|
|
148
|
+
marginTop: 200,
|
|
149
|
+
fontSize: 16,
|
|
94
150
|
}}
|
|
95
151
|
>
|
|
96
|
-
|
|
152
|
+
{loading ? 'Processing...' : 'Scanning for barcode...'}
|
|
97
153
|
</Text>
|
|
98
|
-
|
|
99
|
-
|
|
154
|
+
{scannedData && (
|
|
155
|
+
<Text
|
|
156
|
+
style={{
|
|
157
|
+
color: '#0f0',
|
|
158
|
+
textAlign: 'center',
|
|
159
|
+
marginTop: 20,
|
|
160
|
+
fontSize: 12,
|
|
161
|
+
}}
|
|
162
|
+
>
|
|
163
|
+
Detected: {scannedData.substring(0, 30)}...
|
|
164
|
+
</Text>
|
|
165
|
+
)}
|
|
166
|
+
</View>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<View style={styles.container}>
|
|
173
|
+
<Text style={styles.topLabel}>
|
|
174
|
+
Fill the box with the barcode{'\n'}until it turns green
|
|
175
|
+
</Text>
|
|
176
|
+
|
|
177
|
+
{renderBarcodeScanner()}
|
|
100
178
|
|
|
101
179
|
{/* Barcode overlay box */}
|
|
102
180
|
<View
|
|
@@ -112,7 +190,7 @@ export default function BarcodeCapture() {
|
|
|
112
190
|
}}
|
|
113
191
|
/>
|
|
114
192
|
|
|
115
|
-
{loading && <Loader />}
|
|
193
|
+
{loading && <Loader message="Processing barcode..." />}
|
|
116
194
|
</View>
|
|
117
195
|
);
|
|
118
196
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useState, useEffect } from 'react';
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react';
|
|
2
2
|
import { View, Text, StyleSheet, Alert } from 'react-native';
|
|
3
3
|
import { useNavigation } from '@react-navigation/native';
|
|
4
4
|
import { useTheme } from '../context/ThemeContext';
|
|
@@ -17,6 +17,11 @@ export default function MrzCapture() {
|
|
|
17
17
|
const navigation = useNavigation();
|
|
18
18
|
const [loading, setLoading] = useState(false);
|
|
19
19
|
const [scannedData, setScannedData] = useState<string | null>(null);
|
|
20
|
+
const [isScanning, setIsScanning] = useState(true);
|
|
21
|
+
const [hasPermission, setHasPermission] = useState(false);
|
|
22
|
+
const [device, setDevice] = useState<any>(null);
|
|
23
|
+
const cameraRef = useRef<any>(null);
|
|
24
|
+
const frameProcessorRef = useRef<any>(null);
|
|
20
25
|
|
|
21
26
|
// Get MRZ engine type from metadata
|
|
22
27
|
const getMRZEngine = () => {
|
|
@@ -27,9 +32,84 @@ export default function MrzCapture() {
|
|
|
27
32
|
return flowManager.getMRZEngine();
|
|
28
33
|
};
|
|
29
34
|
|
|
30
|
-
//
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
// Initialize camera with ML Kit
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
let isMounted = true;
|
|
38
|
+
|
|
39
|
+
const initializeCamera = async () => {
|
|
40
|
+
try {
|
|
41
|
+
const { Camera, useCameraDevice, useCameraPermission } = require('react-native-vision-camera');
|
|
42
|
+
|
|
43
|
+
const { hasPermission: hasPerm, requestPermission } = useCameraPermission();
|
|
44
|
+
|
|
45
|
+
if (!hasPerm) {
|
|
46
|
+
const granted = await requestPermission();
|
|
47
|
+
if (!granted) {
|
|
48
|
+
navigation.navigate('CameraPermission' as never);
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (isMounted) {
|
|
54
|
+
setHasPermission(true);
|
|
55
|
+
|
|
56
|
+
const backDevice = useCameraDevice('back');
|
|
57
|
+
if (!backDevice) {
|
|
58
|
+
navigation.navigate('NoCameraFound' as never);
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
setDevice(backDevice);
|
|
63
|
+
}
|
|
64
|
+
} catch (error) {
|
|
65
|
+
console.warn('Camera initialization failed:', error);
|
|
66
|
+
if (isMounted) {
|
|
67
|
+
simulateMRZScan();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
initializeCamera();
|
|
73
|
+
|
|
74
|
+
return () => {
|
|
75
|
+
isMounted = false;
|
|
76
|
+
setIsScanning(false);
|
|
77
|
+
};
|
|
78
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
79
|
+
}, []);
|
|
80
|
+
|
|
81
|
+
// Process MRZ with ML Kit Text Recognition
|
|
82
|
+
const processMRZWithMLKit = async (frame: any) => {
|
|
83
|
+
if (!isScanning) return;
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
const { recognizeText } = require('@react-native-ml-kit/text-recognition');
|
|
87
|
+
|
|
88
|
+
const result = await recognizeText(frame);
|
|
89
|
+
|
|
90
|
+
if (result && result.text) {
|
|
91
|
+
// Check if text contains MRZ pattern
|
|
92
|
+
const lines = result.text.split('\n');
|
|
93
|
+
const mrzLines = lines.filter((line: string) =>
|
|
94
|
+
line.length >= 30 && /^[A-Z0-9<]+$/.test(line)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
if (mrzLines.length >= 2) {
|
|
98
|
+
const mrzCode = mrzLines.join('\n');
|
|
99
|
+
handleMRZScanned(mrzCode);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.warn('ML Kit text recognition error:', error);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Handle MRZ scan result
|
|
108
|
+
const handleMRZScanned = async (mrzCode: string) => {
|
|
109
|
+
if (loading || !mrzCode || !isScanning) return;
|
|
110
|
+
|
|
111
|
+
setIsScanning(false);
|
|
112
|
+
setScannedData(mrzCode);
|
|
33
113
|
|
|
34
114
|
try {
|
|
35
115
|
setLoading(true);
|
|
@@ -53,36 +133,72 @@ export default function MrzCapture() {
|
|
|
53
133
|
// Navigate to ThankYou
|
|
54
134
|
navigation.navigate('ThankYou' as never);
|
|
55
135
|
} else {
|
|
56
|
-
Alert.alert('Error', result.errorMessage || 'Failed to process MRZ'
|
|
57
|
-
|
|
136
|
+
Alert.alert('Error', result.errorMessage || 'Failed to process MRZ', [
|
|
137
|
+
{
|
|
138
|
+
text: 'Retry',
|
|
139
|
+
onPress: () => {
|
|
140
|
+
setIsScanning(true);
|
|
141
|
+
setScannedData(null);
|
|
142
|
+
setLoading(false);
|
|
143
|
+
},
|
|
144
|
+
},
|
|
145
|
+
]);
|
|
58
146
|
}
|
|
59
147
|
} catch (error: any) {
|
|
60
148
|
console.error('Error processing MRZ:', error);
|
|
61
|
-
Alert.alert('Error', 'Failed to process MRZ'
|
|
62
|
-
|
|
149
|
+
Alert.alert('Error', 'Failed to process MRZ', [
|
|
150
|
+
{
|
|
151
|
+
text: 'Retry',
|
|
152
|
+
onPress: () => {
|
|
153
|
+
setIsScanning(true);
|
|
154
|
+
setScannedData(null);
|
|
155
|
+
setLoading(false);
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
]);
|
|
63
159
|
}
|
|
64
160
|
};
|
|
65
161
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
// TODO: Integrate actual MRZ scanning library (e.g., @react-native-ml-kit/text-recognition)
|
|
69
|
-
// For now, simulate scanning after 3 seconds
|
|
162
|
+
// Fallback simulation if ML Kit not available
|
|
163
|
+
const simulateMRZScan = () => {
|
|
70
164
|
const timer = setTimeout(() => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
165
|
+
if (isScanning) {
|
|
166
|
+
const simulatedMRZ =
|
|
167
|
+
'P<UTOERIKSSON<<ANNA<MARIA<<<<<<<<<<<<<<<<<<<<\nL898902C36UTO7408122F1204159ZE184226B<<<<<10';
|
|
168
|
+
handleMRZScanned(simulatedMRZ);
|
|
169
|
+
}
|
|
75
170
|
}, 3000);
|
|
76
171
|
|
|
77
172
|
return () => clearTimeout(timer);
|
|
78
|
-
|
|
79
|
-
}, []);
|
|
173
|
+
};
|
|
80
174
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
175
|
+
// Render camera with frame processor
|
|
176
|
+
const renderCamera = () => {
|
|
177
|
+
try {
|
|
178
|
+
const { Camera } = require('react-native-vision-camera');
|
|
179
|
+
|
|
180
|
+
if (hasPermission && device) {
|
|
181
|
+
return (
|
|
182
|
+
<Camera
|
|
183
|
+
ref={cameraRef}
|
|
184
|
+
style={StyleSheet.absoluteFill}
|
|
185
|
+
device={device}
|
|
186
|
+
isActive={isScanning}
|
|
187
|
+
frameProcessor={(frame) => {
|
|
188
|
+
'worklet';
|
|
189
|
+
if (isScanning) {
|
|
190
|
+
processMRZWithMLKit(frame);
|
|
191
|
+
}
|
|
192
|
+
}}
|
|
193
|
+
/>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.warn('Camera render failed:', error);
|
|
198
|
+
}
|
|
84
199
|
|
|
85
|
-
|
|
200
|
+
// Fallback UI
|
|
201
|
+
return (
|
|
86
202
|
<View style={[StyleSheet.absoluteFill, { backgroundColor: '#000' }]}>
|
|
87
203
|
<Text
|
|
88
204
|
style={{
|
|
@@ -108,6 +224,14 @@ export default function MrzCapture() {
|
|
|
108
224
|
</Text>
|
|
109
225
|
)}
|
|
110
226
|
</View>
|
|
227
|
+
);
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
return (
|
|
231
|
+
<View style={styles.container}>
|
|
232
|
+
<Text style={styles.topLabel}>Align the MRZ code in the box</Text>
|
|
233
|
+
|
|
234
|
+
{renderCamera()}
|
|
111
235
|
|
|
112
236
|
{/* MRZ overlay box */}
|
|
113
237
|
<View
|
|
@@ -123,7 +247,7 @@ export default function MrzCapture() {
|
|
|
123
247
|
}}
|
|
124
248
|
/>
|
|
125
249
|
|
|
126
|
-
{loading && <Loader />}
|
|
250
|
+
{loading && <Loader message="Processing MRZ..." />}
|
|
127
251
|
</View>
|
|
128
252
|
);
|
|
129
253
|
}
|
|
@@ -72,17 +72,37 @@ const getUserData = async (): Promise<UserData> => {
|
|
|
72
72
|
try {
|
|
73
73
|
// Try to import geolocation if available
|
|
74
74
|
const Geolocation = require('react-native-geolocation-service');
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
75
|
+
|
|
76
|
+
// Check if Geolocation is properly imported and has the method
|
|
77
|
+
if (Geolocation && typeof Geolocation.getCurrentPosition === 'function') {
|
|
78
|
+
location = await new Promise((resolve, reject) => {
|
|
79
|
+
Geolocation.getCurrentPosition(
|
|
80
|
+
resolve,
|
|
81
|
+
reject,
|
|
82
|
+
{
|
|
83
|
+
enableHighAccuracy: true,
|
|
84
|
+
timeout: 15000,
|
|
85
|
+
maximumAge: 10000,
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
} else if (Geolocation && Geolocation.default && typeof Geolocation.default.getCurrentPosition === 'function') {
|
|
90
|
+
// Try default export
|
|
91
|
+
location = await new Promise((resolve, reject) => {
|
|
92
|
+
Geolocation.default.getCurrentPosition(
|
|
93
|
+
resolve,
|
|
94
|
+
reject,
|
|
95
|
+
{
|
|
96
|
+
enableHighAccuracy: true,
|
|
97
|
+
timeout: 15000,
|
|
98
|
+
maximumAge: 10000,
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
} else {
|
|
103
|
+
console.warn('Geolocation library not properly configured');
|
|
104
|
+
location = null;
|
|
105
|
+
}
|
|
86
106
|
} catch (err) {
|
|
87
107
|
console.warn('Location fetch error:', err);
|
|
88
108
|
location = null;
|