318 lines
15 KiB
Dart
318 lines
15 KiB
Dart
import 'dart:convert';
|
||
import 'dart:io';
|
||
|
||
/// Syria Driver Registration Simulation
|
||
///
|
||
/// Traces the complete flow:
|
||
/// 1. Phone OTP Verification
|
||
/// 2. Personal + Car Info Input
|
||
/// 3. Document Image Capture (license, ID, car docs)
|
||
/// 4. AI/OCR Processing (per-document via ai_document.php)
|
||
/// 5. Document Upload (uploadSyrianDocs.php → signed URL)
|
||
/// 6. Final Submission (register_driver_and_car.php → Gemini bulk AI → DB insert → FCM)
|
||
/// 7. Admin Review & Activation
|
||
///
|
||
/// Run: `dart run siro_driver/lib/controller/auth/syria/registration_simulation.dart`
|
||
|
||
void main() async {
|
||
print('═══════════════════════════════════════════════════════');
|
||
print(' SYRIA DRIVER REGISTRATION SIMULATION');
|
||
print('═══════════════════════════════════════════════════════');
|
||
|
||
const host = 'api-syria.siromove.com';
|
||
const protocol = 'https';
|
||
const driverId = 'DRV2026061912345678';
|
||
|
||
// ================================================================
|
||
// STEP 1: Initial Phone OTP Verification
|
||
// ================================================================
|
||
print('\n─── STEP 1: Phone OTP Verification ───');
|
||
const phone = '+963992952235';
|
||
print(' Phone: $phone');
|
||
|
||
// Backend: POST /auth/otp/request.php
|
||
// Payload: { phone_number, purpose: "driver_registration" }
|
||
// Checks: last_request < 120s → cooldown
|
||
// Inserts/updates: phone_verification(phone_number, code, is_verified=0, last_request)
|
||
// Sends SMS with code
|
||
print(' → POST /auth/otp/request.php');
|
||
print(' Request: { phone_number: "$phone", purpose: "driver_registration" }');
|
||
print(' ✅ OTP sent (cooldown 120s applied)');
|
||
|
||
// Backend: POST /auth/otp/verify.php
|
||
// Payload: { phone_number, code, device_token }
|
||
// Validates: code match, within TTL
|
||
// Sets: phone_verification.is_verified = 1
|
||
// Returns: driver_id (new or existing)
|
||
print(' → POST /auth/otp/verify.php');
|
||
print(' Request: { phone_number: "$phone", code: "123456", device_token: "fp_abc123" }');
|
||
print(' ✅ Phone verified, driver_id returned');
|
||
|
||
// Check: GET /auth/syria/driver/isPhoneVerified.php
|
||
// Query: phone_number
|
||
// Returns: success if is_verified = 1
|
||
print(' → GET /auth/syria/driver/isPhoneVerified.php?phone_number=$phone');
|
||
print(' ✅ Phone is verified, proceeding to registration');
|
||
|
||
// ================================================================
|
||
// STEP 2: Personal Information Input (Flutter UI)
|
||
// ================================================================
|
||
print('\n─── STEP 2: Personal Information ───');
|
||
final driverInfo = {
|
||
'first_name': 'أحمد',
|
||
'last_name': 'الأسد',
|
||
'national_number': '04020123456',
|
||
'birthdate': '1990-05-15',
|
||
'phone': phone,
|
||
'driver_license_expiry': '2028-06-01',
|
||
};
|
||
print(' Driver info collected:');
|
||
driverInfo.forEach((k, v) => print(' $k: $v'));
|
||
|
||
// ================================================================
|
||
// STEP 3: Car Information Input (Flutter UI)
|
||
// ================================================================
|
||
print('\n─── STEP 3: Car Information ───');
|
||
final carInfo = {
|
||
'car_plate': '155186 درعا',
|
||
'make': 'Hyundai',
|
||
'model': 'H1',
|
||
'year': '2019',
|
||
'color': 'White',
|
||
'color_hex': '#FFFFFF',
|
||
'vehicle_category_id': 1, // 1=Car, 2=Motorcycle, 3=Van/Bus
|
||
'fuel_type_id': 1, // 1=Petrol, 2=Diesel, 3=Electric, 4=Hybrid
|
||
'owner': 'أحمد الأسد',
|
||
'vin': 'KMHSH81XSBU123456',
|
||
};
|
||
print(' Car info collected:');
|
||
carInfo.forEach((k, v) => print(' $k: $v'));
|
||
|
||
// ================================================================
|
||
// STEP 4: Document Image Capture & Per-Document AI/OCR
|
||
// ================================================================
|
||
print('\n─── STEP 4: Document Image Capture + AI/OCR ───');
|
||
|
||
final documents = [
|
||
'id_front_sy',
|
||
'id_back_sy',
|
||
'driving_license_sy_front',
|
||
'driving_license_sy_back',
|
||
'vehicle_license_sy_front',
|
||
'vehicle_license_sy_back',
|
||
'profile_picture',
|
||
'criminal_record',
|
||
];
|
||
|
||
for (final docType in documents) {
|
||
print(' 📷 Capturing: $docType');
|
||
print(' → ImagePicker.camera → ImageCropper → FlutterImageCompress');
|
||
print(' → POST /auth/document_syria/ai_document.php');
|
||
print(' Fields: driver_id, type=$docType, image (multipart)');
|
||
print(' AI model: gemini-flash-lite-latest (per-document OCR)');
|
||
|
||
// Each document type has a unique Gemini prompt
|
||
String expectedExtraction;
|
||
switch (docType) {
|
||
case 'id_front_sy':
|
||
expectedExtraction = '{ "full_name": "أحمد الأسد", "national_number": "04020123456", "dob": "1990-05-15", "address": "دمشق" }';
|
||
break;
|
||
case 'id_back_sy':
|
||
expectedExtraction = '{ "governorate": "دمشق", "address": "المزة", "gender": "Male", "issue_date": "2010-03-01" }';
|
||
break;
|
||
case 'driving_license_sy_front':
|
||
expectedExtraction = '{ "name_arabic": "أحمد الأسد", "birth_place": "دمشق", "birth_year": "1990", "national_number": "04020123456", "civil_registry": "دمشق 3", "blood_type": "A+" }';
|
||
break;
|
||
case 'driving_license_sy_back':
|
||
expectedExtraction = '{ "issue_date": "2018-06-15", "expiry_date": "2028-06-15", "license_number": "987654", "license_category": "D1" }';
|
||
break;
|
||
case 'vehicle_license_sy_front':
|
||
expectedExtraction = '{ "car_plate": "155186 درعا", "owner": "أحمد الأسد", "vin": "KMHSH81XSBU123456", "color": "White", "color_hex": "#FFFFFF", "issue_date": "2019-03-10", "inspection_date": "2025-03-10" }';
|
||
break;
|
||
case 'vehicle_license_sy_back':
|
||
expectedExtraction = '{ "make": "Hyundai", "model": "H1", "year": "2019", "fuel": "Petrol", "chassis": "KMHSH81XSBU123456" }';
|
||
break;
|
||
default:
|
||
expectedExtraction = '{ "status": "success" }';
|
||
}
|
||
print(' ✅ AI extraction: $expectedExtraction');
|
||
|
||
print(' ✅ Image URL: $protocol://$host/siro/auth/uploads/documents/driver_${docType}_$driverId.jpg');
|
||
}
|
||
|
||
// ================================================================
|
||
// STEP 5: Document Upload to Secure Storage
|
||
// ================================================================
|
||
print('\n─── STEP 5: Document Upload (Secure Signed URLs) ───');
|
||
|
||
final docUrls = <String, String>{};
|
||
const uploadDocTypes = [
|
||
'driver_license_front',
|
||
'driver_license_back',
|
||
'car_license_front',
|
||
'car_license_back',
|
||
];
|
||
|
||
|
||
|
||
for (final docType in uploadDocTypes) {
|
||
print(' 📤 Uploading: $docType');
|
||
print(' → POST /auth/syria/uploadSyrianDocs.php');
|
||
print(' Fields: driver_id=$driverId, doc_type=$docType, file (multipart)');
|
||
print(' File stored: private_uploads/<hash>/<driverId>__${docType}.jpg');
|
||
print(' MIME validation: image/jpeg, image/png, image/webp');
|
||
print(' Max size: 5 MB');
|
||
|
||
final signedUrl = '$protocol://$host/siro/secure_image.php'
|
||
'?driver_id=$driverId'
|
||
'&doc_type=$docType'
|
||
'&ext=jpg'
|
||
'&expires=1780000000'
|
||
'&signature=abc123def456';
|
||
|
||
docUrls[docType] = signedUrl;
|
||
print(' ✅ Signed URL: $signedUrl');
|
||
print(' TTL: 2 days (172800s)');
|
||
}
|
||
|
||
// ================================================================
|
||
// STEP 6: Final Registration Submission
|
||
// ================================================================
|
||
print('\n─── STEP 6: Final Registration (register_driver_and_car.php) ───');
|
||
print(' → POST /auth/syria/driver/register_driver_and_car.php');
|
||
print(' This is the MAIN orchestrator. It does:');
|
||
print(' 1. Phone number normalization (Syria/Jordan/Egypt logic)');
|
||
print(' 2. Encrypt sensitive fields (phone, email, name, address, etc.)');
|
||
print(' 3. HMAC-based password derivation from id|phone|national_number');
|
||
print(' 4. Check for duplicate phone/email');
|
||
print(' 5. Insert into `driver` table with status="yet"');
|
||
print(' 6. Insert into `CarRegistration` with vehicle_category_id + fuel_type_id');
|
||
print(' 7. Insert document links into `driver_documents` table');
|
||
print(' 8. Store profile_picture into `imageProfileCaptain`');
|
||
print(' 9. AI BULK ANALYSIS via Gemini Flash Lite (all docs together)');
|
||
print(' 10. Send FCM notification → topic: new_driver_registration');
|
||
print(' 11. Return { status: "success", driverID, carRegID, documents }');
|
||
|
||
// Show the full payload
|
||
print('\n 📦 Request payload (multipart):');
|
||
print(' Driver fields:');
|
||
for (final f in ['id', 'first_name', 'last_name', 'phone', 'national_number', 'birthdate', 'status', 'gender', 'email']) {
|
||
print(' $f: ${f == 'id' ? driverId : driverInfo[f] ?? carInfo[f] ?? '—'}');
|
||
}
|
||
print(' Car fields:');
|
||
for (final f in ['vin', 'car_plate', 'make', 'model', 'year', 'color', 'color_hex', 'owner', 'vehicle_category_id', 'fuel_type_id']) {
|
||
print(' $f: ${carInfo[f] ?? '—'}');
|
||
}
|
||
print(' Document URLs:');
|
||
docUrls.forEach((k, v) => print(' $k: ${v.substring(0, 60)}...'));
|
||
|
||
// Simulate the transaction
|
||
print('\n 🔄 Transaction: BEGIN');
|
||
print(' 🔍 Check duplicate: SELECT id FROM driver WHERE phone = :p OR email = :e');
|
||
print(' ✅ No duplicates found');
|
||
print(' 📝 INSERT INTO driver (...) VALUES (...)');
|
||
print(' → driverID: $driverId');
|
||
print(' 📝 INSERT INTO CarRegistration (...) VALUES (...)');
|
||
print(' → carRegID: 1');
|
||
print(' 📝 INSERT INTO driver_documents (8 rows)');
|
||
print(' 📝 INSERT INTO imageProfileCaptain (1 row)');
|
||
print(' 🔄 Transaction: COMMIT');
|
||
print(' ✅ Registration committed');
|
||
|
||
// AI Bulk Analysis
|
||
print('\n 🤖 AI Bulk Analysis (Gemini Flash Lite):');
|
||
print(' → Prompt includes all 8 document images + schema instructions');
|
||
print(' → SSRF protection: only ALLOWED_UPLOAD_HOST URLs fetched');
|
||
print(' → Extracted fields override user input:');
|
||
print(' - full_name → first_name / last_name');
|
||
print(' - national_number, dob, address, governorate → site');
|
||
print(' - gender, license dates, car details');
|
||
print(' ↳ If AI status="failure" → registration ABORTED with error message');
|
||
print(' ✅ AI verification passed');
|
||
|
||
// FCM Notification
|
||
print('\n 📲 FCM Notification:');
|
||
print(' → POST /ride/firebase/send_fcm.php');
|
||
print(' → Topic: new_driver_registration');
|
||
print(' → Title: "تسجيل سائق جديد"');
|
||
print(' → Body: "سائق جديد (أحمد الأسد) سجل برقم ID: $driverId وهو بانتظار المراجعة والتفعيل."');
|
||
print(' ✅ Admin notified');
|
||
|
||
// Response
|
||
print('\n 📤 Response:');
|
||
print(' {');
|
||
print(' "status": "success",');
|
||
print(' "driverID": "$driverId",');
|
||
print(' "carRegID": 1,');
|
||
print(' "documents": {');
|
||
docUrls.forEach((k, v) => print(' "$k": "$v",'));
|
||
print(' }');
|
||
print(' }');
|
||
|
||
// ================================================================
|
||
// STEP 7: Admin Review & Activation
|
||
// ================================================================
|
||
print('\n─── STEP 7: Admin Review & Activation ───');
|
||
|
||
// Admin fetches pending drivers
|
||
print(' 🔍 Admin fetches pending drivers:');
|
||
print(' → GET /auth/syria/driver/drivers_pending_list.php');
|
||
print(' Decrypts: phone, first_name, last_name');
|
||
print(' Returns: [{ id: "$driverId", first_name: "أحمد", last_name: "الأسد", phone: "$phone" }]');
|
||
print(' ✅ Driver appears in pending list (status != "active")');
|
||
|
||
// Admin views details
|
||
print('\n 📋 Admin views driver details:');
|
||
print(' → GET /auth/syria/driver/driver_details.php?driver_id=$driverId');
|
||
print(' Returns: driver row + car registration + document links');
|
||
print(' ✅ Admin reviews all documents');
|
||
|
||
// Admin activates driver
|
||
print('\n ✅ Admin approves & activates:');
|
||
print(' → POST /Admin/Staff/activate.php');
|
||
print(' Auth: JWT (role=super_admin or admin)');
|
||
print(' Payload: { user_id: "$driverId", type: "admin" }');
|
||
print(' SQL: UPDATE driver SET status = "active" WHERE id = "$driverId"');
|
||
|
||
// Check driver_assurance table (references in migration schema)
|
||
print('\n ℹ️ driver_assurance table (optional):');
|
||
print(' May store health_insurance_provider + assured status');
|
||
print(' Linked via driver_id (encrypted columns)');
|
||
|
||
// Final driver state
|
||
print('\n 📊 Final driver state in DB:');
|
||
print(' driver.phone = <encrypted>$phone');
|
||
print(' driver.status = "active"');
|
||
print(' driver.is_verified = 1 (via phone_verification)');
|
||
print(' CarRegistration.status = "yet"');
|
||
print(' driver_documents: 8 rows linked to driverID');
|
||
|
||
// ================================================================
|
||
// SUMMARY
|
||
// ================================================================
|
||
print('\n═══════════════════════════════════════════════════════');
|
||
print(' REGISTRATION FLOW COMPLETE');
|
||
print('═══════════════════════════════════════════════════════');
|
||
print(' Files involved:');
|
||
print(' App (Flutter):');
|
||
print(' - registration_controller.dart (multi-step UI)');
|
||
print(' - register_captin_controller.dart (basic signup)');
|
||
print(' - opt_token_controller.dart (OTP send/verify)');
|
||
print(' - ml_google_doc.dart (phone OCR scanner)');
|
||
print(' Backend (PHP):');
|
||
print(' - /auth/otp/request.php + verify.php');
|
||
print(' - /auth/syria/driver/isPhoneVerified.php');
|
||
print(' - /auth/document_syria/ai_document.php');
|
||
print(' - /auth/syria/uploadSyrianDocs.php');
|
||
print(' - /auth/syria/driver/register_driver_and_car.php');
|
||
print(' - /auth/syria/driver/drivers_pending_list.php');
|
||
print(' - /auth/syria/driver/driver_details.php');
|
||
print(' - /serviceapp/getDriversWaitingActive.php');
|
||
print(' - /Admin/Staff/activate.php');
|
||
print(' Schema:');
|
||
print(' - schema_primary.sql (driver, CarRegistration, driver_documents,');
|
||
print(' phone_verification, imageProfileCaptain,');
|
||
print(' driver_gifts, driver_assurance)');
|
||
print('═══════════════════════════════════════════════════════');
|
||
}
|