larkfinserv-vue-multi-sdk
v1.0.0
Published
Vue.js SDK for Lark FinServ loan eligibility integration
Downloads
16
Maintainers
Readme
LarkFinServ Vue SDK
Professional Vue.js SDK for seamless integration of LarkFinServ's loan eligibility and mutual fund loan services.
Overview
LarkFinServ Vue SDK provides a modern, autonomous integration solution for embedding loan eligibility checking and mutual fund loan services directly into Vue 3 applications. The SDK features intelligent mode detection, automatic initialization, and comprehensive event handling - all with zero configuration complexity.
Key Features
- Autonomous Mode System - SDK automatically detects and handles display modes (inline, popup, embedded)
- Vue 3 Composition API - Built with modern Vue 3 patterns and best practices
- TypeScript First - Complete type safety with full TypeScript definitions
- Zero Configuration - One function call handles initialization, mode detection, and rendering
- Cross-Platform - Works seamlessly on web, iOS, and Android via Capacitor
- Hybrid HTTP Client - Automatic SSL handling for both browser and mobile platforms
- Event-Driven Architecture - Comprehensive event system for journey tracking
- Customizable UI - Brand colors, logos, and embedded mode headers
- Session Management - Automatic session persistence and restoration
- Responsive Design - Optimized for mobile and desktop viewports
Installation
Install the SDK via npm:
npm install larkfinserv-vue-sdkOr using yarn:
yarn add larkfinserv-vue-sdkDependencies: The SDK requires Vue 3.3+ and automatically includes all necessary dependencies.
Quick Start
Basic Integration (Autonomous Mode)
The SDK uses an autonomous architecture where a single function call handles everything:
<template>
<div class="app">
<button @click="checkEligibility">Check Loan Eligibility</button>
<!-- Widget automatically renders based on mode -->
<LarkFinServWidget
v-if="sdk && currentMode !== 'embedded'"
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@close="showSDK = false"
@event="handleEvent"
/>
<!-- Embedded mode: renders in page content -->
<div v-if="showSDK && currentMode === 'embedded'" class="embedded-container">
<LarkFinServWidget
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@close="showSDK = false"
@event="handleEvent"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { LarkFinServWidget, useLarkSDK } from 'larkfinserv-vue-sdk';
const {
sdk,
showSDK,
currentMode,
eligibilityResult,
error,
openEligibilityCheck,
handleEvent,
} = useLarkSDK({
apiKey: 'your-api-key',
apiSecret: 'your-api-secret',
environment: 'production',
});
// One function call - SDK handles everything
const checkEligibility = () => {
openEligibilityCheck('inline', '+919876543210');
};
</script>
<style>
.embedded-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 10000;
}
</style>Event Handling
The SDK emits events throughout the user journey:
const handleEvent = (event: SDKEventData) => {
switch (event.type) {
case 'READY':
// SDK has loaded and is ready for interaction
console.log('SDK initialized successfully');
break;
case 'ELIGIBILITY_RESULT':
// User completed the eligibility check
const result = event.data;
console.log('Loan approved:', result.amount);
// Navigate to confirmation page, show success message, etc.
break;
case 'ERROR':
// An error occurred during the process
console.error('SDK Error:', event.data.error);
// Display error message to user
break;
case 'CLOSE':
case 'CLOSE_FRAME':
// User closed the SDK widget
console.log('SDK closed by user');
break;
case 'JOURNEY_STEP_COMPLETED':
// User completed a step in the journey
console.log('Step completed:', event.data.completedStep);
// Track analytics, show progress, etc.
break;
case 'SESSION_CLEARED':
// Session was cleared (user logged out or session expired)
console.log('Session cleared');
break;
}
};Configuration
SDK Initialization Configuration
Required Parameters
interface PartnerConfig {
apiKey: string; // Your SDK API key (required)
apiSecret: string; // Your SDK API secret (required)
environment: 'production' | 'sandbox' | 'development'; // Environment mode
}Optional Parameters
interface PartnerConfig {
// Partner Information
partnerId?: string; // Unique partner identifier
partnerName?: string; // Partner display name
userId?: string; // User identifier for tracking
sessionId?: string; // Custom session ID
// User Pre-fill Data
phoneNumber?: string; // Pre-fill phone number (format: +91XXXXXXXXXX)
// Branding & Theme
theme?: {
primaryColor?: string; // Primary brand color (hex)
secondaryColor?: string; // Secondary brand color (hex)
tertiaryColor?: string; // Tertiary accent color (hex)
fontFamily?: string; // Custom font family
logoUrl?: string; // Brand logo URL (HTTPS)
name?: string; // Brand/company name
brandTagline?: string; // Brand tagline or slogan
};
// User Consent
consentData?: {
privacyConsent: boolean; // Privacy policy acceptance
promotionalConsent: boolean; // Marketing communications consent
};
// Journey State (Advanced)
currentJourneyStep?: string; // Resume from specific step
stepProgressSummary?: any; // Progress data for resumption
hasActiveLoan?: boolean; // User has active loan
loanDetails?: any; // Existing loan information
requiresEmailVerification?: boolean; // Email verification required
}Environment Configuration
The SDK supports three environments:
| Environment | Description | SDK URL | API URL |
|-------------|-------------|---------|---------|
| production | Live production environment | https://sdk-lark.larkfinserv.com | https://backend-sdk.larkfinserv.com |
| sandbox | Testing environment | https://sdk-lark.larkfinserv.in | https://backend-sdk.larkfinserv.in |
Example:
const { sdk } = useLarkSDK({
apiKey: 'sdk_live_1b744f2305b2b5b46791fdfgfdgdfgfdgdsfd',
apiSecret: 'secret_live_e8b0a7fhfdgdfgdfdfgdfdfgdfgfd',
environment: 'production',
partnerId: 'partner_abc123',
theme: {
primaryColor: '#1a73e8',
secondaryColor: '#34a853',
name: 'John Financial Services',
logoUrl: 'https://john.com/logo.png',
},
});Display Modes
The SDK supports three autonomous display modes. Each mode is automatically detected and handled by the SDK based on the parameter passed to openEligibilityCheck().
Mode 1: Inline (Modal Overlay)
Opens the SDK in a centered modal overlay with backdrop. Best for desktop web applications.
Characteristics:
- Centered modal window (500x700px)
- Semi-transparent backdrop
- Close button in header
- Responsive (full-screen on mobile)
Implementation:
<template>
<div>
<button @click="openEligibilityCheck('inline', phoneNumber)">
Check Eligibility
</button>
<!-- Renders outside page content with Teleport -->
<LarkFinServWidget
v-if="sdk"
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@close="showSDK = false"
@event="handleEvent"
/>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useLarkSDK, LarkFinServWidget } from 'larkfinserv-vue-sdk';
const phoneNumber = ref('+919876543210');
const { sdk, showSDK, currentMode, openEligibilityCheck, handleEvent } = useLarkSDK({
apiKey: 'your-key',
apiSecret: 'your-secret',
environment: 'production',
});
// SDK automatically shows modal overlay
</script>Mode 2: Popup (New Window)
Opens the SDK in a new browser window. Best for desktop applications when you want to keep the main application accessible.
Characteristics:
- New browser window (500x700px, centered)
- Independent from main application window
- Automatic window close monitoring
- Suitable for desktop browsers
Implementation:
const checkInNewWindow = () => {
// SDK automatically opens window.open()
openEligibilityCheck('popup', '+919876543210');
// SDK monitors window closure and emits CLOSE_FRAME event
};Note: Popup blockers may prevent window opening. Always call from user-initiated event (click, touch).
Mode 3: Embedded (Full-Screen)
Renders the SDK inline within the page content as a full-screen view. Best for mobile applications and single-page flows.
Characteristics:
- Full viewport rendering (100vw x 100vh)
- No modal overlay or backdrop
- Custom header with back button support
- Seamless mobile experience
Implementation:
<template>
<div>
<button @click="openEligibilityCheck('embedded', phoneNumber)">
Start Application
</button>
<!-- Embedded mode: renders in page content -->
<div v-if="showSDK && currentMode === 'embedded'" class="embedded-sdk">
<LarkFinServWidget
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
:embedded-header-config="headerConfig"
@close="handleClose"
@event="handleEvent"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useLarkSDK, LarkFinServWidget } from 'larkfinserv-vue-sdk';
const phoneNumber = ref('+919876543210');
const headerConfig = ref({
title: 'Loan Application',
backgroundColor: '#1a73e8',
textColor: '#ffffff',
backButtonColor: '#ffffff',
showBackButton: true,
});
const { sdk, showSDK, currentMode, openEligibilityCheck, handleEvent } = useLarkSDK({
apiKey: 'your-key',
apiSecret: 'your-secret',
environment: 'production',
});
const handleClose = () => {
// Handle back button click
showSDK.value = false;
// Navigate back, clear state, etc.
};
</script>
<style scoped>
.embedded-sdk {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 10000;
background: white;
}
</style>Embedded Mode Header Customization
The embedded mode supports custom header styling:
interface EmbeddedHeaderConfig {
title?: string; // Header title text
backgroundColor?: string; // Header background color (hex)
textColor?: string; // Header text color (hex)
backButtonColor?: string; // Back button color (hex)
showBackButton?: boolean; // Show/hide back button
}Example:
const headerConfig = ref({
title: 'Mutual Fund Loan',
backgroundColor: '#667eea', // Purple header
textColor: '#ffffff', // White text
backButtonColor: '#ffffff', // White back button
showBackButton: true, // Show back button
});Mode Comparison
| Feature | Inline | Popup | Embedded | |---------|--------|-------|----------| | User Experience | Modal overlay | New window | Full-screen inline | | Desktop Suitability | Excellent | Excellent | Good | | Mobile Suitability | Good | Poor | Excellent | | Main App Accessibility | Background visible | Main app accessible | App hidden | | Back Navigation | Close button | Window close | Custom back button | | Customization | Limited | Limited | Full header control | | Use Case | Quick checks | Multi-tasking | Mobile apps, complete flows |
API Reference
useLarkSDK Composable
The primary composable for SDK integration. Provides reactive state and autonomous mode handling.
Signature:
function useLarkSDK(config: PartnerConfig): UseLarkSDKReturnReturns:
interface UseLarkSDKReturn {
// Reactive State
sdk: Ref<LarkFinServSDK | null>; // SDK instance
isReady: Ref<boolean>; // SDK initialization status
isLoading: Ref<boolean>; // Loading state
showSDK: Ref<boolean>; // Widget visibility
currentMode: Ref<SDKMode>; // Current display mode
eligibilityResult: Ref<EligibilityResult | null>; // Result data
error: Ref<string | null>; // Error message
// Methods
initialize: (config?: Partial<PartnerConfig>) => Promise<void>;
openEligibilityCheck: (mode: SDKMode, phoneNumber?: string) => Promise<void>;
closeSDK: () => void;
handleEvent: (event: SDKEventData) => void;
reset: () => void;
getSessionInfo: () => SessionInfo | null;
clearSession: () => void;
}Method Details:
initialize(config?)
Initializes the SDK with optional configuration override.
await initialize({
phoneNumber: '+919876543210',
userId: 'user_123',
});openEligibilityCheck(mode, phoneNumber?)
Opens the SDK in specified mode with optional phone number.
// Inline mode with phone number
await openEligibilityCheck('inline', '+919876543210');
// Popup mode (uses pre-initialized phone)
await openEligibilityCheck('popup');
// Embedded mode with phone number
await openEligibilityCheck('embedded', '+919876543210');Parameters:
mode:'inline' | 'popup' | 'embedded'phoneNumber: Optional phone number string (format: +91XXXXXXXXXX)
Behavior:
- Automatically initializes SDK with phone number if provided
- Sets
currentModeref to selected mode - Opens popup window for 'popup' mode
- Sets
showSDKto true for 'inline' and 'embedded' modes
closeSDK()
Closes the SDK widget and cleans up.
closeSDK();handleEvent(event)
Processes SDK events. Automatically called by widget but can be used for custom handling.
handleEvent({
type: 'ELIGIBILITY_RESULT',
data: { amount: 50000, eligible: true },
});reset()
Resets all state to initial values.
reset();
// Sets: eligibilityResult = null, error = null, isReady = false, showSDK = falsegetSessionInfo()
Returns current session information.
const session = getSessionInfo();
console.log(session.sessionId, session.userId, session.partnerId);clearSession()
Clears session data and resets SDK.
clearSession();LarkFinServWidget Component
Vue component that renders the SDK interface.
Props:
interface WidgetProps {
sdk: LarkFinServSDK; // SDK instance (required)
visible: boolean; // Widget visibility (required)
mode?: SDKMode; // Display mode (default: 'inline')
closeOnBackdrop?: boolean; // Close on backdrop click (default: true)
embeddedHeaderConfig?: EmbeddedHeaderConfig; // Embedded mode header config
}Events:
@close- Emitted when widget is closed (user clicks close/back button)@event- Emitted for all SDK events withSDKEventDatapayload
Example:
<LarkFinServWidget
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
:close-on-backdrop="true"
:embedded-header-config="headerConfig"
@close="showSDK = false"
@event="handleEvent"
/>LarkFinServSDK Class
Low-level SDK class for advanced usage.
Constructor:
const sdk = new LarkFinServSDK(config: PartnerConfig);Methods:
class LarkFinServSDK {
// Initialize SDK with configuration
initialize(config?: Partial<PartnerConfig>): Promise<InitResponse>;
// Get iframe URL for manual rendering
getIframeUrl(): string;
// Get current configuration
getConfig(): PartnerConfig;
// Event system
on(event: string, callback: Function): void;
off(event: string, callback?: Function): void;
emit(event: string, data?: any): void;
// Mode handling
openInBrowser(): void; // Open in popup window
closePopup(): void; // Close popup window
// Session management
getSessionInfo(): SessionInfo;
clearSession(): void;
// Data submission
submitConsents(payload: ConsentPayload): Promise<any>;
}Event System
The SDK emits events throughout the user journey. All events follow the SDKEventData interface:
interface SDKEventData {
type: SDKEventType;
data?: any;
}
enum SDKEventType {
INITIATED = 'INITIATED',
READY = 'READY',
ELIGIBILITY_RESULT = 'ELIGIBILITY_RESULT',
ERROR = 'ERROR',
CLOSE = 'CLOSE',
CLOSE_FRAME = 'CLOSE_FRAME',
JOURNEY_STEP_COMPLETED = 'JOURNEY_STEP_COMPLETED',
SESSION_CLEARED = 'SESSION_CLEARED',
}Event Reference
| Event | When Emitted | Data Payload | Use Case |
|-------|--------------|--------------|----------|
| INITIATED | SDK popup window opened | {} | Track popup openings |
| READY | SDK loaded and ready | {} | Hide loading indicators |
| ELIGIBILITY_RESULT | User completed eligibility check | EligibilityResult | Show results, navigate to next step |
| ERROR | Error occurred | { error: SDKError } | Display error message |
| CLOSE | User clicked close button | {} | Track abandonment |
| CLOSE_FRAME | SDK iframe/window closed | {} | Cleanup, navigation |
| JOURNEY_STEP_COMPLETED | User completed a step | { completedStep, nextStep } | Analytics, progress tracking |
| SESSION_CLEARED | Session was cleared | { reason, mobileNumber } | Handle logout, re-authentication |
EligibilityResult Interface
interface EligibilityResult {
eligible: boolean; // Loan eligibility status
amount?: number; // Approved loan amount
interestRate?: number; // Interest rate (annual %)
terms?: string[]; // Loan terms and conditions
reasons?: string[]; // Rejection reasons (if not eligible)
mobile?: string; // User's mobile number
partnerId?: string; // Partner identifier
sessionId?: string; // Session identifier
selectedOffer?: { // Selected offer details
loanAmount: number;
tenure: number;
interestRate: number;
emi: number;
};
}Event Handling Example
const handleEvent = (event: SDKEventData) => {
switch (event.type) {
case 'READY':
console.log('[SDK] Ready for user interaction');
break;
case 'ELIGIBILITY_RESULT':
const result = event.data as EligibilityResult;
if (result.eligible) {
console.log(`[SDK] Approved for ₹${result.amount?.toLocaleString('en-IN')}`);
router.push({
name: 'LoanApproval',
params: {
amount: result.amount,
rate: result.interestRate,
},
});
} else {
console.log('[SDK] Application rejected:', result.reasons);
}
break;
case 'ERROR':
const error = event.data.error;
console.error(`[SDK] Error ${error.code}:`, error.message);
showNotification({
type: 'error',
message: error.message,
});
break;
case 'JOURNEY_STEP_COMPLETED':
console.log('[SDK] Completed step:', event.data.completedStep);
analytics.track('sdk_step_completed', {
step: event.data.completedStep,
next: event.data.nextStep,
});
break;
case 'CLOSE':
case 'CLOSE_FRAME':
console.log('[SDK] User closed widget');
analytics.track('sdk_closed');
break;
case 'SESSION_CLEARED':
console.log('[SDK] Session cleared, reason:', event.data.reason);
// Re-authenticate user
break;
}
};Advanced Usage Patterns
Pattern 1: Manual SDK Initialization
For use cases requiring fine-grained control over initialization timing:
import { ref, onMounted } from 'vue';
import { LarkFinServSDK } from 'larkfinserv-vue-sdk';
const sdk = ref<LarkFinServSDK | null>(null);
const isInitialized = ref(false);
onMounted(async () => {
try {
sdk.value = new LarkFinServSDK({
apiKey: import.meta.env.VITE_SDK_KEY,
apiSecret: import.meta.env.VITE_SDK_SECRET,
environment: 'production',
});
const response = await sdk.value.initialize({
partnerId: 'partner_abc123',
userId: 'user_xyz789',
phoneNumber: '+919876543210',
theme: {
primaryColor: '#1a73e8',
name: 'Acme Finance',
logoUrl: 'https://acme.com/logo.png',
},
});
console.log('SDK initialized:', response.sessionId);
console.log('Iframe URL:', sdk.value.getIframeUrl());
isInitialized.value = true;
} catch (error) {
console.error('SDK initialization failed:', error);
}
});Pattern 2: Dynamic Configuration
Update SDK configuration based on user context:
import { ref, watch } from 'vue';
import { useLarkSDK } from 'larkfinserv-vue-sdk';
const userStore = useUserStore();
const dynamicConfig = ref({
apiKey: import.meta.env.VITE_SDK_KEY,
apiSecret: import.meta.env.VITE_SDK_SECRET,
environment: 'production' as const,
userId: userStore.userId,
phoneNumber: userStore.phoneNumber,
});
const { sdk, initialize } = useLarkSDK(dynamicConfig.value);
// Re-initialize when user changes
watch(() => userStore.userId, async (newUserId) => {
if (newUserId && sdk.value) {
await initialize({
userId: newUserId,
phoneNumber: userStore.phoneNumber,
});
}
});Pattern 3: Multi-Mode Application
Support all three modes in a single application:
<template>
<div class="loan-application">
<!-- Mode selector -->
<div class="mode-selector">
<button @click="launchSDK('inline')">Quick Check (Modal)</button>
<button @click="launchSDK('popup')">Open in New Window</button>
<button @click="launchSDK('embedded')">Full Application</button>
</div>
<!-- Inline & Popup rendering -->
<LarkFinServWidget
v-if="sdk && currentMode !== 'embedded'"
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@close="handleClose"
@event="handleEvent"
/>
<!-- Embedded rendering -->
<div v-if="showSDK && currentMode === 'embedded'" class="embedded-view">
<LarkFinServWidget
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
:embedded-header-config="{
title: 'Mutual Fund Loan Application',
backgroundColor: '#1a73e8',
textColor: '#ffffff',
showBackButton: true,
}"
@close="handleClose"
@event="handleEvent"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useLarkSDK, LarkFinServWidget } from 'larkfinserv-vue-sdk';
import type { SDKMode } from 'larkfinserv-vue-sdk';
const { sdk, showSDK, currentMode, openEligibilityCheck, handleEvent } = useLarkSDK({
apiKey: import.meta.env.VITE_SDK_KEY,
apiSecret: import.meta.env.VITE_SDK_SECRET,
environment: 'production',
});
const launchSDK = async (mode: SDKMode) => {
const phoneNumber = prompt('Enter mobile number:');
if (phoneNumber) {
await openEligibilityCheck(mode, `+91${phoneNumber}`);
}
};
const handleClose = () => {
showSDK.value = false;
console.log('SDK closed');
};
</script>
<style scoped>
.embedded-view {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 10000;
background: white;
}
</style>Pattern 4: Ionic/Capacitor Integration
Integration with Ionic Framework for mobile apps:
<template>
<ion-page>
<ion-header>
<ion-toolbar>
<ion-title>Loan Services</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-button expand="block" @click="checkEligibility">
Check Loan Eligibility
</ion-button>
<!-- Embedded mode for mobile-first experience -->
<div v-if="showSDK && currentMode === 'embedded'" class="sdk-fullscreen">
<LarkFinServWidget
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
:embedded-header-config="mobileHeaderConfig"
@close="handleClose"
@event="handleEvent"
/>
</div>
</ion-content>
<!-- Inline mode as fallback -->
<LarkFinServWidget
v-if="sdk && currentMode === 'inline'"
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@close="showSDK = false"
@event="handleEvent"
/>
</ion-page>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue';
import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent, IonButton } from '@ionic/vue';
import { useLarkSDK, LarkFinServWidget } from 'larkfinserv-vue-sdk';
import { Capacitor } from '@capacitor/core';
const isMobile = computed(() => Capacitor.isNativePlatform());
const mobileHeaderConfig = ref({
title: 'Loan Application',
backgroundColor: '#3880ff',
textColor: '#ffffff',
backButtonColor: '#ffffff',
showBackButton: true,
});
const { sdk, showSDK, currentMode, openEligibilityCheck, handleEvent } = useLarkSDK({
apiKey: import.meta.env.VITE_SDK_KEY,
apiSecret: import.meta.env.VITE_SDK_SECRET,
environment: 'production',
});
const checkEligibility = async () => {
const phoneNumber = localStorage.getItem('userPhone') || '+919876543210';
const mode = isMobile.value ? 'embedded' : 'inline';
await openEligibilityCheck(mode, phoneNumber);
};
const handleClose = () => {
showSDK.value = false;
// Handle back navigation in Ionic
};
</script>
<style scoped>
.sdk-fullscreen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 99999;
background: white;
}
</style>Demo Application
A complete demo application is available in the lark-ionic-vue-demo folder:
cd lark-ionic-vue-demo
npm install
npm run devThe demo showcases:
- All three display modes (inline, popup, embedded)
- Embedded mode header customization
- Event handling
- Error management
- Result display
- Mobile-responsive design
TypeScript Support
The SDK is written in TypeScript and provides complete type definitions out of the box.
Type Imports
import type {
// Configuration
PartnerConfig,
ThemeConfig,
EmbeddedHeaderConfig,
ConsentData,
// SDK Types
SDKMode,
SDKEventData,
SDKEventType,
SDKError,
// Results
EligibilityResult,
InitResponse,
SessionInfo,
// Functions
EventHandler,
} from 'larkfinserv-vue-sdk';Type Definitions
type SDKMode = 'inline' | 'popup' | 'embedded';
enum SDKEventType {
INITIATED = 'INITIATED',
READY = 'READY',
ELIGIBILITY_RESULT = 'ELIGIBILITY_RESULT',
ERROR = 'ERROR',
CLOSE = 'CLOSE',
CLOSE_FRAME = 'CLOSE_FRAME',
JOURNEY_STEP_COMPLETED = 'JOURNEY_STEP_COMPLETED',
SESSION_CLEARED = 'SESSION_CLEARED',
}
interface EmbeddedHeaderConfig {
title?: string;
backgroundColor?: string;
textColor?: string;
backButtonColor?: string;
showBackButton?: boolean;
}TypeScript Configuration
Ensure your tsconfig.json includes:
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"jsx": "preserve",
"types": ["vite/client"]
}
}Security
Data Handling
- Client-Side: No sensitive financial data stored in browser
- Transmission: All communication over HTTPS (TLS 1.2+)
- Session: Secure session tokens with server-side validation
- Authentication: API key/secret validated server-side on each request
Best Practices
- Never expose credentials: Use environment variables for API keys
- Validate on server: Always validate results server-side
- Monitor sessions: Implement session timeout and monitoring
- Log events: Track SDK events for fraud detection
- HTTPS only: Never load SDK over HTTP in production
Content Security Policy
Add SDK domains to your CSP:
<meta http-equiv="Content-Security-Policy"
content="frame-src https://sdk-lark.larkfinserv.com https://backend-sdk.larkfinserv.com;">Browser & Platform Support
Web Browsers
| Browser | Version | Support Level | |---------|---------|---------------| | Chrome | 90+ | Full Support | | Firefox | 88+ | Full Support | | Safari | 14+ | Full Support | | Edge | 90+ | Full Support |
Mobile Platforms
| Platform | Framework | Support Level | |----------|-----------|---------------| | iOS | Safari, Capacitor | Full Support | | Android | Chrome, Capacitor | Full Support | | PWA | All modern browsers | Full Support |
Framework Compatibility
- Vue 3.3+
- Nuxt 3
- Ionic Vue 7+
- Vite 4+
- Webpack 5+
Troubleshooting
Common Issues
SDK Not Initializing
Symptom: isReady remains false
Solutions:
- Verify API credentials are correct
- Check network connectivity
- Ensure backend API is accessible
- Check browser console for errors
const { sdk, isReady, error } = useLarkSDK({
apiKey: import.meta.env.VITE_SDK_KEY,
apiSecret: import.meta.env.VITE_SDK_SECRET,
environment: 'production',
});
watch(error, (newError) => {
if (newError) {
console.error('SDK Error:', newError);
}
});Iframe Not Loading
Symptom: Blank widget or loading indicator stuck
Solutions:
- Check Content Security Policy allows iframe
- Verify SDK URL is accessible
- Check for mixed content warnings (HTTP/HTTPS)
- Inspect iframe URL:
console.log(sdk.value?.getIframeUrl())
Events Not Firing
Symptom: @event handler not called
Solutions:
- Ensure
handleEventis passed to widget - Check event listener is registered correctly
- Verify iframe origin in browser console
<LarkFinServWidget
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@event="handleEvent"
/>Popup Blocked
Symptom: Popup mode doesn't open window
Solutions:
- Call
openEligibilityCheckfrom user interaction (click event) - Check browser popup blocker settings
- Add site to browser's allowed popups list
TypeScript Errors
Symptom: Type errors in IDE
Solutions:
- Update to latest SDK version:
npm update larkfinserv-vue-sdk - Check
tsconfig.jsonhas correct settings - Restart TypeScript server in IDE
Debug Mode
Enable verbose logging:
const { sdk } = useLarkSDK({
apiKey: 'your-key',
apiSecret: 'your-secret',
environment: 'development', // Enables debug logs
});
// Manual logging
sdk.value?.on('*', (event: string, data: any) => {
console.log(`[SDK Event] ${event}`, data);
});Performance Optimization
Lazy Loading
Load SDK only when needed:
import { defineAsyncComponent } from 'vue';
const LarkFinServWidget = defineAsyncComponent(
() => import('larkfinserv-vue-sdk').then(m => m.LarkFinServWidget)
);Preloading
Preload SDK for faster initialization:
<script setup lang="ts">
import { onMounted } from 'vue';
import { useLarkSDK } from 'larkfinserv-vue-sdk';
const { initialize } = useLarkSDK({
apiKey: 'your-key',
apiSecret: 'your-secret',
environment: 'production',
});
// Initialize on mount for instant availability
onMounted(() => {
initialize();
});
</script>Migration Guide
From v1.x to v2.x
Breaking Changes:
openEligibilityChecknow accepts phone number as second parametercurrentModeref added to return object- Embedded mode requires separate rendering logic
Migration:
// v1.x
openEligibilityCheck('inline');
await sdk.value.initialize({ phoneNumber: '+919876543210' });
// v2.x (Autonomous)
openEligibilityCheck('inline', '+919876543210');Redirection Handling (KYC, Mandate, Agreement)
The SDK supports redirection handling for external flows like KYC verification, e-Mandate setup, and loan agreement signing. This section explains how to handle redirections for both websites and mobile apps.
How Redirection Works
- User initiates flow: User starts KYC/Mandate/Agreement in the SDK
- External redirect: User is redirected to external service (DigiLocker, bank, etc.)
- Success page: After completion, user lands on SDK success page
- Auto-redirect: Success page automatically redirects back to your app after 3-5 seconds
- Callback: Your app receives result data via deep link or postMessage
Using useDeepLinkHandler (Recommended)
The SDK provides a useDeepLinkHandler composable that handles all callback scenarios automatically:
- Native deep links (e.g.,
myapp://callback?...) - Web URL callbacks (e.g.,
/callback?...) - postMessage from popup/iframe
import { useLarkSDK, useDeepLinkHandler } from 'larkfinserv-vue-sdk';
import type { RedirectionEventData } from 'larkfinserv-vue-sdk';
// Handle redirection events from any source
const onRedirectionEvent = (data: RedirectionEventData) => {
console.log('Received:', data.type, data.status);
if (data.status === 'success') {
// KYC/Mandate/Agreement completed successfully
if (data.type === 'KYC_COMPLETED') {
console.log('KYC Doc ID:', data.digioDocId);
} else if (data.type === 'MANDATE_COMPLETED') {
console.log('Mandate ID:', data.mandateId);
} else if (data.type === 'LOAN_AGREEMENT_COMPLETED') {
console.log('Agreement ID:', data.agreementId);
}
} else {
console.error('Failed:', data.message);
}
};
// Initialize deep link handler - handles EVERYTHING automatically!
const {
lastRedirectionData, // Reactive ref with last callback data
getCallbackUrl, // Get correct URL for current environment
isNative, // Check if running in native app
clearCallbackData, // Clear stored callback data
} = useDeepLinkHandler({
urlScheme: 'myapp', // Your app's URL scheme
callbackPath: '/callback', // Callback path
onRedirectionEvent, // Called when any callback is received
});
// Initialize SDK with the correct callback URL
const { sdk, openEligibilityCheck, setAppRedirectionUrl } = useLarkSDK({
apiKey: 'your-key',
apiSecret: 'your-secret',
environment: 'production',
appRedirectionUrl: getCallbackUrl('myapp', '/callback'),
});
// Start loan application - SDK handles everything!
openEligibilityCheck('embedded', '+919876543210');Native App Setup (Capacitor/Ionic)
For the deep link handler to work in native apps, configure your app to handle the URL scheme:
Android Configuration
Add to android/app/src/main/AndroidManifest.xml:
<activity ...>
<!-- Existing intent filters -->
<!-- Deep Link Handler -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<!-- Replace 'myapp' with your app's scheme -->
<data android:scheme="myapp" />
</intent-filter>
</activity>iOS Configuration
Add to ios/App/App/Info.plist:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLName</key>
<string>com.yourcompany.yourapp</string>
<key>CFBundleURLSchemes</key>
<array>
<!-- Replace 'myapp' with your app's scheme -->
<string>myapp</string>
</array>
</dict>
</array>Capacitor App Plugin
Ensure @capacitor/app is installed:
npm install @capacitor/app
npx cap syncComplete Mobile Example
<template>
<ion-page>
<ion-content>
<ion-button expand="block" @click="startLoan">
Apply for Loan
</ion-button>
<!-- Show result after callback -->
<ion-card v-if="lastRedirectionData">
<ion-card-header>
<ion-card-title>
{{ lastRedirectionData.status === 'success' ? '✅' : '❌' }}
{{ formatEventType(lastRedirectionData.type) }}
</ion-card-title>
</ion-card-header>
<ion-card-content>
<p>Status: {{ lastRedirectionData.status }}</p>
<p v-if="lastRedirectionData.message">{{ lastRedirectionData.message }}</p>
</ion-card-content>
</ion-card>
<!-- SDK Widget -->
<div v-if="showSDK && currentMode === 'embedded'" class="sdk-fullscreen">
<LarkFinServWidget
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@close="showSDK = false"
@event="handleEvent"
/>
</div>
</ion-content>
</ion-page>
</template>
<script setup lang="ts">
import {
LarkFinServWidget,
useLarkSDK,
useDeepLinkHandler,
} from 'larkfinserv-vue-sdk';
import type { RedirectionEventData } from 'larkfinserv-vue-sdk';
// Deep link handler - handles native deep links, web callbacks, and postMessage
const {
lastRedirectionData,
getCallbackUrl,
} = useDeepLinkHandler({
urlScheme: 'myapp',
callbackPath: '/callback',
onRedirectionEvent: (data) => {
console.log('Callback received:', data);
// Show toast, update UI, etc.
},
});
// SDK with auto-detected callback URL
const {
sdk,
showSDK,
currentMode,
openEligibilityCheck,
handleEvent,
} = useLarkSDK({
apiKey: import.meta.env.VITE_SDK_KEY,
apiSecret: import.meta.env.VITE_SDK_SECRET,
environment: 'production',
appRedirectionUrl: getCallbackUrl('myapp', '/callback'),
});
const startLoan = () => {
openEligibilityCheck('embedded', '+919876543210');
};
const formatEventType = (type: string) => {
return type.replace(/_/g, ' ').replace(/COMPLETED/g, 'Completed');
};
</script>
<style scoped>
.sdk-fullscreen {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
z-index: 99999;
}
</style>How Auto-Redirect Works
When the user completes KYC/Mandate/Agreement in the external browser:
- Success Page Loads: User sees "KYC Successful!" with countdown
- Auto-Redirect (3-5 sec): Page automatically redirects to your
appRedirectionUrl - Deep Link Opens App: Browser opens your app via deep link
- Handler Processes:
useDeepLinkHandlerparses the URL and calls your callback - SDK Continues: User can proceed with next step in the loan journey
Example redirect URL:
myapp://callback?type=KYC_COMPLETED&status=success&digioDocId=DOC123456×tamp=1703001234567Website Integration (postMessage)
For websites, the SDK uses postMessage to communicate completion status back to the parent window.
Step 1: Listen for postMessage Events
import { onMounted, onUnmounted } from 'vue';
import type { RedirectionEventData } from 'larkfinserv-vue-sdk';
onMounted(() => {
window.addEventListener('message', handleRedirectionMessage);
});
onUnmounted(() => {
window.removeEventListener('message', handleRedirectionMessage);
});
const handleRedirectionMessage = (event: MessageEvent) => {
const data = event.data;
// Check if it's a redirection event
if (data?.type === 'KYC_COMPLETED' ||
data?.type === 'MANDATE_COMPLETED' ||
data?.type === 'LOAN_AGREEMENT_COMPLETED') {
console.log('Received redirection event:', data);
const redirectionData: RedirectionEventData = {
type: data.type,
status: data.status,
message: data.message,
digioDocId: data.digioDocId, // KYC
mandateId: data.mandateId, // Mandate
agreementId: data.agreementId, // Agreement
};
if (data.status === 'success') {
// Handle successful completion
console.log('Operation successful!');
} else {
// Handle failure
console.error('Operation failed:', data.message);
}
}
};Step 2: Use SDK's Built-in Handler (Recommended)
const {
sdk,
redirectionData,
handleRedirectionCallback,
} = useLarkSDK({
apiKey: 'your-key',
apiSecret: 'your-secret',
environment: 'production',
appRedirectionUrl: `${window.location.origin}/callback`, // For web
});
// The SDK automatically handles postMessage events and updates redirectionData
// You can also manually handle callbacks:
const handleMessage = (event: MessageEvent) => {
if (event.data?.type?.includes('COMPLETED')) {
handleRedirectionCallback(event.data);
}
};Mobile App Integration (Deep Links)
For mobile apps (Ionic/Capacitor, React Native), use deep links to redirect users back to your app.
Step 1: Configure Deep Link URL
import { Capacitor } from '@capacitor/core';
// Detect platform and set appropriate URL
const appRedirectionUrl = Capacitor.isNativePlatform()
? 'myapp://loan-callback' // Deep link for native app
: `${window.location.origin}/callback`; // Web URL for browser
const { sdk, setAppRedirectionUrl } = useLarkSDK({
apiKey: 'your-key',
apiSecret: 'your-secret',
environment: 'production',
appRedirectionUrl,
});Step 2: Configure Deep Links in Your App
Android (AndroidManifest.xml):
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="myapp" android:host="loan-callback" />
</intent-filter>iOS (Info.plist):
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>myapp</string>
</array>
</dict>
</array>Step 3: Handle Deep Link in Your App
Capacitor/Ionic:
import { App } from '@capacitor/app';
App.addListener('appUrlOpen', (event) => {
const url = new URL(event.url);
// Parse query parameters
const type = url.searchParams.get('type');
const status = url.searchParams.get('status');
const digioDocId = url.searchParams.get('digioDocId');
const mandateId = url.searchParams.get('mandateId');
const agreementId = url.searchParams.get('agreementId');
const message = url.searchParams.get('message');
if (type) {
handleRedirectionCallback({
type: type as RedirectionEventData['type'],
status: status || 'unknown',
digioDocId,
mandateId,
agreementId,
message,
});
}
});Callback Data Format
When the user completes KYC/Mandate/Agreement, the callback URL receives these parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| type | string | Event type: KYC_COMPLETED, MANDATE_COMPLETED, LOAN_AGREEMENT_COMPLETED |
| status | string | success or failed |
| message | string | Optional message (usually for errors) |
| digioDocId | string | Document ID (KYC only) |
| mandateId | string | Mandate ID (Mandate only) |
| agreementId | string | Agreement ID (Agreement only) |
Example callback URL:
myapp://loan-callback?type=KYC_COMPLETED&status=success&digioDocId=DOC123456Complete Integration Example
<template>
<div>
<button @click="startLoanApplication">Apply for Loan</button>
<!-- Show SDK widget -->
<LarkFinServWidget
v-if="sdk"
:sdk="sdk"
:visible="showSDK"
:mode="currentMode"
@close="showSDK = false"
@event="handleEvent"
/>
<!-- Show redirection result -->
<div v-if="redirectionData">
<h3>{{ redirectionData.type }}</h3>
<p>Status: {{ redirectionData.status }}</p>
<p v-if="redirectionData.message">{{ redirectionData.message }}</p>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted, computed } from 'vue';
import { Capacitor } from '@capacitor/core';
import { App } from '@capacitor/app';
import {
LarkFinServWidget,
useLarkSDK,
type RedirectionEventData
} from 'larkfinserv-vue-sdk';
const isNative = computed(() => Capacitor.isNativePlatform());
const appRedirectionUrl = computed(() =>
isNative.value
? 'myapp://loan-callback'
: `${window.location.origin}/callback`
);
const {
sdk,
showSDK,
currentMode,
redirectionData,
openEligibilityCheck,
handleEvent,
handleRedirectionCallback,
setAppRedirectionUrl,
} = useLarkSDK({
apiKey: import.meta.env.VITE_SDK_KEY,
apiSecret: import.meta.env.VITE_SDK_SECRET,
environment: 'production',
appRedirectionUrl: appRedirectionUrl.value,
});
// Handle postMessage for web
const handlePostMessage = (event: MessageEvent) => {
if (event.data?.type?.includes('COMPLETED')) {
handleRedirectionCallback(event.data);
}
};
onMounted(() => {
// Web: Listen for postMessage
window.addEventListener('message', handlePostMessage);
// Native: Listen for deep links
if (isNative.value) {
App.addListener('appUrlOpen', (event) => {
const url = new URL(event.url);
const type = url.searchParams.get('type');
if (type) {
handleRedirectionCallback({
type: type as RedirectionEventData['type'],
status: url.searchParams.get('status') || 'unknown',
digioDocId: url.searchParams.get('digioDocId'),
mandateId: url.searchParams.get('mandateId'),
agreementId: url.searchParams.get('agreementId'),
message: url.searchParams.get('message'),
});
}
});
}
});
onUnmounted(() => {
window.removeEventListener('message', handlePostMessage);
});
const startLoanApplication = () => {
openEligibilityCheck('embedded', '+919876543210');
};
</script>Dynamic App Redirection URL
You can change the redirection URL at runtime:
const { setAppRedirectionUrl } = useLarkSDK({ ... });
// Change URL before opening SDK
setAppRedirectionUrl('myapp://custom-callback');
openEligibilityCheck('embedded', phoneNumber);Redirection Event Types
| Event Type | Description | Data Fields |
|------------|-------------|-------------|
| KYC_COMPLETED | KYC/identity verification completed | status, digioDocId, message |
| MANDATE_COMPLETED | e-Mandate setup completed | status, mandateId, message |
| LOAN_AGREEMENT_COMPLETED | Loan agreement signed | status, agreementId, message |
Troubleshooting Redirections
postMessage Not Received
- Check if the SDK is running in an iframe or popup
- Verify your domain is in the allowed origins list
- Check browser console for cross-origin errors
Deep Link Not Working
- Verify URL scheme is registered in your app config
- Test deep link using:
adb shell am start -W -a android.intent.action.VIEW -d "myapp://loan-callback" - Check that the app is installed and URL scheme is unique
Callback Data Missing
- Ensure
appRedirectionUrlis set before starting the flow - Check that success pages are properly passing query parameters
- Verify URL encoding of parameters
Support & Resources
Documentation
- Autonomous Mode Guide - Detailed mode system documentation
- Integration Examples - Complete working examples
- API Reference - Complete API documentation
Support Channels
- Email: [email protected]
- Technical Support: [email protected]
- Business Inquiries: [email protected]
Issue Reporting
When reporting issues, please include:
- SDK version (
npm list larkfinserv-vue-sdk) - Vue version
- Browser/platform details
- Console errors (if any)
- Minimal reproduction code
License
MIT License - Copyright (c) 2025 LarkFinServ Private Limited
See LICENSE file for details.
Built by LarkFinServ Engineering Team
For enterprise support and custom integrations, contact [email protected]
