Update: 2026-06-29 00:07:33

This commit is contained in:
Hamza-Ayed
2026-06-29 00:07:33 +03:00
parent 24da2bc7ca
commit d695a4e812
15 changed files with 190 additions and 60 deletions

View File

@@ -72,7 +72,7 @@ $result['path'] = $simplePath;
// --------- بناء الرابط العام --------- // --------- بناء الرابط العام ---------
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http'; $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$host = getenv('APP_DOMAIN') ?: ($_SERVER['HTTP_HOST'] ?? 'api.siromove.com'); $host = $_SERVER['HTTP_HOST'] ?? (getenv('APP_DOMAIN') ?: 'api.siromove.com');
$basePath = rtrim(dirname(dirname(dirname($_SERVER['SCRIPT_NAME']))), '/'); $basePath = rtrim(dirname(dirname(dirname($_SERVER['SCRIPT_NAME']))), '/');
$url = "$protocol://$host{$basePath}/auth/uploads/{$country}/{$result['filename']}"; $url = "$protocol://$host{$basePath}/auth/uploads/{$country}/{$result['filename']}";

View File

@@ -5,6 +5,21 @@
// ============================================================ // ============================================================
require_once __DIR__ . '/core/bootstrap.php'; require_once __DIR__ . '/core/bootstrap.php';
// --------- تحقق من تطابق المنطقة (Region Mismatch Guard) ---------
$requestHost = $_SERVER['HTTP_HOST'] ?? '';
$appDomain = getenv('APP_DOMAIN') ?: '';
if (!empty($appDomain) && !empty($requestHost) && strtolower($requestHost) !== strtolower($appDomain)) {
if ($requestHost !== 'localhost' && !preg_match('/^127\.0\.0\./', $requestHost)) {
http_response_code(400);
exit(json_encode([
'status' => 'failure',
'error_code' => 'REGION_MISMATCH',
'message' => "Region mismatch: Request host '$requestHost' does not match server domain '$appDomain'."
]));
}
}
require_once __DIR__ . '/functions.php'; require_once __DIR__ . '/functions.php';
// 1. Rate Limiting and JWT Authentication // 1. Rate Limiting and JWT Authentication

View File

@@ -1,10 +0,0 @@
<?php
require_once __DIR__ . '/core/bootstrap.php';
try {
$db = Database::get('main');
$stmt = $db->prepare("UPDATE drivers SET status = 'pending_review' WHERE driverID = 'TEST202606252141546122'");
$stmt->execute();
echo "Driver status updated to pending_review successfully!";
} catch (Exception $e) {
echo "Error: " . $e->getMessage();
}

View File

@@ -460,14 +460,17 @@ class AppLink {
static String addNotesPassenger = "$serviceApp/addNotesPassenger.php"; static String addNotesPassenger = "$serviceApp/addNotesPassenger.php";
static String getPackages = "$serviceApp/getPackages.php"; static String getPackages = "$serviceApp/getPackages.php";
static String updatePackages = "$serviceApp/updatePackages.php"; static String updatePackages = "$serviceApp/updatePackages.php";
//////
static String sendSms = "https://sms.kazumi.me/api/sms/send-sms";
static String senddlr = "https://sms.kazumi.me/api/sms/send-dlr";
static String sendvalidity = "https://sms.kazumi.me/api/sms/send-validity";
static String sendmany = "https://sms.kazumi.me/api/sms/send-many";
static String checkCredit = "https://sms.kazumi.me/api/sms/check-credit";
static String getSender = "$server/auth/sms/getSender.php";
static String checkStatus = "https://sms.kazumi.me/api/sms/check-status";
static String updatePhoneInvalidSMSPassenger = static String updatePhoneInvalidSMSPassenger =
"$server/auth/sms/updatePhoneInvalidSMSPassenger.php"; "$server/auth/sms/updatePhoneInvalidSMSPassenger.php";
static String detectCountryFromPhone(String phone) {
final clean = phone.replaceAll(RegExp(r'[^0-9]'), '');
if (clean.startsWith('962')) return 'Jordan';
if (clean.startsWith('963')) return 'Syria';
if (clean.startsWith('20')) return 'Egypt';
if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan';
if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria';
if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt';
return '';
}
} }

View File

@@ -86,21 +86,21 @@ class DashboardController extends GetxController {
update(); update();
} }
sendSMSMethod() async { // sendSMSMethod() async {
if (formKey.currentState!.validate()) { // if (formKey.currentState!.validate()) {
for (var phoneNumber in box.read(BoxName.tokensDrivers)['message']) { // for (var phoneNumber in box.read(BoxName.tokensDrivers)['message']) {
// for (var i = 0; i < 2; i++) { // // for (var i = 0; i < 2; i++) {
await CRUD().sendSmsEgypt( // await CRUD().sendSmsEgypt(
phoneNumber['phone'].toString(), // phoneNumber['phone'].toString(),
// box.read(BoxName.tokensDrivers)['message'][i]['phone'].toString(), // // box.read(BoxName.tokensDrivers)['message'][i]['phone'].toString(),
smsText.text, // smsText.text,
); // );
// print('CRUD().phoneDriversTest.: ${phoneNumber['phone']}'); // // print('CRUD().phoneDriversTest.: ${phoneNumber['phone']}');
Future.delayed(const Duration(microseconds: 20)); // Future.delayed(const Duration(microseconds: 20));
} // }
Get.back(); // Get.back();
} // }
} // }
@override @override
void onInit() async { void onInit() async {

View File

@@ -26,7 +26,10 @@ class OtpHelper extends GetxController {
/// إرسال OTP /// إرسال OTP
static Future<bool> sendOtp(String phoneNumber) async { static Future<bool> sendOtp(String phoneNumber) async {
try { try {
// await CRUD().getJWT(); final detectedCountry = AppLink.detectCountryFromPhone(phoneNumber);
if (detectedCountry.isNotEmpty) {
await box.write(BoxName.countryCode, detectedCountry);
}
final response = await CRUD().post( final response = await CRUD().post(
link: _sendOtpUrl, link: _sendOtpUrl,
payload: {'receiver': phoneNumber, 'user_type': 'admin'}, payload: {'receiver': phoneNumber, 'user_type': 'admin'},

View File

@@ -48,7 +48,8 @@ class CRUD {
final jwt = decodedResponse1['jwt']; final jwt = decodedResponse1['jwt'];
Log.print('jwt: $jwt'); Log.print('jwt: $jwt');
await box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs)); await box.write(BoxName.jwt, X.c(X.c(X.c(jwt, cn), cC), cs));
await storage.write(key: BoxName.jwt, value: X.c(X.c(X.c(jwt, cn), cC), cs)); await storage.write(
key: BoxName.jwt, value: X.c(X.c(X.c(jwt, cn), cC), cs));
// await AppInitializer().getKey(); // await AppInitializer().getKey();
} }
} }
@@ -448,8 +449,7 @@ class CRUD {
return response.statusCode; return response.statusCode;
} }
Future allMethodForAI(String prompt, driverID, imagePath) async { Future allMethodForAI(String prompt, driverID, imagePath) async {}
}
Map<String, List<Map<String, String>>> getAllTextValuesWithLineNumbers( Map<String, List<Map<String, String>>> getAllTextValuesWithLineNumbers(
Map json) { Map json) {
@@ -569,7 +569,6 @@ class CRUD {
return response.statusCode; return response.statusCode;
} }
Future<dynamic> kazumiSMS({ Future<dynamic> kazumiSMS({
required String link, required String link,
Map<String, dynamic>? payload, Map<String, dynamic>? payload,
@@ -594,25 +593,6 @@ class CRUD {
} else {} } else {}
} }
Future<dynamic> sendSmsEgypt(String phone, otp) async {
// String sender = await getSender();
var headers = {'Content-Type': 'application/json'};
var body = jsonEncode({
"username": "Sefer",
"password": "E)Pu=an/@Z",
"message": otp,
"language": "e",
"sender": "Sefer Egy",
"receiver": phone
});
await _client.post(
Uri.parse(AppLink.sendSms),
body: body,
headers: headers,
);
}
Future<dynamic> postPayMob({ Future<dynamic> postPayMob({
required String link, required String link,
Map<String, dynamic>? payload, Map<String, dynamic>? payload,

View File

@@ -622,4 +622,15 @@ class AppLink {
"$serviceApp/getComplaintAllData.php"; "$serviceApp/getComplaintAllData.php";
static String get getComplaintAllDataForDriver => static String get getComplaintAllDataForDriver =>
"$serviceApp/getComplaintAllDataForDriver.php"; "$serviceApp/getComplaintAllDataForDriver.php";
static String detectCountryFromPhone(String phone) {
final clean = phone.replaceAll(RegExp(r'[^0-9]'), '');
if (clean.startsWith('962')) return 'Jordan';
if (clean.startsWith('963')) return 'Syria';
if (clean.startsWith('20')) return 'Egypt';
if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan';
if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria';
if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt';
return '';
}
} }

View File

@@ -24,6 +24,10 @@ class PhoneAuthHelper {
/// Sends an OTP to the provided phone number. /// Sends an OTP to the provided phone number.
static Future<bool> sendOtp(String phoneNumber) async { static Future<bool> sendOtp(String phoneNumber) async {
try { try {
final detectedCountry = AppLink.detectCountryFromPhone(phoneNumber);
if (detectedCountry.isNotEmpty) {
await box.write(BoxName.countryCode, detectedCountry);
}
final fixedPhone = CountryLogic.formatCurrentCountryPhone(phoneNumber); final fixedPhone = CountryLogic.formatCurrentCountryPhone(phoneNumber);
Log.print('fixedPhone: $fixedPhone'); Log.print('fixedPhone: $fixedPhone');

View File

@@ -526,4 +526,15 @@ class AppLink {
static String get checkStatus => "https://sms.kazumi.me/api/sms/check-status"; static String get checkStatus => "https://sms.kazumi.me/api/sms/check-status";
static String get updatePhoneInvalidSMSPassenger => static String get updatePhoneInvalidSMSPassenger =>
"$server/auth/sms/updatePhoneInvalidSMSPassenger.php"; "$server/auth/sms/updatePhoneInvalidSMSPassenger.php";
static String detectCountryFromPhone(String phone) {
final clean = phone.replaceAll(RegExp(r'[^0-9]'), '');
if (clean.startsWith('962')) return 'Jordan';
if (clean.startsWith('963')) return 'Syria';
if (clean.startsWith('20')) return 'Egypt';
if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan';
if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria';
if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt';
return '';
}
} }

View File

@@ -23,6 +23,10 @@ class PhoneAuthHelper {
/// Sends an OTP to the provided phone number. /// Sends an OTP to the provided phone number.
static Future<bool> sendOtp(String phoneNumber) async { static Future<bool> sendOtp(String phoneNumber) async {
try { try {
final detectedCountry = AppLink.detectCountryFromPhone(phoneNumber);
if (detectedCountry.isNotEmpty) {
await box.write(BoxName.countryCode, detectedCountry);
}
// إصلاح الرقم قبل الإرسال // إصلاح الرقم قبل الإرسال
final fixedPhone = CountryLogic.formatCurrentCountryPhone(phoneNumber); final fixedPhone = CountryLogic.formatCurrentCountryPhone(phoneNumber);

View File

@@ -188,4 +188,15 @@ class AppLink {
static String addCartoDriver = "$serviceApp/addCartoDriver.php"; static String addCartoDriver = "$serviceApp/addCartoDriver.php";
static String getRegisrationCar = "$ride/RegisrationCar/get.php"; static String getRegisrationCar = "$ride/RegisrationCar/get.php";
static String updateRegisrationCar = "$ride/RegisrationCar/update.php"; static String updateRegisrationCar = "$ride/RegisrationCar/update.php";
static String detectCountryFromPhone(String phone) {
final clean = phone.replaceAll(RegExp(r'[^0-9]'), '');
if (clean.startsWith('962')) return 'Jordan';
if (clean.startsWith('963')) return 'Syria';
if (clean.startsWith('20')) return 'Egypt';
if (clean.startsWith('07') || clean.startsWith('7')) return 'Jordan';
if (clean.startsWith('09') || clean.startsWith('9')) return 'Syria';
if (clean.startsWith('01') || clean.startsWith('1')) return 'Egypt';
return '';
}
} }

View File

@@ -22,6 +22,12 @@ class LoginController extends GetxController {
final FlutterSecureStorage storage = const FlutterSecureStorage(); final FlutterSecureStorage storage = const FlutterSecureStorage();
void login() async { void login() async {
final emailStr = email.text.trim();
final detectedCountry = AppLink.detectCountryFromPhone(emailStr);
if (detectedCountry.isNotEmpty) {
await box.write(BoxName.countryCode, detectedCountry);
}
// Ensure fingerprint is ready // Ensure fingerprint is ready
String fingerprint = box.read(BoxName.fingerPrint) ?? ''; String fingerprint = box.read(BoxName.fingerPrint) ?? '';
if (fingerprint.isEmpty) { if (fingerprint.isEmpty) {

View File

@@ -50,7 +50,8 @@ class MainController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
// refreshDashboardStats(); // Removed to save data consumption at start final country = box.read('countryCode')?.toString() ?? 'Jordan';
Log.print('🌍 [SIRO-SERVICE-STARTUP] Current countryCode stored in box: $country');
} }
Future<void> refreshDashboardStats() async { Future<void> refreshDashboardStats() async {

View File

@@ -123,6 +123,42 @@ class ReviewDriverController extends GetxController {
}; };
List<List<dynamic>> getFieldsForTab(String tabKey) { List<List<dynamic>> getFieldsForTab(String tabKey) {
final countryCode = country;
if (countryCode == 'Syria') {
if (tabKey == 'driver_license_front') {
return [
['licenseTypeController', 'License Type', false, false, false, false],
[
'licenseIssueDateController',
'License Issue Date',
true,
false,
false,
false
],
[
'expiryDateController',
'License Expiry Date',
true,
false,
false,
false
],
];
}
if (tabKey == 'driver_license_back') {
return [
[
'licenseCategoriesController',
'License Categories',
false,
false,
false,
false
],
];
}
}
return fieldConfig[tabKey] ?? []; return fieldConfig[tabKey] ?? [];
} }
@@ -161,6 +197,10 @@ class ReviewDriverController extends GetxController {
driverId.value = args['driverId'] ?? ''; driverId.value = args['driverId'] ?? '';
phone.value = args['phone'] ?? ''; phone.value = args['phone'] ?? '';
} }
if (country == 'Jordan' || country == 'Egypt') {
docUrls.remove('driver_license_back');
}
_initializeDocUrls();
fetchData(); fetchData();
} }
@@ -210,13 +250,64 @@ class ReviewDriverController extends GetxController {
} }
} }
String reconstructDocumentUrl(String originalLink, String docType) {
if (originalLink.isEmpty) {
return "${AppLink.server}/auth/syria/driversDocs/syria.intaleq.xyz-${driverId.value}-$docType.jpg";
}
try {
final origUri = Uri.parse(originalLink);
final query = origUri.query;
final path = origUri.path;
if (path.contains('secure_image.php')) {
return "${AppLink.server}/secure_image.php?$query";
}
if (path.contains('auth/syria/driversDocs/')) {
final parts = path.split('auth/syria/driversDocs/');
final filename = parts.last;
return "${AppLink.server}/auth/syria/driversDocs/$filename";
}
if (originalLink.startsWith('http://') ||
originalLink.startsWith('https://')) {
final serverUri = Uri.parse(AppLink.server);
final host = serverUri.host;
final newUri = Uri(
scheme: 'https',
host: host,
path: path,
query: query.isNotEmpty ? query : null,
);
return newUri.toString();
}
final cleanPath = path.startsWith('/') ? path : '/$path';
return "${AppLink.server}$cleanPath${query.isNotEmpty ? '?$query' : ''}";
} catch (e) {
if (originalLink.startsWith('http://')) {
return originalLink.replaceFirst('http://', 'https://');
}
return originalLink;
}
}
void _initializeDocUrls() {
for (var key in docUrls.keys) {
docUrls[key]!.value = reconstructDocumentUrl('', key);
}
}
void _populateDocUrls(dynamic docs) { void _populateDocUrls(dynamic docs) {
if (docs is List) { if (docs is List) {
for (var doc in docs) { for (var doc in docs) {
if (doc is Map && doc['doc_type'] != null && doc['link'] != null) { if (doc is Map && doc['doc_type'] != null && doc['link'] != null) {
String type = doc['doc_type'].toString(); String type = doc['doc_type'].toString();
if (docUrls.containsKey(type)) { if (docUrls.containsKey(type)) {
docUrls[type]!.value = doc['link'].toString(); docUrls[type]!.value =
reconstructDocumentUrl(doc['link'].toString(), type);
} }
} }
} }