Initial push to my private server

This commit is contained in:
Hamza-Ayed
2025-09-21 15:02:12 +03:00
parent 7e904ae460
commit f08ee61a7e
32 changed files with 1622 additions and 373 deletions

View File

@@ -7,12 +7,14 @@ import 'package:sefer_driver/constant/colors.dart';
import 'package:sefer_driver/constant/style.dart';
import 'package:sefer_driver/controller/home/payment/captain_wallet_controller.dart';
import 'package:sefer_driver/controller/payment/payment_controller.dart';
import 'package:sefer_driver/controller/payment/smsPaymnet/payment_services.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../../constant/box_name.dart';
import '../../../constant/links.dart';
import '../../../controller/functions/crud.dart';
import '../../../main.dart';
import '../../../print.dart';
import '../../widgets/elevated_btn.dart';
import '../../widgets/my_textField.dart';
import 'ecash.dart';
@@ -40,21 +42,29 @@ class PointsCaptain extends StatelessWidget {
title: 'Which method you will pay'.tr,
titleStyle: AppStyle.title,
content: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'${'you can buy '.tr}$countPoint ${'L.S'.tr}${'by '.tr}${'$pricePoint'.tr}',
style: AppStyle.title,
),
MyElevatedButton(
title: 'Pay with Credit Card'.tr,
onPressed: () async {
Get.back();
payWithEcashDriver(context, pricePoint.toString());
// var d = jsonDecode(res);
}, //51524
),
// Add some spacing between buttons
GestureDetector(
onTap: () async {
Get.back();
payWithEcashDriver(context, pricePoint.toString());
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Pay with Debit Card'.tr),
const SizedBox(width: 10),
Icon(Icons.credit_card_sharp,
color: AppColor.blueColor, size: 70),
],
)),
GestureDetector(
onTap: () async {
Get.back();
@@ -84,44 +94,122 @@ class PointsCaptain extends StatelessWidget {
}
}));
},
child: Image.asset(
'assets/images/mtn.png',
width: 70,
height: 70,
fit: BoxFit.fill,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Pay by MTN Wallet'.tr),
const SizedBox(width: 10),
Image.asset(
'assets/images/cashMTN.png',
width: 70,
height: 70,
fit: BoxFit.fill,
),
],
)),
GestureDetector(
onTap: () async {
Get.back();
Get.defaultDialog(
barrierDismissible: false,
title: 'Insert Wallet phone number'.tr,
content: Form(
key: paymentController.formKey,
child: MyTextForm(
controller:
paymentController.walletphoneController,
label: 'Insert Wallet phone number'.tr,
hint: '963991234567',
type: TextInputType.phone)),
confirm: MyElevatedButton(
title: 'OK'.tr,
onPressed: () async {
Get.back();
if (paymentController.formKey.currentState!
.validate()) {
box.write(
BoxName.phoneWallet,
paymentController
.walletphoneController.text);
await payWithSyriaTelWallet(
context, pricePoint.toString(), 'SYP');
}
}));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Pay by Syriatel Wallet'.tr),
const SizedBox(width: 10),
Image.asset(
'assets/images/syriatel.jpeg',
width: 70,
height: 70,
fit: BoxFit.fill,
),
],
)),
GestureDetector(
onTap: () async {
Get.back();
Get.defaultDialog(
barrierDismissible: false,
title: 'Insert Wallet phone number'.tr,
content: Form(
key: paymentController.formKey,
child: MyTextForm(
controller:
paymentController.walletphoneController,
label: 'Insert Wallet phone number'.tr,
hint: '963941234567',
type: TextInputType.phone)),
confirm: MyElevatedButton(
title: 'OK'.tr,
onPressed: () async {
Get.back();
if (paymentController.formKey.currentState!
.validate()) {
box.write(
BoxName.phoneWallet,
paymentController
.walletphoneController.text);
// await payWithSyriaTelWallet(
// context, pricePoint.toString(), 'SYP');
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;
}
}
Get.to(() => PaymentScreenSmsProvider(
amount: pricePoint));
}
}));
},
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('Pay by Sham Cash'.tr),
const SizedBox(width: 10),
Image.asset(
'assets/images/shamCash.png',
width: 70,
height: 70,
fit: BoxFit.fill,
),
],
)),
// MyElevatedButton(
// kolor: AppColor.redColor,
// title: 'Pay with Wallet'.tr,
// onPressed: () async {
// Get.back();
// Get.defaultDialog(
// barrierDismissible: false,
// title: 'Insert Wallet phone number'.tr,
// content: Form(
// key: paymentController.formKey,
// child: MyTextForm(
// controller:
// paymentController.walletphoneController,
// label: 'Insert Wallet phone number'.tr,
// hint: '963941234567',
// type: TextInputType.phone)),
// confirm: MyElevatedButton(
// title: 'OK'.tr,
// onPressed: () async {
// Get.back();
// if (paymentController.formKey.currentState!
// .validate()) {
// box.write(
// BoxName.phoneWallet,
// paymentController
// .walletphoneController.text);
// await payWithMTNWallet(
// context, pricePoint.toString(), 'SYP');
// }
// }));
// },
// ),
],
));
},
@@ -485,7 +573,7 @@ Future<void> payWithMTNWallet(
barrierDismissible: false);
try {
String phone = box.read(BoxName.phoneWallet) ?? '963992952235';
String phone = box.read(BoxName.phoneWallet);
String driverID = box.read(BoxName.driverID).toString();
String formattedAmount = double.parse(amount).toStringAsFixed(0);
@@ -507,12 +595,13 @@ Future<void> payWithMTNWallet(
}
// 1⃣ استدعاء mtn_start_payment.php (الملف الجديد)
var responseData = await CRUD().postWallet(
var responseData = await CRUD().postWalletMtn(
link: AppLink.payWithMTNStart,
payload: {
"amount": formattedAmount,
"passengerId": driverID,
"phone": phone,
"lang": box.read(BoxName.lang) ?? 'ar',
},
);
@@ -540,7 +629,7 @@ Future<void> payWithMTNWallet(
}
if (startRes['status'] != 'success') {
String errorMsg = startRes['message']?.toString() ??
final errorMsg = startRes['message']['Error']?.toString().tr ??
"فشل بدء عملية الدفع. حاول مرة أخرى.";
throw Exception(errorMsg);
}
@@ -555,7 +644,7 @@ Future<void> payWithMTNWallet(
print(
"📄 invoiceNumber: $invoiceNumber, 🔢 operationNumber: $operationNumber, 🧭 guid: $guid");
if (Get.isDialogOpen ?? false)
if (Get.isDialogOpen == true)
Get.back(); // إغلاق مؤشر التحميل قبل عرض حوار OTP
// 2⃣ عرض واجهة إدخال OTP
@@ -609,7 +698,8 @@ Future<void> payWithMTNWallet(
if (Get.isDialogOpen ?? false) Get.back();
print("✅ استجابة mtn_confirm.php:");
print(confirmRes);
// print(confirmRes);
Log.print('confirmRes: ${confirmRes}');
if (confirmRes != null && confirmRes['status'] == 'success') {
Get.defaultDialog(
@@ -635,3 +725,158 @@ Future<void> payWithMTNWallet(
);
}
}
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):");
Log.print('responseData: ${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,
),
actions: [
TextButton(
child: const Text("تأكيد"),
onPressed: () => Navigator.of(context).pop(input),
),
TextButton(
child: const Text("إلغاء"),
onPressed: () => Navigator.of(context).pop(),
),
],
);
},
);
if (otp == null || otp.isEmpty) {
print("❌ OTP was not entered.");
return;
}
print("🔐 OTP entered: $otp");
Get.dialog(const Center(child: CircularProgressIndicator()),
barrierDismissible: false);
// --- CHANGE 4: Updated API link and payload for confirming payment ---
// Make sure you have defined `payWithSyriatelConfirm` in your AppLink class
var confirmRes = await CRUD().postWalletMtn(
// Changed from postWalletMtn if they are different
link: AppLink.payWithSyriatelConfirm, // Use the new Syriatel confirm link
payload: {
"transactionID": transactionID, // Use the transaction ID
"otp": otp,
// The other parameters (phone, guid, etc.) are no longer needed
},
);
if (Get.isDialogOpen ?? false) Get.back();
print("✅ Response from confirm_payment.php:");
Log.print('confirmRes: ${confirmRes}');
if (confirmRes != null && 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() ?? "فشل في تأكيد الدفع";
Get.defaultDialog(
title: "❌ فشل",
content: Text(errorMsg.tr),
);
}
} 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();
Get.defaultDialog(
title: 'حدث خطأ',
content: Text(e.toString().replaceFirst("Exception: ", "")),
);
}
}