diff --git a/app/Http/Controllers/Api/PaymentTokenController.php b/app/Http/Controllers/Api/PaymentTokenController.php index 967a6f0..7a32c36 100644 --- a/app/Http/Controllers/Api/PaymentTokenController.php +++ b/app/Http/Controllers/Api/PaymentTokenController.php @@ -5,15 +5,24 @@ namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use Firebase\JWT\JWT; -use Illuminate\Support\Facades\File; +/** + * PaymentTokenController — توليد رموز الدفع المتوافقة مع سيرفر المحفظة V1 + * + * ⚠️ مهم جداً: + * سيرفر المحفظة (walletintaleq.intaleq.xyz) يعمل بكود V1 ويتحقق من التوكن باستخدام: + * - المفتاح: /home/intaleq-api/.secret_key (وليس PAYMENT_INTERNAL_KEY_PATH) + * - الـ Issuer: 'Tripz' أو 'Tripz-Wallet' + * - الـ Claim: user_id (وليس sub) + * + * لذلك يجب أن يكون التوكن المُولّد هنا متوافقاً تماماً مع V1. + */ class PaymentTokenController extends Controller { // 1. مسار الراكب public function generatePassengerToken(Request $request) { $userId = $request->attributes->get('_jwt_user_id'); - // تحقق خاص بالراكب (لا يوجد بصمة سيارة مثلاً) return $this->buildToken($userId, 'android/ios_passenger', $request->input('fingerPrint')); } @@ -21,7 +30,6 @@ class PaymentTokenController extends Controller public function generateDriverToken(Request $request) { $userId = $request->attributes->get('_jwt_user_id'); - // تحقق خاص بالسائق (ضرورة وجود بصمة جهاز قوية) return $this->buildToken($userId, 'android/ios_driver', $request->input('fingerPrint')); } @@ -29,36 +37,43 @@ class PaymentTokenController extends Controller public function generateAdminToken(Request $request) { $userId = $request->attributes->get('_jwt_user_id'); - // المدراء لديهم صلاحيات أوسع، قد يكون الـ aud مختلفاً return $this->buildToken($userId, 'web_admin', 'admin_secure_context'); } - // 4. دالة البناء المركزية (Private) + // 4. دالة البناء المركزية — متوافقة مع V1 authenticateJWT() private function buildToken($userId, $audience, $fingerprint) { - $keyPath = env('PAYMENT_INTERNAL_KEY_PATH'); + // ⚠️ مهم جداً لموافاة V1: + // سيرفر المحفظة (walletintaleq.intaleq.xyz) يستخدم V1authenticateJWT() + // التي تقرأ المفتاح من: /home/intaleq-api/.secret_key + // لذلك يجب استخدام jwt_secret هنا وليس wallet_jwt_secret. + $secret = config('intaleq.jwt_secret'); - if (!File::exists($keyPath)) { - return response()->json(['status' => 'error', 'message' => 'Security Key Missing'], 500); + if (empty($secret)) { + return response()->json(['status' => 'error', 'message' => 'Security Key Missing (JWT)'], 500); } - $internalSecret = trim(File::get($keyPath)); - + // بناء التوكن بنفس الهيكل المطلوب من V1 $payload = [ - 'iss' => 'Intaleq_V2', - 'sub' => $userId, - 'aud' => $audience, - 'iat' => time(), - 'exp' => time() + 60, - 'fingerprint' => $fingerprint + 'user_id' => $userId, // V1 يستخرج: $decoded->user_id + 'iss' => 'Tripz', // V1 يتحقق: $decoded->iss === 'Tripz' + 'aud' => $audience, + 'iat' => time(), + 'exp' => time() + 120, // زيادة الوقت قليلاً لـ 120 ثانية + 'fingerPrint' => hash('sha256', ($fingerprint ?? '') . config('intaleq.fp_pepper', '')), + 'jti' => bin2hex(random_bytes(16)), ]; - $token = JWT::encode($payload, $internalSecret, 'HS256'); + $token = JWT::encode($payload, $secret, 'HS256'); + + // HMAC: يستخدم SECRET_KEY_HMAC (متوفر في .env) + $hmacSecret = config('intaleq.wallet_hmac_secret'); + $hmac = hash_hmac('sha256', $userId, $hmacSecret); return response()->json([ 'status' => 'success', - 'token' => $token, - 'hmac' => hash_hmac('sha256', $token, $internalSecret) + 'token' => $token, + 'hmac' => $hmac ]); } } \ No newline at end of file diff --git a/app/Http/Controllers/OverlayController.php b/app/Http/Controllers/OverlayController.php new file mode 100644 index 0000000..7d14d73 --- /dev/null +++ b/app/Http/Controllers/OverlayController.php @@ -0,0 +1,127 @@ +attributes->get('_jwt_user_id'); + + if (empty($driverId)) { + return response()->json(['status' => 'failure', 'message' => 'Missing driver ID']); + } + + $row = DB::connection('primary') + ->table('write_argument_after_applied_from_background') + ->where('driver_id', $driverId) + ->whereRaw('TIMESTAMPDIFF(MINUTE, time_of_order, NOW()) <= 2') + ->orderBy('time_of_order', 'desc') + ->first(); + + if ($row) { + return response()->json(['status' => 'success', 'message' => (array) $row]); + } + + return response()->json(['status' => 'failure', 'message' => 'No data found']); + } + + /** + * POST /v2/overlay/background-args + * تخزين بيانات الرحلة المقبولة من الخلفية + */ + public function storeBackgroundArgs(Request $request): JsonResponse + { + $driverId = $request->attributes->get('_jwt_user_id'); + + $rideId = $request->input('rideId'); + $passengerLocation = $request->input('passengerLocation'); + $passengerDestination = $request->input('passengerDestination'); + + if (empty($rideId) || empty($driverId) || empty($passengerLocation) || empty($passengerDestination)) { + return response()->json([ + 'status' => 'failure', + 'message' => 'Missing required fields (rideId, driver_id, or locations)' + ]); + } + + try { + DB::connection('primary') + ->table('write_argument_after_applied_from_background') + ->insert([ + 'ride_id' => $rideId, + 'driver_id' => $driverId, + 'passenger_id' => $request->input('passengerId'), + 'passenger_location' => $passengerLocation, + 'passenger_destination' => $passengerDestination, + 'duration' => (int) $request->input('Duration', 0), + 'duration_to_passenger' => (int) $request->input('DurationToPassenger', 0), + 'duration_of_ride' => (int) $request->input('durationOfRideValue', 0), + 'distance' => (float) $request->input('Distance', 0), + 'total_cost' => (float) $request->input('totalCost', 0), + 'payment_amount' => (float) $request->input('paymentAmount', 0), + 'payment_method' => $request->input('paymentMethod'), + 'wallet_checked' => $request->input('WalletChecked') === 'true' ? 1 : 0, + 'has_steps' => !empty($request->input('isHaveSteps')) ? 1 : 0, + 'step0' => $request->input('step0'), + 'step1' => $request->input('step1'), + 'step2' => $request->input('step2'), + 'step3' => $request->input('step3'), + 'step4' => $request->input('step4'), + 'passenger_wallet_burc' => (float) $request->input('passengerWalletBurc', 0), + 'token_passenger' => $request->input('tokenPassenger'), + 'name' => $request->input('name'), + 'phone' => $request->input('phone'), + 'email' => $request->input('email'), + 'start_name_location' => $request->input('startNameLocation'), + 'end_name_location' => $request->input('endNameLocation'), + 'car_type' => $request->input('carType'), + 'kazan' => (float) $request->input('kazan', 0), + 'direction_url' => $request->input('direction'), + 'time_of_order' => $request->input('timeOfOrder', now()), + 'total_passenger' => (int) $request->input('totalPassenger', 0), + ]); + + return response()->json(['status' => 'success', 'message' => 'Background args saved']); + + } catch (\Exception $e) { + \Log::error('OverlayController Error: ' . $e->getMessage()); + return response()->json(['status' => 'failure', 'message' => 'Database error']); + } + } + + /** + * DELETE /v2/overlay/background-args + * حذف بيانات الرحلة المقبولة بعد استلامها + */ + public function deleteBackgroundArgs(Request $request): JsonResponse + { + $driverId = $request->attributes->get('_jwt_user_id'); + + DB::connection('primary') + ->table('write_argument_after_applied_from_background') + ->where('driver_id', $driverId) + ->delete(); + + return response()->json(['status' => 'success', 'message' => 'Background args deleted']); + } +} diff --git a/routes/api.php b/routes/api.php index b8689f7..b7f3d4b 100644 --- a/routes/api.php +++ b/routes/api.php @@ -30,6 +30,7 @@ use App\Http\Controllers\InviteController; use App\Http\Controllers\DriverDocController; use App\Http\Controllers\SupportController; use App\Http\Controllers\Api\PaymentTokenController; +use App\Http\Controllers\OverlayController; /* @@ -194,6 +195,11 @@ Route::prefix('v2')->middleware(['hmac.auth', 'jwt.auth'])->group(function () { // ── Support ── Route::post('/support/complaints', [SupportController::class, 'storeComplaint']); + + // ── Overlay / Background Args ── + Route::get('/overlay/background-args', [OverlayController::class, 'getBackgroundArgs']); + Route::post('/overlay/background-args', [OverlayController::class, 'storeBackgroundArgs']); + Route::delete('/overlay/background-args', [OverlayController::class, 'deleteBackgroundArgs']); }); // ══════════════════════════════════════════════