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 furtherMust 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 scloansor add it directly to your pubspec.yaml (check the changelog / pub.dev for the latest version):
dependencies:
scloans: ^5.2.0Then run flutter pub get.
A. Android
- 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.
NoteIf 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.
- Add the below configurations to your proguard-rules.pro file at
android/app/proguard-rules.proin 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.
NoteRunning
pod installafter 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:
- environment (required): The API environment to target.
Possible values:ScLoanEnvironment.PRODUCTION|ScLoanEnvironment.STAGING|ScLoanEnvironment.DEVELOPMENT - gateway (required): The unique name given to every gateway consumer.
Eg:moneycontrol
NoteCall
setupevery time there is any change in configuration.setupmust be the first method called. All other methods will not work ifsetuphasn'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
triggerInteraction: unified loan interactiontry {
final loanInfo = ScLoanInfo(interactionToken);
final ScLoanSuccess response = await ScLoan.triggerInteraction(loanInfo);
// Handle the response
} on ScLoanError catch (e) {
// Handle the error
}Params — ScLoanInfo:
- 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>"
}
}
NoteThe servicing dashboard (
SERVICEintent) will always throwScLoanErrorwithuser_cancelledwhen 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.
Updated 15 days ago