Update: 2026-06-12 01:23:54
This commit is contained in:
@@ -16,8 +16,9 @@ try {
|
||||
exit;
|
||||
}
|
||||
|
||||
/* ================== General Settings ================== */
|
||||
$PUBLIC_BASE = "https://intaleq.xyz/driver_docs";
|
||||
$host = $_SERVER['HTTP_HOST'] ?? 'api-syria.siromove.com';
|
||||
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? "https" : "http";
|
||||
$PUBLIC_BASE = "$protocol://$host/siro/auth/uploads/documents";
|
||||
|
||||
/* ================== 1) Input Fields ================== */
|
||||
$raw_first_name = null;
|
||||
@@ -38,8 +39,12 @@ try {
|
||||
// vehicle_category_id, fuel_type_id
|
||||
|
||||
$docKeys = [
|
||||
'driver_license_front',
|
||||
'id_front',
|
||||
'id_back',
|
||||
'driver_license',
|
||||
'driver_license_back',
|
||||
'profile_picture',
|
||||
'criminal_record',
|
||||
'car_license_front',
|
||||
'car_license_back'
|
||||
];
|
||||
@@ -63,6 +68,7 @@ try {
|
||||
}
|
||||
|
||||
/* ================== 🟢 START PHONE FORMATTING LOGIC 🟢 ================== */
|
||||
$country = 'Syria'; // Default
|
||||
if (!empty($data['phone'])) {
|
||||
$phone = $data['phone'];
|
||||
|
||||
@@ -70,39 +76,46 @@ try {
|
||||
$phone = preg_replace('/[ \-\(\)\+]/', '', $phone);
|
||||
$phone = trim($phone);
|
||||
|
||||
// 2. توحيد البادئات الدولية
|
||||
if (strpos($phone, '00963') === 0) {
|
||||
$phone = substr($phone, 2);
|
||||
} elseif (strpos($phone, '0963') === 0) {
|
||||
$phone = substr($phone, 1);
|
||||
}
|
||||
if (strpos($phone, '962') === 0 || strpos($phone, '00962') === 0) {
|
||||
if (strpos($phone, '00962') === 0) $phone = substr($phone, 2);
|
||||
$country = 'Jordan';
|
||||
} elseif (strpos($phone, '20') === 0 || strpos($phone, '0020') === 0) {
|
||||
if (strpos($phone, '0020') === 0) $phone = substr($phone, 2);
|
||||
$country = 'Egypt';
|
||||
} else {
|
||||
// 2. توحيد البادئات الدولية (سوريا)
|
||||
if (strpos($phone, '00963') === 0) {
|
||||
$phone = substr($phone, 2);
|
||||
} elseif (strpos($phone, '0963') === 0) {
|
||||
$phone = substr($phone, 1);
|
||||
}
|
||||
|
||||
// 3. معالجة الحالات الخاصة بالصفر الزائد بعد الرمز الدولي
|
||||
if (strpos($phone, '96309') === 0) {
|
||||
$phone = '9639' . substr($phone, 5);
|
||||
}
|
||||
elseif (strpos($phone, '9630') === 0) {
|
||||
$phone = '9639' . substr($phone, 4);
|
||||
}
|
||||
// 3. معالجة الحالات الخاصة بالصفر الزائد بعد الرمز الدولي
|
||||
if (strpos($phone, '96309') === 0) {
|
||||
$phone = '9639' . substr($phone, 5);
|
||||
}
|
||||
elseif (strpos($phone, '9630') === 0) {
|
||||
$phone = '9639' . substr($phone, 4);
|
||||
}
|
||||
|
||||
// 4. معالجة الأرقام المحلية
|
||||
elseif (strpos($phone, '09') === 0) {
|
||||
$phone = '963' . substr($phone, 1);
|
||||
}
|
||||
elseif (strpos($phone, '9') === 0 && strlen($phone) == 9) {
|
||||
$phone = '963' . $phone;
|
||||
}
|
||||
elseif (strpos($phone, '0') === 0 && strlen($phone) == 10) {
|
||||
$phone = '963' . substr($phone, 1);
|
||||
}
|
||||
|
||||
// 5. التأكد من وجود 9 بعد الرمز الدولي
|
||||
if (strpos($phone, '963') === 0 && strlen($phone) > 3) {
|
||||
if (strpos($phone, '9639') !== 0) {
|
||||
$phone = '9639' . substr($phone, 3);
|
||||
// 4. معالجة الأرقام المحلية
|
||||
elseif (strpos($phone, '09') === 0) {
|
||||
$phone = '963' . substr($phone, 1);
|
||||
}
|
||||
elseif (strpos($phone, '9') === 0 && strlen($phone) == 9) {
|
||||
$phone = '963' . $phone;
|
||||
}
|
||||
elseif (strpos($phone, '0') === 0 && strlen($phone) == 10) {
|
||||
$phone = '963' . substr($phone, 1);
|
||||
}
|
||||
|
||||
// 5. التأكد من وجود 9 بعد الرمز الدولي
|
||||
if (strpos($phone, '963') === 0 && strlen($phone) > 3) {
|
||||
if (strpos($phone, '9639') !== 0) {
|
||||
$phone = '9639' . substr($phone, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$data['phone'] = $phone;
|
||||
}
|
||||
/* ================== 🔴 END PHONE FORMATTING LOGIC 🔴 ================== */
|
||||
@@ -131,6 +144,7 @@ try {
|
||||
$docUrls = [];
|
||||
foreach ($docKeys as $k) {
|
||||
$u = filterRequest($k);
|
||||
if (($k === 'driver_license_back' || $k === 'criminal_record') && ($u === null || $u === '')) continue;
|
||||
if ($u === null || $u === '') {
|
||||
jsonError("Missing document URL: $k");
|
||||
exit;
|
||||
@@ -142,6 +156,149 @@ try {
|
||||
$docUrls[$k] = $u;
|
||||
}
|
||||
|
||||
/* ================== AI PROCESSING START ================== */
|
||||
$apiKey = getenv("GEMINI_API_KEY");
|
||||
if ($apiKey) {
|
||||
$promptBase = '
|
||||
You are a highly secure AI Assistant specialized in analyzing identification and driver documents.
|
||||
Country Context: ' . ($country ?? 'Syria') . '
|
||||
|
||||
### TASK
|
||||
We are providing you with multiple images representing a driver\'s documents (National ID, Driver License, Profile Picture, Criminal Record, and Car Registration).
|
||||
Extract all the required data accurately according to the exact schema provided, and perform a FACE MATCHING analysis.
|
||||
Since the driver may be from Jordan, Egypt, or Syria, the layout, fields, and distribution of information between the front and back of each card varies widely by country.
|
||||
Therefore, do NOT assume a specific field is on the front or the back of a card. You must scan all provided document images (e.g., both ID images, both license images) and intelligently locate the requested fields wherever they appear on the cards.
|
||||
|
||||
### RULES
|
||||
1. Convert any Eastern-Arabic digits (٠١٢٣٤٥٦٧٨٩) to Western digits (0-9).
|
||||
2. Dates must be formatted as ISO `YYYY-MM-DD`.
|
||||
3. Smart Extraction: Scan all provided document images without restriction. Do not fail the overall request if some optional fields (like governorate or address or issue dates) are missing or unreadable on the card. Simply set those specific fields to `null` in the JSON, but do NOT set the overall status to failure. Overall status should only be \'failure\' if there is a critical security/authenticity issue (e.g., face mismatch, fake/forged documents, or missing primary driver identity).
|
||||
4. FACE MATCHING (CRITICAL): Compare the face in the "Profile Picture" with the photos on the "National ID" and "Driver License".
|
||||
5. Ensure the Criminal/Non-Conviction record is valid and matches the driver\'s name.
|
||||
6. The `national_number` and `vin` (chassis) must contain Latin digits/characters only.
|
||||
7. Normalize color names (e.g. "أبيض" -> "White") and provide a matching Hex code (e.g. "#FFFFFF").
|
||||
8. Do NOT add markdown formatting around the output. Return ONLY raw JSON.
|
||||
|
||||
### REQUIRED JSON OUTPUT FORMAT
|
||||
{
|
||||
"status": "success|failure",
|
||||
"reason": "If failure, state the reason (e.g., Face mismatch, blurry, invalid record)",
|
||||
"face_match_confidence": "high|low",
|
||||
"driver": {
|
||||
"full_name": "", // Full name in Arabic
|
||||
"national_number": "", // National ID/National number (Latin digits)
|
||||
"dob": "YYYY-MM-DD", // Date of birth
|
||||
"address": "", // Full address
|
||||
"governorate": "", // Governorate/Site/City
|
||||
"gender": "Male|Female", // Gender
|
||||
"id_issue_date": "YYYY-MM-DD", // National ID issue date
|
||||
"license_issue_date": "YYYY-MM-DD", // Driver license issue date
|
||||
"license_expiry_date": "YYYY-MM-DD", // Driver license expiry date
|
||||
"license_number": "", // Driver license number
|
||||
"license_category": "", // License category (e.g., D1, B, Private, Public)
|
||||
"blood_type": "", // Blood type (e.g., A+, O-)
|
||||
"civil_registry": "", // Civil registry/Place of registration
|
||||
"birth_place": "" // Place of birth
|
||||
},
|
||||
"car": {
|
||||
"car_plate": "", // Full car plate (e.g., 155186 درعا)
|
||||
"owner": "", // Owner full name
|
||||
"vin": "", // Chassis/VIN number
|
||||
"color": "", // Color name
|
||||
"color_hex": "", // Color hex code (e.g., #FFFFFF)
|
||||
"car_issue_date": "YYYY-MM-DD", // Car registration issue date
|
||||
"inspection_date": "YYYY-MM-DD", // Car next inspection date
|
||||
"make": "", // Car Make (e.g., Hyundai)
|
||||
"model": "", // Car Model (e.g., H1)
|
||||
"year": "", // Manufacturing year (e.g., 2019)
|
||||
"fuel": "" // Fuel type (e.g., Petrol, Diesel, Electric)
|
||||
}
|
||||
}';
|
||||
|
||||
$contents = [
|
||||
["role" => "user", "parts" => [["text" => $promptBase]]]
|
||||
];
|
||||
|
||||
foreach ($docUrls as $key => $url) {
|
||||
$imgData = @file_get_contents($url);
|
||||
if ($imgData !== false) {
|
||||
$base64 = base64_encode($imgData);
|
||||
$ext = strtolower(pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION));
|
||||
$mime = ($ext === 'png') ? 'image/png' : 'image/jpeg';
|
||||
$contents[0]["parts"][] = ["text" => "Image type: " . $key];
|
||||
$contents[0]["parts"][] = ["inlineData" => ["mimeType" => $mime, "data" => $base64]];
|
||||
}
|
||||
}
|
||||
|
||||
$apiURL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-lite-latest:generateContent?key=$apiKey";
|
||||
$payload = ["contents" => $contents];
|
||||
|
||||
$ch = curl_init($apiURL);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
if ($response) {
|
||||
$aiData = json_decode($response, true);
|
||||
$textRaw = $aiData['candidates'][0]['content']['parts'][0]['text'] ?? '';
|
||||
$textRaw = trim(preg_replace('/```json|```/', '', $textRaw));
|
||||
$json = json_decode($textRaw, true);
|
||||
|
||||
if ($json && isset($json['status']) && strtolower($json['status']) === 'failure') {
|
||||
jsonError("AI Verification Failed: " . ($json['reason'] ?? 'Unknown reason'));
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($json && isset($json['driver'])) {
|
||||
$ex = $json['driver'];
|
||||
if (!empty($ex['full_name'])) {
|
||||
$data['name_arabic'] = $ex['full_name'];
|
||||
$parts = explode(' ', trim($ex['full_name']));
|
||||
if (count($parts) >= 2) {
|
||||
$data['first_name'] = $parts[0];
|
||||
$data['last_name'] = implode(' ', array_slice($parts, 1));
|
||||
} else {
|
||||
$data['first_name'] = $ex['full_name'];
|
||||
$data['last_name'] = '';
|
||||
}
|
||||
}
|
||||
if (!empty($ex['national_number'])) $data['national_number'] = $ex['national_number'];
|
||||
if (!empty($ex['dob'])) {
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $ex['dob'])) {
|
||||
$data['birthdate'] = $ex['dob'];
|
||||
} elseif (preg_match('/^\d{4}$/', $ex['dob'])) {
|
||||
$data['birthdate'] = $ex['dob'] . '-01-01';
|
||||
}
|
||||
}
|
||||
if (!empty($ex['address'])) $data['address'] = $ex['address'];
|
||||
if (!empty($ex['governorate'])) $data['site'] = $ex['governorate'];
|
||||
if (!empty($ex['gender'])) $data['gender'] = $ex['gender'];
|
||||
if (!empty($ex['id_issue_date'])) $data['issue_date'] = $ex['id_issue_date'];
|
||||
if (!empty($ex['license_issue_date'])) $data['licenseIssueDate'] = $ex['license_issue_date'];
|
||||
if (!empty($ex['license_expiry_date'])) $data['expiry_date'] = $ex['license_expiry_date'];
|
||||
if (!empty($ex['license_category'])) $data['license_categories'] = $ex['license_category'];
|
||||
// Not mapped directly in basic DB schema but extracted: blood_type, civil_registry, birth_place
|
||||
}
|
||||
|
||||
if ($json && isset($json['car'])) {
|
||||
$ex = $json['car'];
|
||||
if (!empty($ex['car_plate'])) $car['car_plate'] = $ex['car_plate'];
|
||||
if (!empty($ex['make'])) $car['make'] = $ex['make'];
|
||||
if (!empty($ex['model'])) $car['model'] = $ex['model'];
|
||||
if (!empty($ex['year'])) $car['year'] = $ex['year'];
|
||||
if (!empty($ex['color'])) $car['color'] = $ex['color'];
|
||||
if (!empty($ex['color_hex'])) $car['color_hex'] = $ex['color_hex'];
|
||||
if (!empty($ex['vin'])) $car['vin'] = $ex['vin'];
|
||||
if (!empty($ex['owner'])) $car['owner'] = $ex['owner'];
|
||||
if (!empty($ex['fuel'])) $car['fuel'] = $ex['fuel'];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* ================== AI PROCESSING END ================== */
|
||||
|
||||
/* ================== 2) Generate default id/email ================== */
|
||||
if (empty($data['id'])) {
|
||||
$data['id'] = 'DRV' . date('YmdHis') . random_int(1000, 9999);
|
||||
@@ -320,6 +477,7 @@ $pwdHashed = password_hash($rawSecret, PASSWORD_DEFAULT);
|
||||
");
|
||||
|
||||
foreach ($docKeys as $k) {
|
||||
if (!isset($docUrls[$k])) continue;
|
||||
$url = $docUrls[$k];
|
||||
$name = basename(parse_url($url, PHP_URL_PATH) ?? '');
|
||||
if ($name === '') { $name = $k . '_' . time() . '.jpg'; }
|
||||
@@ -330,6 +488,18 @@ $pwdHashed = password_hash($rawSecret, PASSWORD_DEFAULT);
|
||||
':image_name' => $name,
|
||||
':link' => $url,
|
||||
]);
|
||||
|
||||
if ($k === 'profile_picture') {
|
||||
$insProfile = $con->prepare("
|
||||
INSERT INTO imageProfileCaptain (driverID, image_name, link)
|
||||
VALUES (:driverID, :image_name, :link)
|
||||
");
|
||||
$insProfile->execute([
|
||||
':driverID' => $driverID,
|
||||
':image_name' => $name,
|
||||
':link' => $url,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/* ================== 10) Commit ================== */
|
||||
|
||||
Reference in New Issue
Block a user