diff --git a/siro_driver/android/app/build.gradle b/siro_driver/android/app/build.gradle index ac2a9488..7cf79cf4 100644 --- a/siro_driver/android/app/build.gradle +++ b/siro_driver/android/app/build.gradle @@ -122,7 +122,7 @@ dependencies { coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5' - implementation 'com.scottyab:rootbeer-lib:0.1.0' + implementation 'com.scottyab:rootbeer-lib:0.1.2' // تمت الترقية لتطابق تطبيق الراكب implementation 'com.google.android.gms:play-services-safetynet:18.1.0' diff --git a/siro_driver/android/app/src/main/kotlin/com/example/intaleq_driver/MainActivity.kt b/siro_driver/android/app/src/main/kotlin/com/example/intaleq_driver/MainActivity.kt index 84b23699..d087500b 100644 --- a/siro_driver/android/app/src/main/kotlin/com/example/intaleq_driver/MainActivity.kt +++ b/siro_driver/android/app/src/main/kotlin/com/example/intaleq_driver/MainActivity.kt @@ -2,6 +2,7 @@ package com.siro.siro_driver import android.app.AlertDialog import android.content.Intent +import android.content.pm.ApplicationInfo import android.os.Bundle import android.util.Log import android.widget.LinearLayout @@ -134,11 +135,17 @@ class MainActivity : FlutterFragmentActivity() { // --- بقية كود الحماية الخاص بك --- private fun isDeviceCompromised(): Boolean { + val isDebug = (applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) != 0 + if (isDebug) { + Log.d("MainActivity", "Debug build: bypassing root check") + return false + } return try { val isRootedByRootBeer = RootBeer(this).isRooted isRootedByRootBeer - } catch (e: Exception) { - true + } catch (t: Throwable) { + Log.e("MainActivity", "RootBeer check failed: ", t) + false } } diff --git a/siro_driver/lib/constant/box_name.dart b/siro_driver/lib/constant/box_name.dart index 12357ad1..c9697289 100755 --- a/siro_driver/lib/constant/box_name.dart +++ b/siro_driver/lib/constant/box_name.dart @@ -6,6 +6,7 @@ class BoxName { static const String initializationVector = 'initializationVector'; static const String firstTimeLoadKey = 'firstTimeLoadKey'; static const String jwt = "jwt"; + static const String walletJwt = "walletJwt"; static const String blockUntilDate = "blockUntilDate"; static const String rideId = "rideId"; static const String rideArgumentsFromBackground = diff --git a/siro_driver/lib/controller/auth/captin/login_captin_controller.dart b/siro_driver/lib/controller/auth/captin/login_captin_controller.dart index 81548cd4..307980b1 100755 --- a/siro_driver/lib/controller/auth/captin/login_captin_controller.dart +++ b/siro_driver/lib/controller/auth/captin/login_captin_controller.dart @@ -142,11 +142,55 @@ class LoginDriverController extends GetxController { } var dev = ''; + Future? _walletJwtFuture; + getJwtWallet() async { + if (_walletJwtFuture != null) { + Log.print('⏳ getJwtWallet: Request already in progress, reusing future.'); + return _walletJwtFuture!; + } + + _walletJwtFuture = _getJwtWalletInternal(); + try { + return await _walletJwtFuture!; + } finally { + _walletJwtFuture = null; + } + } + + Future _getJwtWalletInternal() async { if (box.read(BoxName.security_check).toString() != 'passed') { Log.print('Security check failed'); - return; + return ''; } + + // 1. Check GetStorage first to avoid redundant API calls + String? cachedJwt = box.read(BoxName.walletJwt)?.toString(); + if (cachedJwt != null && cachedJwt.isNotEmpty) { + bool isTokenValid = false; + try { + final parts = cachedJwt.split('.'); + if (parts.length == 3) { + var payload = parts[1]; + switch (payload.length % 4) { + case 2: payload += '=='; break; + case 3: payload += '='; break; + } + final decoded = jsonDecode(utf8.decode(base64Url.decode(payload))); + final exp = decoded['exp']; + if (exp != null) { + // Check if token has at least 10 seconds remaining + isTokenValid = DateTime.now().millisecondsSinceEpoch < (exp * 1000 - 10000); + } + } + } catch (_) {} + + if (isTokenValid) { + Log.print('🔑 Valid Wallet JWT found in storage. Skipping generation.'); + return cachedJwt; + } + } + Log.print('Security check passed'); dev = Platform.isAndroid ? 'android' : 'ios'; var fingerPrint = box.read(BoxName.deviceFingerprint)?.toString() ?? @@ -172,8 +216,12 @@ class LoginDriverController extends GetxController { : decoded['hmac']; Log.print('payment["jwt"]: $jwt'); - await box.write(BoxName.hmac, hmac); - return jwt.toString(); + if (jwt != null) { + await box.write(BoxName.walletJwt, jwt.toString()); + await box.write(BoxName.hmac, hmac); + return jwt.toString(); + } + return ''; } getJWT() async { diff --git a/siro_driver/lib/controller/functions/package_info.dart b/siro_driver/lib/controller/functions/package_info.dart index 63f7e1f5..57c53e91 100755 --- a/siro_driver/lib/controller/functions/package_info.dart +++ b/siro_driver/lib/controller/functions/package_info.dart @@ -3,6 +3,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:ui'; import 'package:device_info_plus/device_info_plus.dart'; +import 'package:flutter/foundation.dart'; import 'package:jailbreak_root_detection/jailbreak_root_detection.dart'; import 'package:siro_driver/constant/box_name.dart'; import 'package:siro_driver/constant/colors.dart'; @@ -204,6 +205,11 @@ class DeviceHelper { class SecurityHelper { /// Performs security checks and handles potential risks static Future performSecurityChecks() async { + if (kDebugMode) { + debugPrint("Debug mode: skipping security helper check"); + box.write(BoxName.security_check, 'passed'); + return; + } bool isNotTrust = false; bool isJailBroken = false; bool isRealDevice = true; diff --git a/siro_driver/lib/controller/home/captin/home_captain_controller.dart b/siro_driver/lib/controller/home/captin/home_captain_controller.dart index b3a484dd..f8b3449c 100755 --- a/siro_driver/lib/controller/home/captin/home_captain_controller.dart +++ b/siro_driver/lib/controller/home/captin/home_captain_controller.dart @@ -770,17 +770,30 @@ class HomeCaptainController extends GetxController { payload: {'country': box.read(BoxName.countryCode).toString()}, ); if (res != 'failure') { - var json = jsonDecode(res); - kazan = double.parse(json['message'][0]['kazan']); - naturePrice = double.parse(json['message'][0]['naturePrice']); - heavyPrice = double.parse(json['message'][0]['heavyPrice']); - latePrice = double.parse(json['message'][0]['latePrice']); - comfortPrice = double.parse(json['message'][0]['comfortPrice']); - speedPrice = double.parse(json['message'][0]['speedPrice']); - deliveryPrice = double.parse(json['message'][0]['deliveryPrice']); - mashwariPrice = double.parse(json['message'][0]['freePrice']); - familyPrice = double.parse(json['message'][0]['familyPrice']); - fuelPrice = double.parse(json['message'][0]['fuelPrice']); + try { + var json = jsonDecode(res); + if (json['message'] is List && json['message'].isNotEmpty) { + final item = json['message'][0]; + + double parseDouble(dynamic val) { + if (val == null) return 0.0; + return double.tryParse(val.toString()) ?? 0.0; + } + + kazan = parseDouble(item['kazanPercent'] ?? item['kazan']); + naturePrice = parseDouble(item['normalMinPrice'] ?? item['naturePrice']); + heavyPrice = parseDouble(item['peakMinPrice'] ?? item['heavyPrice']); + latePrice = parseDouble(item['lateMinPrice'] ?? item['latePrice']); + comfortPrice = parseDouble(item['comfortPrice']); + speedPrice = parseDouble(item['speedPrice']); + deliveryPrice = parseDouble(item['deliveryPrice']); + mashwariPrice = parseDouble(item['freePrice'] ?? item['mishwarVipPrice']); + familyPrice = parseDouble(item['familyPrice'] ?? item['ladyPrice']); + fuelPrice = parseDouble(item['fuelPrice']); + } + } catch (e) { + Log.print("Error parsing kazan percent: $e"); + } } update(); } diff --git a/siro_driver/lib/views/home/Captin/About Us/about_us.dart b/siro_driver/lib/views/home/Captin/About Us/about_us.dart index 50d72f0a..dbcb4f9c 100755 --- a/siro_driver/lib/views/home/Captin/About Us/about_us.dart +++ b/siro_driver/lib/views/home/Captin/About Us/about_us.dart @@ -26,7 +26,7 @@ class AboutPage extends StatelessWidget { Padding( padding: const EdgeInsets.all(16.0), child: Text( - 'Siro LLC\n${'Syria'.tr}', + 'Siro LLC\n${(box.read(BoxName.countryCode)?.toString() ?? 'Syria').tr}', style: AppStyle.headTitle2, textAlign: TextAlign.center, ),