The Rabobank Payment Based Lending / Credit web component is a custom web component designed to streamline the integration process for implementing a loan approval system into web applications. This component simplifies the integration by encapsulating the entire loan approval process within a single web component, making it easier for clients to incorporate loan approval functionality into their applications.
To incorporate the Rabobank Payment Based Lending / Credit into your project, install it using npm or yarn:
npm i @embedded-banking-fundr/pbl@latest
yarn add @embedded-banking-fundr/pbl@latest
Configure the widget using the properties below and pass them as component properties. The web component essentially functions as an HTML element, allowing you to include HTML properties in the widget as well.
The identifier
and partner
properties are crucial for initializing the widget. Without these properties, the widget cannot function properly. They are utilized within the initWidget
function to ensure the widget operates correctly.
The properties will pre-fill input elements, and in the case of a KvK number (Chamber of Commerce number), the manual company check screen will be automated, bypassing the need for user interaction. The checks are conducted automatically, and if a company is deemed ineligible, an error modal will be displayed accordingly.
initWidget | Description | Type | Example | Required |
---|---|---|---|---|
identifier |
Identifier for the partner | string | "unique_string" |
x |
partner |
Identifier for the partner | string | "unique_string" |
x |
Webcomponent | Description | Type | Example | Required |
---|---|---|---|---|
mode |
Mode of the widget | string | "sandbox" |
|
contact-details |
Contact person's details | json | ||
contact-details.name |
Contact person's name | string | "John" |
|
contact-details.surname |
Contact person's surname | string | "Doe" |
|
contact-details.phone |
Contact person's phone number | string | "0612345678" |
|
contact-details.email |
Contact person's email address | string | "john.doe@example.com" |
|
is-modal |
Shows a button to close the widget | boolean | true |
|
kvk-number |
KVK number for the company | string | "12345678" |
|
campaign-id |
Campaign name | string | "campaign" |
|
loan-goal |
Estimated goal for the loan | string | "INVENTORY" |
|
loan-amount |
Desired amount for the loan | number | "10000" |
|
product-type |
type of product | json | ['PBL'] |
Currently there are four options for loan goals:
INVENTORY
REFINANCE
GROWTH_AND_EXPANSION
OTHER
During development, you can configure the mode as either sandbox or mock. When set to sandbox, the API URL will be automatically adjusted to utilize the testing environment for the backend. Although the endpoints are real, the majority of the data is mocked in the backend. To utilize the sandbox mode, an API key is required. It's important to note that this key differs from the production API key.
When the mode is configured as mock
, all endpoints will be mocked, removing the necessity for a backend environment. This functionality is limited to local environments and simplifies development by eliminating the reliance on an external backend environment. To activate the mock
mode, you need to initialize MSW first by following these steps:
npx msw init ./public
npx msw init ./src
In the angular.json
file, you need to include src/mockServiceWorker.js
within the assets array of the project.
npx msw init ./
npx msw init ./public
This mode is intended for actual production usage and generates genuine requests for clients. It should only be utilized when deploying to a production environment. Access to production mode requires a unique API key provided to the partner.
The isModal property is a boolean that controls the display of a special button at the top of the widget. When isModal is set to true, a button appears, offering users an additional level of interaction. This button is designed to emit the exit
event, as detailed in the Available Events and Data section. The exit
event can be leveraged to close the widget or trigger other closing-related actions, providing a convenient mechanism for managing the widget's lifecycle.
Currently, there are two product types available:
PBL
PBC
By default, both options are enabled.
- PBL: This product offers a loan to clients.
- PBC: This product offers credit and is currently available only for Rabobank clients.
Web components are universally compatible with every framework. To integrate them, simply follow the steps outlined for your preferred framework. Execute the initWidget
function to configure the partner identification. This step is crucial, as the widget will not operate properly without these specifics.
import React from 'react';
import { type ContactDetails, initWidget } from '@embedded-banking-fundr/pbl';
import '@embedded-banking-fundr/pbl/style.css';
function Widget() {
const contactDetails: ContactDetails = {
name: 'John',
surname: 'Doe',
phone: '0612345678',
email: 'john.doe@example.com',
};
const contact = JSON.stringify(contactDetails);
initWidget({
identifier: 'unique_key',
partner: 'partner_id',
});
return (
<rabobank-pbl
kvk-number="12345678"
loan-goal="INVENTORY"
mode="sandbox"
loan-amount={10000}
contact-details={contact}
/>
);
}
export default Widget;
Update your schemas in either a module or component to include "CUSTOM_ELEMENTS_SCHEMA":
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
...
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [
AppComponent,
],
schemas:[
CUSTOM_ELEMENTS_SCHEMA,
]
})
import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core';
import { initWidget } from '@embedded-banking-fundr/pbl';
import '@embedded-banking-fundr/pbl/style.css';
@Component({
selector: 'app-rabobank-pbl-container',
standalone: true,
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<rabobank-pbl
[kvkNumber]=kvkNumber
[loanGoal]=goal
[mode]=mode
[loanAmount]=amount
[contactDetails]=contact
/>`,
})
export class PblWrapperComponent {
constructor() {
initWidget({
identifier: 'unique_key',
partner: 'partner_id',
});
};
goal = 'INVENTORY';
kvkNumber = '12345678';
mode = 'mock';
amount = 10000;
contact = {
name: 'John',
surname: 'Doe',
email: 'john.doe@example.com',
phone: '0612345678',
};
}
Please be aware that when utilizing variables for the web component, the properties are in camel case. However, when directly hardcoding values to the web component, they must be in kebab case, otherwise, it will not function correctly.
<script setup lang="ts">
import {
type ContactDetails,
initWidget,
} from '@embedded-banking-fundr/pbl';
import '@embedded-banking-fundr/pbl/style.css';
const contactDetails: ContactDetails = {
name: 'John',
surname: 'Doe',
phone: '0612345678',
email: 'john.doe@example.com',
};
const contact = JSON.stringify(contactDetails);
initWidget({
identifier: 'unique_key',
partner: 'partner_id',
});
</script>
<template>
<rabobank-pbl
kvk-number='12345678'
loan-goal='INVENTORY'
mode='mock'
loan-amount=10000
:contact-details="contact"
/>
</template>
'use client';
import { useEffect, useState } from 'react';
import '@embedded-banking-fundr/pbl/style.css';
export default function Home() {
const [isFinished, setIsFinished] = useState(false);
const contactDetails = {
name: 'John',
surname: 'Doe',
phone: '0612345678',
email: 'john.doe@example.com',
};
const contact = JSON.stringify(contactDetails);
useEffect(() => {
const handleImport = async () => {
const { initWidget } = await import('@embedded-banking-fundr/pbl');
initWidget({
identifier: 'unique_key',
partner: 'partner_id',
});
setIsFinished(true);
}
handleImport();
}, []);
return isFinished && (
<rabobank-pbl
kvk-number='12345678'
loan-goal='INVENTORY'
mode="mock"
loan-amount={10000}
contact-details={contact}
/>
);
}
Customize the component's visual attributes using CSS variables. The foreground variable determines the text color, adapting it based on the background color.
<style>
rabobank-pbl {
--rabo-font-family: 'Manrope';
--rabo-foreground: 220 2% 26%;
--rabo-off-black: 0 0% 20%;
--rabo-white: 0 0% 100%;
--rabo-font-lineheight-xs: 1.00rem;
--rabo-font-lineheight-sm: 1.50rem;
--rabo-font-lineheight-md: 1.25rem;
--rabo-font-lineheight-lg: 1.50rem;
--rabo-font-lineheight-xl: 2.50rem;
--rabo-font-size-xs: 0.750rem;
--rabo-font-size-sm: 0.900rem;
--rabo-font-size-md: 1.000rem;
--rabo-font-size-lg: 1.250rem;
--rabo-font-size-xl: 2.000rem;
--rabo-primary: 202 90% 58%;
--rabo-primary-foreground: var(--rabo-white);
--rabo-secondary: 202 79% 26%;
--rabo-secondary-foreground: var(--rabo-white);
--rabo-input-disabled: 210 40% 98%;
--rabo-input-disabled-foreground: 215 11% 65%;
--rabo-button-disabled: 213 27% 84%;
--rabo-button-disabled-foreground: var(--rabo-white);
--rabo-destructive: 0 60% 52%;
--rabo-destructive-foreground: var(--rabo-white);
--rabo-success: 160 100% 40%;
--rabo-success-foreground: var(--rabo-white);
--rabo-warning: 49 93% 67%;
--rabo-warning-foreground: var(--rabo-foreground);
--rabo-border: 220 2% 74%;
--rabo-radius: 0.25rem;
--rabo-min-height: 35.5rem; /* 568px */
--rabo-max-height: 52.0rem; /* 832px */
--rabo-min-width: 23rem; /* 368px */
--rabo-max-width: 40rem; /* 640px */
--rabo-app-background: var(--rabo-white);
--rabo-navigation-bar: var(--rabo-white);
--rabo-modal-overlay: var(--rabo-off-black);
--rabo-shadow: 0 0% 0%;
--rabo-app-border-radius: 0.25rem;
--rabo-input-border: 0 0% 80%;
--rabo-input-placeholder: 210 2% 62%;
}
</style>
For optimal performance, the web component is most effective when integrated into a page where the parent element(s) either possess a fixed height or have a height set to 100%. If this prerequisite isn't fulfilled, it's recommended to introduce a wrapper or apply inline styling to ensure the web component maintains a fixed height. In cases where a fixed height is not needed, the application will utilize its minimum and maximum heights to display the content. The minimum width is set at 320px, with a default minimum height of 568px and a default maximum height of 832px. These values are customizable, as indicated in the styling section above.
The widget emits various events that can be captured by subscribing to a listener, enabling notifications for different interactions and states. Below is a list of these events along with their descriptions:
To respond to these events, you can subscribe to the listener from anywhere within your application using the subscribeToWidgetEvents function. Below is an example of how to subscribe to the listener:
import { subscribeToWidgetEvents } from '@embedded-banking-fundr/pbl';
const subscription = subscribeToWidgetEvents(({ caseId, event, reason }) => {
console.log('event', `${event}-${caseId}`);
if (event === 'error' && reason) {
console.log('error:', reason);
}
});
// Remember to unsubscribe when you're done listening to the event
subscription.unsubscribe();
This system for handling events enables you to observe and respond to different states and interactions occurring within the lending process.
Event Name | Description | Data |
---|---|---|
start |
Emitted when user starts the journey. | { partnerId, caseId } |
abandon |
Emitted when the widget closes and the flow has not been completed. | { partnerId, caseId } |
success |
Emitted when the lending process is completed. | { partnerId, caseId } |
error |
Emitted when the user isn't eligible for an offer. | { partnerId, caseId, reason } |
exit |
Emitted when the widget closes. | { partnerId, caseId } |
If it's an error event, it will include an extra property called "reason". In such instances, the reason provided can be one of the following:
Reason |
---|
GENERIC |
TIMEOUT |
RED_SCORE |
TRANSACTION_STATUS |
NO_CONNECTION_ID |
GET_TRANSACTIONS |
CONSENT_DECLINED |
CREATE_CONNECTION |
INSUFFICIENT_TRANSACTIONS |
INSUFFICIENT_REVENUE |
TRANSACTIONS_NOT_RECENT |
TRANSACTIONS_NO_MATCHES |
To trigger an error event, follow these steps:
- Switch the mode (in the widget component) to
mock
. - Navigate through the app until you reach the point where you need to select a bank for transactions.
- Choose "RegioBank" as the bank.
- Proceed further to obtain an offer.
- A rejection screen should appear, and an error event will be emitted.