Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates fraud detection endpoint consumer #577

Merged
merged 1 commit into from
Jan 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 41 additions & 14 deletions lib/recurly/fraud.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import each from 'component-each';
import find from 'component-find';
import Emitter from 'component-emitter';
import dom from '../util/dom';
Expand Down Expand Up @@ -62,22 +61,50 @@ export class Fraud extends Emitter {
this.dataCollectorInitiated = true;

this.recurly.request.get({
route: '/fraud_data_collector',
route: '/risk/info',
done: (error, response) => {
debug('response from recurly data collector', error, response);
debug('risk info', error, response);

if (error) {
const requestFailedError = errors('fraud-data-collector-request-failed', { error });
this.emit('error', requestFailedError);
} else if (response.content) {
const form = dom.element(this.recurly.config.fraud.kount.form) || this.getHostedFieldParentForm();
const tempContainer = document.createElement('div');
tempContainer.innerHTML = response.content;
each(tempContainer.childNodes, node => {
this.attachedNodes.push(node);
form.appendChild(node);
});
this.emit('ready');
return this.emit('error', errors('fraud-data-collector-request-failed', { error }));
}

const { profiles } = response;

profiles.forEach(profile => {
snodgrass23 marked this conversation as resolved.
Show resolved Hide resolved
const { processor, params } = profile;
if (processor === 'kount') {
const configuredForm = this.recurly.config.fraud.kount.form;
const scriptElement = document.createElement('script');
const initializerElement = document.createElement('div');
const sessionIdInputElement = dom.createHiddenInput({
'data-recurly': 'fraud_session_id',
'value': params.session_id
});
const initialize = () => {
if (!window.ka) {
return this.emit('error', errors('fraud-data-collector-request-failed', {
error: 'Kount SDK failed to load.'
}));
}
// eslint-disable-next-line no-undef
const client = new ka.ClientSDK();
snodgrass23 marked this conversation as resolved.
Show resolved Hide resolved
client.autoLoadEvents();
};

scriptElement.setAttribute('src', params.script_url);
scriptElement.onload = initialize;

initializerElement.className = 'kaxsdc';
initializerElement.setAttribute('data-event', 'load');

const form = dom.element(configuredForm) || this.getHostedFieldParentForm();
form.appendChild(sessionIdInputElement);
form.appendChild(scriptElement);
form.appendChild(initializerElement);
this.emit('ready');
}
});
}
});
}
Expand Down
143 changes: 0 additions & 143 deletions test/fraud.test.js
Original file line number Diff line number Diff line change
@@ -1,143 +0,0 @@
import assert from 'assert';
import clone from 'component-clone';
import {Recurly} from '../lib/recurly';
import {fixture} from './support/fixtures';
import {initRecurly} from './support/helpers';

describe('Fraud', () => {
describe('params', () => {
var litleSessionId = '98as6d09df907asd';
var fraudSessionId = 'a0s89d09adfsadsgf34';
var data = { fraud_session_id: fraudSessionId }
var recurly;

function initializeRecurlyWithConfig(config) {
recurly = initRecurly(config);
sinon.stub(recurly, 'request');
recurly.emit('ready');
return recurly;
}

// beforeEach(() => {
// fixture('minimal');
// });

// it('inserts both fraud processor session ids when configured', () => {
// let fraudParams = initializeRecurlyWithConfig({ fraud: {
// kount: { dataCollector: true },
// litle: { sessionId: litleSessionId }
// }}).fraud.params(data);
// assert(fraudParams.length == 2);
// assert(fraudParams[0].processor == 'kount');
// assert(fraudParams[0].session_id == fraudSessionId);
// assert(fraudParams[1].processor == 'litle_threat_metrix');
// assert(fraudParams[1].session_id == litleSessionId);
// });

// it('inserts only kount processor when litle not configured', () => {
// let fraudParams = initializeRecurlyWithConfig({ fraud: {
// kount: { dataCollector: true }
// }}).fraud.params(data);
// assert(fraudParams.length == 1);
// assert(fraudParams[0].processor == 'kount');
// assert(fraudParams[0].session_id == fraudSessionId);
// });

// it('inserts only litle processor when only litle and not kount configured', () => {
// let fraudParams = initializeRecurlyWithConfig({ fraud: {
// litle: { sessionId: litleSessionId }
// }}).fraud.params(data);
// assert(fraudParams.length == 1);
// assert(fraudParams[0].processor == 'litle_threat_metrix');
// assert(fraudParams[0].session_id == litleSessionId);
// });

// it('returns empty array when both processors are not configured or ran', () => {
// let fraudParams = initializeRecurlyWithConfig({ fraud: {} }).fraud.params(data);
// assert(fraudParams.length == 0);
// });
});


describe('dataCollector', () => {
const defaultConfig = {
fraud: {
kount: { dataCollector: true },
litle: { sessionId: '98as6d09df907asd' }
}
};
let testId = 'testDataCollector';
const fixtures = {
successfulResponse: {
err: null, res: { content: `<div id='${testId}'>response from server<div>` }
},
serverError: {
err: 'server error', res: null
}
}
var recurly;
var config;

function initializeRecurlyWith(responseType) {
recurly = initRecurly(config);
sinon.stub(recurly, 'request', (function () {
return function(method, url, callback) {
callback(fixtures[responseType].err, fixtures[responseType].res);
}
})());
recurly.emit('ready');
}

// beforeEach(() => {
// fixture('minimal');
// config = clone(defaultConfig);
// });

// it("doesn't run unless set to true in config", () => {
// config.fraud.kount.dataCollector = false;
// initializeRecurlyWith('serverError');
// assert(!recurly.request.calledOnce);
// });

// it('throws general data collector error when receiving error from server', () => {
// let errorCaught = false;

// try {
// initializeRecurlyWith('serverError');
// } catch (e) {
// errorCaught = true;
// assert(e.name == 'fraud-data-collector-request-failed');
// }

// assert(recurly.request.calledOnce);
// assert(errorCaught === true);
// });

// it('throws error if no form found to inject new fields into', () => {
// fixture();
// let errorCaught = false;

// try {
// initializeRecurlyWith('successfulResponse');
// } catch (e) {
// errorCaught = true;
// assert(e.name == 'fraud-data-collector-missing-form');
// }

// assert(recurly.request.calledOnce);
// assert(errorCaught === true);
// });

// it('injects successfully received content from server', () => {
// let testId = 'testDataCollector';
// let content = `<div id='${testId}'>response from server<div>`;

// assert(window.document.getElementById(testId) === null);

// initializeRecurlyWith('successfulResponse');

// assert(recurly.request.calledOnce);
// assert(window.document.getElementById(testId) != null);
// });
});
});
3 changes: 0 additions & 3 deletions test/server/fixtures/fraud_data_collector.json

This file was deleted.

11 changes: 11 additions & 0 deletions test/server/fixtures/risk/info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"profiles": [
{
"processor": "kount",
"params": {
"session_id": "9a87s6dfaso978ljk",
"script_url": "/api/mock-200"
}
}
]
}
2 changes: 2 additions & 0 deletions test/server/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ app.use(route.get('/gift_cards/:id', json));
app.use(route.get('/items/:id', json));
app.use(route.get('/plans/:plan_id', json));
app.use(route.get('/plans/:plan_id/coupons/:id', json));
app.use(route.get('/risk/info', json));
app.use(route.get('/risk/preflights', json));
app.use(route.get('/tax', json));
app.use(route.get('/token', json));
Expand All @@ -49,6 +50,7 @@ app.use(route.get('/relay', html('relay')));
app.use(route.get('/field.html', html('field')));

app.use(route.get('/mock-404'), ctx => ctx.status = 404);
app.use(route.get('/mock-200'), ok);

app.listen(port, () => {
fs.writeFileSync(`${__dirname}/pid.txt`, process.pid, 'utf-8');
Expand Down