SAAFE SDK for Flutter
This Flutter SDK provides a simple interface to integrate SAAFE's secure authentication and financial experience into your Flutter applications.
Features
- 🔒 Secure authentication and redirection flows
- 📱 Platform detection (iOS, Android, Flutter)
- 🌓 Theme support (light, dark, system)
- 📏 Forced portrait orientation during flows
- 🔗 External links handling with intelligent fallbacks
- ✅ Confirmation dialogs for closing flows
- 🖥️ High-resolution WebView with optimized text rendering
- 🎛️ Customizable display modes (bottom sheet or full page)
- 🔘 Optional close button visibility control
Installation
Add the SDK to your pubspec.yaml:
dependencies:
saafe_aa_sdk: ^0.1.6
Usage
Initialize the SDK
Initialize the SDK in your main.dart file before calling runApp():
import 'package:saafe_aa_sdk/saafe_sdk.dart';
void main() async {
// Initialize with default settings (sandbox environment)
await SaafeSdk.initialize();
// Or specify sandbox/production environment
// await SaafeSdk.initialize(useSandbox: true); // For sandbox (default)
// await SaafeSdk.initialize(useSandbox: false); // For production
// Or with a custom redirect URL
// await SaafeSdk.initialize(customRedirectUrl: 'https://your-custom-url.example.com/login');
runApp(const MyApp());
}
Environment Configuration
The SDK supports two environments:
- Sandbox (default): Uses
https://stage-redirection.saafe.in/login- For development and testing - Production: Uses
https://app-redirection.saafe.in/login- For live applications
To switch environments, use the useSandbox parameter during initialization:
// For sandbox (development/testing)
await SaafeSdk.initialize(useSandbox: true);
// For production (live environment)
await SaafeSdk.initialize(useSandbox: false);
Display Modes
The SDK supports two display modes for the WebView:
- Bottom Sheet (default): Shows the WebView in a modal bottom sheet
- Full Page: Shows the WebView as a full page with left-to-right transition
// Bottom sheet mode (default)
final redirectInstance = await SaafeSdk.triggerRedirect(
context,
SaafeRedirectOptions(
// ... other parameters
displayMode: DisplayMode.bottomSheet,
),
);
// Full page mode
final redirectInstance = await SaafeSdk.triggerRedirect(
context,
SaafeRedirectOptions(
// ... other parameters
displayMode: DisplayMode.fullPage,
),
);
Close Button Visibility
You can control whether the close button is shown in the WebView:
final redirectInstance = await SaafeSdk.triggerRedirect(
context,
SaafeRedirectOptions(
// ... other parameters
showCloseButton: true, // Show close button (default)
// showCloseButton: false, // Hide close button
),
);
Note: In full page mode, the close button is optional since users can use the system back button to exit. In bottom sheet mode, the close button provides an additional way to close the modal alongside the drag-to-dismiss gesture.
Both display modes support system back navigation with confirmation dialog to prevent accidental exits.
The SDK will automatically trigger the onComplete callback with the received data.
Trigger the Redirect Flow
Trigger the redirect flow using the parameters from your generated consent response:
// First, get the consent response from SAAFE API
// The response will look like this:
/*
{
"status": "success",
"code": "OperationSuccess",
"msg": "Operation Success",
"request_id": 7788,
"txn_id": "daa53abbc1-7fe7-4984-8879-197883daba9d",
"url": "https://sandbox.redirection.saafe.in/login/?fi=WU9AUEBGV0dXUB5QWUc=&reqdate=160520250536024&ecreq=PuH3d0DSVsNCH3tfu86D4iNKTOYZyyftje7GLsc84gwMcmjFifpO9Pf4v8gDZ0lN4pD7Koskq-CkrHFGRpkvh16HVVjCjmhHiQaKRGuRo1MjoxiqicJJcQP0k-MJwDYR6krtMHFr3RP_W4Trlj2aAxeoucAvoJhGI1Lm5fnsCnnU64BHl7vPHGyXovHZIXl4sr8_HLQPuBkgLUy5oeu0fDDY62ajnztF40KufzuNe5MLI0Aut2_OjR-S94rdFrkbM6IseaBsPbpZnnibU8GuKL3A9idlvBDbLRNvEtgnjKy6AKGMAWQtEC1l6waJKeedhl0j4qCpNLtNBOCXb3VS5sf5kafDitfuSgpJ0pfuA-8=",
"consent_handle": [
"8bce1c3b-f289-4c1c-8d4b-7ed2e0d3a31b",
"b6bc69f8-c77d-4070-a9ec-0d4ad7c72be2"
],
"vua": "8682807087@dashboard-aa-preprod",
"fi": "WU9AUEBGV0dXUB5QWUc=",
"reqdate": "160520250536024",
"ecreq": "PuH3d0DSVsNCH3tfu86D4iNKTOYZyyftje7GLsc84gwMcmjFifpO9Pf4v8gDZ0lN4pD7Koskq-CkrHFGRpkvh16HVVjCjmhHiQaKRGuRo1MjoxiqicJJcQP0k-MJwDYR6krtMHFr3RP_W4Trlj2aAxeoucAvoJhGI1Lm5fnsCnnU64BHl7vPHGyXovHZIXl4sr8_HLQPuBkgLUy5oeu0fDDY62ajnztF40KufzuNe5MLI0Aut2_OjR-S94rdFrkbM6IseaBsPbpZnnibU8GuKL3A9idlvBDbLRNvEtgnjKy6AKGMAWQtEC1l6waJKeedhl0j4qCpNLtNBOCXb3VS5sf5kafDitfuSgpJ0pfuA-8="
}
*/
// Extract the required parameters from the consent response
final consentResponse = await yourApiCallToGetConsent();
// Now use these parameters with the SDK
final redirectInstance = await SaafeSdk.triggerRedirect(
context,
SaafeRedirectOptions(
fi: consentResponse['fi'], // Use the 'fi' value from consent response
reqdate: consentResponse['reqdate'], // Use the 'reqdate' value from consent response
ecreq: consentResponse['ecreq'], // Use the 'ecreq' value from consent response
theme: 'light', // Optional: 'light', 'dark', or null for system default
displayMode: DisplayMode.bottomSheet, // Optional: DisplayMode.bottomSheet (default) or DisplayMode.fullPage
showCloseButton: true, // Optional: true (default) to show close button, false to hide
onComplete: (data) {
print('Flow completed: $data');
// Handle successful completion
},
onCancel: () {
print('Flow cancelled by user');
// Handle user cancellation
},
onError: (error) {
print('Error during flow: $error');
// Handle errors
},
onLoad: () {
print('WebView loaded successfully');
// Optional: handle WebView load event
},
),
);
Close the Redirect Flow
You can programmatically close the flow:
// This will show a confirmation dialog before closing
redirectInstance.close();
URL Parameters
The SDK automatically adds the following parameters to the redirect URL:
Platform Detection
platform=ios- For iOS devicesplatform=android- For Android devicesplatform=flutter- For other Flutter platforms
Theme Support
theme=light- Light themetheme=dark- Dark theme
External URL Handling
The SDK intelligently handles external URLs by:
- Detecting external links in the WebView
- Automatically opening them in the system's default browser
- Providing multiple fallback mechanisms if the default method fails
- Showing a useful error dialog with copy functionality if all launch attempts fail
You can also use the URL launcher directly in your app:
// Launch a URL in the external browser
await SaafeSdk.launchExternalUrl(
'https://example.com',
context: context, // Optional: provide context to show error dialog if needed
);
Example
See the example folder for a complete implementation example.
License
This project is licensed under the MIT License - see the LICENSE file for details.