Update: 2026-06-29 00:07:33
This commit is contained in:
@@ -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']}";
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
|
||||||
@@ -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 '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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'},
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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');
|
||||||
|
|
||||||
|
|||||||
@@ -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 '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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 '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user