diff --git a/lib/api/services/auth_service.dart b/lib/api/services/auth_service.dart index e66538e..2a22a4f 100644 --- a/lib/api/services/auth_service.dart +++ b/lib/api/services/auth_service.dart @@ -8,73 +8,40 @@ class AuthService { final Dio _dio; AuthService(this._dio); - Future simVerify(String uuid, String cifNo) async{ + Future simVerify(String uuid, String cifNo) async { + try { + final response = await _dio.post('/api/sim-details-verify', data: { + 'uuid': uuid, + 'cifNo': cifNo, + }); - try{ - - final response = await _dio.post( - - '/api/sim-details-verify', - - data: { - - 'uuid': uuid, - - 'cifNo': cifNo, - - } - - ); - - if (response.statusCode == 200) { - - final String message = response.data.toString().toUpperCase(); - - if (message.contains("VERIFIED")) { - - return; // Success - - } else { - - throw AuthException(message); // Throw message received - - } + if (response.statusCode == 200) { + final String message = response.data.toString().toUpperCase(); + if (message.contains("VERIFIED")) { + return; // Success } else { - - throw AuthException('Verification Failed'); - + throw AuthException(message); // Throw message received } - - } on DioException catch (e) { - - if (kDebugMode) { - - print(e.toString()); - - } - - if (e.response?.statusCode == 401) { - - throw AuthException( - - e.response?.data['error'] ?? 'SOMETHING WENT WRONG'); - - } - - throw NetworkException('Network error during verification'); - + } else { + throw AuthException('Verification Failed'); + } + } on DioException catch (e) { + if (kDebugMode) { + print(e.toString()); } - catch (e) { - - throw UnexpectedException( - - 'Unexpected error during verification: ${e.toString()}'); - + if (e.response?.statusCode == 401) { + throw AuthException( + e.response?.data['error'] ?? 'SOMETHING WENT WRONG'); } + throw NetworkException('Network error during verification'); + } catch (e) { + throw UnexpectedException( + 'Unexpected error during verification: ${e.toString()}'); } + } Future login(AuthCredentials credentials) async { try { diff --git a/lib/api/services/send_sms_service.dart b/lib/api/services/send_sms_service.dart index caf5c1c..310643e 100644 --- a/lib/api/services/send_sms_service.dart +++ b/lib/api/services/send_sms_service.dart @@ -1,102 +1,102 @@ import 'dart:io'; - import 'package:flutter/material.dart'; - import 'package:permission_handler/permission_handler.dart'; - import 'package:send_message/send_message.dart' show sendSMS; - import 'package:simcards/sim_card.dart'; - import 'package:simcards/simcards.dart'; +import 'package:flutter/material.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:send_message/send_message.dart' show sendSMS; +import 'package:simcards/sim_card.dart'; +import 'package:simcards/simcards.dart'; - // This enum provides detailed status back to the UI layer. - enum PermissionStatusResult { granted, denied, permanentlyDenied, restricted } +// This enum provides detailed status back to the UI layer. +enum PermissionStatusResult { granted, denied, permanentlyDenied, restricted } - class SmsService { - final Simcards _simcards = Simcards(); +class SmsService { + final Simcards _simcards = Simcards(); - /// Handles the requesting of SMS and Phone permissions. - /// Returns a detailed status: granted, denied, or permanentlyDenied. - Future handleSmsPermission() async { - var smsStatus = await Permission.sms.status; - var phoneStatus = await Permission.phone.status; + /// Handles the requesting of SMS and Phone permissions. + /// Returns a detailed status: granted, denied, or permanentlyDenied. + Future handleSmsPermission() async { + var smsStatus = await Permission.sms.status; + var phoneStatus = await Permission.phone.status; - // Check initial status - if (smsStatus.isGranted && phoneStatus.isGranted) { - return PermissionStatusResult.granted; - } - if (smsStatus.isPermanentlyDenied || phoneStatus.isPermanentlyDenied) { - return PermissionStatusResult.permanentlyDenied; - } - if (smsStatus.isRestricted || phoneStatus.isRestricted) { - return PermissionStatusResult.restricted; - } + // Check initial status + if (smsStatus.isGranted && phoneStatus.isGranted) { + return PermissionStatusResult.granted; + } + if (smsStatus.isPermanentlyDenied || phoneStatus.isPermanentlyDenied) { + return PermissionStatusResult.permanentlyDenied; + } + if (smsStatus.isRestricted || phoneStatus.isRestricted) { + return PermissionStatusResult.restricted; + } - // Request permissions if not granted - print("Requesting SMS and Phone permissions..."); - await [Permission.phone, Permission.sms].request(); + // Request permissions if not granted + print("Requesting SMS and Phone permissions..."); + await [Permission.phone, Permission.sms].request(); - // Re-check status after request - smsStatus = await Permission.sms.status; - phoneStatus = await Permission.phone.status; + // Re-check status after request + smsStatus = await Permission.sms.status; + phoneStatus = await Permission.phone.status; - if (smsStatus.isGranted && phoneStatus.isGranted) { - return PermissionStatusResult.granted; - } - if (smsStatus.isPermanentlyDenied || phoneStatus.isPermanentlyDenied) { - return PermissionStatusResult.permanentlyDenied; - } - if (smsStatus.isRestricted || phoneStatus.isRestricted) { - return PermissionStatusResult.restricted; - } + if (smsStatus.isGranted && phoneStatus.isGranted) { + return PermissionStatusResult.granted; + } + if (smsStatus.isPermanentlyDenied || phoneStatus.isPermanentlyDenied) { + return PermissionStatusResult.permanentlyDenied; + } + if (smsStatus.isRestricted || phoneStatus.isRestricted) { + return PermissionStatusResult.restricted; + } - // If none of the above, it's denied - return PermissionStatusResult.denied; - } + // If none of the above, it's denied + return PermissionStatusResult.denied; + } - /// Tries to send a single verification SMS. - /// This should only be called AFTER permissions have been granted. - Future sendVerificationSms({ - required BuildContext context, - required String destinationNumber, - required String message, - }) async { - try { - List simCardList = await _simcards.getSimCards(); - if (simCardList.isEmpty) { - print("No SIM card detected."); - return false; - } - return await _sendSms(destinationNumber, message, simCardList.first); - } catch (e) { - print("An error occurred in the SMS process: $e"); - return false; - } - } + /// Tries to send a single verification SMS. + /// This should only be called AFTER permissions have been granted. + Future sendVerificationSms({ + required BuildContext context, + required String destinationNumber, + required String message, + }) async { + try { + List simCardList = await _simcards.getSimCards(); + if (simCardList.isEmpty) { + print("No SIM card detected."); + return false; + } + return await _sendSms(destinationNumber, message, simCardList.first); + } catch (e) { + print("An error occurred in the SMS process: $e"); + return false; + } + } - /// Private function to perform the SMS sending action. - Future _sendSms( - String destinationNumber, String message, SimCard selectedSim) async { - if (Platform.isAndroid) { - try { - String smsMessage = message; - String result = await sendSMS( - message: smsMessage, - recipients: [destinationNumber], - sendDirect: true, - ); - print("Background SMS send attempt result: $result"); + /// Private function to perform the SMS sending action. + Future _sendSms( + String destinationNumber, String message, SimCard selectedSim) async { + if (Platform.isAndroid) { + try { + String smsMessage = message; + String result = await sendSMS( + message: smsMessage, + recipients: [destinationNumber], + sendDirect: true, + ); + print("Background SMS send attempt result: $result"); - if (result.toLowerCase().contains('sent')) { - print("Success: SMS appears to have been sent."); - return true; - } else { - print("Failure: SMS was not sent. Result: $result"); - return false; - } - } catch (e) { - print("Error attempting to send SMS directly: $e"); - return false; - } - } else { - print("SMS sending is only supported on Android."); - return false; - } - } - } \ No newline at end of file + if (result.toLowerCase().contains('sent')) { + print("Success: SMS appears to have been sent."); + return true; + } else { + print("Failure: SMS was not sent. Result: $result"); + return false; + } + } catch (e) { + print("Error attempting to send SMS directly: $e"); + return false; + } + } else { + print("SMS sending is only supported on Android."); + return false; + } + } +} diff --git a/lib/di/injection.dart b/lib/di/injection.dart index e3eba3a..0e7aabc 100644 --- a/lib/di/injection.dart +++ b/lib/di/injection.dart @@ -75,8 +75,8 @@ Dio _createDioClient() { BaseOptions( baseUrl: 'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080', //test - //'http://lb-kccb-mobile-banking-app-848675342.ap-south-1.elb.amazonaws.com', //prod - //'https://kccbmbnk.net', //prod small + //'http://lb-kccb-mobile-banking-app-848675342.ap-south-1.elb.amazonaws.com', //prod + //'https://kccbmbnk.net', //prod small connectTimeout: const Duration(seconds: 60), receiveTimeout: const Duration(seconds: 60), headers: { diff --git a/lib/features/auth/screens/sms_verification_helper.dart b/lib/features/auth/screens/sms_verification_helper.dart index ee6732b..178fc7f 100644 --- a/lib/features/auth/screens/sms_verification_helper.dart +++ b/lib/features/auth/screens/sms_verification_helper.dart @@ -1,4 +1,3 @@ - import 'package:flutter/material.dart'; import 'package:kmobile/api/services/send_sms_service.dart'; import 'package:permission_handler/permission_handler.dart'; @@ -12,7 +11,8 @@ class SmsVerificationHelper { context: context, builder: (context) => AlertDialog( title: const Text("Permission Required"), - content: const Text("SMS and Phone permissions are required for device verification. Please enable them in your app settings to continue."), + content: const Text( + "SMS and Phone permissions are required for device verification. Please enable them in your app settings to continue."), actions: [ TextButton( child: const Text("Cancel"), @@ -39,17 +39,24 @@ class SmsVerificationHelper { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text("It seems your device is restricting this app from sending SMS messages, which is required for verification. Please follow these steps to enable it:\n"), - Text("1. Open your device Settings.", style: TextStyle(fontWeight: FontWeight.bold)), + Text( + "It seems your device is restricting this app from sending SMS messages, which is required for verification. Please follow these steps to enable it:\n"), + Text("1. Open your device Settings.", + style: TextStyle(fontWeight: FontWeight.bold)), Text("2. Go to 'Apps' or 'Apps & notifications'."), Text("3. Find and tap on this app ('KMobile')."), Text("4. Tap on the three dots (⋮) in the top right corner."), - Text("5. Select 'Allow restricted settings' and confirm. This is crucial to allow SMS permission."), + Text( + "5. Select 'Allow restricted settings' and confirm. This is crucial to allow SMS permission."), Text("6. Now you have two options to allow SMS permission:"), - Text(" a. Tap on 'Permissions', then find 'SMS' is set to 'Allow'."), - Text(" b. Alternatively, you can return to the KMobile app, and the SMS permission pop-up should appear again, allowing you to grant it directly."), - Text("\nSome devices have an additional setting for 'Premium SMS'. If the above doesn't work, look for a 'Premium SMS access' setting (you can search for it in your Settings app) and set it to 'Always Allow' for this app.\n"), - Text("After you've enabled the permission, please come back to the app."), + Text( + " a. Tap on 'Permissions', then find 'SMS' is set to 'Allow'."), + Text( + " b. Alternatively, you can return to the KMobile app, and the SMS permission pop-up should appear again, allowing you to grant it directly."), + Text( + "\nSome devices have an additional setting for 'Premium SMS'. If the above doesn't work, look for a 'Premium SMS access' setting (you can search for it in your Settings app) and set it to 'Always Allow' for this app.\n"), + Text( + "After you've enabled the permission, please come back to the app."), ], ), ), @@ -63,15 +70,6 @@ class SmsVerificationHelper { ); } - void _showSnackBar(BuildContext context, String message) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(message), - duration: const Duration(seconds: 3), - ), - ); - } - Future initiateSmsSequence({ required BuildContext context, }) async { @@ -85,7 +83,9 @@ class SmsVerificationHelper { switch (status) { case PermissionStatusResult.granted: ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("Permissions Granted! Proceeding..."), duration: Duration(seconds: 2)), + const SnackBar( + content: Text("Permissions Granted! Proceeding..."), + duration: Duration(seconds: 2)), ); hasPermission = true; // This will break the loop break; @@ -96,7 +96,8 @@ class SmsVerificationHelper { context: context, builder: (context) => AlertDialog( title: const Text("Permission Required"), - content: const Text("This app requires SMS and Phone permissions to verify your device. Please grant the permissions to continue."), + content: const Text( + "This app requires SMS and Phone permissions to verify your device. Please grant the permissions to continue."), actions: [ TextButton( child: const Text("Cancel"), @@ -136,9 +137,12 @@ class SmsVerificationHelper { var uuid = const Uuid(); String uniqueId = uuid.v4(); String smsMessage = uniqueId; - + ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text("Attempting to send verification SMS... (${4 - retries})"), duration: const Duration(seconds: 2)), + SnackBar( + content: + Text("Attempting to send verification SMS... (${4 - retries})"), + duration: const Duration(seconds: 2)), ); bool isSmsSent = await _smsService.sendVerificationSms( @@ -148,21 +152,25 @@ class SmsVerificationHelper { ); if (isSmsSent) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("SMS sent successfully!"), duration: Duration(seconds: 2)), + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("SMS sent successfully!"), + duration: Duration(seconds: 2)), ); return uniqueId; } else { retries--; if (retries > 0) { - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text("SMS failed to send. Retrying in 5 seconds..."), duration: Duration(seconds: 4)), + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar( + content: Text("SMS failed to send. Retrying in 5 seconds..."), + duration: Duration(seconds: 4)), ); await Future.delayed(const Duration(seconds: 5)); } } } - + // If all retries fail return null; } diff --git a/lib/features/auth/screens/verification_screen.dart b/lib/features/auth/screens/verification_screen.dart index 460f8f2..31d072a 100644 --- a/lib/features/auth/screens/verification_screen.dart +++ b/lib/features/auth/screens/verification_screen.dart @@ -78,7 +78,7 @@ class _VerificationScreenState extends State { setState(() { _statusMessage = "SMS sent. Waiting for network delivery..."; }); - + // Adding a 10-second delay to account for SMS network latency. await Future.delayed(const Duration(seconds: 10)); @@ -101,7 +101,6 @@ class _VerificationScreenState extends State { // Pop with success result Navigator.of(context).pop(true); - } catch (e) { setState(() { _statusMessage = e.toString(); @@ -111,7 +110,8 @@ class _VerificationScreenState extends State { } } else if (mounted) { setState(() { - _statusMessage = "SMS sending failed. Please check permissions and try again."; + _statusMessage = + "SMS sending failed. Please check permissions and try again."; _isVerifying = false; _verificationFailed = true; }); @@ -131,13 +131,12 @@ class _VerificationScreenState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - if (_isVerifying) - const CircularProgressIndicator(), + if (_isVerifying) const CircularProgressIndicator(), if (!_isVerifying && _verificationFailed) const Icon(Icons.error_outline, color: Colors.red, size: 50), if (!_isVerifying && !_verificationFailed) - const Icon(Icons.check_circle_outline, color: Colors.green, size: 50), - + const Icon(Icons.check_circle_outline, + color: Colors.green, size: 50), const SizedBox(height: 32), Text( _statusMessage, @@ -163,4 +162,4 @@ class _VerificationScreenState extends State { ), ); } -} \ No newline at end of file +}