refactor: optimize wallet JWT management, update security checks for debug builds, and improve pricing data parsing

This commit is contained in:
Hamza-Ayed
2026-06-27 22:50:28 +03:00
parent 43e3f8c939
commit a87cb7c082
7 changed files with 93 additions and 18 deletions

View File

@@ -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 =

View File

@@ -142,11 +142,55 @@ class LoginDriverController extends GetxController {
}
var dev = '';
Future<String>? _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<String> _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 {

View File

@@ -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<void> 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;

View File

@@ -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();
}

View File

@@ -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,
),