import 'package:flutter/material.dart'; import 'package:razorpay_flutter/razorpay_flutter.dart'; import 'package:marco/helpers/services/payment_service.dart'; import 'package:marco/helpers/services/app_logger.dart'; class PaymentController with ChangeNotifier { final Razorpay _razorpay = Razorpay(); final PaymentService _paymentService = PaymentService(); bool isProcessing = false; BuildContext? _context; // For showing dialogs/snackbars PaymentController() { // Razorpay event listeners _razorpay.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess); _razorpay.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError); _razorpay.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet); } void disposeController() { _razorpay.clear(); } /// ============================== /// START PAYMENT /// ============================== Future startPayment({ required double amount, required String description, required BuildContext context, }) async { _context = context; isProcessing = true; notifyListeners(); logSafe("đŸŸĸ Starting payment for ₹$amount - $description"); // Call backend to create Razorpay order final result = await _paymentService.createOrder(amount); if (result == null) { _showError(context, "Failed to connect to server."); isProcessing = false; notifyListeners(); return; } final orderId = result['orderId']; final key = result['key']; if (orderId == null || key == null) { _showError(context, "Invalid response from server."); isProcessing = false; notifyListeners(); return; } var options = { 'key': key, 'amount': (amount * 100).toInt(), // Razorpay takes amount in paise 'name': 'Your Company Name', 'description': description, 'order_id': orderId, 'theme': {'color': '#0D47A1'}, 'timeout': 120, // 2 minutes timeout }; try { logSafe("🟠 Opening Razorpay with options: $options"); _razorpay.open(options); } catch (e) { logSafe("❌ Error opening Razorpay: $e", level: LogLevel.error); _showError(context, "Error opening payment gateway."); isProcessing = false; notifyListeners(); } } /// ============================== /// EVENT HANDLERS /// ============================== void _handlePaymentSuccess(PaymentSuccessResponse response) async { logSafe("✅ Payment Success: ${response.paymentId}"); isProcessing = true; notifyListeners(); final result = await _paymentService.verifyPayment( paymentId: response.paymentId!, orderId: response.orderId!, signature: response.signature!, ); isProcessing = false; notifyListeners(); if (result != null && result['verified'] == true) { _showDialog( title: "Payment Successful 🎉", message: "Your payment was verified successfully.", success: true, ); } else { _showDialog( title: "Verification Failed ❌", message: "Payment completed but could not be verified.", success: false, ); } } void _handlePaymentError(PaymentFailureResponse response) { logSafe("❌ Payment Failed: ${response.message}"); isProcessing = false; notifyListeners(); _showDialog( title: "Payment Failed ❌", message: "Reason: ${response.message ?? 'Unknown error'}", success: false, ); } void _handleExternalWallet(ExternalWalletResponse response) { logSafe("â„šī¸ External Wallet Used: ${response.walletName}"); } /// ============================== /// HELPER DIALOGS / SNACKBARS /// ============================== void _showDialog({ required String title, required String message, required bool success, }) { if (_context == null) return; showDialog( context: _context!, builder: (ctx) => AlertDialog( title: Text(title), content: Text(message), actions: [ TextButton( child: const Text("OK"), onPressed: () { Navigator.of(ctx).pop(); if (success) { Navigator.of(_context!).pop(true); // Return success } }, ), ], ), ); } void _showError(BuildContext context, String message) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(message), backgroundColor: Colors.red), ); } }