25-10-9/1
This commit is contained in:
@@ -673,312 +673,305 @@ class PaymentController extends GetxController {
|
||||
|
||||
/// شاشة جديدة ومبسطة خاصة بدفع السائقين عبر ecash
|
||||
|
||||
Future<void> payWithMTNWallet(
|
||||
BuildContext context, String amount, String currency) async {
|
||||
// خزن سياق علوي آمن من البداية
|
||||
final BuildContext safeContext =
|
||||
Get.overlayContext ?? Get.context ?? context;
|
||||
// Future<void> payWithMTNWallet(
|
||||
// BuildContext context, String amount, String currency) async {
|
||||
// // خزن سياق علوي آمن من البداية
|
||||
// final BuildContext safeContext =
|
||||
// Get.overlayContext ?? Get.context ?? context;
|
||||
|
||||
// سبينر تحميل
|
||||
if (!(Get.isDialogOpen ?? false)) {
|
||||
Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
barrierDismissible: false);
|
||||
// // سبينر تحميل
|
||||
// if (!(Get.isDialogOpen ?? false)) {
|
||||
// Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
// barrierDismissible: false);
|
||||
// }
|
||||
|
||||
// try {
|
||||
// final phone = box.read(BoxName.phoneWallet) as String;
|
||||
// final passengerID = box.read(BoxName.passengerID).toString();
|
||||
// final formattedAmount = double.parse(amount).toStringAsFixed(0);
|
||||
|
||||
// print("🚀 بدء عملية دفع MTN");
|
||||
// print(
|
||||
// "📦 Payload: passengerID: $passengerID, amount: $formattedAmount, phone: $phone");
|
||||
|
||||
// // التحقق بالبصمة (اختياري) + حماية من الـ await
|
||||
// final localAuth = LocalAuthentication();
|
||||
// final isAuthSupported = await localAuth.isDeviceSupported();
|
||||
// if (isAuthSupported) {
|
||||
// final didAuth = await localAuth.authenticate(
|
||||
// localizedReason: 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع',
|
||||
// );
|
||||
// if (!didAuth) {
|
||||
// if (Get.isDialogOpen == true) Get.back();
|
||||
// print("❌ المستخدم لم يؤكد بالبصمة/الوجه");
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 1) بدء الدفع
|
||||
// final responseData = await CRUD().postWalletMtn(
|
||||
// link: AppLink.payWithMTNStart,
|
||||
// payload: {
|
||||
// "amount": formattedAmount,
|
||||
// "passengerId": passengerID,
|
||||
// "phone": phone,
|
||||
// "lang": box.read(BoxName.lang) ?? 'ar',
|
||||
// },
|
||||
// );
|
||||
|
||||
// // print("✅ استجابة الخادم (mtn_start_payment.php):");
|
||||
// // print(responseData);
|
||||
// Log.print('responseData: ${responseData}');
|
||||
|
||||
// // فحص الاستجابة بقوة
|
||||
// late final Map<String, dynamic> startRes;
|
||||
// if (responseData is Map<String, dynamic>) {
|
||||
// startRes = responseData;
|
||||
// } else if (responseData is String) {
|
||||
// startRes = json.decode(responseData) as Map<String, dynamic>;
|
||||
// } else {
|
||||
// throw Exception("تم استلام نوع بيانات غير متوقع من الخادم.");
|
||||
// }
|
||||
|
||||
// if (startRes['status'] != 'success') {
|
||||
// final errorMsg = startRes['message']['Error']?.toString().tr ??
|
||||
// "فشل بدء عملية الدفع. حاول مرة أخرى.";
|
||||
// throw Exception(errorMsg);
|
||||
// }
|
||||
|
||||
// final messageData = startRes["message"] as Map<String, dynamic>;
|
||||
// final invoiceNumber = messageData["invoiceNumber"].toString();
|
||||
// final operationNumber = messageData["operationNumber"].toString();
|
||||
// final guid = messageData["guid"].toString();
|
||||
|
||||
// // print(
|
||||
// // "📄 invoiceNumber: $invoiceNumber, 🔢 operationNumber: $operationNumber, 🧭 guid: $guid");
|
||||
|
||||
// // أغلق السبينر قبل إظهار حوار OTP
|
||||
// if (Get.isDialogOpen == true) Get.back();
|
||||
|
||||
// // 2) إدخال OTP بـ Get.defaultDialog (لا يستخدم context قابل للتلف)
|
||||
// String otpInput = "";
|
||||
// await Get.defaultDialog(
|
||||
// title: "أدخل كود التحقق",
|
||||
// barrierDismissible: false,
|
||||
// content: TextField(
|
||||
// keyboardType: TextInputType.number,
|
||||
// decoration: const InputDecoration(hintText: "كود OTP"),
|
||||
// onChanged: (v) => otpInput = v,
|
||||
// ),
|
||||
// confirm: TextButton(
|
||||
// onPressed: () {
|
||||
// if (otpInput.isEmpty ||
|
||||
// otpInput.length < 4 ||
|
||||
// otpInput.length > 8) {
|
||||
// Get.snackbar("تنبيه", "أدخل كود OTP صحيح (4–8 أرقام)");
|
||||
// return;
|
||||
// }
|
||||
// Get.back(result: otpInput);
|
||||
// },
|
||||
// child: const Text("تأكيد"),
|
||||
// ),
|
||||
// cancel: TextButton(
|
||||
// onPressed: () => Get.back(result: null),
|
||||
// child: const Text("إلغاء"),
|
||||
// ),
|
||||
// ).then((res) => otpInput = (res ?? "") as String);
|
||||
|
||||
// if (otpInput.isEmpty) {
|
||||
// print("❌ لم يتم إدخال OTP");
|
||||
// return;
|
||||
// }
|
||||
// print("🔐 تم إدخال OTP: $otpInput");
|
||||
|
||||
// // سبينر أثناء التأكيد
|
||||
// Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
// barrierDismissible: false);
|
||||
|
||||
// // 3) تأكيد الدفع
|
||||
// final confirmRes = await CRUD().postWalletMtn(
|
||||
// link: AppLink.payWithMTNConfirm,
|
||||
// payload: {
|
||||
// "invoiceNumber": invoiceNumber,
|
||||
// "operationNumber": operationNumber,
|
||||
// "guid": guid,
|
||||
// "otp": otpInput,
|
||||
// "phone": phone,
|
||||
// "lang": box.read(BoxName.lang) ?? 'ar',
|
||||
// },
|
||||
// );
|
||||
|
||||
// if (Get.isDialogOpen == true) Get.back();
|
||||
|
||||
// // print("✅ استجابة mtn_confirm.php:");
|
||||
// // Log.print('confirmRes: ${confirmRes}');
|
||||
|
||||
// final ok = (confirmRes is Map && confirmRes['status'] == 'success');
|
||||
// if (ok) {
|
||||
// Get.defaultDialog(
|
||||
// title: "✅ نجاح",
|
||||
// content: const Text("تمت عملية الدفع وإضافة الرصيد إلى محفظتك."),
|
||||
// );
|
||||
// await getPassengerWallet();
|
||||
// } else {
|
||||
// final errorMsg = (confirmRes['message']['message']?.toString()) ??
|
||||
// "فشل في تأكيد الدفع";
|
||||
// Get.defaultDialog(title: "❌ فشل", content: Text(errorMsg.tr));
|
||||
// }
|
||||
// } catch (e, s) {
|
||||
// print("🔥 خطأ أثناء الدفع عبر MTN:");
|
||||
// print(e);
|
||||
// print(s);
|
||||
// if (Get.isDialogOpen == true) Get.back();
|
||||
// Get.defaultDialog(
|
||||
// title: 'حدث خطأ',
|
||||
// content: Text(e.toString().replaceFirst("Exception: ", "")),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
Future<void> payWithSyriaTelWallet(String amount, String currency) async {
|
||||
// helper لفتح لودينغ بأمان
|
||||
Future<void> _showLoading() async {
|
||||
if (!(Get.isDialogOpen ?? false)) {
|
||||
Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
barrierDismissible: false);
|
||||
}
|
||||
}
|
||||
|
||||
// helper لإغلاق أي حوار مفتوح
|
||||
void _closeAnyDialog() {
|
||||
if (Get.isDialogOpen ?? false) {
|
||||
Get.back();
|
||||
}
|
||||
}
|
||||
|
||||
await _showLoading();
|
||||
try {
|
||||
final phone = box.read(BoxName.phoneWallet) as String;
|
||||
final passengerID = box.read(BoxName.passengerID).toString();
|
||||
final passengerId = box.read(BoxName.passengerID).toString();
|
||||
final formattedAmount = double.parse(amount).toStringAsFixed(0);
|
||||
|
||||
print("🚀 بدء عملية دفع MTN");
|
||||
print("🚀 Syriatel payment start");
|
||||
print(
|
||||
"📦 Payload: passengerID: $passengerID, amount: $formattedAmount, phone: $phone");
|
||||
"📦 Payload => passengerId:$passengerId amount:$formattedAmount phone:$phone");
|
||||
|
||||
// التحقق بالبصمة (اختياري) + حماية من الـ await
|
||||
final localAuth = LocalAuthentication();
|
||||
final isAuthSupported = await localAuth.isDeviceSupported();
|
||||
if (isAuthSupported) {
|
||||
final didAuth = await localAuth.authenticate(
|
||||
// مصادقة حيوية (اختياري)
|
||||
final auth = LocalAuthentication();
|
||||
if (await auth.isDeviceSupported()) {
|
||||
final ok = await auth.authenticate(
|
||||
localizedReason: 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع',
|
||||
);
|
||||
if (!didAuth) {
|
||||
if (Get.isDialogOpen == true) Get.back();
|
||||
print("❌ المستخدم لم يؤكد بالبصمة/الوجه");
|
||||
if (!ok) {
|
||||
_closeAnyDialog();
|
||||
print("❌ User did not authenticate");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 1) بدء الدفع
|
||||
final responseData = await CRUD().postWalletMtn(
|
||||
link: AppLink.payWithMTNStart,
|
||||
// 1) بدء عملية الدفع
|
||||
final startRaw = await CRUD().postWalletMtn(
|
||||
link: AppLink.payWithSyriatelStart,
|
||||
payload: {
|
||||
"amount": formattedAmount,
|
||||
"passengerId": passengerID,
|
||||
"passengerId": passengerId,
|
||||
"phone": phone,
|
||||
"lang": box.read(BoxName.lang) ?? 'ar',
|
||||
},
|
||||
);
|
||||
|
||||
// print("✅ استجابة الخادم (mtn_start_payment.php):");
|
||||
// print(responseData);
|
||||
Log.print('responseData: ${responseData}');
|
||||
print("✅ Server response (start): $startRaw");
|
||||
|
||||
// فحص الاستجابة بقوة
|
||||
// تحويل الاستجابة إلى Map
|
||||
late final Map<String, dynamic> startRes;
|
||||
if (responseData is Map<String, dynamic>) {
|
||||
startRes = responseData;
|
||||
} else if (responseData is String) {
|
||||
startRes = json.decode(responseData) as Map<String, dynamic>;
|
||||
if (startRaw is Map<String, dynamic>) {
|
||||
startRes = startRaw;
|
||||
} else if (startRaw is String) {
|
||||
startRes = json.decode(startRaw) as Map<String, dynamic>;
|
||||
} else {
|
||||
throw Exception("تم استلام نوع بيانات غير متوقع من الخادم.");
|
||||
throw Exception("Unexpected start response type");
|
||||
}
|
||||
|
||||
if (startRes['status'] != 'success') {
|
||||
final errorMsg = startRes['message']['Error']?.toString().tr ??
|
||||
"فشل بدء عملية الدفع. حاول مرة أخرى.";
|
||||
throw Exception(errorMsg);
|
||||
final msg =
|
||||
(startRes['message'] ?? 'Failed to start payment').toString();
|
||||
throw Exception(msg);
|
||||
}
|
||||
|
||||
final messageData = startRes["message"] as Map<String, dynamic>;
|
||||
final invoiceNumber = messageData["invoiceNumber"].toString();
|
||||
final operationNumber = messageData["operationNumber"].toString();
|
||||
final guid = messageData["guid"].toString();
|
||||
final messageData = startRes['message'] as Map<String, dynamic>;
|
||||
final transactionID = messageData['transactionID'].toString();
|
||||
print("📄 transactionID: $transactionID");
|
||||
|
||||
// print(
|
||||
// "📄 invoiceNumber: $invoiceNumber, 🔢 operationNumber: $operationNumber, 🧭 guid: $guid");
|
||||
|
||||
// أغلق السبينر قبل إظهار حوار OTP
|
||||
if (Get.isDialogOpen == true) Get.back();
|
||||
|
||||
// 2) إدخال OTP بـ Get.defaultDialog (لا يستخدم context قابل للتلف)
|
||||
String otpInput = "";
|
||||
await Get.defaultDialog(
|
||||
title: "أدخل كود التحقق",
|
||||
barrierDismissible: false,
|
||||
content: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: "كود OTP"),
|
||||
onChanged: (v) => otpInput = v,
|
||||
),
|
||||
confirm: TextButton(
|
||||
onPressed: () {
|
||||
if (otpInput.isEmpty ||
|
||||
otpInput.length < 4 ||
|
||||
otpInput.length > 8) {
|
||||
Get.snackbar("تنبيه", "أدخل كود OTP صحيح (4–8 أرقام)");
|
||||
return;
|
||||
}
|
||||
Get.back(result: otpInput);
|
||||
},
|
||||
child: const Text("تأكيد"),
|
||||
),
|
||||
cancel: TextButton(
|
||||
onPressed: () => Get.back(result: null),
|
||||
child: const Text("إلغاء"),
|
||||
),
|
||||
).then((res) => otpInput = (res ?? "") as String);
|
||||
|
||||
if (otpInput.isEmpty) {
|
||||
print("❌ لم يتم إدخال OTP");
|
||||
return;
|
||||
}
|
||||
print("🔐 تم إدخال OTP: $otpInput");
|
||||
|
||||
// سبينر أثناء التأكيد
|
||||
Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
barrierDismissible: false);
|
||||
|
||||
// 3) تأكيد الدفع
|
||||
final confirmRes = await CRUD().postWalletMtn(
|
||||
link: AppLink.payWithMTNConfirm,
|
||||
payload: {
|
||||
"invoiceNumber": invoiceNumber,
|
||||
"operationNumber": operationNumber,
|
||||
"guid": guid,
|
||||
"otp": otpInput,
|
||||
"phone": phone,
|
||||
"lang": box.read(BoxName.lang) ?? 'ar',
|
||||
},
|
||||
);
|
||||
|
||||
if (Get.isDialogOpen == true) Get.back();
|
||||
|
||||
// print("✅ استجابة mtn_confirm.php:");
|
||||
// Log.print('confirmRes: ${confirmRes}');
|
||||
|
||||
final ok = (confirmRes is Map && confirmRes['status'] == 'success');
|
||||
if (ok) {
|
||||
Get.defaultDialog(
|
||||
title: "✅ نجاح",
|
||||
content: const Text("تمت عملية الدفع وإضافة الرصيد إلى محفظتك."),
|
||||
);
|
||||
await getPassengerWallet();
|
||||
} else {
|
||||
final errorMsg = (confirmRes['message']['message']?.toString()) ??
|
||||
"فشل في تأكيد الدفع";
|
||||
Get.defaultDialog(title: "❌ فشل", content: Text(errorMsg.tr));
|
||||
}
|
||||
} catch (e, s) {
|
||||
print("🔥 خطأ أثناء الدفع عبر MTN:");
|
||||
print(e);
|
||||
print(s);
|
||||
if (Get.isDialogOpen == true) Get.back();
|
||||
Get.defaultDialog(
|
||||
title: 'حدث خطأ',
|
||||
content: Text(e.toString().replaceFirst("Exception: ", "")),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> payWithSyriaTelWallet(
|
||||
BuildContext context, String amount, String currency) async {
|
||||
// Show a loading indicator for better user experience
|
||||
Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
barrierDismissible: false);
|
||||
|
||||
try {
|
||||
String phone = box.read(BoxName.phoneWallet);
|
||||
String driverID = box.read(BoxName.driverID).toString();
|
||||
String formattedAmount = double.parse(amount).toStringAsFixed(0);
|
||||
|
||||
// --- CHANGE 1: Updated log messages for clarity ---
|
||||
print("🚀 Starting Syriatel payment process");
|
||||
print(
|
||||
"📦 Payload: driverID: $driverID, amount: $formattedAmount, phone: $phone");
|
||||
|
||||
// Optional: Biometric authentication
|
||||
bool isAuthSupported = await LocalAuthentication().isDeviceSupported();
|
||||
if (isAuthSupported) {
|
||||
bool didAuthenticate = await LocalAuthentication().authenticate(
|
||||
localizedReason: 'استخدم بصمة الإصبع أو الوجه لتأكيد الدفع',
|
||||
);
|
||||
if (!didAuthenticate) {
|
||||
if (Get.isDialogOpen ?? false) Get.back();
|
||||
print("❌ User did not authenticate with biometrics");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// --- CHANGE 2: Updated API link and payload for starting payment ---
|
||||
// Make sure you have defined `payWithSyriatelStart` in your AppLink class
|
||||
var responseData = await CRUD().postWalletMtn(
|
||||
link: AppLink.payWithSyriatelStart, // Use the new Syriatel start link
|
||||
payload: {
|
||||
"amount": formattedAmount,
|
||||
"driverId": driverID, // Key changed from 'passengerId' to 'driverId'
|
||||
"phone": phone,
|
||||
"lang": box.read(BoxName.lang) ?? 'ar',
|
||||
},
|
||||
);
|
||||
|
||||
print("✅ Server response (start_payment.php):");
|
||||
print(responseData);
|
||||
|
||||
// Robustly parse the server's JSON response
|
||||
Map<String, dynamic> startRes;
|
||||
if (responseData is Map<String, dynamic>) {
|
||||
startRes = responseData;
|
||||
} else if (responseData is String) {
|
||||
try {
|
||||
startRes = json.decode(responseData);
|
||||
} catch (e) {
|
||||
throw Exception(
|
||||
"Failed to parse server response. Response: $responseData");
|
||||
}
|
||||
} else {
|
||||
throw Exception("Received an unexpected data type from the server.");
|
||||
}
|
||||
|
||||
if (startRes['status'] != 'success') {
|
||||
String errorMsg = startRes['message']?.toString() ??
|
||||
"Failed to start the payment process. Please try again.";
|
||||
throw Exception(errorMsg);
|
||||
}
|
||||
|
||||
// --- CHANGE 3: Extract `transactionID` from the response ---
|
||||
// The response structure is now simpler. We only need the transaction ID.
|
||||
final messageData = startRes["message"];
|
||||
final transactionID = messageData["transactionID"].toString();
|
||||
|
||||
print("📄 TransactionID: $transactionID");
|
||||
|
||||
if (Get.isDialogOpen == true) Get.back(); // Close loading indicator
|
||||
|
||||
// Show the OTP input dialog
|
||||
String? otp = await showDialog<String>(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (context) {
|
||||
String input = "";
|
||||
return AlertDialog(
|
||||
title: const Text("أدخل كود التحقق"),
|
||||
content: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: "كود OTP"),
|
||||
onChanged: (val) => input = val,
|
||||
// 2) اطلب من المستخدم إدخال OTP عبر Get.dialog (بدون context)
|
||||
_closeAnyDialog(); // أغلق اللودينغ أولاً
|
||||
final otpController = TextEditingController();
|
||||
final otp = await Get.dialog<String>(
|
||||
AlertDialog(
|
||||
title: const Text("أدخل كود التحقق"),
|
||||
content: TextField(
|
||||
controller: otpController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(hintText: "كود OTP"),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text("تأكيد"),
|
||||
onPressed: () => Get.back(result: otpController.text.trim()),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text("تأكيد"),
|
||||
onPressed: () => Navigator.of(context).pop(input),
|
||||
),
|
||||
TextButton(
|
||||
child: const Text("إلغاء"),
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
TextButton(
|
||||
child: const Text("إلغاء"),
|
||||
onPressed: () => Get.back(result: null),
|
||||
),
|
||||
],
|
||||
),
|
||||
barrierDismissible: false,
|
||||
);
|
||||
|
||||
if (otp == null || otp.isEmpty) {
|
||||
print("❌ OTP was not entered.");
|
||||
print("❌ OTP not provided");
|
||||
return;
|
||||
}
|
||||
print("🔐 OTP entered: $otp");
|
||||
print("🔐 OTP: $otp");
|
||||
|
||||
Get.dialog(const Center(child: CircularProgressIndicator()),
|
||||
barrierDismissible: false);
|
||||
await _showLoading();
|
||||
|
||||
// --- CHANGE 4: Updated API link and payload for confirming payment ---
|
||||
// Make sure you have defined `payWithSyriatelConfirm` in your AppLink class
|
||||
var confirmRes = await CRUD().postWallet(
|
||||
// Changed from postWalletMtn if they are different
|
||||
link:
|
||||
AppLink.payWithSyriatelConfirm, // Use the new Syriatel confirm link
|
||||
// 3) تأكيد الدفع
|
||||
final confirmRaw = await CRUD().postWallet(
|
||||
link: AppLink.payWithSyriatelConfirm,
|
||||
payload: {
|
||||
"transactionID": transactionID, // Use the transaction ID
|
||||
"transactionID": transactionID,
|
||||
"otp": otp,
|
||||
// The other parameters (phone, guid, etc.) are no longer needed
|
||||
},
|
||||
);
|
||||
|
||||
if (Get.isDialogOpen ?? false) Get.back();
|
||||
_closeAnyDialog(); // أغلق اللودينغ
|
||||
|
||||
print("✅ Response from confirm_payment.php:");
|
||||
Log.print('confirmRes: ${confirmRes}');
|
||||
print("✅ Response (confirm): $confirmRaw");
|
||||
|
||||
if (confirmRes != null && confirmRes['status'] == 'success') {
|
||||
late final Map<String, dynamic> confirmRes;
|
||||
if (confirmRaw is Map<String, dynamic>) {
|
||||
confirmRes = confirmRaw;
|
||||
} else if (confirmRaw is String) {
|
||||
confirmRes = json.decode(confirmRaw) as Map<String, dynamic>;
|
||||
} else {
|
||||
throw Exception("Unexpected confirm response type");
|
||||
}
|
||||
|
||||
if (confirmRes['status'] == 'success') {
|
||||
Get.defaultDialog(
|
||||
title: "✅ نجاح",
|
||||
content: const Text("تمت عملية الدفع وإضافة الرصيد إلى محفظتك."),
|
||||
);
|
||||
} else {
|
||||
// --- CHANGE 5: Simplified error message extraction ---
|
||||
// The new PHP script sends the error directly in the 'message' field.
|
||||
String errorMsg =
|
||||
confirmRes?['message']?.toString() ?? "فشل في تأكيد الدفع";
|
||||
final msg = (confirmRes['message'] ?? 'فشل في تأكيد الدفع').toString();
|
||||
Get.defaultDialog(
|
||||
title: "❌ فشل",
|
||||
content: Text(errorMsg.tr),
|
||||
content: Text(msg),
|
||||
);
|
||||
}
|
||||
} catch (e, s) {
|
||||
// --- CHANGE 6: Updated general error log message ---
|
||||
print("🔥 Error during Syriatel Wallet payment:");
|
||||
print(e);
|
||||
print(s);
|
||||
if (Get.isDialogOpen ?? false) Get.back();
|
||||
print("🔥 Error during Syriatel Wallet payment:\n$e\n$s");
|
||||
_closeAnyDialog();
|
||||
Get.defaultDialog(
|
||||
title: 'حدث خطأ',
|
||||
content: Text(e.toString().replaceFirst("Exception: ", "")),
|
||||
|
||||
Reference in New Issue
Block a user