303 lines
12 KiB
PHP
303 lines
12 KiB
PHP
<?php
|
|
/**
|
|
* Endpoint: register_driver_and_car.php (نسخة محدثة)
|
|
* Method: POST (multipart/form-data أو x-www-form-urlencoded)
|
|
* الوظيفة: إنشاء سائق + تسجيل مركبة + حفظ روابط الوثائق الموقّعة (من السيرفر السوري)
|
|
* ملاحظة: لا نتلقّى ملفات هنا. نتلقى فقط روابط secure_image.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;
|
|
}
|
|
|
|
/* ========== إعدادات عامة ========== */
|
|
// الدومينات المسموح بها للروابط الموقّعة (السيرفر السوري)
|
|
$ALLOWED_SIGNED_HOSTS = [
|
|
'syria.intaleq.xyz', // عدّل حسب بيئتك
|
|
'applink.syria', // مثال آخر إن كان لديك دومين إضافي
|
|
];
|
|
|
|
// توثيق شكل الروابط: secure_image.php?driver_id=...&doc_type=...&ext=jpg|png|webp&expires=...&signature=...
|
|
$allowedDocTypes = [
|
|
'driver_license_front',
|
|
'driver_license_back',
|
|
'car_license_front',
|
|
'car_license_back',
|
|
];
|
|
$allowedExts = ['jpg','png','webp'];
|
|
|
|
/* ========== 1) جلب الحقول ========== */
|
|
$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"
|
|
];
|
|
|
|
// روابط الوثائق (مطلوبة)
|
|
$docUrlKeys = [
|
|
'driver_license_front_url',
|
|
'driver_license_back_url',
|
|
'car_license_front_url',
|
|
'car_license_back_url'
|
|
];
|
|
|
|
$data = [];
|
|
foreach ($required as $f) {
|
|
$v = filterRequest($f);
|
|
if ($v === null || $v === '') {
|
|
jsonError("Missing required field: $f");
|
|
exit;
|
|
}
|
|
$data[$f] = $v;
|
|
}
|
|
|
|
foreach ($optional as $f) {
|
|
$v = filterRequest($f);
|
|
$data[$f] = ($v === null || $v === '' || $v === 'Not specified') ? null : $v;
|
|
}
|
|
|
|
$car = [];
|
|
foreach ($carRequired as $f) {
|
|
$v = filterRequest($f);
|
|
if ($v === null || $v === '') {
|
|
jsonError("Missing required field: $f");
|
|
exit;
|
|
}
|
|
$car[$f] = $v;
|
|
}
|
|
|
|
$docUrls = [];
|
|
foreach ($docUrlKeys as $k) {
|
|
$v = filterRequest($k);
|
|
if ($v === null || trim($v) === '') {
|
|
jsonError("Missing signed URL: $k");
|
|
exit;
|
|
}
|
|
$docUrls[$k] = trim($v);
|
|
}
|
|
|
|
/* ========== 2) توليد 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';
|
|
}
|
|
$driverID = $data['id'];
|
|
|
|
/* ========== 3) تشفير الحقول الحساسة ========== */
|
|
$toEncryptDriver = [
|
|
"phone","email","first_name","last_name","name_arabic","gender",
|
|
"national_number","address","site","fullNameMaritial"
|
|
];
|
|
foreach ($toEncryptDriver as $f) {
|
|
if (!empty($data[$f])) {
|
|
$data[$f] = $encryptionHelper->encryptData($data[$f]);
|
|
}
|
|
}
|
|
// حساسات السيارة
|
|
$car['vin'] = $encryptionHelper->encryptData($car['vin']);
|
|
$car['car_plate'] = $encryptionHelper->encryptData($car['car_plate']);
|
|
$car['owner'] = $encryptionHelper->encryptData($car['owner']);
|
|
|
|
/* ========== 4) هَش كلمة المرور ========== */
|
|
$pwdHashed = password_hash(filterRequest('password'), PASSWORD_DEFAULT);
|
|
|
|
/* ========== 5) بدء معاملة ========== */
|
|
$con->beginTransaction();
|
|
|
|
/* ========== 6) فحص تكرار هاتف/ايميل (المشفّرين) ========== */
|
|
$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) إدراج السائق ========== */
|
|
$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' => $driverID,
|
|
':phone' => $data['phone'],
|
|
':email' => $data['email'],
|
|
':pwd' => $pwdHashed,
|
|
':gender' => $data['gender'],
|
|
':license_type' => $data['license_type'],
|
|
':national_number' => $data['national_number'],
|
|
':name_arabic' => $data['name_arabic'],
|
|
':issue_date' => $data['issue_date'],
|
|
':expiry_date' => $data['expiry_date'],
|
|
':license_categories'=> !empty($data['license_categories']) ? $data['license_categories'] : 'B',
|
|
':address' => $data['address'],
|
|
':licenseIssueDate' => $data['licenseIssueDate'],
|
|
':status' => !empty($data['status']) ? $data['status'] : 'yet',
|
|
':birthdate' => $data['birthdate'],
|
|
':site' => $data['site'],
|
|
':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; }
|
|
|
|
/* ========== 8) إدراج السيارة ========== */
|
|
$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, isDefault, created_at, status
|
|
) VALUES (
|
|
:driverID, :vin, :car_plate, :make, :model, :year, :expiration_date,
|
|
:color, :owner, :color_hex, :fuel, :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'],
|
|
':isDefault' => $isDefault,
|
|
]);
|
|
if (!$okC) { $con->rollBack(); jsonError("Failed to insert car registration."); exit; }
|
|
|
|
$carRegID = $con->lastInsertId();
|
|
|
|
/* ========== 9) التحقّق من الروابط الموقّعة وحفظها ========== */
|
|
|
|
// دالة مساعدة تتحقّق من شكل الرابط وتستخرج doc_type/ext
|
|
$validateSignedUrl = function(string $url) use ($allowedDocTypes, $allowedExts) {
|
|
$parts = parse_url($url);
|
|
if (!$parts || empty($parts['scheme']) || empty($parts['host']) || empty($parts['path'])) {
|
|
throw new Exception("Invalid URL format.");
|
|
}
|
|
if (!in_array($parts['host'], $ALLOWED_SIGNED_HOSTS, true)) {
|
|
throw new Exception("URL host not allowed: {$parts['host']}");
|
|
}
|
|
if (stripos($parts['path'], 'secure_image.php') === false) {
|
|
throw new Exception("URL path not allowed.");
|
|
}
|
|
if (empty($parts['query'])) {
|
|
throw new Exception("URL missing query string.");
|
|
}
|
|
parse_str($parts['query'], $q);
|
|
foreach (['driver_id','doc_type','ext','expires','signature'] as $k) {
|
|
if (empty($q[$k])) throw new Exception("URL missing param: $k");
|
|
}
|
|
if (!in_array($q['doc_type'], $allowedDocTypes, true)) {
|
|
throw new Exception("Invalid doc_type in URL.");
|
|
}
|
|
if (!in_array(strtolower($q['ext']), $allowedExts, true)) {
|
|
throw new Exception("Invalid ext in URL.");
|
|
}
|
|
return [
|
|
'doc_type' => $q['doc_type'],
|
|
'ext' => strtolower($q['ext']),
|
|
// بإمكانك التحقق من driver_id = $driverID إذا تحب تربطهما
|
|
'driver_id_in_url' => $q['driver_id'],
|
|
];
|
|
};
|
|
|
|
$docsToInsert = []; // [['doc_type'=>..., 'link'=>..., 'image_name'=>...], ...]
|
|
foreach ($docUrlKeys as $k) {
|
|
$link = $docUrls[$k];
|
|
$meta = $validateSignedUrl($link);
|
|
// image_name ليس ضروريًا هنا (الرابط موقّع إلى بوابة قراءة)، احفظ doc_type + link فقط
|
|
$docsToInsert[] = [
|
|
'doc_type' => $meta['doc_type'], // يجب أن يتطابق مع $k منطقيًا
|
|
'link' => $link,
|
|
'image_name' => $meta['doc_type'] . '.' . $meta['ext'], // اسماً رمزياً فقط
|
|
];
|
|
}
|
|
|
|
// إدراج في driver_documents
|
|
// CREATE TABLE driver_documents (
|
|
// id INT AUTO_INCREMENT PRIMARY KEY,
|
|
// driverID VARCHAR(64) NOT NULL,
|
|
// doc_type VARCHAR(64) NOT NULL,
|
|
// image_name VARCHAR(255) NULL,
|
|
// link VARCHAR(1024) NOT NULL,
|
|
// upload_date DATETIME NOT NULL,
|
|
// INDEX(driverID)
|
|
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
|
$insDoc = $con->prepare("
|
|
INSERT INTO driver_documents (driverID, doc_type, image_name, link, upload_date)
|
|
VALUES (:driverID, :doc_type, :image_name, :link, NOW())
|
|
");
|
|
foreach ($docsToInsert as $row) {
|
|
$insDoc->execute([
|
|
':driverID' => $driverID,
|
|
':doc_type' => $row['doc_type'],
|
|
':image_name' => $row['image_name'],
|
|
':link' => $row['link'],
|
|
]);
|
|
}
|
|
|
|
/* ========== 10) إنهاء المعاملة ========== */
|
|
$con->commit();
|
|
|
|
printSuccess([
|
|
'driverID' => $driverID,
|
|
'carRegID' => $carRegID,
|
|
'documents' => [
|
|
'driver_license_front_url' => $docUrls['driver_license_front_url'],
|
|
'driver_license_back_url' => $docUrls['driver_license_back_url'],
|
|
'car_license_front_url' => $docUrls['car_license_front_url'],
|
|
'car_license_back_url' => $docUrls['car_license_back_url'],
|
|
]
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
if (isset($con) && $con->inTransaction()) { $con->rollBack(); }
|
|
error_log("register_driver_and_car ERROR: " . $e->getMessage());
|
|
jsonError("Server error");
|
|
} catch (PDOException $e) {
|
|
if (isset($con) && $con->inTransaction()) { $con->rollBack(); }
|
|
error_log("register_driver_and_car PDO: " . $e->getMessage());
|
|
jsonError("Database error.");
|
|
} |