Prefilling user input fields inside the subscription flow
Context
During the smallcase subscription flow, the user has to fill in a couple of inputs like PAN, Name, DOB, Email, Mobile, State, Subscription duration and Offer code.
Objective
This integration doc outlines the changes required so that you can pass available data points to smallcase so that those data points are prefilled for the user to confirm and proceed ahead.
Approach
Steps to prefill data
- Before opening the smallcase distribution module via SDK, your backend will
- Create a JSON payload with available data points (refer appendix 1 for JSON schema)
- Convert JSON to string
- Encrypt the string using AES-256-CBC algo and shared secret (refer appendix 2 for encryption logic)
- On the client side, your website/app will launch the distribution module by passing the encrypted data a “param” (refer appendix 3 for details)
- Once SDK launches the distribution module and the user eventually starts the subscription flow, smallcase will decrypt the data on the server and prefill the masked data on the UI
Appendices
Appendix 1: JSON data format (with sample)
Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON schema for pre-populating user input fields during subscription flow for fee-based smallcase",
"type": "object",
"properties": {
"pan": {
"type": "string",
"description": "PAN number"
},
"name": {
"type": "string",
"description": "Investor name as per PAN"
},
"dob": {
"type": "string",
"description": "Date of birth as per PAN (YYYY-MM-DD format)"
},
"mobile": {
"type": "object",
"properties": {
"countryCode": {
"type": "string",
"description": "Country code with plus sign. Eg. +91, +1, +44"
},
"number": {
"type": "string",
"description": "Mobile number without country code. Eg. 9876543210"
}
},
"description": "mobile number with country code"
},
"email": {
"type": "string",
"description": "Email address"
},
"subscriptionOfferCode": {
"type": "string",
"description": "Offer code to be auto-applied during subscription flow"
},
"subsriptionPlanDuration": {
"type": "string",
"description": "Duration for which the offer code is applied. This is required for the offer code to be applied"
},
"state": {
"type": "string",
"description": "State name if in India, otherwise `Outside India`",
"enum": ["Andaman and Nicobar Islands", "Andhra Pradesh", "Arunachal Pradesh", "Assam", "Bihar", "Chandigarh", "Chhattisgarh", "Dadra and Nagar Haveli", "Daman and Diu", "Delhi", "Goa", "Gujarat", "Haryana", "Himachal Pradesh", "Jammu and Kashmir", "Jharkhand", "Karnataka", "Kerala", "Lakshadweep", "Madhya Pradesh", "Maharashtra", "Manipur", "Meghalaya", "Mizoram", "Nagaland", "Odisha", "Puducherry", "Punjab", "Rajasthan", "Sikkim", "Tamil Nadu", "Telangana", "Tripura", "Uttar Pradesh", "Uttarakhand", "West Bengal", "Outside India"]
}
},
"required": []
}
Sample JSON
{
"pan": "ABCPE123F",
"name": "John Doe",
"dob": "1990-12-31",
"mobile": {
"countryCode": "+91",
"number": "9876543210"
},
"email": "[email protected]",
"subscriptionOfferCode": "FLAT50",
"subsriptionPlanDuration": "1Y",
"state": "Gujarat"
}
Appendix 2: Encryption logic
- Algo: “aes-256-cbc”
- IV: randomly generated string of 16 bytes
- Key: Use the gateway secret key corresponding to the gateway used on SDK
Sample code (Node) -
const crypto = require("crypto");
const ALGORITHM = 'aes-256-cbc';
const IV_LENGTH = 16; // Must be 16 bytes for AES-256-CBC
const SHARED_GW_SECRET = 'gateway-name_blah65678aaa426d5djskjsdkjksd3232sa'; // Use the gateway secret key corresponding to the gateway used on SDK
// This function encrypts the utf-8 encoded string
// It returns the IV & Encrypted data as hex strings
function encrypt(text) {
const key = crypto.createHash('sha256').update(SHARED_GW_SECRET).digest(); // Must be 32 bytes for AES-256
const iv = crypto.randomBytes(IV_LENGTH); // Must be 16 bytes for AES-256
const cipher = crypto.createCipheriv(ALGORITHM, key, iv);
let encryptedData = cipher.update(text, 'utf8', 'hex');
encryptedData += cipher.final('hex');
return { iv: iv.toString('hex'), encryptedData };
}
// This function decrypts the encrypted data (hex) & IV (hex)
// It returns the utf-8 encoded string
function decrypt(encryptedData, _iv) {
const key = crypto.createHash('sha256').update(SHARED_GW_SECRET).digest(); // Must be 32 bytes for AES-256
const iv = Buffer.from(_iv, 'hex'); // Convert hex string to buffer
const decipher = crypto.createDecipheriv(ALGORITHM, key, iv);
let decryptedData = decipher.update(encryptedData, 'hex', 'utf8');
decryptedData += decipher.final('utf8');
return decryptedData;
}
// Partner will encrypted the data before passing that as query param to smallcase SDK's openSmallplug method
function GetEnryptedDataWithIV(text) {
const { iv, encryptedData } = encrypt(text);
// Append IV to the encrypted data, so that we can decrypt the data at our end.
// The first 16 bytes of the encrypted data will be the IV, and the rest will be the actual encrypted data
return iv + encryptedData;
}
// Decryption is not required at your end. Below method is just for testing purposes.
// In production, the partner does not have any usecase to decrypt the data. It will just send the encrypted data to the smallcase SDK.
function GetDecryptedDataFromEnryptedDataWithIV(encryptedDataWithIv) {
// first 16 bytes are IV
encryptedDataWithIv = Buffer.from(encryptedDataWithIv, 'hex');
const iv = Buffer.from(encryptedDataWithIv, 'hex').subarray(0, IV_LENGTH).toString('hex');
const data = Buffer.from(encryptedDataWithIv, 'hex').subarray(IV_LENGTH).toString('hex');
console.log('*'.repeat(20));
console.log({ iv, data });
console.log('*'.repeat(20));
return decrypt(data, iv);
}
// Sample execution -
const data = {
"pan": "ABCPE123F",
"name": "John Doe",
"dob": "31/12/1900",
"mobile": {
"countryCode": "+91",
"number": "9876543210"
},
"email": "[email protected]",
"subscriptionOfferCode": "FLAT50",
"subsriptionPlanDuration": "1Y",
"state": "Gujarat"
};
const enc = GetEnryptedDataWithIV(JSON.stringify(data));
console.log('Encrypted data that the partner will share as `ssed` query param:', enc);
const decString = GetDecryptedDataFromEnryptedDataWithIV(enc);
console.log('Gateway will read the encrypted data from URL query param and decrypt at its backend using the shared secret:', decString);
Appendix 3: Passing encrypted data to SDK
All smallcase SDK has launchSmallplug/openSmallplug method to launch distribution module. These methods accept -
- Custom URL path to launch distribution module instead of homepage (eg. directly open smallcase details page)
- Custom URL params to append query param to the URL that opens up
For the subscription flow optimisation, pass an addtiional query param - &swd=encypteduserdata, to share the encrypted data with smallcase. Using this query param (swd), smallcase will decrypt & prefill the data inside subscription flow.
Updated 12 days ago
Next steps