From 209f721cd68ffa943d6116377aae966ee5919eb8 Mon Sep 17 00:00:00 2001 From: Hamza-Ayed Date: Thu, 7 May 2026 03:35:04 +0300 Subject: [PATCH] Update: 2026-05-07 03:35:03 --- app/modules_app/payments/bot_webhook.php | 22 +++++++++- .../views/payment_receipt_view.dart | 42 ++++++++++++++++--- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/app/modules_app/payments/bot_webhook.php b/app/modules_app/payments/bot_webhook.php index 65e3e76..67810af 100644 --- a/app/modules_app/payments/bot_webhook.php +++ b/app/modules_app/payments/bot_webhook.php @@ -17,7 +17,7 @@ use App\Core\Validator; $data = Security::sanitize(input()); // Simple Auth for the Bot -$botToken = env('BOT_WEBHOOK_TOKEN', 'musadaq-bot-secret-123'); +$botToken = env('BOT_WEBHOOK_TOKEN'); $providedToken = $_SERVER['HTTP_X_BOT_TOKEN'] ?? $data['token'] ?? ''; if ($providedToken !== $botToken) { @@ -37,8 +37,26 @@ $bankReference = trim($data['bank_reference'] ?? ''); $amount = (float)($data['amount'] ?? 0); $senderName = $data['sender_name'] ?? 'غير معروف'; +// Robust Parsing Fallback (for Orange Money / CliQ Jordan) if (empty($bankReference) || $amount <= 0) { - json_error('بيانات التحويل غير مكتملة.', 422); + // Try to extract amount: بمبلغ 15 دينار + if (preg_match('/بمبلغ\s+([\d\.]+)\s+دينار/', $rawMessage, $matches)) { + $amount = (float)$matches[1]; + } + + // Try to extract reference: بالرقم المرجعي JIBA... + if (preg_match('/بالرقم المرجعي\s+([A-Z0-9a-z]+)/', $rawMessage, $matches)) { + $bankReference = $matches[1]; + } + + // Try to extract sender: من FERAS... + if (preg_match('/من\s+([^من]+)\s+من مزود/', $rawMessage, $matches)) { + $senderName = trim($matches[1]); + } +} + +if (empty($bankReference) || $amount <= 0) { + json_error('فشل استخراج بيانات التحويل من الرسالة.', 422); } $db = Database::getInstance(); diff --git a/musadaq-app/lib/features/subscription/views/payment_receipt_view.dart b/musadaq-app/lib/features/subscription/views/payment_receipt_view.dart index 61aedf0..a8400cb 100644 --- a/musadaq-app/lib/features/subscription/views/payment_receipt_view.dart +++ b/musadaq-app/lib/features/subscription/views/payment_receipt_view.dart @@ -43,12 +43,15 @@ class PaymentReceiptView extends StatelessWidget { )), const SizedBox(height: 24), - Text('الخطوة التالية:', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: isDark ? Colors.white : Colors.black87)), + Text('الخطوات التالية:', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16, color: isDark ? Colors.white : Colors.black87)), + const SizedBox(height: 12), + _buildStepRow('1', 'افتح تطبيق البنك أو المحفظة الإلكترونية الخاصة بك.', isDark), const SizedBox(height: 8), - Text( - 'قم بتحويل المبلغ عبر تطبيق البنك الخاص بك إلى الاسم المستعار المذكور أعلاه (CliQ). بعد إتمام الحوالة بنجاح، ستصلك رسالة أو إشعار من البنك يحتوي على "رقم المرجع" للعملية. انسخه والصقه هنا.', - style: TextStyle(fontSize: 13, color: isDark ? Colors.white70 : Colors.grey.shade700, height: 1.5), - ), + _buildStepRow('2', 'اختر خدمة "كليك" (CliQ) للتحويل الفوري.', isDark), + const SizedBox(height: 8), + _buildStepRow('3', 'قم بالتحويل للاسم المستعار الموضح أعلاه.', isDark), + const SizedBox(height: 8), + _buildStepRow('4', 'بعد إتمام العملية، انسخ "رقم المرجع" من رسالة البنك أو الإشعار والصقه هنا.', isDark), const SizedBox(height: 24), // Reference Number Input Area @@ -117,6 +120,35 @@ class PaymentReceiptView extends StatelessWidget { ); } + Widget _buildStepRow(String number, String text, bool isDark) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + width: 24, + height: 24, + decoration: BoxDecoration( + color: const Color(0xFF0F4C81).withOpacity(0.1), + shape: BoxShape.circle, + ), + child: Center( + child: Text( + number, + style: const TextStyle(color: Color(0xFF0F4C81), fontWeight: FontWeight.bold, fontSize: 12), + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + text, + style: TextStyle(fontSize: 13, color: isDark ? Colors.white70 : Colors.grey.shade700, height: 1.4), + ), + ), + ], + ); + } + Widget _buildInfoRow(String label, String value, bool isDark, {bool isHighlight = false}) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween,