Files
Siro/backend/auth/syria/driver/register_driver_and_car.php
2026-06-09 08:40:31 +03:00

391 lines
15 KiB
PHP
Executable File

<?php
/**
* Endpoint: register_driver_and_car.php
* [MODIFIED] Added vehicle_category_id and fuel_type_id support.
* [MODIFIED] Fixed birthdate logic: Append -01-01 BEFORE encryption.
* [MODIFIED] Added Syrian phone number formatting logic.
*/
//register_driver_and_car.php
$allowRegistration = true;
require_once __DIR__ . '/../../../connect.php';
header('Content-Type: application/json; charset=utf-8');
try {
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
jsonError("Invalid method.");
exit;
}
/* ================== General Settings ================== */
$PUBLIC_BASE = "https://intaleq.xyz/driver_docs";
/* ================== 1) Input Fields ================== */
$raw_first_name = null;
$raw_last_name = null;
$required = ["phone", "password", "first_name", "last_name"];
$optional = [
"id","email","gender","license_type","national_number",
"name_arabic","issue_date","expiry_date","license_categories",
"address","licenseIssueDate","status","birthdate","site",
"employmentType","maritalStatus","fullNameMaritial","expirationDate"
];
$carRequired = [
"vin","car_plate","make","model","year","expiration_date",
"color","owner","color_hex","fuel"
];
// حقول اختيارية للسيارة (التصنيف والوقود الرقمي)
// vehicle_category_id, fuel_type_id
$docKeys = [
'driver_license_front',
'driver_license_back',
'car_license_front',
'car_license_back'
];
// Read driver fields
$data = [];
foreach ($required as $f) {
$v = filterRequest($f);
if ($v === null || $v === '') {
jsonError("Missing required field: $f");
exit;
}
$data[$f] = $v;
if ($f === 'first_name') $raw_first_name = $v;
if ($f === 'last_name') $raw_last_name = $v;
}
foreach ($optional as $f) {
$v = filterRequest($f);
$data[$f] = ($v === null || $v === '' || $v === 'Not specified') ? null : $v;
}
/* ================== 🟢 START PHONE FORMATTING LOGIC 🟢 ================== */
if (!empty($data['phone'])) {
$phone = $data['phone'];
// 1. إزالة المسافات والرموز
$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);
}
// 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);
}
}
$data['phone'] = $phone;
}
/* ================== 🔴 END PHONE FORMATTING LOGIC 🔴 ================== */
// تجهيز تاريخ الميلاد قبل التشفير
if (!empty($data['birthdate'])) {
$data['birthdate'] = trim($data['birthdate']);
$data['birthdate'] = $data['birthdate'] . '-01-01';
} else {
$data['birthdate'] = '1970-01-01';
}
// Read car fields
$car = [];
foreach ($carRequired as $f) {
$v = filterRequest($f);
if ($v === null || $v === '') {
jsonError("Missing required field: $f");
exit;
}
$car[$f] = $v;
}
// Read document links
$docUrls = [];
foreach ($docKeys as $k) {
$u = filterRequest($k);
if ($u === null || $u === '') {
jsonError("Missing document URL: $k");
exit;
}
if (!filter_var($u, FILTER_VALIDATE_URL)) {
jsonError("Invalid document URL: $k");
exit;
}
$docUrls[$k] = $u;
}
/* ================== 2) Generate default id/email ================== */
if (empty($data['id'])) {
$data['id'] = 'DRV' . date('YmdHis') . random_int(1000, 9999);
}
if ($data['email'] === null) {
$data['email'] = $data['phone'] . '@intaleqapp.com';
}
/* ================== 3) Encrypt sensitive fields ================== */
$toEncryptDriver = [
"phone","email","first_name","last_name","name_arabic","gender",
"national_number","address","site","fullNameMaritial","birthdate"
];
foreach ($toEncryptDriver as $f) {
if (!empty($data[$f])) {
$data[$f] = $encryptionHelper->encryptData($data[$f]);
}
}
// Encrypt car sensitive data
$car['vin'] = $encryptionHelper->encryptData($car['vin']);
$car['car_plate'] = $encryptionHelper->encryptData($car['car_plate']);
$car['owner'] = $encryptionHelper->encryptData($car['owner']);
/* ================== 4) Hash password (HMAC + password_hash) ================== */
// نقرأ الـ HMAC key من env
$pepper = getenv('SECRET_KEY_HMAC');
// نبني baseString من أكثر من بارامتر
// هنا نستخدم id + phone (بعد ما طبّقنا منطق تنسيق الهاتف)
$baseParts = [
$data['id'],
$data['phone'],
];
// نضيف رقم وطني أو سنة الميلاد إن توفروا (كما في الـ migration)
if (!empty($data['national_number'])) {
$baseParts[] = $data['national_number'];
} elseif (!empty($data['birthdate'])) {
// birthdate حالياً أصبح بصيغة YYYY-01-01
$year = substr($data['birthdate'], 0, 4);
if (preg_match('/^\d{4}$/', $year)) {
$baseParts[] = $year;
}
}
$baseString = implode('|', $baseParts);
// نشتق السر الخام باستخدام HMAC-SHA256 مع SECRET_KEY_HMAC
$rawSecret = hash_hmac('sha256', $baseString, $pepper, true);
// نخزّن فقط الهاش الناتج من password_hash في قاعدة البيانات
$pwdHashed = password_hash($rawSecret, PASSWORD_DEFAULT);
/* ================== 5) Start transaction ================== */
$con->beginTransaction();
/* ================== 6) Check duplicate ================== */
$dup = $con->prepare("SELECT id FROM driver WHERE phone = :p OR email = :e");
$dup->execute([':p' => $data['phone'], ':e' => $data['email']]);
if ($dup->rowCount() > 0) {
$con->rollBack();
jsonError("Phone or email already registered.");
exit;
}
/* ================== 7) Insert 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()
)
";
$insD = $con->prepare($sqlDriver);
$okD = $insD->execute([
':id' => $data['id'],
':phone' => $data['phone'],
':email' => $data['email'],
':pwd' => $pwdHashed,
':gender' => !empty($data['gender']) ? $data['gender'] : 'Male',
':license_type' => !empty($data['license_type']) ? $data['license_type'] : 'yet',
':national_number' => $data['national_number'],
':name_arabic' => $data['name_arabic'],
':issue_date' => !empty($data['issue_date']) ? $data['issue_date'] : '2020-01-01',
':expiry_date' => !empty($data['expiry_date']) ? $data['expiry_date'] : 'yet',
':license_categories' => !empty($data['license_categories']) ? $data['license_categories'] : 'B',
':address' => $data['address'],
':licenseIssueDate' => !empty($data['licenseIssueDate']) ? $data['licenseIssueDate'] : '2020-01-01',
':status' => !empty($data['status']) ? $data['status'] : 'yet',
':birthdate' => $data['birthdate'],
':site' => !empty($data['site']) ? $data['site'] : 'demascus',
':first_name' => $data['first_name'],
':last_name' => $data['last_name'],
':accountBank' => 'yet',
':bankCode' => 'yet',
':employmentType' => !empty($data['employmentType']) ? $data['employmentType'] : 'yet',
':maritalStatus' => !empty($data['maritalStatus']) ? $data['maritalStatus'] : 'yet',
':fullNameMaritial' => !empty($data['fullNameMaritial']) ? $data['fullNameMaritial'] : 'yet',
':expirationDate' => !empty($data['expirationDate']) ? $data['expirationDate'] : 'yet',
]);
if (!$okD) {
$con->rollBack();
jsonError("Failed to insert driver.");
exit;
}
$driverID = $data['id'];
/* ================== 8) Insert Vehicle ================== */
// ✅ استقبال القيم الجديدة (التصنيف والوقود) مع تعيين افتراضي 1
$vCatID = filterRequest("vehicle_category_id");
$vCatID = ($vCatID !== null && $vCatID !== '') ? $vCatID : 1; // 1 = Car
$fTypeID = filterRequest("fuel_type_id");
$fTypeID = ($fTypeID !== null && $fTypeID !== '') ? $fTypeID : 1; // 1 = Petrol
$hasCar = $con->prepare("SELECT 1 FROM CarRegistration WHERE driverID = :d LIMIT 1");
$hasCar->execute([':d' => $driverID]);
$isDefault = $hasCar->rowCount() === 0 ? 1 : 0;
$sqlCar = "
INSERT INTO CarRegistration (
driverID, vin, car_plate, make, model, year, expiration_date,
color, owner, color_hex, fuel,
vehicle_category_id, fuel_type_id,
isDefault, created_at, status
) VALUES (
:driverID, :vin, :car_plate, :make, :model, :year, :expiration_date,
:color, :owner, :color_hex, :fuel,
:vehicle_category_id, :fuel_type_id,
:isDefault, NOW(), 'yet'
)
";
$insC = $con->prepare($sqlCar);
$okC = $insC->execute([
':driverID' => $driverID,
':vin' => $car['vin'],
':car_plate' => $car['car_plate'],
':make' => $car['make'],
':model' => $car['model'],
':year' => $car['year'],
':expiration_date' => $car['expiration_date'],
':color' => $car['color'],
':owner' => $car['owner'],
':color_hex' => $car['color_hex'],
':fuel' => $car['fuel'], // النص القديم (للتوافق)
':vehicle_category_id' => $vCatID, // ✅ العمود الجديد
':fuel_type_id' => $fTypeID, // ✅ العمود الجديد
':isDefault' => $isDefault,
]);
if (!$okC) {
$con->rollBack();
jsonError("Failed to insert car registration.");
exit;
}
$carRegID = $con->lastInsertId();
/* ================== 9) Store document links ================== */
$insDoc = $con->prepare("
INSERT INTO driver_documents (driverID, doc_type, image_name, link, upload_date)
VALUES (:driverID, :doc_type, :image_name, :link, NOW())
");
foreach ($docKeys as $k) {
$url = $docUrls[$k];
$name = basename(parse_url($url, PHP_URL_PATH) ?? '');
if ($name === '') { $name = $k . '_' . time() . '.jpg'; }
$insDoc->execute([
':driverID' => $driverID,
':doc_type' => $k,
':image_name' => $name,
':link' => $url,
]);
}
/* ================== 10) Commit ================== */
$con->commit();
/* ================== 11) Notification ================== */
try {
$fcmSendUrl = 'https://api.intaleq.xyz/intaleq/ride/firebase/send_fcm.php';
$driverFullName = $raw_first_name . ' ' . $raw_last_name;
$notificationTitle = 'تسجيل سائق جديد';
$notificationBody = "سائق جديد ($driverFullName) سجل برقم ID: $driverID وهو بانتظار المراجعة والتفعيل.";
$notificationPayload = json_encode([
'target' => 'service',
'title' => $notificationTitle,
'body' => $notificationBody,
'isTopic' => true,
'category' => 'new_driver_registration'
]);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $fcmSendUrl);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json; charset=UTF-8']);
curl_setopt($ch, CURLOPT_POSTFIELDS, $notificationPayload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_exec($ch);
curl_close($ch);
} catch (Exception $notifyEx) {
error_log("register_driver_and_car NOTIFY ERROR: " . $notifyEx->getMessage());
}
printSuccess([
'status' => 'success',
'driverID' => $driverID,
'carRegID' => $carRegID,
'documents' => $docUrls
]);
} catch (Exception $e) {
if (isset($con) && $con instanceof PDO && $con->inTransaction()) {
$con->rollBack();
}
error_log("register_driver_and_car ERROR: " . $e->getMessage());
jsonError("Server error: " . $e->getMessage());
} catch (PDOException $e) {
if (isset($con) && $con instanceof PDO && $con->inTransaction()) {
$con->rollBack();
}
error_log("register_driver_and_car PDO: " . $e->getMessage());
jsonError("Database error.");
}
?>