feat: استيراد كود سيرو إلى تريبز (سيرو @ecfe7568) — بلا تعديل

قرار المالك 2026-07-27: باك إند سيرو PHP هو المعتمد، وتطبيقاته المجرّبة
ميدانياً تحل محل إعادة البناء المؤرشفة. سيرو نفسه لم يُمسّ.

الخريطة:
  backend · payment_server · loction_server · ride_server ·
  passenger_server · docker · dashboard · stress_test  → الجذر
  siro_rider  → apps/rider          siro_driver  → apps/driver
  siro_admin  → dashboards/admin    siro_service → dashboards/service
  android_bot → apps/android_bot    socialBot    → apps/socialBot

نُسخ المتعقَّب في git سيرو فقط عبر `git archive` (3,198 ملفاً / ~169 م.ب)
لا `cp -r` — فاستُثنيت مخلفات البناء تلقائياً. بلا أي تعديل محتوى عمداً:
كل ما يلي يصير فرقاً مقروءاً مقابل المصدر.

لم يُستورد وسببه: siromove.com (الموقع التسويقي يبقى marketing/ في تريبز،
سيرو فيه 8 ملفات) · docs و planning (تريبز له docs/ الخاص) · deploy.sh
(ليس نشراً على سيرفر بل `git add . && git push origin --all` — فخّ في
مستودع آخر) · transit_dashboard (بانتظار قرار مصير backend-transit و
dashboards/transit-web).

⚠️ لا يبني بعد — ثلاثة نواقص متوقعة ومقصودة:
1. `.env` و `lib/env/env.g.dart` غير متعقَّبين في سيرو (أسرار لكل مستأجر):
   كل تطبيق فلاتر يحتاج .env خاصاً ثم توليد env.g.dart بـ build_runner.
2. إعدادات Firebase (9 ملفات google-services.json و GoogleService-Info.plist)
   يستبعدها .gitignore تريبز — ولكل مستأجر مشروع Firebase خاص أصلاً.
3. apps/driver في سيرو يشير إلى `../../Intaleq/packages/get` خارج المستودع →
   يجب ضمّ الحزم داخله أسوة بـ apps/rider.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-27 05:14:13 +03:00
co-authored by Claude Opus 5
parent 9909d9b4c1
commit 4d8414c96b
3198 changed files with 766859 additions and 0 deletions
+96
View File
@@ -0,0 +1,96 @@
<?php
require_once __DIR__ . '/../../connect.php';
function generateUniqueCode($con) {
while (true) {
$letters = substr(str_shuffle("ABCDEFGHJKLMNPQRSTUVWXYZ"), 0, 2); // Excluded I, O for clarity
$numbers = substr(str_shuffle("23456789"), 0, 3); // Excluded 0, 1 for clarity
$code = $letters . $numbers;
$stmt = $con->prepare("SELECT COUNT(*) FROM invites WHERE inviteCode = ?");
$stmt->execute([$code]);
if ($stmt->fetchColumn() == 0) {
return $code;
}
}
}
// Force driverId from JWT — only drivers can manage invitations
if ($role !== 'driver') {
jsonError("Only drivers can create invitations");
exit;
}
$driverId = $user_id;
$inviterDriverPhone = filterRequest("inviterDriverPhone");
// 🔐 تشفير رقم الهاتف
$inviterDriverPhoneEncrypted = $encryptionHelper->encryptData($inviterDriverPhone);
// تحقق من وجود رقم الهاتف مسبقًا
$checkSql = "SELECT `id`, `inviteCode`, `isInstall` FROM `invites` WHERE `inviterDriverPhone` = :inviterDriverPhone";
$checkStmt = $con->prepare($checkSql);
$checkStmt->bindParam(':inviterDriverPhone', $inviterDriverPhoneEncrypted, PDO::PARAM_STR);
$checkStmt->execute();
if ($checkStmt->rowCount() > 0) {
$existingInvite = $checkStmt->fetch(PDO::FETCH_ASSOC);
if ($existingInvite['isInstall'] == 1) {
jsonError($existingInvite['inviteCode']);
} else {
// تحديث الدعوة الحالية
$updateSql = "UPDATE `invites` SET `driverId` = :driverId, `expirationTime` = :expirationTime, `createdAt` = NOW() WHERE `id` = :id";
$updateStmt = $con->prepare($updateSql);
$expirationTime = date('Y-m-d H:i:s', strtotime('+24 hours'));
$updateStmt->bindParam(':driverId', $driverId, PDO::PARAM_INT);
$updateStmt->bindParam(':expirationTime', $expirationTime);
$updateStmt->bindParam(':id', $existingInvite['id'], PDO::PARAM_INT);
try {
$updateStmt->execute();
printSuccess([
"message" => "Invite updated successfully",
"inviteId" => $existingInvite['id'],
"inviteCode" => $existingInvite['inviteCode'],
"expirationTime" => $expirationTime
]);
} catch (PDOException $e) {
error_log("[invitor/add] DB Error: " . $e->getMessage());
jsonError("Database error occurred");
}
}
} else {
// إنشاء دعوة جديدة
$inviteCode = generateUniqueCode($con);
$expirationTime = date('Y-m-d H:i:s', strtotime('+24 hours'));
$sql = "INSERT INTO `invites` (`driverId`, `inviterDriverPhone`, `inviteCode`, `expirationTime`, `createdAt`, `isInstall`)
VALUES (:driverId, :inviterDriverPhone, :inviteCode, :expirationTime, NOW(), 0)";
$stmt = $con->prepare($sql);
$stmt->bindParam(':driverId', $driverId, PDO::PARAM_INT);
$stmt->bindParam(':inviterDriverPhone', $inviterDriverPhoneEncrypted, PDO::PARAM_STR);
$stmt->bindParam(':inviteCode', $inviteCode);
$stmt->bindParam(':expirationTime', $expirationTime);
try {
$stmt->execute();
if ($stmt->rowCount() > 0) {
$insertedID = $con->lastInsertId();
printSuccess([
"message" => "Invite created successfully",
"inviteId" => $insertedID,
"inviteCode" => $inviteCode,
"expirationTime" => $expirationTime
]);
} else {
jsonError("Failed to save invite data");
}
} catch (PDOException $e) {
error_log("[invitor/add] DB Error: " . $e->getMessage());
jsonError("Database error occurred");
}
}
?>
@@ -0,0 +1,99 @@
<?php
require_once __DIR__ . '/../../connect.php';
function generateUniqueCode($con, $length = 7) {
while (true) {
$letters = substr(str_shuffle("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 4);
$numbers = substr(str_shuffle("0123456789"), 0, 3);
$code = $letters . $numbers;
$stmt = $con->prepare("SELECT COUNT(*) FROM invitesToPassengers WHERE inviteCode = ?");
$stmt->execute([$code]);
if ($stmt->fetchColumn() == 0) {
return $code;
}
}
}
$driverId = filterRequest("driverId");
$inviterPassengerPhone = filterRequest("inviterPassengerPhone");
if (!$driverId || !$inviterPassengerPhone) {
jsonError("Missing required parameters: driverId or inviterPassengerPhone");
}
// 🔐 تشفير رقم الهاتف
$inviterPassengerPhoneEncrypted = $encryptionHelper->encryptData($inviterPassengerPhone);
// التحقق من وجود الرقم مسبقًا
$checkSql = "SELECT `id`, `inviteCode`, `isInstall`, `isGiftToken` FROM `invitesToPassengers` WHERE `inviterPassengerPhone` = :inviterPassengerPhone";
$checkStmt = $con->prepare($checkSql);
$checkStmt->bindParam(':inviterPassengerPhone', $inviterPassengerPhoneEncrypted, PDO::PARAM_STR);
$checkStmt->execute();
if ($checkStmt->rowCount() > 0) {
$existingInvite = $checkStmt->fetch(PDO::FETCH_ASSOC);
if ($existingInvite['isInstall'] == 1 || $existingInvite['isGiftToken'] == 1) {
printFailure([
"message" => "Invite code already used or gift token already applied",
"inviteCode" => $existingInvite['inviteCode']
]);
} else {
// تحديث الدعوة
$updateSql = "UPDATE `invitesToPassengers` SET `driverId` = :driverId, `expirationTime` = :expirationTime, `createdAt` = NOW() WHERE `id` = :id";
$updateStmt = $con->prepare($updateSql);
$expirationTime = date('Y-m-d H:i:s', strtotime('+1 hour'));
$updateStmt->bindParam(':driverId', $driverId, PDO::PARAM_INT);
$updateStmt->bindParam(':expirationTime', $expirationTime);
$updateStmt->bindParam(':id', $existingInvite['id'], PDO::PARAM_INT);
try {
$updateStmt->execute();
printSuccess([
"message" => "Invite updated successfully",
"inviteId" => $existingInvite['id'],
"inviteCode" => $existingInvite['inviteCode'],
"expirationTime" => $expirationTime
]);
} catch (PDOException $e) {
error_log("[addInvitationPassenger.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
}
} else {
// إنشاء دعوة جديدة
$inviteCode = generateUniqueCode($con);
$expirationTime = date('Y-m-d H:i:s', strtotime('+4 hour'));
$sql = "INSERT INTO `invitesToPassengers`
(`driverId`, `inviterPassengerPhone`, `inviteCode`, `expirationTime`, `createdAt`, `isInstall`, `isGiftToken`)
VALUES
(:driverId, :inviterPassengerPhone, :inviteCode, :expirationTime, NOW(), 0, 0)";
$stmt = $con->prepare($sql);
$stmt->bindParam(':driverId', $driverId, PDO::PARAM_INT);
$stmt->bindParam(':inviterPassengerPhone', $inviterPassengerPhoneEncrypted, PDO::PARAM_STR);
$stmt->bindParam(':inviteCode', $inviteCode);
$stmt->bindParam(':expirationTime', $expirationTime);
try {
$stmt->execute();
if ($stmt->rowCount() > 0) {
$insertedID = $con->lastInsertId();
printSuccess([
"message" => "Invite created successfully",
"inviteId" => $insertedID,
"inviteCode" => $inviteCode,
"expirationTime" => $expirationTime
]);
} else {
jsonError("Failed to save invite data");
}
} catch (PDOException $e) {
error_log("[addInvitationPassenger.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
}
?>
@@ -0,0 +1,38 @@
<?php
require_once __DIR__ . '/../../connect.php';
$inviterCode = filterRequest("inviter_code");
// Use JWT token variables provided by connect.php
if (!$inviterCode || !$user_id || !in_array($role, ['driver', 'passenger'])) {
jsonError("Invalid parameters or unauthorized token");
}
// Ensure the code exists and get the inviter details
$stmtCheck = $con->prepare("SELECT user_id, user_type FROM user_referral_codes WHERE referral_code = ?");
$stmtCheck->execute([$inviterCode]);
if ($stmtCheck->rowCount() == 0) {
jsonError("Invalid referral code");
}
$inviterData = $stmtCheck->fetch(PDO::FETCH_ASSOC);
// Check if user was already invited
$stmtExisting = $con->prepare("SELECT id FROM unified_referrals WHERE invited_user_id = ? AND invited_user_type = ?");
$stmtExisting->execute([$user_id, $role]);
if ($stmtExisting->rowCount() > 0) {
jsonError("User already registered with a referral code");
}
// Insert new referral
$insertStmt = $con->prepare("INSERT INTO unified_referrals (inviter_code, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed) VALUES (?, ?, ?, 'registered', 0, 0)");
try {
$insertStmt->execute([$inviterCode, $user_id, $role]);
printSuccess(["message" => "Referral linked successfully"]);
} catch (PDOException $e) {
error_log("[add_unified_invite.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
?>
+122
View File
@@ -0,0 +1,122 @@
<?php
// --- backend/ride/invitor/claim.php ---
include "../../connect.php";
include "../../functions.php"; // Assuming a functions file exists for helper methods
header('Content-Type: application/json');
try {
$inviteId = filterRequest("invite_id");
// Force user ID from JWT based on role
if ($role === 'driver') {
$driverId = $user_id;
$passengerId = null;
} elseif ($role === 'passenger') {
$passengerId = $user_id;
$driverId = null;
} else {
echo json_encode(["status" => "failure", "message" => "Invalid user role."]);
exit;
}
$countryCode = filterRequest("country_code"); // Expected: Jordan, Syria, Egypt
if (empty($inviteId)) {
echo json_encode(["status" => "failure", "message" => "Invite ID required."]);
exit;
}
$walletServer = "https://walletintaleq.intaleq.xyz"; // Default
if (strtolower($countryCode) == 'jordan') {
$rewardAmount = 5;
$currency = "JOD";
$walletServer = $_ENV['WALLET_SERVER_JORDAN'] ?? "https://walletintaleq.intaleq.xyz";
} elseif (strtolower($countryCode) == 'egypt') {
$rewardAmount = 500;
$currency = "EGP";
$walletServer = $_ENV['WALLET_SERVER_EGYPT'] ?? "https://walletintaleq.intaleq.xyz";
} else {
$rewardAmount = 500; // Default Syria
$currency = "SYP";
$walletServer = $_ENV['WALLET_SERVER_SYRIA'] ?? "https://walletintaleq.intaleq.xyz";
}
$walletUrl = "$walletServer/v2/main/ride/payment/add.php";
$con->beginTransaction();
if (!empty($driverId)) {
// Driver Invitation Reward Logic
$stmt = $con->prepare("SELECT * FROM invites WHERE id = :invite_id AND driverId = :driver_id AND isGiftToken = 0 FOR UPDATE");
$stmt->execute([':invite_id' => $inviteId, ':driver_id' => $driverId]);
$invitation = $stmt->fetch(PDO::FETCH_ASSOC);
if ($invitation) {
$upd = $con->prepare("UPDATE invites SET isGiftToken = 1 WHERE id = :invite_id");
$upd->execute([':invite_id' => $inviteId]);
// Reward for current driver
addWalletBalance($walletUrl, $driverId, "driver", $rewardAmount);
// Reward for inviter
addWalletBalance($walletUrl, $invitation['driverId'], "driver", $rewardAmount);
$con->commit();
echo json_encode(["status" => "success", "message" => "Reward of $rewardAmount $currency claimed successfully."]);
} else {
$con->rollBack();
echo json_encode(["status" => "failure", "message" => "Invitation not valid or already claimed."]);
}
} elseif (!empty($passengerId)) {
// Passenger Invitation Reward Logic
$stmt = $con->prepare("SELECT * FROM invitesToPassengers WHERE id = :invite_id AND passengerID = :passenger_id AND isGiftToken = 0 FOR UPDATE");
$stmt->execute([':invite_id' => $inviteId, ':passenger_id' => $passengerId]);
$invitation = $stmt->fetch(PDO::FETCH_ASSOC);
if ($invitation) {
$upd = $con->prepare("UPDATE invitesToPassengers SET isGiftToken = 1 WHERE id = :invite_id");
$upd->execute([':invite_id' => $inviteId]);
// Call Wallet Server
addWalletBalance($walletUrl, $passengerId, "passenger", $rewardAmount);
$con->commit();
echo json_encode(["status" => "success", "message" => "Reward of $rewardAmount $currency claimed successfully."]);
} else {
$con->rollBack();
echo json_encode(["status" => "failure", "message" => "Invitation not valid or already claimed."]);
}
} else {
echo json_encode(["status" => "failure", "message" => "User ID required."]);
}
} catch (Exception $e) {
if ($con && $con->inTransaction()) { $con->rollBack(); }
error_log("Error in claim.php: " . $e->getMessage());
echo json_encode(["status" => "error", "message" => "Server error."]);
}
function addWalletBalance($url, $userId, $userType, $amount) {
$s2sKey = getenv('S2S_SHARED_KEY');
$data = [
"user_id" => $userId,
"user_type" => $userType,
"amount" => $amount,
"action" => "add",
"reason" => "Invitation Reward"
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
if ($s2sKey) {
curl_setopt($ch, CURLOPT_HTTPHEADER, ["X-Auth-Token: $s2sKey"]);
}
$response = curl_exec($ch);
curl_close($ch);
return $response;
}
?>
@@ -0,0 +1,150 @@
<?php
require_once __DIR__ . '/../../connect.php';
$referralId = filterRequest("referral_id");
$claimType = filterRequest("claim_type"); // 'wallet' or 'cash'
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'driver' || !$referralId || !in_array($claimType, ['wallet', 'cash'])) {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the referral info
$stmt = $con->prepare("
SELECT r.id, r.inviter_code, r.invited_user_id, r.invited_user_type, r.trip_count, r.is_reward_claimed, c.user_id as inviter_id, c.user_type as inviter_type
FROM unified_referrals r
JOIN user_referral_codes c ON r.inviter_code = c.referral_code
WHERE r.id = ? AND c.user_id = ? AND c.user_type = 'driver'
");
$stmt->execute([$referralId, $user_id]);
if ($stmt->rowCount() == 0) {
jsonError("Referral not found or unauthorized");
}
$referral = $stmt->fetch(PDO::FETCH_ASSOC);
if ($referral['is_reward_claimed'] == 1) {
jsonError("Reward already claimed");
}
// 2. Get local currency dynamically
$stmtKazan = $con->prepare("SELECT country, currency FROM kazan LIMIT 1");
$stmtKazan->execute();
$kazanData = $stmtKazan->fetch(PDO::FETCH_ASSOC);
$country = $kazanData['country'] ?? 'Syria';
$currency = $kazanData['currency'] ?? 'SYP';
$driverRewardBase = 0;
$passengerRewardPerTrip = 0;
switch ($currency) {
case 'SYP':
$driverRewardBase = 50000;
$passengerRewardPerTrip = 2000;
break;
case 'EGP':
$driverRewardBase = 300;
$passengerRewardPerTrip = 15;
break;
case 'JOD':
default:
$driverRewardBase = 10;
$passengerRewardPerTrip = 0.5;
break;
}
$rewardAmount = 0;
if ($referral['invited_user_type'] == 'driver') {
if ($referral['trip_count'] >= 50) {
$rewardAmount = $driverRewardBase;
} else {
jsonError("Requirement not met (50 trips required)");
}
} else if ($referral['invited_user_type'] == 'passenger') {
if ($referral['trip_count'] >= 1) {
$tripsToClaim = min($referral['trip_count'], 10);
$rewardAmount = $tripsToClaim * $passengerRewardPerTrip;
} else {
jsonError("Requirement not met (At least 1 trip required)");
}
}
if ($rewardAmount <= 0) {
jsonError("No reward available to claim");
}
try {
$con->beginTransaction();
// Mark as claimed
$updateStmt = $con->prepare("UPDATE unified_referrals SET is_reward_claimed = 1, status = 'claimed' WHERE id = ?");
$updateStmt->execute([$referralId]);
if ($claimType == 'wallet') {
// Add to driver wallet via Payment Server S2S API
$walletServer = "https://walletintaleq.intaleq.xyz";
if (strtolower($country) == 'jordan') {
$walletServer = getenv('WALLET_SERVER_JORDAN') ?: "https://walletintaleq.intaleq.xyz";
} elseif (strtolower($country) == 'egypt') {
$walletServer = getenv('WALLET_SERVER_EGYPT') ?: "https://walletintaleq.intaleq.xyz";
} else {
$walletServer = getenv('WALLET_SERVER_SYRIA') ?: "https://walletintaleq.intaleq.xyz";
}
$paymentID = "REF_" . time();
$walletUrl = "$walletServer/v2/main/ride/driverWallet/add_s2s_reward.php";
$payload = [
"driverID" => $user_id,
"paymentID" => $paymentID,
"amount" => $rewardAmount,
"paymentMethod" => "referral_reward"
];
$ch = curl_init($walletUrl);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query($payload),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => [
'Content-Type: application/x-www-form-urlencoded',
'X-S2S-Api-Key: ' . getenv('S2S_SHARED_KEY')
]
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$curlErr = curl_error($ch);
curl_close($ch);
$s2sSuccess = false;
if (!$curlErr && $httpCode === 200) {
$resDecoded = json_decode($response, true);
if ($resDecoded && isset($resDecoded['status']) && $resDecoded['status'] === 'success') {
$s2sSuccess = true;
}
}
if (!$s2sSuccess) {
throw new Exception("S2S Wallet credit failed: " . ($curlErr ?: "HTTP $httpCode - Response: $response"));
}
} else if ($claimType == 'cash') {
// Request manual cash out
$cashStmt = $con->prepare("INSERT INTO driver_cash_claims (driver_id, referral_id, amount_syp, status) VALUES (?, ?, ?, 'pending')");
$cashStmt->execute([$user_id, $referralId, $rewardAmount]);
}
$con->commit();
printSuccess(["message" => "Reward claimed successfully as " . $rewardAmount . " " . $currency]);
} catch (Exception $e) {
if ($con->inTransaction()) {
$con->rollBack();
}
jsonError("An internal error occurred. Please try again later.");
}
?>
+52
View File
@@ -0,0 +1,52 @@
<?php
require_once __DIR__ . '/../../connect.php';
$driverId = filterRequest("driverId");
$sql = "SELECT
i.`id`,
i.`driverId`,
i.`inviterDriverPhone`,
i.`createdAt`,
i.`isInstall`,
d.`id` AS driverInviterId,
d.`phone` AS invitorPhone,
d.`nameArabic` AS invitorName,
COALESCE(r.finishedTrips, 0) AS countOfInvitDriver
FROM
`invites` i
LEFT JOIN `driver` d ON d.phone = i.inviterDriverPhone
LEFT JOIN (
SELECT
driver_id,
COUNT(*) AS finishedTrips
FROM
ride
WHERE
status = 'Finished'
GROUP BY
driver_id
) r ON r.driver_id = d.id
WHERE
i.driverId = :driverId
AND i.isInstall = 1";
$stmt = $con->prepare($sql);
$stmt->bindParam(':driverId', $driverId, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 🔓 فك التشفير للحقول المطلوبة
foreach ($rows as &$row) {
$row['inviterDriverPhone'] = $encryptionHelper->decryptData($row['inviterDriverPhone']);
$row['invitorPhone'] = $encryptionHelper->decryptData($row['invitorPhone']);
$row['invitorName'] = $encryptionHelper->decryptData($row['invitorName']);
}
jsonSuccess($rows);
} else {
jsonError("No records found.");
}
?>
@@ -0,0 +1,48 @@
<?php
require_once __DIR__ . '/../../connect.php';
$driverId = filterRequest("driverId");
$sql = "SELECT
i.`id`,
i.`driverId`,
i.inviterPassengerPhone,
i.`createdAt`,
i.`isInstall`,
p.`id` AS passengerId,
p.first_name AS passengerName,
COALESCE(r.finishedTrips, 0) AS countOfInvitDriver
FROM
invitesToPassengers i
LEFT JOIN `driver` d ON
d.id = i.driverId
LEFT JOIN passengers p ON
p.phone = i.inviterPassengerPhone
LEFT JOIN (
SELECT passenger_id,
COUNT(*) AS finishedTrips
FROM ride
WHERE `status` = 'Finished'
GROUP BY passenger_id
) r ON r.passenger_id = i.passengerID
WHERE
i.driverId = :driverId AND i.isInstall = 1 AND p.id != ''";
$stmt = $con->prepare($sql);
$stmt->bindParam(':driverId', $driverId, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
// 🔓 فك التشفير للحقول المطلوبة
foreach ($rows as &$row) {
$row['inviterPassengerPhone'] = $encryptionHelper->decryptData($row['inviterPassengerPhone']);
$row['passengerName'] = $encryptionHelper->decryptData($row['passengerName']);
}
jsonSuccess($rows);
} else {
jsonError("No records found.");
}
?>
@@ -0,0 +1,60 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'driver') {
jsonError("Invalid parameters or unauthorized token");
}
// 1. Get the driver's referral code
$stmtCode = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = 'driver'");
$stmtCode->execute([$user_id]);
if ($stmtCode->rowCount() == 0) {
// If no code exists, return empty stats
printSuccess([
"referral_code" => null,
"total_invited_drivers" => 0,
"total_invited_passengers" => 0,
"referrals" => []
]);
exit;
}
$referralCode = $stmtCode->fetchColumn();
// 2. Fetch all referrals made by this code
$stmtRefs = $con->prepare("
SELECT id, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed, created_at
FROM unified_referrals
WHERE inviter_code = ?
ORDER BY created_at DESC
");
$stmtRefs->execute([$referralCode]);
$referrals = $stmtRefs->fetchAll(PDO::FETCH_ASSOC);
$totalDrivers = 0;
$totalPassengers = 0;
// Format data and calculate stats
foreach ($referrals as &$ref) {
if ($ref['invited_user_type'] == 'driver') {
$totalDrivers++;
$ref['target_trips'] = 50;
$ref['reward_syp'] = 500;
$ref['can_claim'] = ($ref['trip_count'] >= 50 && $ref['is_reward_claimed'] == 0) ? true : false;
} else {
$totalPassengers++;
$ref['target_trips'] = 1;
$ref['reward_syp'] = 30 * min($ref['trip_count'], 10); // Or max depending on logic
$ref['can_claim'] = ($ref['trip_count'] >= 1 && $ref['is_reward_claimed'] == 0) ? true : false;
}
}
printSuccess([
"referral_code" => $referralCode,
"total_invited_drivers" => $totalDrivers,
"total_invited_passengers" => $totalPassengers,
"referrals" => $referrals
]);
?>
@@ -0,0 +1,85 @@
<?php
require_once __DIR__ . '/../../connect.php';
// Use JWT token variables provided by connect.php
if (!$user_id || $role != 'passenger') {
jsonError("Invalid parameters or unauthorized token");
}
$country_code = $_POST['country_code'] ?? 'Jordan';
// 1. Get the passenger's referral code
$stmtCode = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = 'passenger'");
$stmtCode->execute([$user_id]);
if ($stmtCode->rowCount() == 0) {
// If no code exists, return empty stats
printSuccess([
"referral_code" => null,
"total_invited_drivers" => 0,
"total_invited_passengers" => 0,
"referrals" => []
]);
exit;
}
$referralCode = $stmtCode->fetchColumn();
// 2. Fetch all referrals made by this code
$stmtRefs = $con->prepare("
SELECT id, invited_user_id, invited_user_type, status, trip_count, is_reward_claimed, created_at
FROM unified_referrals
WHERE inviter_code = ?
ORDER BY created_at DESC
");
$stmtRefs->execute([$referralCode]);
$referrals = $stmtRefs->fetchAll(PDO::FETCH_ASSOC);
$totalDrivers = 0;
$totalPassengers = 0;
// Country-specific reward thresholds
switch ($country_code) {
case 'Syria':
$driverTargetTrips = 50;
$driverReward = 500;
$passengerTargetTrips = 1;
$passengerReward = 30;
break;
case 'Egypt':
$driverTargetTrips = 30;
$driverReward = 100;
$passengerTargetTrips = 2;
$passengerReward = 20;
break;
case 'Jordan':
default:
$driverTargetTrips = 20;
$driverReward = 5;
$passengerTargetTrips = 2;
$passengerReward = 2;
break;
}
// Format data and calculate stats
foreach ($referrals as &$ref) {
if ($ref['invited_user_type'] == 'driver') {
$totalDrivers++;
$ref['target_trips'] = $driverTargetTrips;
$ref['reward_syp'] = $driverReward;
$ref['can_claim'] = ($ref['trip_count'] >= $driverTargetTrips && $ref['is_reward_claimed'] == 0) ? true : false;
} else {
$totalPassengers++;
$ref['target_trips'] = $passengerTargetTrips;
$ref['reward_syp'] = $passengerReward;
$ref['can_claim'] = ($ref['trip_count'] >= $passengerTargetTrips && $ref['is_reward_claimed'] == 0) ? true : false;
}
}
printSuccess([
"referral_code" => $referralCode,
"total_invited_drivers" => $totalDrivers,
"total_invited_passengers" => $totalPassengers,
"referrals" => $referrals
]);
?>
+42
View File
@@ -0,0 +1,42 @@
<?php
require_once __DIR__ . '/../../connect.php';
function generateUnifiedCode($con) {
while (true) {
$letters = substr(str_shuffle("ABCDEFGHJKLMNPQRSTUVWXYZ"), 0, 2);
$numbers = substr(str_shuffle("23456789"), 0, 4);
$code = $letters . $numbers;
$stmt = $con->prepare("SELECT COUNT(*) FROM user_referral_codes WHERE referral_code = ?");
$stmt->execute([$code]);
if ($stmt->fetchColumn() == 0) {
return $code;
}
}
}
// Ensure the JWT values exist
if (!$user_id || !in_array($role, ['driver', 'passenger'])) {
jsonError("Invalid or missing user information in token");
}
$stmt = $con->prepare("SELECT referral_code FROM user_referral_codes WHERE user_id = ? AND user_type = ?");
$stmt->execute([$user_id, $role]);
if ($stmt->rowCount() > 0) {
$row = $stmt->fetch(PDO::FETCH_ASSOC);
printSuccess(["referral_code" => $row['referral_code']]);
} else {
$newCode = generateUnifiedCode($con);
$insertStmt = $con->prepare("INSERT INTO user_referral_codes (user_id, user_type, referral_code) VALUES (?, ?, ?)");
try {
$insertStmt->execute([$user_id, $role, $newCode]);
printSuccess(["referral_code" => $newCode]);
} catch (PDOException $e) {
error_log("[get_unified_code.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
}
?>
+16
View File
@@ -0,0 +1,16 @@
<?php
require_once __DIR__ . '/../../connect.php';
$id = filterRequest("id");
$sql = "UPDATE `invites` SET `isGiftToken` = 1 WHERE `id` = :id";
$stmt = $con->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
jsonSuccess(null, "Record updated successfully.");
} else {
jsonError("No records were updated");
}
?>
@@ -0,0 +1,59 @@
<?php
require_once __DIR__ . '/../../connect.php';
$inviterDriverPhone = filterRequest("inviterDriverPhone");
if (empty($inviterDriverPhone)) {
jsonError("Invalid or missing inviter phone.");
exit;
}
try {
// تشفير الرقم
$inviterDriverPhoneEncrypted = $encryptionHelper->encryptData($inviterDriverPhone);
// ✅ الآن الاستعلام نظيف وطبيعي جداً لأن قاعدة البيانات تم إصلاحها
$fetchSql = "SELECT
i.`id`,
i.`driverId`,
i.`inviterDriverPhone`,
i.`createdAt`,
i.`inviteCode`,
i.`isInstall`,
i.`isGiftToken`,
i.`expirationTime`,
dt.token
FROM `invites` i
LEFT JOIN `driverToken` dt ON dt.captain_id = i.driverId
WHERE i.`inviterDriverPhone` = :inviterDriverPhone
AND i.`expirationTime` > NOW()";
$fetchStmt = $con->prepare($fetchSql);
$fetchStmt->bindParam(':inviterDriverPhone', $inviterDriverPhoneEncrypted);
$fetchStmt->execute();
if ($fetchStmt->rowCount() > 0) {
$invite = $fetchStmt->fetch(PDO::FETCH_ASSOC);
// فك التشفير
$invite['inviterDriverPhone'] = $encryptionHelper->decryptData($invite['inviterDriverPhone']);
if (!empty($invite['token'])) {
$invite['token'] = $encryptionHelper->decryptData($invite['token']);
}
// التحديث
$updateSql = "UPDATE `invites` SET `isInstall` = 1 WHERE `id` = :id";
$updateStmt = $con->prepare($updateSql);
$updateStmt->bindParam(':id', $invite['id'], PDO::PARAM_INT);
$updateStmt->execute();
printSuccess("Record found and updated successfully.", $invite);
} else {
jsonError("No records found.");
}
} catch (PDOException $e) {
error_log("DB Error: " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
?>
@@ -0,0 +1,45 @@
<?php
require_once __DIR__ . '/../../connect.php';
$inviteCode = filterRequest("inviteCode");
if (empty($inviteCode)) {
jsonError("Invalid or missing invite code.");
exit;
}
try {
$checkSql = "SELECT `id`, `expirationTime`, `driverId` FROM `invites`
WHERE `inviteCode` = :inviteCode
AND `isInstall` = 0
AND `expirationTime` > NOW()";
$checkStmt = $con->prepare($checkSql);
$checkStmt->bindParam(':inviteCode', $inviteCode);
$checkStmt->execute();
if ($checkStmt->rowCount() > 0) {
$invite = $checkStmt->fetch(PDO::FETCH_ASSOC);
$updateSql = "UPDATE `invites` SET `isInstall` = 1 WHERE `id` = :id";
$updateStmt = $con->prepare($updateSql);
$updateStmt->bindParam(':id', $invite['id'], PDO::PARAM_INT);
$updateStmt->execute();
if ($updateStmt->rowCount() > 0) {
printSuccess([
"message" => "Invite code successfully used and marked as installed.",
"driverId" => $invite['driverId'],
"expirationTime" => $invite['expirationTime']
]);
} else {
jsonError("Failed to update the invite record.");
}
} else {
jsonError("Invalid invite code, already installed, or expired.");
}
} catch (PDOException $e) {
error_log("[updateInvitationCodeFromRegister.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
?>
@@ -0,0 +1,16 @@
<?php
require_once __DIR__ . '/../../connect.php';
$id = filterRequest("id");
$sql = "UPDATE `invitesToPassengers` SET `isGiftToken` = 1 WHERE `id` = :id";
$stmt = $con->prepare($sql);
$stmt->bindParam(':id', $id, PDO::PARAM_INT);
$stmt->execute();
if ($stmt->rowCount() > 0) {
jsonSuccess(null, "Record updated successfully.");
} else {
jsonError("No records were updated");
}
?>
@@ -0,0 +1,46 @@
<?php
require_once __DIR__ . '/../../connect.php';
$inviteCode = filterRequest("inviteCode");
$passengerID = filterRequest("passengerID");
if (empty($inviteCode) || empty($passengerID)) {
jsonError("Invalid or missing invite code or passenger ID.");
exit;
}
try {
$checkSql = "SELECT `id`, `expirationTime` FROM `invitesToPassengers`
WHERE `inviteCode` = :inviteCode
AND `isInstall` = 0
AND `isGiftToken` = 0";
$checkStmt = $con->prepare($checkSql);
$checkStmt->bindParam(':inviteCode', $inviteCode);
$checkStmt->execute();
if ($checkStmt->rowCount() > 0) {
$invite = $checkStmt->fetch(PDO::FETCH_ASSOC);
$updateSql = "UPDATE `invitesToPassengers`
SET `isInstall` = 1, `passengerID` = :passengerID
WHERE `id` = :id";
$updateStmt = $con->prepare($updateSql);
$updateStmt->bindParam(':id', $invite['id'], PDO::PARAM_INT);
$updateStmt->bindParam(':passengerID', $passengerID);
$updateStmt->execute();
if ($updateStmt->rowCount() > 0) {
jsonSuccess(null, "Invite code successfully used and marked as installed.");
} else {
jsonError("Invite found but update failed.");
}
} else {
jsonError("Invalid invite code, already used, or marked as gift.");
}
} catch (PDOException $e) {
error_log("[updatePassengersInvitation.php] " . $e->getMessage());
jsonError("An internal error occurred. Please try again later.");
}
?>