Flutter SDK

Overview

The AiPrise Flutter SDK is designed to allow developers to seamlessly integrate our pre-built KYC user experience into their existing Flutter applications with just 5 lines of code.

Install the AiPrise Flutter SDK

Start by running the following command in the root folder of your Flutter project:

flutter pub add aiprise_flutter_sdk

Enabling Permissions

Since our onboarding screens need access to the device camera to capture document images, selfies, etc your app will need to enable camera permissions.

We internally use the permission_handler package to ask for permissions at runtime however your application will have to list them in the respective manifest / info files.

Android

  1. Open your_project/android/app/src/main/AndroidManifest.xml and add the following line:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- Add the camera permission -->
    <uses-permission android:name="android.permission.CAMERA"/>
    
    <!-- <application /> here -->
</manifest>
  1. In your_project/android/app/build.gradle make sure to set the compileSdkVersion to 33.
android {
  compileSdkVersion 33
  ...
}
  1. Add the following to your your_project/android/gradle.properties file:
android.useAndroidX=true
android.enableJetifier=true

iOS

  1. Open your_project/ios/Runer/Info.plist and add the following line:
<plist version="1.0">
<dict>
  <!-- OTHER STUFF HERE -->

  <!-- Add This Line -->
  <key>NSCameraUsageDescription</key>
  <string>Explanation on why the camera access is needed.</string>
</dict>
</plist>

Option 1: AiPriseMaterialButton and AiPriseCupertinoButton

Our button widgets allow you to quickly integrate the onboarding screens in your Flutter application. On clicking the button, an overlay will be shown where the user data will be collected. When the user completes the form, the overlay will close and a callback will be fired to inform your app that the session was successful.

Depending on your app's theme, you can either use the Material button or the Cupertino button.

Basic Usage

Just add the button widgets in your page wherever you want to place it. The templateID and mode are the only required arguments. You can add others as per your requirements.

import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

// MATERIAL EXAMPLE
class SomeRandomMaterialWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseMaterialButton(
      mode: AiPriseEnvironment.sandbox, // sandbox or production
      templateID: 'TEMPLATE_ID_HERE'
    );
  }
}

// CUPERTINO EXAMPLE
class SomeRandomCupertinoWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseCupertinoButton(
      mode: AiPriseEnvironment.sandbox, // sandbox or production
      templateID: 'TEMPLATE_ID_HERE'
    );
  }
}

Advanced Usage

Apart from templateID and mode, there are a few more arguments that you can pass that allow you to pass in additional parameters for verification. All of them are listed in the example below.

In addition to the arguments, there are also five callbacks fired by the button which you can listen to:
(i) onStart: Will be fired after the session starts. i.e. when the user clicks on the button, the overlay opens and a new session gets created (callback will be fired after the loading screen is completed).
(ii) onAbandoned: Will be fired when the user quits out of the verification flow by clicking the close button and confirming that they want to stop the verification.
(iii) onSuccess: This will be fired when the user completes filing out the entire verification form and reaches the last page. They may not have clicked the close button yet so the overlay is still visibile at this point but no other information has to be collected from them. Note: "successful" does not mean that the KYC is approved. It just means form is successfully filled by the user.
(iv) onComplete: This will be fired AFTER the user clicks the close or continue button on the last page. The SDK will handle closing of the overlay automatically in that case so no action is required on your end. The callback is just in case you want to perform any task in your application after this point.
(v) onError: This callback is fired in case the session creation failed. This can happen for a number of reasons like invalid template ID, internet issues, camera permission not given, etc.

The example below shows all the extra arguments along with the callbacks:

import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

class SomeRandomMaterialWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseMaterialButton(
        // ARGUMENTS
        mode: AiPriseEnvironment.sandbox, // sandbox or production
        templateID: 'TEMPLATE_ID_HERE',

        callbackURL: 'http://yourcallbackurl.com',
        eventsCallbackURL: 'http://yourcallbackurl.com',

        clientReferenceID: 'SOME_ID_YOU_WANT_TO_ASSOCIATE_WITH_YOUR_REQUEST',
        clientReferenceData: {'some_data': 'some_value'},
  
        uiOptions: AiPriseUiOptions(
            id_verification_module: AiPriseUiOptionIdVerification(
                allowed_country_code: 'US' // 2-Letter Country Code. Disables all other countries.
            )
        ),
        verificationOptions: AiPriseVerificationOptions(
            AML_CONFIG: AiPriseVerificationOptionAmlConfig(
                fuzziness_score: 0.8,
                exact_match: 0.8,
                monitoring: false
            )
        ),
  
        // Optional / Only for KYC
        userData: AiPriseUserData(
            first_name: 'Your Users First Name',
            middle_name: 'Your Users Middle Name',
            last_name: 'Your Users Last Name',
            date_of_birth: 'YYYY-MM-DD',
            phone_number: '+11234567890',
            email_address: '[email protected]',
            ip_address: '0.0.0.0',
            address: AiPriseUserAddress(
                address_street_1: '...',
                address_street_2: '...',
                address_city: '...',
                address_state: '...',
                address_zip_code: '...',
                address_country: '...',
            )
        ),
        
        // Optional / Only for KYC
        additionalInfo: [
            AiPriseAdditionalInfo(
                additional_info_type: 'TYPE_HERE',
                additional_info_data: 'DATA_HERE',
            ),
            AiPriseAdditionalInfo(
                additional_info_type: 'TYPE_2_HERE',
                additional_info_data: 'DATA_2_HERE',
            ),
        ],

        // CALLBACKS
        onStart: (sessionID) {
            // session started
        },
        onBusinessProfileCreated: (businessProfileId) {
            // business profile created (kyb only)
        },
        onAbandoned: (sessionID) {
            // session abandoned
        },
        onSuccess: (sessionID) {
            // session success
        },
        onComplete: (sessionID) {
            // session complete
        },
        onError: (errorCode) {
            // Error Codes:
            // SESSION_FAILED is fired when session creation fails (due to incorrect values, internet or server issues, etc)
            // SESSION_EXPIRED happens when you try to resume a session but the session ID has expired
            // SESSION_COMPLETED happens when you try to resume a session but the session has already been completed by the user
       },
    );
  }
}

Cupertino button also accepts the exact same arguments and callbacks as in the material example above.

Styling the Button

The styling is done very similar to how you would style Flutter's own button widgets (CupertinoButton, ElevatedButton, etc). Our widgets just take the styling attributes and pass it down to these native widgets so they should function exactly the same.

Material Button Styling

(i) Select the button type: elevated, filled, filledTonal, outlined or text. These correspond to the button types listed here. The default value is filled.
(ii) Pass an instance of ButtonStyle to the style argument. This will allow you to change the background color, shadow, etc. This the same ButtonStyle as used by Flutter's native material button widgets like ElevatedButton, FilledButton, etc.
(iii) Pass a custom child widget.

import 'package:flutter/material.dart';
import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

class SomeRandomMaterialWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseMaterialButton(
      // BASIC ARGUMENTS
      mode: AiPriseEnvironment.sandbox, // sandbox or production
      templateID: 'TEMPLATE_ID_HERE',
      
      // TYPE CUSTOMIZATION
      type: AiPriseMaterialButtonType.elevated,
      
      // STYLE CUSTOMIZATION
      style: ButtonStyle(
        // https://api.flutter.dev/flutter/material/ButtonStyle/ButtonStyle.html
      ),
      
      // CHILD CUSTOMIZATION
      child: Text('Start Your KYC!'),
    );
  }
}

Cupertino Button Styling

(i) Select the button type: regular or filled. The default value is filled.
(ii) Pass custom values for the following attributes: padding, color, minSize, pressedOpacity, borderRadius and alignment. These function exactly the same as the attributes of the same name in the native CupertinoButton widget. Read about them here.
(iii) Pass a custom child widget.

import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

class SomeRandomCupertinoWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseCupertinoButton(
      // BASIC ARGUMENTS
      mode: AiPriseEnvironment.sandbox, // sandbox or production
      templateID: 'TEMPLATE_ID_HERE',
      
      // TYPE CUSTOMIZATION
      type: AiPriseCupertinoButtonType.regular,
      
      // STYLE CUSTOMIZATION
      // Read about padding, color, minSize, pressedOpacity, borderRadius and aligment here: https://api.flutter.dev/flutter/cupertino/CupertinoButton-class.html
      
      // CHILD CUSTOMIZATION
      child: Text('Start Your KYC!'),
    );
  }
}

Styling the Verification Screens

To customize the verification screens (the onboarding screens that open up after you click the button) you can pass in the theme options which are documented here. This attribute functions exactly the same in both material and cupertino buttons as well as in the AiPriseFrame widget documented below.

import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

class SomeRandomMaterialWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseMaterialButton(
      // BASIC ARGUMENTS
      mode: AiPriseEnvironment.sandbox, // sandbox or production
      templateID: 'TEMPLATE_ID_HERE',
      
      // THEME OPTIONS
      theme: AiPriseThemeOptions(
        background: "dark",
        color_brand: "#5251FD",
        font_name: "Poppins",
        // Read the entire list here: https://docs.aiprise.com/docs/theme-customization
      ),
    );
  }
}

Option 2: AiPriseFrame

This widget allows you to integrate the verification flow pages directly into your app using a webview. Unlike the button, in the AiPriseFrame widget, you take the responsibility or showing the verification flow (after some user action like a button click) and hiding it when the user has filled the entire form.

Just like the button, the templateID and mode are the only required attribute. You can add others as per your needs.

Basic Usage

import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

class SomeRandomWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseFrame(
      mode: AiPriseEnvironment.sandbox, // sandbox or production
      templateID: 'TEMPLATE_ID_HERE'
    );
  }
}

Advanced Usage

Similar to the button widget, you can pass additional attributes here like callback URL, user data, etc. Full list of attributes are visible in the example below.

There are 4 callbacks that you can listen to: onStart, onSuccess, onComplete & onError. These work exactly the same way as described in the button widget above. Ideally, you may want to listen to the onComplete callbacks to hide the frame after the verification is completed.
Note: There is no onAbandoned callback here unlike the button since frame's cant be abandoned. It's always visible till the host application i.e. your app hides it.

import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

class SomeRandomWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseFrame(
        // ARGUMENTS
        mode: AiPriseEnvironment.sandbox, // sandbox or production
        templateID: 'TEMPLATE_ID_HERE',

        callbackURL: 'http://yourcallbackurl.com',
        eventsCallbackURL: 'http://yourcallbackurl.com',

        clientReferenceID: 'SOME_ID_YOU_WANT_TO_ASSOCIATE_WITH_YOUR_REQUEST',
        clientReferenceData: {'some_data': 'some_value'},
  
        uiOptions: AiPriseUiOptions(
            id_verification_module: AiPriseUiOptionIdVerification(
                allowed_country_code: 'US' // 2-Letter Country Code. Disables all other countries.
            )
        ),
        verificationOptions: AiPriseVerificationOptions(
            AML_CONFIG: AiPriseVerificationOptionAmlConfig(
                fuzziness_score: 0.8,
                exact_match: 0.8,
                monitoring: false
            )
        ),
          
        // Optional / Only for KYC
        userData: AiPriseUserData(
            first_name: 'Your Users First Name',
            middle_name: 'Your Users Middle Name',
            last_name: 'Your Users Last Name',
            date_of_birth: 'YYYY-MM-DD',
            phone_number: '+11234567890',
            email_address: '[email protected]',
            ip_address: '0.0.0.0',
            address: AiPriseUserAddress(
                address_street_1: '...',
                address_street_2: '...',
                address_city: '...',
                address_state: '...',
                address_zip_code: '...',
                address_country: '...',
            )
        ),
          
        // Optional / Only for KYC
        additionalInfo: [
            AiPriseAdditionalInfo(
                additional_info_type: 'TYPE_HERE',
                additional_info_data: 'DATA_HERE',
            ),
            AiPriseAdditionalInfo(
                additional_info_type: 'TYPE_2_HERE',
                additional_info_data: 'DATA_2_HERE',
            ),
        ],
          
        // THEME OPTIONS
        theme: AiPriseThemeOptions(
          background: "dark",
          color_brand: "#5251FD",
          font_name: "Poppins",
          // Read the entire list here: https://docs.aiprise.com/docs/theme-customization
        ),

        // CALLBACKS
        onStart: (sessionID) {
            // session started
        },
        onBusinessProfileCreated: (businessProfileId) {
            // business profile created (kyb only)
        },
        onSuccess: (sessionID) {
            // session success
        },
        onComplete: (sessionID) {
            // session complete
        },
        onError: (errorCode) {
            // Error Codes:
            // SESSION_FAILED is fired when session creation fails (due to incorrect values, internet or server issues, etc)
            // SESSION_EXPIRED happens when you try to resume a session but the session ID has expired
            // SESSION_COMPLETED happens when you try to resume a session but the session has already been completed by the user
        },
    );
  }
}

Resuming Sessions

Each time you click on the AiPriseButton widget and each time the AiPriseFrame widget mounts, we create a new session. However in some cases, you may want to resume an old session.

For example you allow the user to go to another tab and come back. In such cases, you can provide us the old session ID and we will resume it directly instead of creating a new one.

import 'package:aiprise_flutter_sdk/aiprise_flutter_sdk.dart';

class SomeRandomMaterialWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return AiPriseMaterialButton(
        mode: AiPriseEnvironment.sandbox, // sandbox or production
        sessionID: 'THE_ID_OF_THE_SESSION_YOU_WANT_TO_RESUME',
        templateID: 'TEMPLATE_ID_HERE', // This will be ignored when resuming but it's a required field so always pass it
        
        onStart: (sessionID) {
            // Save the session ID in this step. Give it back to the widget when you want to resume
        },
        onResume: (sessionID) {
            // Session resumed with the provided session ID
        },
    );
  }
}

This works the same way for both the buttons and frame widgets.