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:

  1. Sandbox (default): Uses https://stage-redirection.saafe.in/login - For development and testing
  2. 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:

  1. Bottom Sheet (default): Shows the WebView in a modal bottom sheet
  2. 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 devices
  • platform=android - For Android devices
  • platform=flutter - For other Flutter platforms

Theme Support

  • theme=light - Light theme
  • theme=dark - Dark theme

External URL Handling

The SDK intelligently handles external URLs by:

  1. Detecting external links in the WebView
  2. Automatically opening them in the system's default browser
  3. Providing multiple fallback mechanisms if the default method fails
  4. 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.