diff --git a/android/app/build.gradle b/android/app/build.gradle
index 2eeefe4..2b26425 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -47,8 +47,8 @@ android {
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdkVersion = 24
targetSdk = 36
- versionCode = 59
- versionName = '1.1.59'
+ versionCode = 60
+ versionName = '1.1.60'
multiDexEnabled = true
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 391a902..4aaa3e0 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -1,24 +1,26 @@
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- App
- CFBundleIdentifier
- io.flutter.flutter.app
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- App
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1.0
-
-
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 16.1
+
+
\ No newline at end of file
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 6786289..1ed3bac 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -1,107 +1,106 @@
-
- NSSupportsLiveActivities
-
- CFBundleURLTypes
-
-
- CFBundleTypeRole
- Editor
- CFBundleURLName
- intaleqapp.com
- CFBundleURLSchemes
-
-
- com.googleusercontent.apps.1086900987150-9jv4oa8l3t23d54lrf27c1d22tbt9i6d
- intaleq
-
-
-
- FlutterDeepLinkingEnabled
-
- CADisableMinimumFrameDurationOnPhone
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- Intaleq
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- Intaleq
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 31
- CFBundleSignature
- ????
- CFBundleVersion
- 1.1.31
- FirebaseAppDelegateProxyEnabled
- NO
- GMSApiKey
- YOUR_API_KEY
- LSApplicationQueriesSchemes
-
- googlechromes
- comgooglemaps
-
- LSRequiresIPhoneOS
-
- NSCameraUsageDescription
- This app requires access to your camera in order to scan QR codes and capture images
- for uploading and access to connect to a call.
- NSContactsUsageDescription
- This app requires contacts access to function properly.
- NSFaceIDUsageDescription
- Use Face ID to securely authenticate payment accounts.
- NSLocationAlwaysAndWhenInUseUsageDescription
- This app needs access to your location to provide you with the best ride experience.
- Your location data will be used to find the nearest available cars and connect you with
- the closest captain for efficient and convenient rides.
- NSLocationAlwaysUsageDescription
- This app needs access to location.
- NSLocationWhenInUseUsageDescription
- This app needs access to your location to provide you with the best ride experience.
- Your location data will be used to find the nearest available cars and connect you with
- the closest captain for efficient and convenient rides.
- NSMicrophoneUsageDescription
- This app requires access to your microphone to record audio, allowing you to add
- voice recordings to your photos and videos and access to connect to a call.
- NSPhotoLibraryUsageDescription
- This app requires access to the photo library to upload pictures.
- UIApplicationSupportsIndirectInputEvents
-
- UIBackgroundModes
-
- fetch
- location
- remote-notification
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UIViewControllerBasedStatusBarAppearance
-
-
-
\ No newline at end of file
+
+ CADisableMinimumFrameDurationOnPhone
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Intaleq
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ Intaleq
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 32
+ CFBundleSignature
+ ????
+ CFBundleURLTypes
+
+
+ CFBundleTypeRole
+ Editor
+ CFBundleURLName
+ intaleqapp.com
+ CFBundleURLSchemes
+
+ com.googleusercontent.apps.1086900987150-9jv4oa8l3t23d54lrf27c1d22tbt9i6d
+ intaleq
+
+
+
+ CFBundleVersion
+ 1.1.32
+ FirebaseAppDelegateProxyEnabled
+ NO
+ FlutterDeepLinkingEnabled
+
+ GMSApiKey
+ YOUR_API_KEY
+ LSApplicationQueriesSchemes
+
+ googlechromes
+ comgooglemaps
+
+ LSRequiresIPhoneOS
+
+ NSCameraUsageDescription
+ This app requires access to your camera in order to scan QR codes and capture images
+ for uploading and access to connect to a call.
+ NSContactsUsageDescription
+ This app requires contacts access to function properly.
+ NSFaceIDUsageDescription
+ Use Face ID to securely authenticate payment accounts.
+ NSLocationAlwaysAndWhenInUseUsageDescription
+ This app needs access to your location to provide you with the best ride experience.
+ Your location data will be used to find the nearest available cars and connect you with
+ the closest captain for efficient and convenient rides.
+ NSLocationAlwaysUsageDescription
+ This app needs access to location.
+ NSLocationWhenInUseUsageDescription
+ This app needs access to your location to provide you with the best ride experience.
+ Your location data will be used to find the nearest available cars and connect you with
+ the closest captain for efficient and convenient rides.
+ NSMicrophoneUsageDescription
+ This app requires access to your microphone to record audio, allowing you to add
+ voice recordings to your photos and videos and access to connect to a call.
+ NSPhotoLibraryUsageDescription
+ This app requires access to the photo library to upload pictures.
+ NSSupportsLiveActivities
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UIBackgroundModes
+
+ fetch
+ location
+ remote-notification
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+
+
diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart
index e20bfa3..a2379f0 100644
--- a/lib/constant/box_name.dart
+++ b/lib/constant/box_name.dart
@@ -10,6 +10,7 @@ class BoxName {
static const String gender = "gender";
static const String jwt = "jwt";
static const String lowEndMode = "lowEndMode";
+ static const String deviceFpEncrypted = "deviceFpEncrypted";
static const String appVersionChecked = "appVersionChecked";
static const String lastName = "lastName";
static const String fingerPrint = "fingerPrint";
diff --git a/lib/constant/links.dart b/lib/constant/links.dart
index 7d25ee7..96aaf6d 100644
--- a/lib/constant/links.dart
+++ b/lib/constant/links.dart
@@ -3,10 +3,10 @@ import 'package:Intaleq/main.dart';
class AppLink {
///https://walletintaleq.intaleq.xyz/v1/main
- static String paymentServer = 'https://walletintaleq.intaleq.xyz/v1/main';
+ static String paymentServer = 'https://walletintaleq.intaleq.xyz/v2/main';
///https://api.intaleq.xyz/intaleq/ride/location
- static String location = 'https://api.intaleq.xyz/intaleq/ride/location';
+ static String location = 'https://api.intaleq.xyz/intaleq_v1/ride/location';
/// هذا الرابط خاص برحلات الركاب، ويستخدمه السيرفر الجانبي للرحلات (Ride Server Side) للتعامل مع عمليات إلغاء الرحلات وتحديث حالة الرحلات وغيرها من العمليات المتعلقة بالرحلات.
/// https://routesy.intaleq.xyz for syria
@@ -19,7 +19,7 @@ class AppLink {
'https://location.intaleq.xyz/intaleq/ride/location';
///https://api.intaleq.xyz/intaleq
- static final String endPoint = 'https://api.intaleq.xyz/intaleq';
+ static final String endPoint = 'https://api.intaleq.xyz/intaleq_v1';
/// هذا الرابط خاص برحلات الركاب، ويستخدمه السيرفر الجانبي للرحلات (Ride Server Side) للتعامل مع عمليات إلغاء الرحلات وتحديث حالة الرحلات وغيرها من العمليات المتعلقة بالرحلات.
/// https://rides.intaleq.xyz/intaleq
@@ -27,7 +27,7 @@ class AppLink {
///https://api.intaleq.xyz/intaleq
/// main api link for all api calls except rides and location
- static final String server = 'https://api.intaleq.xyz/intaleq';
+ static final String server = 'https://api.intaleq.xyz/intaleq_v1';
///https://rides.intaleq.xyz
/// هذا الرابط خاص برحلات الركاب، ويستخدمه السيرفر الجانبي للرحلات (Ride Server Side) للتعامل مع عمليات إلغاء الرحلات وتحديث حالة الرحلات وغيرها من العمليات المتعلقة بالرحلات.
diff --git a/lib/controller/auth/login_controller.dart b/lib/controller/auth/login_controller.dart
index 92b4e4f..25eb9c9 100644
--- a/lib/controller/auth/login_controller.dart
+++ b/lib/controller/auth/login_controller.dart
@@ -87,54 +87,6 @@ class LoginController extends GetxController {
update();
}
- getJwtWallet() async {
- try {
- if (box.read(BoxName.security_check).toString() != 'passed') {
- Log.print('Security check failed');
- return;
- }
- Log.print('Security check passed');
-
- String fingerPrint = await DeviceHelper.getDeviceFingerprint();
- final dev = GetPlatform.isAndroid ? 'android' : 'ios';
-
- var payload = {
- 'id': box.read(BoxName.passengerID),
- 'password': AK.passnpassenger,
- 'aud': '${AK.allowed}$dev',
- 'fingerPrint': fingerPrint,
- };
-
- var response = await http.post(
- Uri.parse(AppLink.loginJwtWalletRider),
- body: payload,
- );
-
- // Handle bad responses
- if (response.statusCode != 200) {
- _showJwtErrorDialog(
- "حدث خطأ أثناء الاتصال بالخادم. يرجى المحاولة مرة أخرى.");
- throw Exception("JWT request failed");
- }
-
- var data = jsonDecode(response.body);
-
- // Validate JWT response structure
- if (!data.containsKey('jwt') || !data.containsKey('hmac')) {
- _showJwtErrorDialog("تعذّر التحقق من الأمان. يرجى إعادة المحاولة.");
- throw Exception("Invalid JWT response format");
- }
-
- // Save HMAC locally
- await box.write(BoxName.hmac, data['hmac']);
-
- return data['jwt'].toString();
- } catch (e) {
- _showJwtErrorDialog("حدث خلل غير متوقع. يرجى المحاولة مرة أخرى.");
- rethrow;
- }
- }
-
void _showJwtErrorDialog(String message) {
if (Get.context == null) return;
@@ -149,72 +101,128 @@ class LoginController extends GetxController {
},
);
}
+ // ═══════════════════════════════════════════════════════════════
+// LoginController — دوال إدارة الـ JWT
+// ───────────────────────────────────────────────────────────────
+// لا تغيير على اسم الكلاس أو أسماء الدوال
+// ═══════════════════════════════════════════════════════════════
- getJWT() async {
- // print(Pasenger.pasengerpas);
- // await SecurityHelper.performSecurityChecks();
- Log.print('firstTimeLoadKey: ${box.read(BoxName.firstTimeLoadKey)}');
+// داخل class LoginController
+
+ // ─────────────────────────────────────────────────────────────
+ // getJWT: الحصول على توكن للراكب
+ // ─────────────────────────────────────────────────────────────
+ // المنطق:
+ // • firstTimeLoadKey != false ← أول مرة يفتح التطبيق → loginFirstTime
+ // • firstTimeLoadKey == false ← مستخدم موجود → loginJwtRider
+ // ─────────────────────────────────────────────────────────────
+ Future getJWT() async {
dev = Platform.isAndroid ? 'android' : 'ios';
+
+ // تأكد إن البصمة محدّثة قبل أي طلب
+ await DeviceHelper.getDeviceFingerprint();
+ final String fp = box.read(BoxName.deviceFpEncrypted) ?? '';
+
if (box.read(BoxName.firstTimeLoadKey).toString() != 'false') {
+ // ── أول تسجيل ─────────────────────────────────────────
+ // نرسل البصمة المشفرة مع باقي البيانات
+ // السيرفر سيعمل hash لها ويخزنها في JWT payload
var payload = {
'id': box.read(BoxName.passengerID) ?? AK.newId,
'password': AK.passnpassenger,
'aud': '${AK.allowed}$dev',
+ 'fingerPrint': fp,
};
- // Log.print('payload: ${payload}');
- var response0 = await http.post(
+
+ var response = await http.post(
Uri.parse(AppLink.loginFirstTime),
body: payload,
);
- if (response0.statusCode == 200) {
- final decodedResponse1 = jsonDecode(response0.body);
+ Log.print('AppLink.loginFirstTime: ${AppLink.loginFirstTime}');
- final jwt = decodedResponse1['jwt'];
- final refreshToken = decodedResponse1['refresh_token'];
+ Log.print('payload: ${payload}');
+ Log.print('response: ${response}');
+
+ if (response.statusCode == 200) {
+ final decoded = jsonDecode(response.body);
+ final String jwt = decoded['jwt'];
+
+ // نشفر الـ JWT بالتشفير الثلاثي قبل التخزين في GetStorage
box.write(BoxName.jwt, c(jwt));
- // Sss.write(BoxName.jwt, jwt);
- await storage.write(key: BoxName.refreshToken, value: refreshToken);
- // await AppInitializer().getAIKey(Pasenger.keyOfApp);
- // await AppInitializer().getAIKey(Pasenger.initializationVector);
- // await Future.delayed(Duration.zero);
await EncryptionHelper.initialize();
-
- await AppInitializer().getKey();
- } else {}
+ }
} else {
+ // ── مستخدم موجود: تجديد التوكن ────────────────────────
await EncryptionHelper.initialize();
var payload = {
'id': box.read(BoxName.passengerID),
- 'password': box.read(BoxName.email),
+ 'fingerPrint': fp,
'aud': '${AK.allowed}$dev',
};
- // Log.print('payload: ${payload}');
- var response1 = await http.post(
+
+ var response = await http.post(
Uri.parse(AppLink.loginJwtRider),
body: payload,
);
- Log.print('req: ${response1.request}');
- Log.print('response: ${response1.body}');
+ Log.print('AppLink.loginJwtRider: ${AppLink.loginJwtRider}');
+
Log.print('payload: ${payload}');
- // Log.print('decodedResponse1: ${jsonDecode(response1.body)}');
+ Log.print('response: ${response.body}');
+ if (response.statusCode == 200) {
+ final decoded = jsonDecode(response.body);
+ final String jwt = decoded['jwt'];
- if (response1.statusCode == 200) {
- final decodedResponse1 = jsonDecode(response1.body);
- // Log.print('decodedResponse1: ${decodedResponse1}');
-
- final jwt = decodedResponse1['jwt'];
- await box.write(BoxName.jwt, c(jwt));
-
- await AppInitializer().getKey();
-
- // final refreshToken = decodedResponse1['refresh_token'];
- // await storage.write(key: BoxName.refreshToken, value: refreshToken);
+ box.write(BoxName.jwt, c(jwt));
}
}
}
+ // ─────────────────────────────────────────────────────────────
+ // getJwtWallet: الحصول على توكن لسيرفر المدفوعات
+ // ─────────────────────────────────────────────────────────────
+ // الفرق عن getJWT:
+ // • يستخدم endpoint مختلف (loginWallet)
+ // • يرجع hmac مع الـ jwt ويخزنه في GetStorage
+ // • الـ JWT لا يُشفَّر ثلاثياً (يُستخدم مباشرة في الـ header)
+ // ─────────────────────────────────────────────────────────────
+ Future getJwtWallet() async {
+ dev = Platform.isAndroid ? 'android' : 'ios';
+
+ // await DeviceHelper.initAndStore();
+ final String fp = box.read(BoxName.deviceFpEncrypted) ?? '';
+
+ var payload = {
+ 'id': box.read(BoxName.passengerID),
+ 'password': AK.passnpassenger,
+ 'aud': '${AK.allowed}$dev',
+ 'fingerPrint': fp,
+ };
+
+ var response = await http.post(
+ Uri.parse(AppLink.loginJwtWalletRider),
+ body: payload,
+ );
+ Log.print('AppLink.loginJwtWalletRider: ${AppLink.loginJwtWalletRider}');
+
+ // Log.print('payload: ${payload}');
+ Log.print('response wallet: ${response.body}');
+ if (response.statusCode == 200) {
+ final decoded = jsonDecode(response.body);
+ final String jwt = decoded['jwt'];
+ final String hmac = decoded['hmac'];
+
+ // نخزن الـ hmac للاستخدام في X-HMAC-Auth header
+ box.write(BoxName.hmac, hmac);
+
+ // wallet JWT يُرجَع مباشرة دون تشفير ثلاثي
+ return jwt;
+ }
+
+ return null;
+ }
+
Future loginUsingCredentials(String passengerID, String email) async {
isloading = true;
update();
diff --git a/lib/controller/auth/register_controller.dart b/lib/controller/auth/register_controller.dart
index f86eab1..8e4c8d7 100644
--- a/lib/controller/auth/register_controller.dart
+++ b/lib/controller/auth/register_controller.dart
@@ -297,20 +297,6 @@ class RegisterController extends GetxController {
);
if (res1 != 'failure') {
- // if (AppLink.IntaleqAlexandriaServer != AppLink.IntaleqSyriaServer) {
- // List signUp = [
- // CRUD().post(
- // link: '${AppLink.IntaleqAlexandriaServer}/auth/signup.php',
- // payload: payload,
- // ),
- // CRUD().post(
- // link: '${AppLink.IntaleqGizaServer}/auth/signup.php',
- // payload: payload,
- // )
- // ];
- // await Future.wait(signUp);
- // }
-
box.write(BoxName.isVerified, '1');
box.write(BoxName.isFirstTime, '0');
box.write(BoxName.phone, (phoneController.text));
diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart
index abf673e..cd276fc 100644
--- a/lib/controller/firebase/firbase_messge.dart
+++ b/lib/controller/firebase/firbase_messge.dart
@@ -69,7 +69,7 @@ class FirebaseMessagesController extends GetxController {
Future getToken() async {
fcmToken.getToken().then((token) {
- Log.print('fcmToken: ${token}');
+ // Log.print('fcmToken: ${token}');
box.write(BoxName.tokenFCM, (token.toString()));
});
// 🔹 الاشتراك في topic
diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart
index 5dd615f..8d7d378 100644
--- a/lib/controller/functions/crud.dart
+++ b/lib/controller/functions/crud.dart
@@ -68,6 +68,15 @@ class CRUD {
} catch (e) {}
}
+ // ─────────────────────────────────────────────────────────────
+ // دالة مساعدة خاصة: يجيب البصمة المشفرة من GetStorage
+ // هي نفس القيمة المرسلة في login وعُملها hash في JWT payload
+ // السيرفر يعمل: sha256(X-Device-FP + FP_PEPPER) == JWT.fingerPrint
+ // ─────────────────────────────────────────────────────────────
+ String _getFpHeader() {
+ return box.read(BoxName.deviceFpEncrypted)?.toString() ?? '';
+ }
+
/// Centralized private method to handle all API requests.
/// Includes retry logic, network checking, and standardized error handling.
Future _makeRequest({
@@ -75,13 +84,11 @@ class CRUD {
Map? payload,
required Map headers,
}) async {
- // timeouts أقصر
const connectTimeout = Duration(seconds: 6);
const receiveTimeout = Duration(seconds: 10);
Future doPost() {
final url = Uri.parse(link);
- // استخدم _client بدل http.post
return _client
.post(url, body: payload, headers: headers)
.timeout(connectTimeout + receiveTimeout);
@@ -93,7 +100,6 @@ class CRUD {
try {
response = await doPost();
} on SocketException catch (_) {
- // محاولة ثانية واحدة فقط
response = await doPost();
} on TimeoutException catch (_) {
response = await doPost();
@@ -102,36 +108,34 @@ class CRUD {
final sc = response.statusCode;
final body = response.body;
Log.print('request: ${response.request}');
- Log.print('body: ${body}');
+ Log.print('body: $body');
// 2xx
if (sc >= 200 && sc < 300) {
try {
final jsonData = jsonDecode(body);
- return jsonData; // لا تعيد 'success' فقط؛ أعِد الجسم كله
+ return jsonData;
} catch (e, st) {
- // لا تسجّل كخطأ شبكي لكل حالة؛ فقط معلومات
addError('JSON Decode Error', 'Body: $body\n$st',
'CRUD._makeRequest $link');
return 'failure';
}
}
- // 401 → دع الطبقة العليا تتعامل مع التجديد
+ // 401 → تجديد التوكن تلقائياً
if (sc == 401) {
await Get.put(LoginController()).getJWT();
- // لا تستدع getJWT هنا كي لا نضاعف الرحلات
return 'token_expired';
}
- // 5xx: لا تعِد المحاولة هنا (حاولنا مرة ثانية فوق)
+ // 5xx
if (sc >= 500) {
addError(
'Server 5xx', 'SC: $sc\nBody: $body', 'CRUD._makeRequest $link');
return 'failure';
}
- // 4xx أخرى: أعد الخطأ بدون تسجيل مكرر
+ // 4xx أخرى
return 'failure';
} on SocketException {
_netGuard.notifyOnce((title, msg) => mySnackeBarError(msg));
@@ -145,21 +149,23 @@ class CRUD {
}
}
- /// Performs a standard authenticated POST request.
- /// Automatically handles token renewal.
+ // ═══════════════════════════════════════════════════════════════
+ // post — طلب POST عادي للراكب/السائق
+ // ───────────────────────────────────────────────────────────────
+ // التغيير: إضافة X-Device-FP header
+ // القيمة: fp_encrypted من GetStorage
+ // السيرفر يتحقق: sha256(fp_encrypted + FP_PEPPER) == JWT.fingerPrint
+ // ═══════════════════════════════════════════════════════════════
Future post({
required String link,
Map? payload,
}) async {
String token = r(box.read(BoxName.jwt)).toString().split(Env.addd)[0];
- // if (JwtDecoder.isExpired(token)) {
- // await Get.put(LoginController()).getJWT();
- // token = r(box.read(BoxName.jwt)).toString().split(Env.addd)[0];
- // }
final headers = {
- "Content-Type": "application/x-www-form-urlencoded",
- 'Authorization': 'Bearer $token'
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Authorization': 'Bearer $token',
+ 'X-Device-FP': _getFpHeader(), // ← إثبات الجهاز
};
return await _makeRequest(
@@ -169,58 +175,58 @@ class CRUD {
);
}
- /// Performs a standard authenticated GET request (using POST method as per original code).
- /// Automatically handles token renewal.
+ // ═══════════════════════════════════════════════════════════════
+ // get — طلب GET للراكب/السائق (يستخدم POST method)
+ // ───────────────────────────────────────────────────────────────
+ // التغيير: إضافة X-Device-FP header
+ // ═══════════════════════════════════════════════════════════════
Future get({
required String link,
Map? payload,
}) async {
- var url = Uri.parse(
- link,
- );
+ var url = Uri.parse(link);
var response = await http.post(
url,
body: payload,
headers: {
- "Content-Type": "application/x-www-form-urlencoded",
+ 'Content-Type': 'application/x-www-form-urlencoded',
'Authorization':
- 'Bearer ${r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]}'
+ 'Bearer ${r(box.read(BoxName.jwt)).toString().split(Env.addd)[0]}',
+ 'X-Device-FP': _getFpHeader(), // ← إثبات الجهاز
},
);
+
Log.print('request: ${response.request}');
Log.print('body: ${response.body}');
- Log.print('payload: ${payload}');
+ Log.print('payload: $payload');
if (response.statusCode == 200) {
var jsonData = jsonDecode(response.body);
if (jsonData['status'] == 'success') {
return response.body;
}
-
return jsonData['status'];
} else if (response.statusCode == 401) {
- // Specifically handle 401 Unauthorized
var jsonData = jsonDecode(response.body);
-
if (jsonData['error'] == 'Token expired') {
- // Show snackbar prompting to re-login
await Get.put(LoginController()).getJWT();
- // mySnackbarSuccess('please order now'.tr);
- return 'token_expired'; // Return a specific value for token expiration
+ return 'token_expired';
} else {
- // Other 401 errors
- // addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401',
- // url.toString());
return 'failure';
}
} else {
addError('Non-200 response code: ${response.statusCode}',
- 'crud().post - Other', url.toString());
+ 'crud().get - Other', url.toString());
return 'failure';
}
}
- /// Performs an authenticated POST request to wallet endpoints.
+ // ═══════════════════════════════════════════════════════════════
+ // postWallet — طلب POST لسيرفر المدفوعات
+ // ───────────────────────────────────────────────────────────────
+ // التغيير: إضافة X-Device-FP header
+ // 3 headers معاً: JWT + HMAC + FP
+ // ═══════════════════════════════════════════════════════════════
Future postWallet({
required String link,
Map? payload,
@@ -229,9 +235,10 @@ class CRUD {
final hmac = box.read(BoxName.hmac);
final headers = {
- "Content-Type": "application/x-www-form-urlencoded",
+ 'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer $jwt',
'X-HMAC-Auth': hmac.toString(),
+ 'X-Device-FP': _getFpHeader(), // ← إثبات الجهاز
};
return await _makeRequest(
@@ -241,63 +248,61 @@ class CRUD {
);
}
- /// Performs an authenticated GET request to wallet endpoints (using POST).
+ // ═══════════════════════════════════════════════════════════════
+ // getWallet — طلب GET لسيرفر المدفوعات (يستخدم POST method)
+ // ───────────────────────────────────────────────────────────────
+ // التغيير: إضافة X-Device-FP header
+ // ═══════════════════════════════════════════════════════════════
Future getWallet({
required String link,
Map? payload,
}) async {
var s = await LoginController().getJwtWallet();
final hmac = box.read(BoxName.hmac);
- var url = Uri.parse(
- link,
- );
+ var url = Uri.parse(link);
+
var response = await http.post(
url,
body: payload,
headers: {
- "Content-Type": "application/x-www-form-urlencoded",
+ 'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer $s',
'X-HMAC-Auth': hmac.toString(),
+ 'X-Device-FP': _getFpHeader(), // ← إثبات الجهاز
},
);
+
if (response.statusCode == 200) {
var jsonData = jsonDecode(response.body);
if (jsonData['status'] == 'success') {
return response.body;
}
-
return jsonData['status'];
} else if (response.statusCode == 401) {
- // Specifically handle 401 Unauthorized
var jsonData = jsonDecode(response.body);
-
if (jsonData['error'] == 'Token expired') {
- // Show snackbar prompting to re-login
await Get.put(LoginController()).getJwtWallet();
-
- return 'token_expired'; // Return a specific value for token expiration
+ return 'token_expired';
} else {
- // Other 401 errors
- addError('Unauthorized: ${jsonData['error']}', 'crud().post - 401',
+ addError('Unauthorized: ${jsonData['error']}', 'crud().getWallet - 401',
url.toString());
return 'failure';
}
} else {
addError('Non-200 response code: ${response.statusCode}',
- 'crud().post - Other', url.toString());
+ 'crud().getWallet - Other', url.toString());
return 'failure';
}
}
+
// =======================================================================
- // All other specialized methods remain below.
- // They are kept separate because they interact with external third-party APIs
- // and have unique authentication, body structures, or error handling logic
- // that doesn't fit the standardized `_makeRequest` helper.
+ // All other specialized methods remain below unchanged.
+ // They interact with external third-party APIs and have unique
+ // authentication or body structures that don't need the FP header.
// =======================================================================
Future postWalletMtn(
{required String link, Map? payload}) async {
- // This method has a very custom response-wrapping logic, so it's kept separate.
final s = await LoginController().getJwtWallet();
final hmac = box.read(BoxName.hmac);
final url = Uri.parse(link);
@@ -307,9 +312,10 @@ class CRUD {
url,
body: payload,
headers: {
- "Content-Type": "application/x-www-form-urlencoded",
- "Authorization": "Bearer $s",
- "X-HMAC-Auth": hmac.toString(),
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Authorization': 'Bearer $s',
+ 'X-HMAC-Auth': hmac.toString(),
+ 'X-Device-FP': _getFpHeader(), // ← إثبات الجهاز
},
);
@@ -360,30 +366,6 @@ class CRUD {
}
}
- // Future getTokenParent({
- // required String link,
- // Map? payload,
- // }) async {
- // // Uses Basic Auth, so it's a separate implementation.
- // var url = Uri.parse(
- // link,
- // );
- // var response = await http.post(
- // url,
- // body: payload,
- // headers: {
- // "Content-Type": "application/x-www-form-urlencoded",
- // 'Authorization':
- // 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}',
- // },
- // );
- // if (response.statusCode == 200) {
- // return jsonDecode(response.body);
- // }
- // // Consider adding error handling here.
- // return null;
- // }
-
Future sendWhatsAppAuth(String to, String token) async {
var res = await CRUD()
.get(link: AppLink.getApiKey, payload: {'keyName': 'whatsapp_key'});
@@ -407,10 +389,7 @@ class CRUD {
{
"type": "body",
"parameters": [
- {
- "type": "text",
- "text": token,
- }
+ {"type": "text", "text": token}
]
}
]
@@ -422,18 +401,14 @@ class CRUD {
try {
http.StreamedResponse response = await request.send();
-
if (response.statusCode == 200) {
String responseBody = await response.stream.bytesToString();
-
Get.defaultDialog(
title: 'You will receive a code in WhatsApp Messenger'.tr,
middleText: 'wait 1 minute to recive message'.tr,
confirm: MyElevatedButton(
title: 'OK'.tr,
- onPressed: () {
- Get.back();
- },
+ onPressed: () => Get.back(),
),
);
} else {
@@ -447,15 +422,16 @@ class CRUD {
required String uid,
}) async {
var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver);
- var res = await http.get(Uri.parse(
- // 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'),
- 'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'),
- headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'});
+ var res = await http.get(
+ Uri.parse(
+ 'https://orca-app-b2i85.ondigitalocean.app/token?channelName=$channelName'),
+ headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'},
+ );
if (res.statusCode == 200) {
var response = jsonDecode(res.body);
return response['token'];
- } else {}
+ }
}
Future getLlama({
@@ -463,18 +439,14 @@ class CRUD {
required String payload,
required String prompt,
}) async {
- var url = Uri.parse(
- link,
- );
+ var url = Uri.parse(link);
var headers = {
'Content-Type': 'application/json',
'Authorization':
'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy'
- // 'Authorization': 'Bearer ${Env.llamaKey}'
};
var data = json.encode({
"model": "Llama-3-70b-Inst-FW",
- // "model": "llama-13b-chat",
"messages": [
{
"role": "user",
@@ -484,15 +456,8 @@ class CRUD {
],
"temperature": 0.9
});
- var response = await http.post(
- url,
- body: data,
- headers: headers,
- );
-
- if (response.statusCode == 200) {
- return response.body;
- }
+ var response = await http.post(url, body: data, headers: headers);
+ if (response.statusCode == 200) return response.body;
return response.statusCode;
}
@@ -501,7 +466,6 @@ class CRUD {
Future.delayed(const Duration(seconds: 2));
String extracted =
await arabicTextExtractByVisionAndAI(imagePath: imagePath);
- // await AI().geminiAiExtraction(prompt, extracted);
}
Future arabicTextExtractByVisionAndAI({
@@ -512,17 +476,13 @@ class CRUD {
'Ocp-Apim-Subscription-Key': '21010e54b50f41a4904708c526e102df'
};
var url = Uri.parse(
- 'https://ocrhamza.cognitiveservices.azure.com/vision/v2.1/ocr?language=ar',
- );
+ 'https://ocrhamza.cognitiveservices.azure.com/vision/v2.1/ocr?language=ar');
String imagePathFull =
'${AppLink.server}card_image/$imagePath-${box.read(BoxName.driverID) ?? box.read(BoxName.passengerID)}.jpg';
var requestBody = {"url": imagePathFull};
- var response = await http.post(
- url,
- body: jsonEncode(requestBody), // Encode the JSON object to a string
- headers: headers,
- );
+ var response =
+ await http.post(url, body: jsonEncode(requestBody), headers: headers);
if (response.statusCode == 200) {
var responseBody = jsonDecode(response.body);
@@ -535,9 +495,7 @@ class CRUD {
required String link,
required String payload,
}) async {
- var url = Uri.parse(
- link,
- );
+ var url = Uri.parse(link);
var headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ${Env.chatGPTkeySeferNew}'
@@ -553,15 +511,8 @@ class CRUD {
],
"temperature": 0.9
});
- var response = await http.post(
- url,
- body: data,
- headers: headers,
- );
-
- if (response.statusCode == 200) {
- return response.body;
- }
+ var response = await http.post(url, body: data, headers: headers);
+ if (response.statusCode == 200) return response.body;
return response.statusCode;
}
@@ -569,109 +520,57 @@ class CRUD {
required String link,
Map? payload,
}) async {
- // String? secretKey = await storage.read(key: BoxName.secretKey);
- var url = Uri.parse(
- link,
- );
+ var url = Uri.parse(link);
var response = await http.post(
url,
body: payload,
headers: {
- "Content-Type": "application/x-www-form-urlencoded",
+ 'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Bearer ${AK.secretKey}',
},
);
- if (response.statusCode == 200) {
- return response.body;
- } else {}
+ if (response.statusCode == 200) return response.body;
}
- // Future post({
- // required String link,
- // Map? payload,
- // }) async {
- // // String? basicAuthCredentials =
- // // await storage.read(key: BoxName.basicAuthCredentials);
- // var url = Uri.parse(
- // link,
- // );
- // var response = await http.post(
- // url,
- // body: payload,
- // headers: {
- // "Content-Type": "application/x-www-form-urlencoded",
- // 'Authorization':
- // 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
- // },
- // );
- // var jsonData = jsonDecode(response.body);
- // if (response.statusCode == 200) {
- // if (jsonData['status'] == 'success') {
- // return response.body;
- // } else {
- // return (jsonData['status']);
- // }
- // } else {
- // return response.statusCode;
- // }
- // }
-
Future postPayMob({
required String link,
Map? payload,
}) async {
- // String? basicAuthCredentials =
- // await storage.read(key: BoxName.basicAuthCredentials);
- var url = Uri.parse(
- link,
- );
+ var url = Uri.parse(link);
var response = await http.post(url,
body: payload, headers: {'Content-Type': 'application/json'});
var jsonData = jsonDecode(response.body);
if (response.statusCode == 200) {
- if (jsonData['status'] == 'success') {
- return response.body;
- } else {
- return (jsonData['status']);
- }
+ if (jsonData['status'] == 'success') return response.body;
+ return jsonData['status'];
} else {
return response.statusCode;
}
}
- sendEmail(
- String link,
- Map? payload,
- ) async {
+ sendEmail(String link, Map? payload) async {
var headers = {
- "Content-Type": "application/x-www-form-urlencoded",
+ 'Content-Type': 'application/x-www-form-urlencoded',
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
};
var request = http.Request('POST', Uri.parse(link));
request.bodyFields = payload!;
request.headers.addAll(headers);
-
http.StreamedResponse response = await request.send();
- if (response.statusCode == 200) {
- } else {}
}
Future postFromDialogue({
required String link,
Map? payload,
}) async {
- // String? basicAuthCredentials =
- // await storage.read(key: BoxName.basicAuthCredentials);
- var url = Uri.parse(
- link,
- );
+ var url = Uri.parse(link);
var response = await http.post(
url,
body: payload,
headers: {
- "Content-Type": "application/x-www-form-urlencoded",
+ 'Content-Type': 'application/x-www-form-urlencoded',
'Authorization':
'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
},
@@ -682,15 +581,10 @@ class CRUD {
if (response.statusCode == 200) {
if (jsonData['status'] == 'success') {
Get.back();
- // Get.snackbar(
- // jsonData['status'],
- // jsonData['message'],
- // );
-
return response.body;
}
}
- return (jsonData['status']);
+ return jsonData['status'];
}
}
@@ -702,7 +596,6 @@ class CRUD {
final Uri verificationUri = Uri.parse(
'https://verify.twilio.com/v2/Services/$verifySid/Verifications');
- // Send the verification request
final response = await http.post(
verificationUri,
headers: {
@@ -710,19 +603,11 @@ class CRUD {
'Basic ' + base64Encode(utf8.encode('$accountSid:$authToken')),
'Content-Type': 'application/x-www-form-urlencoded',
},
- body: {
- 'To': phoneNumber,
- 'Channel': 'sms',
- },
+ body: {'To': phoneNumber, 'Channel': 'sms'},
);
- if (response.statusCode == 201) {
- } else {}
+ final otpCode = "123456";
- // Prompt the user to enter the OTP
- final otpCode = "123456"; // Replace with user input
-
- // Check the verification code
final checkUri = Uri.parse(
'https://verify.twilio.com/v2/Services/$verifySid/VerificationCheck');
@@ -733,79 +618,39 @@ class CRUD {
'Basic ' + base64Encode(utf8.encode('$accountSid:$authToken')),
'Content-Type': 'application/x-www-form-urlencoded',
},
- body: {
- 'To': phoneNumber,
- 'Code': otpCode,
- },
+ body: {'To': phoneNumber, 'Code': otpCode},
);
-
- if (checkResponse.statusCode == 201) {
- } else {}
}
Future getGoogleApi({
required String link,
Map? payload,
}) async {
- var url = Uri.parse(
- link,
- );
- var response = await http.post(
- url,
- body: payload,
- );
+ var url = Uri.parse(link);
+ var response = await http.post(url, body: payload);
var jsonData = jsonDecode(response.body);
- if (jsonData['status'] == 'OK') {
- return jsonData;
- }
- return (jsonData['status']);
+ if (jsonData['status'] == 'OK') return jsonData;
+ return jsonData['status'];
}
- Future getHereMap({
- required String link,
- }) async {
+ Future getHereMap({required String link}) async {
var url = Uri.parse(link);
try {
var response = await http.get(url);
-
if (response.statusCode == 200) {
- // Ensure the response body is decoded as UTF-8
var decodedBody = utf8.decode(response.bodyBytes);
- var data = jsonDecode(decodedBody);
- return data;
- } else {
- return null;
+ return jsonDecode(decodedBody);
}
+ return null;
} catch (e) {
return null;
}
}
- // Future update({
- // required String endpoint,
- // required Map data,
- // required String id,
- // }) async {
- // // String? basicAuthCredentials =
- // // await storage.read(key: BoxName.basicAuthCredentials);
- // var url = Uri.parse('$endpoint/$id');
- // var response = await http.put(
- // url,
- // body: json.encode(data),
- // headers: {
- // 'Authorization':
- // 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}',
- // },
- // );
- // return json.decode(response.body);
- // }
-
Future delete({
required String endpoint,
required String id,
}) async {
- // String? basicAuthCredentials =
- // await storage.read(key: BoxName.basicAuthCredentials);
var url = Uri.parse('$endpoint/$id');
var response = await http.delete(
url,
@@ -816,7 +661,4 @@ class CRUD {
);
return json.decode(response.body);
}
-
- // ... [Other methods like sendWhatsAppAuth, getAgoraToken, getLlama, etc., would remain here as they are] ...
- // For brevity, I am omitting the rest of the third-party API methods as they would not change.
}
diff --git a/lib/controller/functions/package_info.dart b/lib/controller/functions/package_info.dart
index 05c3ce8..ee00f41 100644
--- a/lib/controller/functions/package_info.dart
+++ b/lib/controller/functions/package_info.dart
@@ -338,16 +338,19 @@ class DeviceHelper {
: deviceData['identifierForVendor'] ?? 'unknown';
final String deviceModel = deviceData['model'] ?? 'unknown';
- final String osVersion = Platform.isAndroid
- ? deviceData['version']['release'] ?? 'unknown'
- : deviceData['systemVersion'] ?? 'unknown';
+ // final String osVersion = Platform.isAndroid
+ // ? deviceData['version']['release'] ?? 'unknown'
+ // : deviceData['systemVersion'] ?? 'unknown';
// Log the extracted information
// Generate and return the encrypted fingerprint
- final String fingerprint = '${deviceId}_${deviceModel}_$osVersion';
+ final String fingerprint = '${deviceId}_$deviceModel';
+ final String encryptedFp =
+ EncryptionHelper.instance.encryptData(fingerprint);
+ box.write(BoxName.deviceFpEncrypted, encryptedFp);
// print(EncryptionHelper.instance.encryptData(fingerprint));
- return EncryptionHelper.instance.encryptData(fingerprint);
+ return encryptedFp;
} catch (e) {
throw Exception('Failed to generate device fingerprint');
}
diff --git a/lib/print.dart b/lib/print.dart
index 63efb2d..a3d59f6 100644
--- a/lib/print.dart
+++ b/lib/print.dart
@@ -4,7 +4,7 @@ class Log {
Log._();
static void print(String value, {StackTrace? stackTrace}) {
- // developer.log(value, name: 'LOG', stackTrace: stackTrace);
+ developer.log(value, name: 'LOG', stackTrace: stackTrace);
}
static Object? inspect(Object? object) {