-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathutils.js
More file actions
105 lines (95 loc) · 3.35 KB
/
utils.js
File metadata and controls
105 lines (95 loc) · 3.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
const requestPromise = require('request-promise-native');
const {
novaEnv,
novaAccessTokenUrl,
novaPassportUrl,
novaClientId,
novaSecretKey,
} = process.env;
const novaBasicAuthCreds = Buffer.from(`${novaClientId}:${novaSecretKey}`).toString('base64');
const BORROW_LOAN_DECISION_THRESHOLD = 650;
/**
* For demo purposes, we'll store the results of a Nova Credit Passport in-memory via a global variable
* Note that production usage should store received data in a database, associated to its respective applicant
*/
let receivedReportData = null;
const retrievePassportData = () => {
return receivedReportData;
};
/**
* Here's where the magic happens!
* Parse the credit passport we received for a given applicant, such as storing applicant metadata and analyzing the tradeline data for underwriting purposes
*/
const parseNovaPassport = ({ userArgs, publicToken }, creditPassport = {}) => {
const { // See https://docs.neednova.com/ for a full explanation of the Nova Credit Passport
personal,
scores,
meta,
currencies,
product,
tradelines,
bank_accounts,
other_assets,
public_records,
frauds,
collections,
nonsufficient_funds,
identifiers,
addresses,
employers,
other_incomes,
disputes,
notices,
metrics,
} = creditPassport;
/**
* Now that we have this data, you can easily add Nova to your existing underwriting engine.
* In this example, our underwriting decision is: accept applicants whose NOVA_SCORE_BETA is greater than BORROW_LOAN_DECISION_THRESHOLD
*/
const novaScoreObj = scores.find((score) => score.score_type === 'NOVA_SCORE_BETA');
/**
* Make our decision:
*/
const borrowLoanDecision = novaScoreObj && novaScoreObj.value > BORROW_LOAN_DECISION_THRESHOLD ? 'APPROVE' : 'DENY';
/**
* Finally, store applicant report data - refresh the page at localhost:3000/dashboard to see the results
*/
const { full_name, email } = personal || {};
receivedReportData = {
userArgs,
publicToken,
applicantName: full_name,
applicantEmail: email,
novaScore: novaScoreObj && novaScoreObj.value,
borrowLoanDecision,
};
};
/**
* Logic for handling the webhook sent by Nova Credit to the callback url once an applicant's report status has changed
*/
const handleNovaWebhook = async (publicToken, userArgs, status) => {
const body = await requestPromise.get({
url: novaAccessTokenUrl,
headers: {
Authorization: `Basic ${novaBasicAuthCreds}`, // Send client id, secret as Basic Auth, base-64 encoded
'X-ENVIRONMENT': novaEnv, // Specify the environment the applicant used to make the request (sandbox or production)
},
});
/**
* Now make a request to Nova to fetch the Credit Passport for the public token provided in the webhook (i.e., unique identifier for the credit file request in Nova's system)
*/
const accessToken = JSON.parse(body).accessToken;
const passport = await requestPromise.get({
url: novaPassportUrl,
headers: {
Authorization: `Bearer ${Buffer.from(accessToken).toString('base64')}`, // Use Bearer Auth since have accessToken, base-64 encoded
'X-ENVIRONMENT': novaEnv, // Must match the environment of the NovaConnect widget and access token
'X-PUBLIC-TOKEN': publicToken, // The unique Passport identifier sent in the callback
},
});
return parseNovaPassport({ userArgs, publicToken }, JSON.parse(passport));
};
module.exports = {
retrievePassportData,
handleNovaWebhook,
};