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:
co-authored by
Claude Opus 5
parent
9909d9b4c1
commit
4d8414c96b
@@ -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.");
|
||||
}
|
||||
?>
|
||||
@@ -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.");
|
||||
}
|
||||
?>
|
||||
@@ -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
|
||||
]);
|
||||
?>
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -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.");
|
||||
}
|
||||
?>
|
||||
Reference in New Issue
Block a user