Deploy: 2026-05-23 01:45:24
This commit is contained in:
245
ai_document.php
245
ai_document.php
@@ -1,245 +0,0 @@
|
|||||||
<?php
|
|
||||||
require_once __DIR__ . '/../../connect.php';
|
|
||||||
|
|
||||||
$driverId = filterRequest("driver_id");
|
|
||||||
$type = filterRequest("type");
|
|
||||||
|
|
||||||
// 🔒 Validate image
|
|
||||||
if (!isset($_FILES['image']) || $_FILES['image']['error'] !== UPLOAD_ERR_OK) {
|
|
||||||
error_log("Upload error: Image not provided or upload failed.");
|
|
||||||
jsonError("Image upload failed");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$file = $_FILES['image'];
|
|
||||||
$extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
|
|
||||||
$allowed = ['jpg', 'jpeg', 'png'];
|
|
||||||
|
|
||||||
if (!in_array($extension, $allowed)) {
|
|
||||||
error_log("Unsupported file type: $extension");
|
|
||||||
jsonError("Unsupported file type");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$uniqueName = "driver_" . $type . "_" . $driverId . ".$extension";
|
|
||||||
$uploadDir = "../uploads/documents/";
|
|
||||||
$uploadPath = $uploadDir . $uniqueName;
|
|
||||||
|
|
||||||
if (!is_dir($uploadDir)) {
|
|
||||||
mkdir($uploadDir, 0755, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!move_uploaded_file($file['tmp_name'], $uploadPath)) {
|
|
||||||
error_log("Failed to move uploaded file.");
|
|
||||||
jsonError("Failed to move uploaded image");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$imageUrl = "https://intaleq.xyz/intaleq/auth/uploads/documents/" . $uniqueName ;
|
|
||||||
$imageData = file_get_contents($uploadPath);
|
|
||||||
$imageBase64 = base64_encode($imageData);
|
|
||||||
|
|
||||||
$mimeType = match ($extension) {
|
|
||||||
'jpg', 'jpeg' => 'image/jpeg',
|
|
||||||
'png' => 'image/png',
|
|
||||||
default => 'application/octet-stream',
|
|
||||||
};
|
|
||||||
|
|
||||||
$prompts = [
|
|
||||||
"id_front_sy" => <<<EOT
|
|
||||||
You are an OCR expert for Syrian national ID cards (green card).
|
|
||||||
|
|
||||||
### TASK
|
|
||||||
Analyse the **front side** of the ID and return **raw JSON only** with exactly these keys:
|
|
||||||
|
|
||||||
{
|
|
||||||
"full_name": "", // الاسم الثلاثي أو الرباعي
|
|
||||||
"national_number": "", // الرقم الوطني (LATIN digits only)
|
|
||||||
"dob": "YYYY-MM-DD", // تاريخ الميلاد
|
|
||||||
"address": "" // العنوان
|
|
||||||
}
|
|
||||||
|
|
||||||
### RULES
|
|
||||||
* Read the red number on the bottom of the card.
|
|
||||||
* Convert any Eastern-Arabic digits (٠١٢٣٤٥٦٧٨٩) to Western-Arabic digits (0-9).
|
|
||||||
* `national_number` must contain **Latin digits only, no spaces or other characters**.
|
|
||||||
* If a field is missing, set it to **null**.
|
|
||||||
* Convert the birth date to ISO `YYYY-MM-DD`.
|
|
||||||
* Return valid JSON only — no extra keys, no markdown.
|
|
||||||
EOT,
|
|
||||||
"id_back_sy" => <<<EOT
|
|
||||||
أنت خبير OCR مختص ببطاقات الهوية السورية (الوجه الخلفي).
|
|
||||||
|
|
||||||
### المطلوب
|
|
||||||
حلّل صورة الوجه الخلفي للهوية السورية وأعد **JSON صِرف** يحتوي المفاتيح التالية فقط:
|
|
||||||
|
|
||||||
{
|
|
||||||
"governorate": "", // المحافظة (مثال: دمشق)
|
|
||||||
"address": "", // العنوان التفصيلي (حيّ، بلدة …)
|
|
||||||
"gender": "", //Male or Female
|
|
||||||
"issue_date": "YYYY-MM-DD"// تاريخ الإصدار بصيغة ISO
|
|
||||||
}
|
|
||||||
|
|
||||||
### القواعد
|
|
||||||
1. حوّل أي أرقام عربية شرقية (٠١٢٣٤٥٦٧٨٩) إلى أرقام لاتينية (0-9).
|
|
||||||
2. أعدّ تاريخ الإصدار بالتقويم الميلادي بصيغة `YYYY-MM-DD`.
|
|
||||||
3. استخدم أحرف لاتينية كبيرة لزمرة الدم مع رمز `+` أو `-` فقط.
|
|
||||||
4. إذا كان أحد الحقول غير موجود مطلقًا، أعد قيمته **null**.
|
|
||||||
5. لا تُرجع أي مفاتيح إضافية أو شروح أو Markdown — JSON صالح فقط.
|
|
||||||
EOT,
|
|
||||||
"driving_license_sy_front" => <<<EOT
|
|
||||||
You are an OCR expert for Syrian documents.
|
|
||||||
|
|
||||||
### TASK
|
|
||||||
Analyse the **front side of a Syrian driving licence** and return **clean JSON only** with the following keys (no extra keys, no markdown):
|
|
||||||
|
|
||||||
{
|
|
||||||
"name_arabic": "", // الاسم الثلاثي أو الرباعي بالعربية
|
|
||||||
"birth_place": "", // المحافظة أو المنطقة المكتوبة بعد كلمة الولادة
|
|
||||||
"birth_year": "", // سنة الميلاد فقط (أربعة أرقام)
|
|
||||||
"national_number": ""
|
|
||||||
"civil_registry": "", // سطر "القيد" (مثال: سهوة 3)
|
|
||||||
"blood_type": "" // زمرة الدم بالشكل: A+ , A- , B+ , B- , AB+ , AB- , O+ , O-
|
|
||||||
}
|
|
||||||
|
|
||||||
### RULES
|
|
||||||
* إذا كانت القيمة مفقودة تمامًا اكتب **null**.
|
|
||||||
* لا تُغيّر ترتيب المفاتيح.
|
|
||||||
* لا تُرسل أى شرح أو أسطر إضافية – JSON خالص فقط.
|
|
||||||
EOT,
|
|
||||||
|
|
||||||
"driving_license_sy_back" => <<<EOT
|
|
||||||
You are an OCR expert for Syrian driving licences.
|
|
||||||
|
|
||||||
### TASK
|
|
||||||
Analyse the **back side** of a Syrian driving licence and return **raw JSON only** with exactly these keys:
|
|
||||||
|
|
||||||
{
|
|
||||||
"issue_date": "YYYY-MM-DD", // تاريخ المنح
|
|
||||||
"expiry_date": "YYYY-MM-DD", // صالحة لغاية
|
|
||||||
"license_number": "", // رقم الإجازة
|
|
||||||
"license_category": "" // D1, D2, D3 … (as printed after "UNIVERSAL DRIVING LICENCE")
|
|
||||||
}
|
|
||||||
|
|
||||||
### RULES
|
|
||||||
* If a value is totally absent, set it to **null**.
|
|
||||||
* Convert all dates to ISO `YYYY-MM-DD` (Gregorian).
|
|
||||||
* Do **NOT** add extra keys, comments, or markdown — return valid JSON only.
|
|
||||||
EOT,
|
|
||||||
"vehicle_license_sy_front" => <<<EOT
|
|
||||||
You are an OCR expert specialized in analyzing Syrian vehicle registration cards (الرخصة البرتقالية).
|
|
||||||
|
|
||||||
Your task is to extract structured data from the **front side** of the Syrian orange vehicle card and return **raw JSON only** with the following exact fields:
|
|
||||||
|
|
||||||
{
|
|
||||||
"car_plate": "", // رقم المركبة الكامل مع اسم المحافظة، مأخوذ من الجهة اليسرى في السطر الأول (مثال: "155186 درعا")
|
|
||||||
"owner": "", // اسم المالك الكامل
|
|
||||||
"vin": "", // رقم الهيكل
|
|
||||||
"color": "", // اللون بالعربية أو الإنجليزية (مثال: "أبيض" أو "White")
|
|
||||||
"color_hex": "", // كود اللون بصيغة Hex (مثال: "#FFFFFF") أو #27332F إن تعذّر
|
|
||||||
"issue_date": "YYYY-MM-DD", // تاريخ المنح بصيغة ISO
|
|
||||||
"inspection_date": "YYYY-MM-DD" // تاريخ الفحص القادم بصيغة ISO
|
|
||||||
}
|
|
||||||
|
|
||||||
### Instructions & Rules:
|
|
||||||
|
|
||||||
1. Do **not** extract the "رمز المركبة" (on the right side of the first line) — use only the **left side** of the first line for `car_plate`.
|
|
||||||
2. Convert any Arabic dates (like `2024/05/13`) into ISO format `YYYY-MM-DD`.
|
|
||||||
3. If any value is missing or unreadable, return `null` for it.
|
|
||||||
4. Maintain Arabic encoding (e.g., owner name, city name, color).
|
|
||||||
5. Never guess — extract only what's visually found on the card.
|
|
||||||
6. Never include any explanation or extra output — return the JSON only.
|
|
||||||
|
|
||||||
Example of valid `car_plate`:
|
|
||||||
- "155186 درعا"
|
|
||||||
- "45291 دمشق"
|
|
||||||
- "122334 حمص"
|
|
||||||
EOT,
|
|
||||||
"vehicle_license_sy_back" => <<<EOT
|
|
||||||
You are an OCR expert for Syrian vehicle registration cards (orange card).
|
|
||||||
|
|
||||||
### TASK
|
|
||||||
Analyse the **back side** of the card and return **raw JSON only** with exactly these keys (no more, no less):
|
|
||||||
|
|
||||||
{
|
|
||||||
"make": "", // الصانع (Hyundai …)
|
|
||||||
"model": "", // الطراز (H1 …)
|
|
||||||
"year": "", // سنة الصنع بالأرقام اللاتينية (e.g. "2019")
|
|
||||||
"fuel": "", // نوع الوقود (بنزين، ديزل …) أو بالإنجليزية (Petrol, Diesel,electric)
|
|
||||||
"chassis": "" // رقم الهيكل (VIN)
|
|
||||||
}
|
|
||||||
|
|
||||||
### RULES
|
|
||||||
* Convert any Eastern-Arabic digits (٠١٢٣٤٥٦٧٨٩) to Western digits (0-9).
|
|
||||||
* Normalise color names to standard English if possible, then map to a common Hex code
|
|
||||||
• "أبيض / White" → **#FFFFFF**
|
|
||||||
• "أسود / Black" → **#000000**
|
|
||||||
• "أحمر / Red" → **#FF0000**
|
|
||||||
• "أزرق / Blue" → **#0000FF**
|
|
||||||
• … (use the closest basic colour); if no match, set **color_hex = null**.
|
|
||||||
* If any field is unreadable or absent, set its value to **null**.
|
|
||||||
* Do **NOT** include extra keys, comments, or markdown — output valid JSON only.
|
|
||||||
EOT
|
|
||||||
];
|
|
||||||
|
|
||||||
$prompt = $prompts[$type] ?? $prompts["id_front_sy"];
|
|
||||||
|
|
||||||
$apiKey = getenv("GEMINI_API_KEY");
|
|
||||||
$apiURL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key=$apiKey";
|
|
||||||
|
|
||||||
$headers = ["Content-Type: application/json"];
|
|
||||||
$payload = [
|
|
||||||
"contents" => [
|
|
||||||
["role" => "user", "parts" => [["text" => $prompt]]],
|
|
||||||
["role" => "user", "parts" => [["inlineData" => ["mimeType" => $mimeType, "data" => $imageBase64]]]]
|
|
||||||
]
|
|
||||||
];
|
|
||||||
|
|
||||||
$ch = curl_init($apiURL);
|
|
||||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
||||||
curl_setopt($ch, CURLOPT_POST, true);
|
|
||||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
|
||||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
|
||||||
|
|
||||||
$response = curl_exec($ch);
|
|
||||||
|
|
||||||
if (curl_errno($ch)) {
|
|
||||||
$error_msg = curl_error($ch);
|
|
||||||
error_log("CURL error: $error_msg");
|
|
||||||
jsonError("AI Error: $error_msg");
|
|
||||||
curl_close($ch);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
curl_close($ch);
|
|
||||||
error_log("AI raw response: $response");
|
|
||||||
|
|
||||||
$data = json_decode($response, true);
|
|
||||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
|
||||||
error_log("JSON decode error: " . json_last_error_msg());
|
|
||||||
jsonError("Failed to parse AI response");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$textRaw = $data['candidates'][0]['content']['parts'][0]['text'] ?? '';
|
|
||||||
$textRaw = trim(preg_replace('/```json|```/', '', $textRaw));
|
|
||||||
$json = json_decode($textRaw, true);
|
|
||||||
|
|
||||||
$requiredKey = match ($type) {
|
|
||||||
'id_front_sy' => 'national_number',
|
|
||||||
'id_back_sy' => 'gender',
|
|
||||||
'driving_license_sy' => 'license_type',
|
|
||||||
'vehicle_license_sy' => 'chassis',
|
|
||||||
default => null,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!$json || ($requiredKey && !isset($json[$requiredKey]))) {
|
|
||||||
error_log("AI response missing required key '$requiredKey': $textRaw");
|
|
||||||
jsonError("AI failed to extract required information");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
printSuccess([
|
|
||||||
"image_url" => $imageUrl,
|
|
||||||
"data" => $json
|
|
||||||
]);
|
|
||||||
@@ -31,8 +31,8 @@ class OTPController extends BaseController
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean phone number (remove non-digits except +)
|
// Clean phone number (remove non-digits including +)
|
||||||
$phone = preg_replace('/[^\d+]/', '', $phone);
|
$phone = preg_replace('/\D/', '', $phone);
|
||||||
|
|
||||||
// 1. Resolve WhatsApp Session
|
// 1. Resolve WhatsApp Session
|
||||||
$session = null;
|
$session = null;
|
||||||
|
|||||||
@@ -1,237 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
// --- 1. Dependencias y Conexión ---
|
|
||||||
require_once __DIR__ . '/../connect.php';
|
|
||||||
|
|
||||||
// دالة مساعدة لتسجيل الخطوات في ملف الـ LOG
|
|
||||||
function logStep($step, $message) {
|
|
||||||
error_log("[DriverReg] Step $step: $message");
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// --- بدء المعاملة ---
|
|
||||||
$con->beginTransaction();
|
|
||||||
logStep(1, "Transaction started via beginTransaction()");
|
|
||||||
|
|
||||||
// --- 2. Recolección de Datos (Conductor + Coche) ---
|
|
||||||
$phone = filterRequest("phone");
|
|
||||||
$password = filterRequest("password");
|
|
||||||
$firstName = filterRequest("first_name");
|
|
||||||
$lastName = filterRequest("last_name");
|
|
||||||
|
|
||||||
// تسجيل البيانات المبدئية (بدون كلمات المرور) للتأكد من وصولها
|
|
||||||
logStep(2, "Inputs received -> Phone: $phone, Name: $firstName $lastName");
|
|
||||||
|
|
||||||
// التحقق من الحقول الإجبارية
|
|
||||||
if (empty($phone) || empty($password) || empty($firstName) || empty($lastName)) {
|
|
||||||
throw new Exception("Required fields missing (phone, password, first_name, last_name).");
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 3. Generar ID de Conductor ---
|
|
||||||
$driverId = substr(md5($phone), 0, 20);
|
|
||||||
logStep(3, "Driver ID generated: $driverId");
|
|
||||||
|
|
||||||
// --- 4. Procesamiento de Datos del Conductor ---
|
|
||||||
$password_hashed = password_hash($password, PASSWORD_DEFAULT);
|
|
||||||
$email = filterRequest("email");
|
|
||||||
|
|
||||||
if (empty($email) || $email === 'Not specified') {
|
|
||||||
$email = $phone . '@intaleqapp.com';
|
|
||||||
}
|
|
||||||
|
|
||||||
$nameArabic = $firstName . ' ' . $lastName;
|
|
||||||
$site = filterRequest("site");
|
|
||||||
$address = $site;
|
|
||||||
|
|
||||||
// بيانات إضافية
|
|
||||||
$gender = filterRequest("gender");
|
|
||||||
$license_type = filterRequest("license_type");
|
|
||||||
$nationalNumber = filterRequest("national_number");
|
|
||||||
$issue_date = filterRequest("issue_date");
|
|
||||||
$expiry_date = filterRequest("expiry_date");
|
|
||||||
$licenseCategories = filterRequest("license_categories");
|
|
||||||
$licenseIssueDate = filterRequest("license_issue_date");
|
|
||||||
$birthdate = filterRequest("birthdate");
|
|
||||||
$maritalStatus = filterRequest("maritalStatus");
|
|
||||||
|
|
||||||
// --- 5. Recolección de Datos del Coche ---
|
|
||||||
$owner = filterRequest("owner");
|
|
||||||
$color = filterRequest("color");
|
|
||||||
$colorHex = filterRequest("color_hex");
|
|
||||||
$model = filterRequest("model");
|
|
||||||
$carPlate = filterRequest("car_plate");
|
|
||||||
$make = filterRequest("make");
|
|
||||||
$fuel = filterRequest("fuel");
|
|
||||||
$year = filterRequest("year");
|
|
||||||
$vin = filterRequest("vin");
|
|
||||||
|
|
||||||
if (empty($vin)) {
|
|
||||||
$vin = 'unknown';
|
|
||||||
}
|
|
||||||
|
|
||||||
$carExpirationDate = filterRequest("expiration_date");
|
|
||||||
|
|
||||||
logStep(4, "Data processing completed. Car Plate: $carPlate, VIN: $vin");
|
|
||||||
|
|
||||||
// --- 6. Cifrado de Datos ---
|
|
||||||
try {
|
|
||||||
$encryptedPhone = $encryptionHelper->encryptData($phone);
|
|
||||||
$encryptedEmail = $encryptionHelper->encryptData($email);
|
|
||||||
$encryptedFirstName = $encryptionHelper->encryptData($firstName);
|
|
||||||
$encryptedLastName = $encryptionHelper->encryptData($lastName);
|
|
||||||
$encryptedNameArabic = $encryptionHelper->encryptData($nameArabic);
|
|
||||||
$encryptedGender = $encryptionHelper->encryptData($gender);
|
|
||||||
$encryptedNationalNumber = $encryptionHelper->encryptData($nationalNumber);
|
|
||||||
$encryptedAddress = $encryptionHelper->encryptData($address);
|
|
||||||
$encryptedSite = $encryptionHelper->encryptData($site);
|
|
||||||
$encryptedBirthdate = $encryptionHelper->encryptData($birthdate);
|
|
||||||
$encryptedOwner = $encryptionHelper->encryptData($owner);
|
|
||||||
$encryptedCarPlate = $encryptionHelper->encryptData($carPlate);
|
|
||||||
|
|
||||||
logStep(5, "Encryption successful for sensitive fields.");
|
|
||||||
} catch (Exception $encEx) {
|
|
||||||
throw new Exception("Encryption Error: " . $encEx->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- 7. Comprobación de Duplicados ---
|
|
||||||
// ملاحظة: إذا كان التشفير عشوائياً، فلن يجد التكرار هنا.
|
|
||||||
$dup = $con->prepare("SELECT id FROM driver WHERE phone = :phone OR email = :email OR national_number = :national_number");
|
|
||||||
$dup->execute([':phone' => $encryptedPhone, ':email' => $encryptedEmail, ':national_number' =>$encryptedNationalNumber]);
|
|
||||||
|
|
||||||
if ($dup->rowCount() > 0) {
|
|
||||||
logStep(6, "Duplicate found! Phone or Email or encryptedNationalNumber already exists.");
|
|
||||||
throw new Exception("Phone or email already registered.");
|
|
||||||
}
|
|
||||||
logStep(6, "No duplicates found. Proceeding.");
|
|
||||||
|
|
||||||
// --- 8. INSERCIÓN 1: Tabla 'driver' ---
|
|
||||||
$sqlDriver = "
|
|
||||||
INSERT INTO driver (
|
|
||||||
id, phone, email, password, gender, license_type, national_number,
|
|
||||||
name_arabic, issue_date, expiry_date, license_categories,
|
|
||||||
address, licenseIssueDate, status, birthdate, site,
|
|
||||||
first_name, last_name, accountBank, bankCode,
|
|
||||||
employmentType, maritalStatus, fullNameMaritial, expirationDate,
|
|
||||||
created_at, updated_at
|
|
||||||
) VALUES (
|
|
||||||
:id, :phone, :email, :pwd, :gender, :license_type, :national_number,
|
|
||||||
:name_arabic, :issue_date, :expiry_date, :license_categories,
|
|
||||||
:address, :licenseIssueDate, :status, :birthdate, :site,
|
|
||||||
:first_name, :last_name, :accountBank, :bankCode,
|
|
||||||
:employmentType, :maritalStatus, :fullNameMaritial, :expirationDate,
|
|
||||||
NOW(), NOW()
|
|
||||||
)
|
|
||||||
";
|
|
||||||
|
|
||||||
$stmtDriver = $con->prepare($sqlDriver);
|
|
||||||
|
|
||||||
// تم توحيد المفاتيح لتشمل النقطتين (:)
|
|
||||||
$driverData = [
|
|
||||||
':id' => $driverId,
|
|
||||||
':phone' => $encryptedPhone,
|
|
||||||
':email' => $encryptedEmail,
|
|
||||||
':pwd' => $password_hashed,
|
|
||||||
':gender' => $encryptedGender,
|
|
||||||
':license_type' => $license_type,
|
|
||||||
':national_number' => $encryptedNationalNumber,
|
|
||||||
':name_arabic' => $encryptedNameArabic,
|
|
||||||
':issue_date' => $issue_date,
|
|
||||||
':expiry_date' => $expiry_date,
|
|
||||||
':license_categories' => $licenseCategories ?? 'B',
|
|
||||||
':address' => $encryptedAddress,
|
|
||||||
':licenseIssueDate' => $licenseIssueDate,
|
|
||||||
':status' => 'actives',
|
|
||||||
':birthdate' => $encryptedBirthdate,
|
|
||||||
':site' => $encryptedSite,
|
|
||||||
':first_name' => $encryptedFirstName,
|
|
||||||
':last_name' => $encryptedLastName,
|
|
||||||
':accountBank' => 'yet',
|
|
||||||
':bankCode' => 'yet',
|
|
||||||
':employmentType' => $maritalStatus ?? 'yet',
|
|
||||||
':maritalStatus' => $maritalStatus ?? 'yet',
|
|
||||||
':fullNameMaritial' => 'yet',
|
|
||||||
':expirationDate' => 'yet',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!$stmtDriver->execute($driverData)) {
|
|
||||||
// تسجيل خطأ SQL بالتفصيل
|
|
||||||
$errInfo = $stmtDriver->errorInfo();
|
|
||||||
throw new Exception("Driver Insert Failed: " . $errInfo[2]);
|
|
||||||
}
|
|
||||||
logStep(7, "Driver table insert successful.");
|
|
||||||
|
|
||||||
// --- 9. INSERCIÓN 2: Tabla 'CarRegistration' ---
|
|
||||||
$sqlCar = "
|
|
||||||
INSERT INTO CarRegistration (
|
|
||||||
driverID, vin, owner, color, color_hex, model, car_plate,
|
|
||||||
make, fuel, `year`, expiration_date, created_at
|
|
||||||
) VALUES (
|
|
||||||
:driverId, :vin, :owner, :color, :color_hex, :model, :car_plate,
|
|
||||||
:make, :fuel, :year, :expiration_date, NOW()
|
|
||||||
)
|
|
||||||
";
|
|
||||||
|
|
||||||
$stmtCar = $con->prepare($sqlCar);
|
|
||||||
$carData = [
|
|
||||||
':driverId' => $driverId,
|
|
||||||
':vin' => $vin,
|
|
||||||
':owner' => $encryptedOwner,
|
|
||||||
':color' => $color,
|
|
||||||
':color_hex' => $colorHex,
|
|
||||||
':model' => $model,
|
|
||||||
':car_plate' => $encryptedCarPlate,
|
|
||||||
':make' => $make,
|
|
||||||
':fuel' => $fuel,
|
|
||||||
':year' => $year,
|
|
||||||
':expiration_date' => $carExpirationDate
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!$stmtCar->execute($carData)) {
|
|
||||||
$errInfo = $stmtCar->errorInfo();
|
|
||||||
throw new Exception("Car Insert Failed: " . $errInfo[2]);
|
|
||||||
}
|
|
||||||
logStep(8, "CarRegistration insert successful.");
|
|
||||||
|
|
||||||
// --- 10. Confirmar Transacción ---
|
|
||||||
$con->commit();
|
|
||||||
logStep(9, "COMMIT successful. Sending Success Response.");
|
|
||||||
|
|
||||||
jsonSuccess(["driverId" => $driverId, "message" => "Driver and car registered successfully."]);
|
|
||||||
|
|
||||||
// --- 11. Enviar Notificación (خارج المعاملة يفضل، ولكن هنا كما في الكود الأصلي) ---
|
|
||||||
try {
|
|
||||||
$supportPhones = ['0952475740', '0952475742'];
|
|
||||||
$randomIndex = array_rand($supportPhones);
|
|
||||||
$phoneToUse = $supportPhones[$randomIndex];
|
|
||||||
$randomNumber = rand(1000, 999999);
|
|
||||||
|
|
||||||
$messageBody = "أهلاً وسهلاً كابتن $firstName 👋\n"
|
|
||||||
. "تم تفعيل حسابك على تطبيق *انطلق*.\n"
|
|
||||||
. "يمكنك الآن تسجيل الدخول والبدء بالعمل مباشرة.\n"
|
|
||||||
. "للمساعدة تواصل معنا على الرقم: $phoneToUse\n"
|
|
||||||
. "نتمنى لك عمل موفق 🚖\n\n"
|
|
||||||
. "معرف الرسالة: $randomNumber";
|
|
||||||
|
|
||||||
sendWhatsAppFromServer($phone, $messageBody);
|
|
||||||
logStep(10, "WhatsApp notification sent.");
|
|
||||||
} catch (Exception $waError) {
|
|
||||||
// لا نوقف العملية إذا فشل الواتساب، فقط نسجل الخطأ
|
|
||||||
logStep(10, "WhatsApp Warning: " . $waError->getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (PDOException $e) {
|
|
||||||
$con->rollBack();
|
|
||||||
$errorMsg = "Database Error (PDO): " . $e->getMessage();
|
|
||||||
logStep("ERROR-PDO", $errorMsg);
|
|
||||||
// إظهار رسالة عامة للمستخدم، وتسجيل التفاصيل في السيرفر
|
|
||||||
jsonError("System error during registration. Please contact support.");
|
|
||||||
} catch (Exception $e) {
|
|
||||||
// إذا كانت المعاملة مفتوحة، قم بإلغائها
|
|
||||||
if ($con->inTransaction()) {
|
|
||||||
$con->rollBack();
|
|
||||||
}
|
|
||||||
$errorMsg = "General Error: " . $e->getMessage();
|
|
||||||
logStep("ERROR-GEN", $errorMsg);
|
|
||||||
jsonError($e->getMessage());
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
Reference in New Issue
Block a user