Applied manual JWT check and restored all driver fields2

This commit is contained in:
Hamza-Ayed
2026-04-25 13:32:35 +03:00
parent e306217806
commit ee9c0f3a04
11 changed files with 36 additions and 257 deletions

View File

@@ -438,8 +438,8 @@ class AuthController extends Controller
$driver['year'] = $driver['year'] ?? ''; $driver['year'] = $driver['year'] ?? '';
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'Success',
'data' => [$driver] 'message' => [$driver]
]); ]);
} }
@@ -472,7 +472,7 @@ class AuthController extends Controller
->first(); ->first();
if (!$row) { if (!$row) {
return response()->json(['status' => 'Failure', 'data' => 'User does not exist.']); return response()->json(['status' => 'Failure', 'message' => 'User does not exist.']);
} }
$driver = (array) $row; $driver = (array) $row;
@@ -499,7 +499,7 @@ class AuthController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'count' => 1, 'count' => 1,
'data' => [$driver] 'message' => [$driver]
]); ]);
} }
@@ -597,7 +597,8 @@ class AuthController extends Controller
'jwt' => $jwt, 'jwt' => $jwt,
'expires_in' => 14400, 'expires_in' => 14400,
'api_key' => $driver->api_key, 'api_key' => $driver->api_key,
'api_secret' => $driver->api_secret 'api_secret' => $driver->api_secret,
'message' => [$driver] // Add driver data in message for unified access
]); ]);
} }

View File

@@ -20,10 +20,11 @@ class InviteController extends Controller
/** POST /v2/invites/driver */ /** POST /v2/invites/driver */
public function inviteDriver(Request $request): JsonResponse public function inviteDriver(Request $request): JsonResponse
{ {
if (!$request->has(['driverId', 'inviterDriverPhone'])) { if (!$request->filled('driverId') || !$request->filled('inviterDriverPhone')) {
\Log::warning('Invite driver parameters missing: ' . json_encode($request->all()));
return response()->json([ return response()->json([
'status' => 'failure', 'status' => 'failure',
'message' => 'Missing required parameters' 'message' => 'Missing required parameters: driverId or inviterDriverPhone'
]); ]);
} }

View File

@@ -40,7 +40,7 @@ class NotificationController extends Controller
->get(); ->get();
} }
return response()->json(['status' => 'success', 'data' => $notifications, 'message' => $notifications]); return response()->json(['status' => 'success', 'message' => $notifications]);
} }
/** PUT /v2/notifications/{id}/read */ /** PUT /v2/notifications/{id}/read */
@@ -109,7 +109,7 @@ class NotificationController extends Controller
} }
if ($userType === 'driver') { if ($userType === 'driver') {
DB::connection('primary')->table('captainToken') DB::connection('primary')->table('driverToken')
->updateOrInsert( ->updateOrInsert(
['captain_id' => $userId], ['captain_id' => $userId],
[ [
@@ -144,7 +144,7 @@ class NotificationController extends Controller
} }
if ($userType === 'driver') { if ($userType === 'driver') {
$data = DB::connection('primary')->table('captainToken') $data = DB::connection('primary')->table('driverToken')
->where('captain_id', $userId) ->where('captain_id', $userId)
->first(); ->first();
} else { } else {
@@ -159,7 +159,7 @@ class NotificationController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => [ 'message' => [
'token' => $data->token, 'token' => $data->token,
'fingerPrint' => $data->fingerPrint ?? null, 'fingerPrint' => $data->fingerPrint ?? null,
] ]

View File

@@ -46,17 +46,15 @@ class ProfileController extends Controller
$data = $this->enc->decryptFields($data, Passenger::ENCRYPTED_FIELDS); $data = $this->enc->decryptFields($data, Passenger::ENCRYPTED_FIELDS);
unset($data['password'], $data['api_secret']); unset($data['password'], $data['api_secret']);
// Attach wallet balance // Note: Wallet balance is managed by the dedicated payment server.
$wallet = DB::connection('primary')->table('passengerWallet') // Flutter fetches it directly via the wallet JWT token.
->where('passenger_id', $id)->first();
$data['wallet_balance'] = $wallet->balance ?? '0.00';
// Attach rating // Attach rating
$rating = DB::connection('primary')->table('ratingPassenger') $rating = DB::connection('primary')->table('ratingPassenger')
->where('passenger_id', $id)->avg('rating'); ->where('passenger_id', $id)->avg('rating');
$data['rating'] = round($rating ?? 5.0, 2); $data['rating'] = round($rating ?? 5.0, 2);
return response()->json(['status' => 'success', 'data' => $data]); return response()->json(['status' => 'success', 'message' => $data]);
} }
/** /**
@@ -89,16 +87,14 @@ class ProfileController extends Controller
// Rating // Rating
$data['rating'] = $driver->getAverageRating(); $data['rating'] = $driver->getAverageRating();
// Wallet Balance // Note: Wallet balance is managed by the dedicated payment server.
$wallet = DB::connection('primary')->table('captain_wallet') // Flutter fetches it directly via the wallet JWT token.
->where('captain_id', $id)->first();
$data['wallet_balance'] = $wallet->balance ?? '0.00';
// Ride count // Ride count
$data['ride_count'] = DB::connection('ride')->table('ride') $data['ride_count'] = DB::connection('ride')->table('ride')
->where('driver_id', $id)->where('status', 'finish')->count(); ->where('driver_id', $id)->where('status', 'finish')->count();
return response()->json(['status' => 'success', 'data' => $data]); return response()->json(['status' => 'success', 'message' => $data]);
} }
/** /**

View File

@@ -34,7 +34,7 @@ class PromoController extends Controller
}) })
->get(); ->get();
return response()->json(['status' => 'success', 'data' => $promos, 'message' => $promos]); return response()->json(['status' => 'success', 'message' => $promos]);
} }
/** GET /v2/promos/check?code=XXX */ /** GET /v2/promos/check?code=XXX */

View File

@@ -123,7 +123,7 @@ class RatingController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => [ 'message' => [
'average' => round($avg ?? 5.0, 2), 'average' => round($avg ?? 5.0, 2),
'count' => $ratings->count(), 'count' => $ratings->count(),
'ratings' => $ratings, 'ratings' => $ratings,

View File

@@ -164,7 +164,7 @@ class RideController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => $insertedId, 'message' => $insertedId,
], 200); ], 200);
} catch (\Exception $e) { } catch (\Exception $e) {
@@ -181,6 +181,7 @@ class RideController extends Controller
public function accept(Request $request, int $rideId): JsonResponse public function accept(Request $request, int $rideId): JsonResponse
{ {
$driverId = $request->attributes->get('_jwt_user_id'); $driverId = $request->attributes->get('_jwt_user_id');
$userType = $request->attributes->get('_jwt_user_type');
$status = $request->input('status', 'Apply'); // Allow dynamic status but default to Apply $status = $request->input('status', 'Apply'); // Allow dynamic status but default to Apply
DB::connection('ride')->beginTransaction(); DB::connection('ride')->beginTransaction();
@@ -291,8 +292,7 @@ class RideController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'message' => 'Ride Accepted', 'message' => $driverInfo
'data' => $driverInfo
]); ]);
} catch (\Exception $e) { } catch (\Exception $e) {
@@ -576,7 +576,7 @@ class RideController extends Controller
if (!$ride) { if (!$ride) {
return response()->json(['status' => 'failure', 'message' => 'Ride not found or access denied'], 404); return response()->json(['status' => 'failure', 'message' => 'Ride not found or access denied'], 404);
} }
return response()->json(['status' => 'success', 'data' => $ride]); return response()->json(['status' => 'success', 'message' => $ride]);
} }
public function active(Request $request): JsonResponse public function active(Request $request): JsonResponse
@@ -595,7 +595,7 @@ class RideController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => $ride, 'message' => $ride,
]); ]);
} }
@@ -625,6 +625,6 @@ class RideController extends Controller
return $ride; return $ride;
}); });
return response()->json(['status' => 'success', 'data' => $rides, 'message' => $rides]); return response()->json(['status' => 'success', 'message' => $rides]);
} }
} }

View File

@@ -46,7 +46,7 @@ class TrackingController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => [ 'message' => [
'latitude' => $location->latitude, 'latitude' => $location->latitude,
'longitude' => $location->longitude, 'longitude' => $location->longitude,
'heading' => $location->heading, 'heading' => $location->heading,
@@ -88,7 +88,7 @@ class TrackingController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => [ 'message' => [
'latitude' => $location->latitude ?? null, 'latitude' => $location->latitude ?? null,
'longitude' => $location->longitude ?? null, 'longitude' => $location->longitude ?? null,
'heading' => $location->heading ?? null, 'heading' => $location->heading ?? null,
@@ -172,7 +172,7 @@ class TrackingController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => $finalData 'message' => $finalData
]); ]);
} }
@@ -222,7 +222,7 @@ class TrackingController extends Controller
return response()->json([ return response()->json([
'status' => 'success', 'status' => 'success',
'data' => [ 'message' => [
'total_rides' => $totalRides, 'total_rides' => $totalRides,
'today_rides' => $todayRides, 'today_rides' => $todayRides,
'today_earnings' => round($todayEarnings, 2), 'today_earnings' => round($todayEarnings, 2),

View File

@@ -1,193 +0,0 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
/**
* Wallet Controller
* Replaces: ride/passenger/**
* متحكم المحفظة (Wallet Controller)
*
* الغرض من الملف:
* إدارة العمليات المالية للركاب، بما في ذلك عرض الرصيد، شحن المحفظة، وعرض سجل العمليات.
*
* كيفية العمل:
* 1. يتواصل مع جداول (passengerWallet) و (payments) لجلب البيانات المالية.
* 2. يسمح للركاب بإضافة أموال لمحفظتهم وتحديث رصيدهم.
* 3. يعرض قائمة بالمعاملات المالية السابقة (Transactions).
*/
class WalletController extends Controller
{
/** GET /v2/wallet/passenger */
public function index(Request $request): JsonResponse
{
$id = $request->attributes->get('_jwt_user_id');
$wallet = DB::connection('primary')->table('passengerWallet')
->where('passenger_id', $id)->first();
return response()->json([
'status' => 'success',
'data' => $wallet ?? ['passenger_id' => $id, 'balance' => '0.00'],
]);
}
/** GET /v2/wallet/passenger/balance */
public function balance(Request $request): JsonResponse
{
$id = $request->attributes->get('_jwt_user_id');
$userType = $request->attributes->get('_jwt_user_type');
if ($userType === 'driver') {
$bal = DB::connection('primary')->table('captain_wallet')
->where('captain_id', $id)->value('balance') ?? '0.00';
} else {
$bal = DB::connection('primary')->table('passengerWallet')
->where('passenger_id', $id)->value('balance') ?? '0.00';
}
return response()->json(['status' => 'success', 'data' => ['balance' => $bal]]);
}
/** GET /v2/wallet/driver/balance (Explicit) */
public function driverBalance(Request $request): JsonResponse
{
$id = $request->attributes->get('_jwt_user_id');
$bal = DB::connection('primary')->table('captain_wallet')
->where('captain_id', $id)->value('balance') ?? '0.00';
return response()->json(['status' => 'success', 'data' => ['balance' => $bal]]);
}
/** POST /v2/wallet/passenger */
public function addFunds(Request $request): JsonResponse
{
$request->validate([
'amount' => 'required|numeric|min:0.01',
'payment_method' => 'required|string',
]);
$id = $request->attributes->get('_jwt_user_id');
$userType = $request->attributes->get('_jwt_user_type');
if ($userType !== 'passenger') {
return response()->json(['status' => 'failure', 'message' => 'Only passengers can add funds manually'], 403);
}
DB::connection('primary')->beginTransaction();
try {
$wallet = DB::connection('primary')->table('passengerWallet')
->where('passenger_id', $id)->lockForUpdate()->first();
if ($wallet) {
DB::connection('primary')->table('passengerWallet')
->where('passenger_id', $id)
->increment('balance', $request->input('amount'));
} else {
DB::connection('primary')->table('passengerWallet')->insert([
'passenger_id' => $id,
'balance' => $request->input('amount'),
]);
}
// Record transaction
DB::connection('primary')->table('passengerWalletTransactions')->insert([
'passenger_id' => $id,
'amount' => $request->input('amount'),
'type' => 'credit',
'payment_method' => $request->input('payment_method'),
'created_at' => now(),
]);
DB::connection('primary')->commit();
$newBalance = DB::connection('primary')->table('passengerWallet')
->where('passenger_id', $id)->value('balance');
return response()->json([
'status' => 'success',
'data' => ['balance' => $newBalance],
]);
} catch (\Exception $e) {
DB::connection('primary')->rollBack();
return response()->json(['status' => 'failure', 'message' => 'Transaction failed'], 500);
}
}
/** PUT /v2/wallet/passenger — ADMIN ONLY */
public function update(Request $request): JsonResponse
{
// Only admins can directly set balance
$userType = $request->attributes->get('_jwt_user_type');
if ($userType !== 'admin') {
return response()->json(['status' => 'failure', 'message' => 'Unauthorized'], 403);
}
$request->validate([
'balance' => 'required|numeric|min:0',
'user_id' => 'required|string',
'type' => 'required|in:passenger,driver',
]);
$table = $request->input('type') === 'driver' ? 'captain_wallet' : 'passengerWallet';
$key = $request->input('type') === 'driver' ? 'captain_id' : 'passenger_id';
DB::connection('primary')->table($table)
->where($key, $request->input('user_id'))
->update(['balance' => $request->input('balance')]);
return response()->json(['status' => 'success']);
}
/** GET /v2/wallet/transactions */
public function transactions(Request $request): JsonResponse
{
$id = $request->attributes->get('_jwt_user_id');
$userType = $request->attributes->get('_jwt_user_type');
$page = (int) $request->input('page', 1);
$limit = min((int) $request->input('limit', 20), 50);
if ($userType === 'driver') {
$transactions = DB::connection('primary')->table('payments')
->where('driverID', $id)
->orderBy('created_at', 'desc')
->skip(($page - 1) * $limit)
->take($limit)
->get();
} else {
$transactions = DB::connection('primary')->table('payments')
->where('passengerID', $id)
->orderBy('created_at', 'desc')
->skip(($page - 1) * $limit)
->take($limit)
->get();
}
return response()->json(['status' => 'success', 'data' => $transactions]);
}
/** POST /v2/wallet/passenger/token */
public function addToken(Request $request): JsonResponse
{
$request->validate([
'token' => 'required|string',
'amount' => 'required|numeric|min:0.01',
]);
$id = $request->attributes->get('_jwt_user_id');
DB::connection('primary')->table('payment_tokens_passenger')->insert([
'token' => $request->input('token'),
'passengerId' => $id,
'dateCreated' => now(),
'amount' => $request->input('amount'),
'isUsed' => 0,
]);
return response()->json(['status' => 'success'], 201);
}
}

View File

@@ -1,23 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
/**
* نموذج محفظة الراكب (PassengerWallet Model)
*
* الغرض من الملف:
* إدارة الرصيد المالي للركاب داخل التطبيق.
*
* كيفية العمل:
* 1. يرتبط بجدول (passengerWallet) في قاعدة البيانات الأساسية.
* 2. يتبع الرصيد الحالي للراكب ويسمح بعمليات الشحن أو الخصم.
*/
class PassengerWallet extends Model {
protected $connection = 'primary';
protected $table = 'passengerWallet';
public $timestamps = true;
const CREATED_AT = 'created_at';
const UPDATED_AT = 'updated_at';
protected $fillable = ['passenger_id', 'balance'];
protected $casts = ['balance' => 'decimal:2'];
}

View File

@@ -19,7 +19,6 @@ use App\Http\Controllers\AuthController;
use App\Http\Controllers\RideController; use App\Http\Controllers\RideController;
use App\Http\Controllers\TrackingController; use App\Http\Controllers\TrackingController;
use App\Http\Controllers\ProfileController; use App\Http\Controllers\ProfileController;
use App\Http\Controllers\WalletController;
use App\Http\Controllers\RatingController; use App\Http\Controllers\RatingController;
use App\Http\Controllers\PromoController; use App\Http\Controllers\PromoController;
use App\Http\Controllers\OtpController; use App\Http\Controllers\OtpController;
@@ -114,12 +113,9 @@ Route::prefix('v2')->middleware(['hmac.auth', 'jwt.auth'])->group(function () {
Route::match(['post', 'put'], '/profile/driver/email', [ProfileController::class, 'updateDriverEmail']); Route::match(['post', 'put'], '/profile/driver/email', [ProfileController::class, 'updateDriverEmail']);
// ── Wallet ── // ── Wallet ──
Route::get('/wallet/passenger', [WalletController::class, 'index']); // All wallet operations (balance, funds, transactions) are handled by the
Route::get('/wallet/passenger/balance', [WalletController::class, 'balance']); // dedicated payment server. V2 only generates 60-second JWT tokens for it
Route::post('/wallet/passenger', [WalletController::class, 'addFunds']); // via POST /v2/auth/passenger/wallet-login and /v2/auth/driver/wallet-login.
Route::put('/wallet/passenger', [WalletController::class, 'update']);
Route::get('/wallet/passenger/transactions', [WalletController::class, 'transactions']);
Route::post('/wallet/passenger/token', [WalletController::class, 'addToken']);
// ── Ratings ── // ── Ratings ──
Route::post('/ratings/driver', [RatingController::class, 'rateDriver']); Route::post('/ratings/driver', [RatingController::class, 'rateDriver']);
@@ -156,7 +152,8 @@ Route::prefix('v2')->middleware(['hmac.auth', 'jwt.auth'])->group(function () {
Route::post('/notifications/update', [NotificationController::class, 'updateNotification']); Route::post('/notifications/update', [NotificationController::class, 'updateNotification']);
Route::get('/notifications/token', [NotificationController::class, 'getToken']); Route::get('/notifications/token', [NotificationController::class, 'getToken']);
Route::post('/notifications/token', [NotificationController::class, 'updateToken']); Route::post('/notifications/token', [NotificationController::class, 'updateToken']);
Route::put('/notifications/{id}/read', [NotificationController::class, 'markRead']); Route::match(['put', 'post'], '/notifications/driver/read', [NotificationController::class, 'updateNotification']);
Route::match(['put', 'post'], '/notifications/{id}/read', [NotificationController::class, 'markRead']);
// ── Misc ── // ── Misc ──
Route::get('/misc/test', [MiscController::class, 'test']); Route::get('/misc/test', [MiscController::class, 'test']);