Flutter Loans SDK Integration

Integrate smallcase loans Flutter SDK to allow your users to apply for loans, pay, withdraw, and much more

🙌

Hey, before you read further

Must read: LAMF: Integration overview , Loans SDK integration guide

Step 1 - Install and Configure

The loans Flutter SDK by smallcase Gateway is published on pub.dev as scloans.

Add it with:

flutter pub add scloans

or add it directly to your pubspec.yaml (check the changelog / pub.dev for the latest version):

dependencies:
  scloans: ^5.2.0

Then run flutter pub get.

A. Android

  1. Configure the SDK via AndroidManifest.xml:
<activity android:name="com.smallcase.loans.features.ScLoanCustomTabActivity"
          android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <category android:name="android.intent.category.BROWSABLE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data
            android:host="<YOUR_GATEWAY_NAME>"
            android:scheme="scgateway-loans"
        />
    </intent-filter>
</activity>

Replace <YOUR_GATEWAY_NAME> with the unique gateway name given to every integration partner.

🚧

Note

If your app targets Android 12 or higher you must explicitly declare the android:exported attribute for these activities. If an activity doesn't have an explicitly-declared value for android:exported, your app can't be installed on a device that runs Android 12 or higher.

  1. Add the below configurations to your proguard-rules.pro file at android/app/proguard-rules.pro in order to use Flutter plugins without any hiccups in release mode:
#Flutter Wrapper
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.**  { *; }
-keep class io.flutter.util.**  { *; }
-keep class io.flutter.view.**  { *; }
-keep class io.flutter.**  { *; }
-keep class io.flutter.plugins.**  { *; }

# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /usr/local/google/home/samstern/android-sdk-linux/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

# Keep custom model classes
-keep class com.google.firebase.** { *; }


# To ignore minifyEnabled: true error
# https://github.com/flutter/flutter/issues/19250
#https://github.com/flutter/flutter/issues/37441
-ignorewarnings
-keep class * {
    public private *;
}

B. iOS

Go to your project's ios folder and run pod install.

📘

Note

Running pod install after adding the dependency will trigger a clone of the source repo. This operation might take time the first time it is run. Subsequent updates will be faster.


Step 2 - Environment Setup

Import the SDK and initialise it by calling the static setup method on the ScLoan class before any other method.

import 'package:scloans/sc_loan.dart';

try {
    final config = ScLoanConfig(ScLoanEnvironment.PRODUCTION, gateway);
    final ScLoanSuccess response = await ScLoan.setup(config);
    // response.data — serialised JSON string
} on ScLoanError catch (e) {
    // e.code, e.message, e.data
}

ScLoanConfig takes positional arguments — environment first, then gateway:

class ScLoanConfig {
  final ScLoanEnvironment environment;
  final String gateway;

  const ScLoanConfig(this.environment, this.gateway);
}

enum ScLoanEnvironment { DEVELOPMENT, PRODUCTION, STAGING }

Params — ScLoanConfig:

  1. environment (required): The API environment to target.
    Possible values: ScLoanEnvironment.PRODUCTION | ScLoanEnvironment.STAGING | ScLoanEnvironment.DEVELOPMENT
  2. gateway (required): The unique name given to every gateway consumer.
    Eg: moneycontrol
📘

Note

Call setup every time there is any change in configuration.
setup must be the first method called. All other methods will not work if setup hasn't completed successfully.


Step 3 - Trigger a loan interaction

All loan flows are triggered through a single method: triggerInteraction. The SDK determines the correct flow (application, repayment, withdrawal, servicing) from the interactionToken you pass in.

Interaction Token must be created before calling any Loans SDK method

All Loans SDK methods require an interaction token passed as an argument. The JWT token holds the context of the user action in the form of an Interaction ID — a unique, one-time-use ID created each time a borrower wants to interact with their loan via the SDK. Learn more in the Glossary & API documentation.

triggerInteraction: unified loan interaction

try {
    final loanInfo = ScLoanInfo(interactionToken);
    final ScLoanSuccess response = await ScLoan.triggerInteraction(loanInfo);
    // Handle the response
} on ScLoanError catch (e) {
    // Handle the error
}

Params — ScLoanInfo:

  1. interactionToken (required): The unique string you received from your backend.

Step 4 - Handle response or error

Each method returns a Future<ScLoanSuccess>. It completes with a ScLoanSuccess, or throws a ScLoanError (which implements Exception) — catch it with on ScLoanError.

Success response

class ScLoanSuccess implements ScLoanResponse {
  bool get isSuccess => true;   // always true
  final String? data;           // serialised JSON — parse to get the intent-specific payload
}

Parse response.data to read the intent-specific result. The structure of the parsed JSON depends on the interaction:

{
  "intent": "LOAN_APPLICATION",
  "userId": "string",
  "loanApplication": {
    "status": "<ApplicationStatus>"
  }
}
{
  "intent": "PAYMENT",
  "userId": "string",
  "payment": {
    "status": "<PaymentStatus>"
  }
}
{
  "intent": "WITHDRAW",
  "userId": "string",
  "withdraw": {
    "status": "<WithdrawStatus>"
  }
}
📘

Note

The servicing dashboard (SERVICE intent) will always throw ScLoanError with user_cancelled when the user closes the dashboard. This is by design — there is no specific user action that constitutes a success for the servicing flow.

See the full list of loan application statuses and their meanings here: Loan application statuses.

Error response

ScLoanError is a typed exception with the following fields:

class ScLoanError implements ScLoanResponse, Exception {
  bool get isSuccess => false;  // always false
  final int code;
  final String message;
  final String? data;           // serialised JSON — parse to get the intent-specific data
}

Read errors via the typed fields, and parse e.data for the intent-specific payload:

} on ScLoanError catch (e) {
    print(e.code);     // 1012
    print(e.message);  // user_cancelled
    final payload = e.data != null ? jsonDecode(e.data!) : null;
}

Example error payloads (the value of e.data, as a serialised JSON string):

// e.code == 1012, e.message == "user_cancelled"
{
  "intent": "LOAN_APPLICATION",
  "loanApplication": {
    "lid": "648c66ffc3488a97c9931a2d",
    "status": "SIGN_AGREEMENT"
  },
  "userId": "648c6705ee286538f7bebbbb"
}
// e.code == 3001, e.message == "existing_loan_found"
{
  "intent": "LOAN_APPLICATION",
  "userId": "64ad01ba0241316d036519c6"
}

For the full list of SDK error codes and their meanings, see SDK error codes.


Deprecated methods

The following intent-specific methods are deprecated. Use triggerInteraction() for all new integrations — the interaction token carries the intent, so a single method handles all flows. They remain available for backward compatibility and share the same signature — (ScLoanInfo loanInfo) → Future<ScLoanSuccess>:

await ScLoan.apply(loanInfo);    // @deprecated — loan origination
await ScLoan.pay(loanInfo);      // @deprecated — repayment
await ScLoan.withdraw(loanInfo); // @deprecated — withdrawal
await ScLoan.service(loanInfo);  // @deprecated — servicing dashboard

👋

Got queries? Ask our AM for an integrations support email. If an email thread exists, post queries as a reply to that.



Did this page help you?