feature/payment #77
@ -14,87 +14,64 @@ class PaymentController with ChangeNotifier {
|
||||
/// ==============================
|
||||
/// START PAYMENT (Safe init)
|
||||
/// ==============================
|
||||
Future<bool> startPayment({
|
||||
Future<void> startPayment({
|
||||
required double amount,
|
||||
required String description,
|
||||
required BuildContext context,
|
||||
}) async {
|
||||
//_context = context;
|
||||
isProcessing = true;
|
||||
notifyListeners();
|
||||
|
||||
logSafe("🟢 Starting payment for ₹$amount - $description");
|
||||
|
||||
// ✅ Clear any old instance (prevents freeze on re-init)
|
||||
_cleanup();
|
||||
|
||||
// ✅ Create order first (no login dependency)
|
||||
Map<String, dynamic>? result;
|
||||
try {
|
||||
result = await _paymentService
|
||||
.createOrder(amount)
|
||||
.timeout(const Duration(seconds: 10));
|
||||
} catch (e) {
|
||||
logSafe("⏱️ API Timeout or Exception while creating order: $e",
|
||||
level: LogLevel.error);
|
||||
}
|
||||
|
||||
if (result == null) {
|
||||
_showError("Failed to connect to server or timeout.");
|
||||
isProcessing = false;
|
||||
isProcessing = true;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
|
||||
final orderId = result['data']?['orderId'];
|
||||
final key = result['data']?['key'];
|
||||
if (orderId == null || key == null) {
|
||||
_showError("Invalid response from server.");
|
||||
logSafe("Invalid response from server.");
|
||||
// Step 1: Create payment order
|
||||
final result = await _paymentService.createOrder(amount);
|
||||
logSafe("🧩 Raw response in PaymentController: $result");
|
||||
|
||||
isProcessing = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
// Step 2: Validate result before accessing keys
|
||||
if (result == null) {
|
||||
_showError("Failed to create order. Server returned null response.");
|
||||
isProcessing = false;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
// ✅ Safe initialization of Razorpay (deferred)
|
||||
try {
|
||||
logSafe("🟡 Initializing Razorpay instance...");
|
||||
_razorpay = Razorpay();
|
||||
_razorpay?.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess);
|
||||
_razorpay?.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError);
|
||||
_razorpay?.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet);
|
||||
logSafe("✅ Razorpay instance initialized successfully.");
|
||||
} catch (e) {
|
||||
logSafe("❌ Razorpay init failed: $e", level: LogLevel.error);
|
||||
_showError("Payment system initialization failed.");
|
||||
isProcessing = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
// Step 2: Handle both wrapped and unwrapped formats
|
||||
final data = result['data'] ?? result;
|
||||
final orderId = data?['orderId'];
|
||||
final key = data?['key'];
|
||||
|
||||
// ✅ Prepare payment options
|
||||
final options = {
|
||||
'key': key,
|
||||
'amount': (amount * 100).toInt(),
|
||||
'name': 'Your Company Name',
|
||||
'description': description,
|
||||
'order_id': orderId,
|
||||
'theme': {'color': '#0D47A1'},
|
||||
'timeout': 120, // seconds
|
||||
};
|
||||
if (orderId == null || key == null) {
|
||||
_showError("Invalid response from server. Missing orderId or key.");
|
||||
logSafe("💥 Invalid response structure: $result");
|
||||
isProcessing = false;
|
||||
notifyListeners();
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 3: Initialize Razorpay if needed
|
||||
_razorpay ??= Razorpay();
|
||||
_razorpay!.on(Razorpay.EVENT_PAYMENT_SUCCESS, _handlePaymentSuccess);
|
||||
_razorpay!.on(Razorpay.EVENT_PAYMENT_ERROR, _handlePaymentError);
|
||||
_razorpay!.on(Razorpay.EVENT_EXTERNAL_WALLET, _handleExternalWallet);
|
||||
|
||||
// Step 4: Open Razorpay checkout
|
||||
final options = {
|
||||
'key': key,
|
||||
'amount': (amount * 100).toInt(), // Razorpay expects amount in paise
|
||||
'name': 'Marco',
|
||||
'description': 'Subscription Payment',
|
||||
'order_id': orderId,
|
||||
'prefill': {'contact': '9999999999', 'email': 'test@marco.com'},
|
||||
};
|
||||
|
||||
try {
|
||||
logSafe("🟠 Opening Razorpay checkout with options: $options");
|
||||
_razorpay!.open(options);
|
||||
return true;
|
||||
} catch (e) {
|
||||
logSafe("❌ Error opening Razorpay: $e", level: LogLevel.error);
|
||||
_showError("Error opening payment gateway.");
|
||||
_cleanup();
|
||||
} catch (e, s) {
|
||||
_showError("Payment initialization failed. Please try again.");
|
||||
logSafe("💥 Exception in startPayment: $e\n$s");
|
||||
} finally {
|
||||
isProcessing = false;
|
||||
notifyListeners();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,8 @@ class PaymentService {
|
||||
try {
|
||||
logSafe("🟢 Calling createPaymentOrder API with amount: ₹$amount");
|
||||
final response = await ApiService.createPaymentOrder(amount);
|
||||
logSafe("🧩 Raw response in PaymentService: $response");
|
||||
|
||||
return response;
|
||||
} catch (e) {
|
||||
logSafe("❌ Error in createOrder: $e", level: LogLevel.error);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user