391 lines
15 KiB
PHP
Executable File
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/siro/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.");
|
|
}
|
|
?>
|