Skip to content

Commit 503a74d

Browse files
oschwaldugexe
authored andcommittedAug 22, 2024
Add support for risk score reasons
1 parent 89919a4 commit 503a74d

8 files changed

+99
-7
lines changed
 

‎CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
CHANGELOG
22
=========
33

4+
7.1.0-beta.1
5+
------------
6+
7+
* Added support for the new risk reasons outputs in minFraud Factors.
8+
49
7.0.0 (2024-07-08)
510
------------------
611

‎e2e/js/package-lock.json

+1-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎e2e/ts/package-lock.json

+1-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎fixtures/reasons.json

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[
2+
{
3+
"multiplier": 45,
4+
"reasons": [
5+
{
6+
"code": "ANONYMOUS_IP",
7+
"reason": "Risk due to IP being an Anonymous IP"
8+
}
9+
]
10+
},
11+
{
12+
"multiplier": 1.8,
13+
"reasons": [
14+
{
15+
"code": "TIME_OF_DAY",
16+
"reason": "Risk due to local time of day"
17+
}
18+
]
19+
},
20+
{
21+
"multiplier": 1.6,
22+
"reasons": [
23+
{
24+
"reason": "Riskiness of newly-sighted email domain",
25+
"code": "EMAIL_DOMAIN_NEW"
26+
}
27+
]
28+
},
29+
{
30+
"multiplier": 0.34,
31+
"reasons": [
32+
{
33+
"code": "EMAIL_ADDRESS_NEW",
34+
"reason": "Riskiness of newly-sighted email address"
35+
}
36+
]
37+
}
38+
]

‎src/response/models/factors.ts

+3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import * as webRecords from '../web-records';
44
import Insights from './insights';
55

66
export default class Factors extends Insights {
7+
public readonly riskScoreReasons?: records.RiskScoreReason[];
8+
79
/**
810
* An object containing GeoIP2 and minFraud Insights information about the IP
911
* address.
@@ -13,6 +15,7 @@ export default class Factors extends Insights {
1315
public constructor(response: webRecords.FactorsResponse) {
1416
super(response);
1517

18+
this.riskScoreReasons = response.risk_score_reasons;
1619
this.subscores = camelizeResponse(response.subscores) as records.Subscores;
1720
}
1821
}

‎src/response/records.ts

+29
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,35 @@ export interface Disposition {
361361
readonly ruleLabel?: string;
362362
}
363363

364+
/**
365+
* This object describes one of the reasons for the multiplier.
366+
*/
367+
export interface Reason {
368+
/**
369+
* The machine-readable code for the reason.
370+
*/
371+
code: string;
372+
/**
373+
* The human-readable description of the reason.
374+
*/
375+
reason: string;
376+
}
377+
378+
/**
379+
* The object describing the risk score multiplier and the reasons for that
380+
* multiplier.
381+
*/
382+
export interface RiskScoreReason {
383+
/**
384+
* The risk score multiplier.
385+
*/
386+
multiplier: number;
387+
/**
388+
* The reasons for the multiplier.
389+
*/
390+
reasons: Reason[];
391+
}
392+
364393
/**
365394
* This object contains scores for many of the individual risk factors that
366395
* are used to calculate the overall risk score.

‎src/response/web-records.ts

+11
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,16 @@ export interface PhoneWebRecord {
121121
readonly number_type?: string;
122122
}
123123

124+
export interface ReasonWebRecord {
125+
code: string;
126+
reason: string;
127+
}
128+
129+
export interface RiskScoreReasonWebRecord {
130+
multiplier: number;
131+
reasons: ReasonWebRecord[];
132+
}
133+
124134
export interface SubscoresWebRecord {
125135
readonly avs_result?: number;
126136
readonly billing_address?: number;
@@ -172,5 +182,6 @@ export interface InsightsResponse extends ScoreResponse {
172182
}
173183

174184
export interface FactorsResponse extends InsightsResponse {
185+
readonly risk_score_reasons?: RiskScoreReasonWebRecord[];
175186
readonly subscores: SubscoresWebRecord;
176187
}

‎src/webServiceClient.spec.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import cloneDeep = require('lodash.clonedeep');
22
import nock from 'nock';
33
import * as models from './response/models';
44
import * as insights from '../fixtures/insights.json';
5+
import reasons from '../fixtures/reasons.json';
56
import * as score from '../fixtures/score.json';
67
import * as subscores from '../fixtures/subscores.json';
78
import {
@@ -26,6 +27,7 @@ const client = new Client(auth.user, auth.pass);
2627
describe('WebServiceClient', () => {
2728
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2829
const factors = cloneDeep(insights) as any;
30+
factors.response.full.risk_score_reasons = cloneDeep(reasons);
2931
factors.response.full.subscores = cloneDeep(subscores);
3032

3133
describe('factors()', () => {
@@ -36,7 +38,7 @@ describe('WebServiceClient', () => {
3638
});
3739

3840
it('handles "full" responses', async () => {
39-
expect.assertions(167);
41+
expect.assertions(172);
4042

4143
nockInstance
4244
.post(fullPath('factors'), factors.request.basic)
@@ -251,6 +253,14 @@ describe('WebServiceClient', () => {
251253
);
252254
expect(got.warnings?.[0].inputPointer).toEqual('/shipping/city');
253255

256+
expect(got.riskScoreReasons).toHaveLength(4);
257+
expect(got.riskScoreReasons?.[0].multiplier).toEqual(45);
258+
expect(got.riskScoreReasons?.[0].reasons).toHaveLength(1);
259+
expect(got.riskScoreReasons?.[0].reasons[0].code).toEqual('ANONYMOUS_IP');
260+
expect(got.riskScoreReasons?.[0].reasons[0].reason).toEqual(
261+
'Risk due to IP being an Anonymous IP'
262+
);
263+
254264
expect(got?.subscores?.avsResult).toEqual(0.01);
255265
expect(got?.subscores?.billingAddress).toEqual(0.02);
256266
expect(got?.subscores?.billingAddressDistanceToIpLocation).toEqual(0.03);

0 commit comments

Comments
 (0)
Please sign in to comment.