diff --git a/README.md b/README.md new file mode 100644 index 0000000..05135d9 --- /dev/null +++ b/README.md @@ -0,0 +1,231 @@ +[![npm](https://img.shields.io/npm/v/fraudlabspro-nodejs.svg)](http://npm.im/fraudlabspro-nodejs) +[![npm](https://img.shields.io/npm/dm/fraudlabspro-nodejs.svg)](http://npm.im/fraudlabspro-nodejs) + +FraudLabs Pro Node.js SDK +========================= + +This Node.js module enables user to easily implement fraud detection feature into their solution using the API from https://www.fraudlabspro.com. + +Below are the features of this Node.js module: +- Fraud analysis and scoring +- IP address geolocation & proxy validation +- Email address validation +- Credit card issuing bank validation +- Transaction velocity validation +- Device transaction validation +- Blacklist validation +- Custom rules trigger +- Email notification of fraud orders +- Mobile app notification of fraud orders + +This module requires an API key to function. You may subscribe for a free API key at https://www.fraudlabspro.com + + +Installation +============ + +To install this module type the following: + + npm install fraudlabspro-nodejs + + +Usage Example +============= +### Validate Order + +#### Object Properties + +| Property Name | Property Type | Description | +| --------------------------------- | ------------- | ------------------------------------------------------------ | +| ip | string | IP address of online transaction. It supports both IPv4 and IPv6 address format. | +| first_name | string | User's first name. | +| last_name | string | User's last name. | +| username | string | User's username. | +| email | string | User's email address. | +| user_phone | string | User's phone number. | +| bill_addr | string | Street address of billing address. | +| bill_city | string | City of billing address. | +| bill_state | string | State of billing address. It supports state codes, e.g. NY (New York), for state or province of United States or Canada. Please refer to [State & Province Codes](https://www.fraudlabspro.com/developer/reference/state-and-province-codes) for complete list. | +| bill_zip_code | string | Postal or ZIP code of billing address. | +| bill_country | string | Country of billing address. It requires the input of ISO-3166 alpha-2 country code, e.g. US for United States. Please refer to [Country Codes](https://www.fraudlabspro.com/developer/reference/country-codes) for complete list. | +| user_order_id | string | Merchant identifier to uniquely identify a transaction. It supports maximum of 15 characters user order id input. | +| user_order_memo | string | Merchant description of an order transaction. It supports maximum of 200 characters. | +| amount | float | Amount of the transaction. | +| quantity | integer | Total quantity of the transaction. | +| currency | string | Currency code used in the transaction. It requires the input of ISO-4217 (3 characters) currency code, e.g. USD for US Dollar. Please refer to [Currency Codes](https://www.fraudlabspro.com/developer/reference/currency-codes) for complete list. | +| department | string | Merchant identifier to uniquely identify a product or service department. | +| payment_mode | string | Payment mode of transaction. Valid values: creditcard, affirm, paypal, googlecheckout, bitcoin, cod, moneyorder, wired, bankdeposit, elviauthorized, paymitco, cybersource, sezzle, viabill, amazonpay, pmnts_gateway, giftcard, others. | +| number | string | Billing credit card number or BIN number. | +| avs_result | string | The single character AVS result returned by the credit card processor. Please refer to [AVS & CVV2 Response Codes](https://www.fraudlabspro.com/developer/reference/avs-and-cvv2-response-codes) for details. | +| cvv_result | string | The single character CVV2 result returned by the credit card processor. Please refer to [AVS & CVV2 Response Codes](https://www.fraudlabspro.com/developer/reference/avs-and-cvv2-response-codes) for details. | +| ship_addr | string | Street address of shipping address. | +| ship_city | string | City of shipping address. | +| ship_state | string | State of shipping address. It supports state codes, e.g. NY - New York, for state or province of United States or Canada. Please refer to [State & Province Codes](https://www.fraudlabspro.com/developer/reference/state-and-province-codes) for complete list. | +| ship_zip_code | string | Postal or ZIP code of shipping address. | +| ship_country | string | Country of shipping address. It requires the input of ISO-3166 alpha-2 country code, e.g. US for United States. Please refer to [Country Codes](https://www.fraudlabspro.com/developer/reference/country-codes) for complete list. | + + +```javascript +const {FraudValidation} = require("fraudlabspro-nodejs"); + +var flp = new FraudValidation('YOUR API KEY'); + +params = { + ip: '146.112.62.105', + user_order_id: '67398', + user_order_memo: 'Online shop', + currency: 'USD', + amount: '79.89', + quantity: 1, + number: '4556553172971283', + payment_mode: 'creditcard', + first_name: 'Hector', + last_name: 'Henderson', + email: 'hh5566@gmail.com', + user_phone: '561-628-8674', + bill_addr: '1766 Powder House Road', + bill_city: 'West Palm Beach', + bill_state: 'FL', + bill_zip_code: '33401', + bill_country: 'US', + ship_addr: '4469 Chestnut Street', + ship_city: 'Tampa', + ship_state: 'FL', + ship_zip_code: '33602', + ship_country: 'US', +}; +flp.validate(params, flpResults); + +function flpResults(err, res, data) { + if (!err && res.statusCode == 200) { + console.log(data); + } +} +``` + + +### Get Transaction + +#### Parameter Properties + +| Parameter Name | Parameter Type | Description | +| -------------- | -------------- | ------------------------------------------------------------ | +| id | string | FraudLabs Pro transaction ID or Order ID. | +| id_type | string | ID type. Valid values: fraudlabspro_id, user_order_id | + + +```javascript +const {FraudValidation} = require("fraudlabspro-nodejs"); + +var flp = new FraudValidation('YOUR API KEY'); + +params = { + id: '20170906MXFHSTRF', + id_type: 'fraudlabspro_id', +}; +flp.getTransaction(params, flpResults); + +function flpResults(err, res, data) { + if (!err && res.statusCode == 200) { + console.log(data); + } +} +``` + + +### Feedback + +#### Object Properties + +| Property Name | Property Type | Description | +| ------------- | ------------- | ------------------------------------------------------------ | +| id | string | Unique transaction ID generated from **Validate** function. | +| action | string | Perform APPROVE, REJECT, or REJECT_BLACKLIST action to transaction. | +| note | string | Notes for the feedback request. | + + +```javascript +const {FraudValidation} = require("fraudlabspro-nodejs"); + +var flp = new FraudValidation('YOUR API KEY'); + +params = { + id: '20170906MXFHSTRF', + action: 'APPROVE', + note: 'This customer made a valid purchase before.', +}; +flp.feedback(params, flpResults); + +function flpResults(err, res, data) { + if (!err && res.statusCode == 200) { + console.log(data); + } +} +``` + + +*** + + +## SMS Verification + +### Send SMS Verification + +#### Object Properties + +| Property Name | Property Type | Description | +| ------------- | :-----------: | ------------------------------------------------------------ | +| tel | string | The recipient mobile phone number in E164 format which is a plus followed by just numbers with no spaces or parentheses. | +| mesg | string | The message template for the SMS. Add as placeholder for the actual OTP to be generated. Max length is 140 characters. | +| otp_timeout | integer | Timeout feature for OTP value in seconds. Default is 3600 seconds(1 hour). Max timeout is 86400 seconds(24 hours). | +| country_code | string | ISO 3166 country code for the recipient mobile phone number. If parameter is supplied, then some basic telephone number validation is done. | + + +```javascript +const {SMSVerification} = require("fraudlabspro-nodejs"); + +var sms = new SMSVerification('YOUR API KEY'); + +params = { + tel: '+123456789', + mesg: 'Hi, your OTP is .', + otp_timeout: 3600, + country_code: 'US', +}; +sms.sendSMS(params, flpResults); + +function flpResults(err, res, data) { + if (!err && res.statusCode == 200) { + console.log(data); + } +} +``` + + +### Get SMS Verification Result + +#### Object Properties + +| Property Name | Property Type | Description | +| ------------- | :-----------: | ------------------------------------------------------------ | +| tran_id | string | The unique ID that was returned by the Send SMS Verification that triggered the OTP sms. | +| otp | string | The OTP that was sent to the recipient’s phone. | + + +```javascript +const {SMSVerification} = require("fraudlabspro-nodejs"); + +var sms = new SMSVerification('YOUR API KEY'); + +params = { + tran_id: 'UNIQUE_TRANS_ID', + otp: 'OTP_RECEIVED', +}; +sms.verifyOTP(params, flpResults); + +function flpResults(err, res, data) { + if (!err && res.statusCode == 200) { + console.log(data); + } +} +``` \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..704fc15 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "fraudlabspro-nodejs", + "version": "2.0.0", + "description": "FraudLabs Pro Node.js module enables users to easily implement fraud detection feature using the FraudLabs Pro API.", + "keywords": ["fraud prevention", "fraud detection", "fraud checker", "fraudlabs pro", "fraudlabspro", "fraud protection"], + "homepage": "https://github.com/fraudlabspro/fraudlabspro-nodejs", + "author": { + "name": "FraudLabsPro.com", + "email": "sales@fraudlabspro.com", + "url": "https://www.fraudlabspro.com/" + }, + "files": ["src/fraudlabspro.js","src/test.js","./README.md"], + "main": "src/fraudlabspro.js", + "license" : "MIT", + "repository": { + "type": "git", + "url": "https://github.com/fraudlabspro/fraudlabspro-nodejs.git" + } +} diff --git a/src/fraudlabspro.js b/src/fraudlabspro.js new file mode 100644 index 0000000..3eb5d2e --- /dev/null +++ b/src/fraudlabspro.js @@ -0,0 +1,340 @@ +var https = require('https'); +var crypto = require('crypto'); +var VERSION = '2.0.0'; +var SOURCE = 'FraudLabsPro Node.js SDK'; +var FORMAT = 'json'; + +function doHash(myStr) { + let stuff = 'fraudlabspro_'; + let hashStr = stuff + myStr; + for (let i = 0; i < 65536; i++) { + let hash = crypto.createHash('sha1'); + hash.update(stuff + hashStr); + hashStr = hash.digest('hex'); + } + return hashStr; +} + +class FraudValidation { + constructor(key) { + this.apiKey = key; + } + + validate(params, callback) { + let data = { + key: this.apiKey, + format: FORMAT, + source: SOURCE, + source_version: VERSION, + flp_checksum: + 'flp_checksum' in params ? params['flp_checksum'] : '', + + // Billing information + ip: 'ip' in params ? params['ip'] : '', + first_name: 'first_name' in params ? params['first_name'] : '', + last_name: 'last_name' in params ? params['last_name'] : '', + username_hash: + 'username_hash' in params ? params['username_hash'] : '', + email: 'email' in params ? params['email'] : '', + email_domain: + 'email_domain' in params ? params['email_domain'] : '', + email_hash: 'email_hash' in params ? params['email_hash'] : '', + user_phone: 'user_phone' in params ? params['user_phone'] : '', + bill_addr: 'bill_addr' in params ? params['bill_addr'] : '', + bill_city: 'bill_city' in params ? params['bill_city'] : '', + bill_state: 'bill_state' in params ? params['bill_state'] : '', + bill_zip_code: + 'bill_zip_code' in params ? params['bill_zip_code'] : '', + bill_country: + 'bill_country' in params ? params['bill_country'] : '', + + // Order information + user_order_id: + 'user_order_id' in params ? params['user_order_id'] : '', + user_order_memo: + 'user_order_memo' in params ? params['user_order_memo'] : '', + amount: 'amount' in params ? params['amount'] : '', + quantity: 'quantity' in params ? params['quantity'] : '', + currency: 'currency' in params ? params['currency'] : 'USD', + department: 'department' in params ? params['department'] : '', + payment_mode: + 'payment_mode' in params ? params['payment_mode'] : '', + + // Credit card information + bin_no: 'bin_no' in params ? params['bin_no'] : '', + card_hash: 'card_hash' in params ? params['card_hash'] : '', + avs_result: 'avs_result' in params ? params['avs_result'] : '', + cvv_result: 'cvv_result' in params ? params['cvv_result'] : '', + + // Shipping information + ship_addr: 'ship_addr' in params ? params['ship_addr'] : '', + ship_city: 'ship_city' in params ? params['ship_city'] : '', + ship_state: 'ship_state' in params ? params['ship_state'] : '', + ship_zip_code: + 'ship_zip_code' in params ? params['ship_zip_code'] : '', + ship_country: + 'ship_country' in params ? params['ship_country'] : '', + }; + + // here we do additional processing/filtering if need be + if ( + data['username_hash'] == '' && + 'username' in params && + params['username'] != '' + ) { + data['username_hash'] = doHash(params['username']); + } + if ( + data['email_domain'] == '' && + 'email' in params && + params['email'].indexOf('@') != -1 + ) { + data['email_domain'] = params['email'].substring( + params['email'].indexOf('@') + 1 + ); + } + if ( + data['email_hash'] == '' && + 'email' in params && + params['email'].indexOf('@') != -1 + ) { + data['email_hash'] = doHash(params['email']); + } + if (data['card_hash'] == '' && 'number' in params) { + data['card_hash'] = doHash(params['number']); + } + if (data['bin_no'] == '' && 'number' in params) { + data['bin_no'] = params['number'].substring(0, 9); + } + data['user_phone'] = data['user_phone'].replace(/\D/g, ''); + if (data['amount'] != '' && !isNaN(data['amount'])) { + data['amount'] = parseFloat(data['amount']).toFixed(2); + } + + let dataStr = ''; + + Object.keys(data).forEach(function (key, index) { + if (this[key] != '') { + dataStr += key + '=' + encodeURIComponent(this[key]) + '&'; + } + }, data); + + dataStr = dataStr.substring(0, dataStr.length - 1); + + let options = { + hostname: 'api.fraudlabspro.com', + port: 443, + path: '/v1/order/screen', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(dataStr), + }, + }; + + let d = ''; + let req = https.request(options, function (res) { + res.on('data', (chunk) => (d = d + chunk)); + res.on('end', function () { + callback(null, res, JSON.parse(d)); + }); + }); + + req.write(dataStr); + req.end(); + req.on('error', function (e) { + callback(e); + }); + } + + feedback(params, callback) { + let data = { + key: this.apiKey, + format: FORMAT, + source: SOURCE, + source_version: VERSION, + + id: 'id' in params ? params['id'] : '', + action: 'action' in params ? params['action'] : '', + note: 'note' in params ? params['note'] : '', + }; + + let dataStr = ''; + + Object.keys(data).forEach(function (key, index) { + if (this[key] != '') { + dataStr += key + '=' + encodeURIComponent(this[key]) + '&'; + } + }, data); + + dataStr = dataStr.substring(0, dataStr.length - 1); + + let options = { + hostname: 'api.fraudlabspro.com', + port: 443, + path: '/v1/order/feedback', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(dataStr), + }, + }; + + let d = ''; + let req = https.request(options, function (res) { + res.on('data', (chunk) => (d = d + chunk)); + res.on('end', function () { + callback(null, res, JSON.parse(d)); + }); + }); + + req.write(dataStr); + req.end(); + req.on('error', function (e) { + callback(e); + }); + } + + getTransaction(params, callback) { + let data = { + key: this.apiKey, + format: FORMAT, + source: SOURCE, + source_version: VERSION, + + id: 'id' in params ? params['id'] : '', + id_type: 'id_type' in params ? params['id_type'] : '', + }; + + let urlStr = 'https://api.fraudlabspro.com/v1/order/result?'; + + Object.keys(data).forEach(function (key, index) { + if (this[key] != '') { + urlStr += key + '=' + encodeURIComponent(this[key]) + '&'; + } + }, data); + + urlStr = urlStr.substring(0, urlStr.length - 1); + + let d = ''; + let req = https.get(urlStr, function (res) { + res.on('data', (chunk) => (d = d + chunk)); + res.on('end', function () { + callback(null, res, JSON.parse(d)); + }); + }); + + req.on('error', function (e) { + callback(e); + }); + } +} + +class SMSVerification { + constructor(key) { + this.apiKey = key; + } + + sendSMS(params, callback) { + let data = { + key: this.apiKey, + format: FORMAT, + source: SOURCE, + source_version: VERSION, + + tel: 'tel' in params ? params['tel'] : '', + otp_timeout: + 'otp_timeout' in params ? params['otp_timeout'] : '3600', + mesg: 'mesg' in params ? params['mesg'] : '', + country_code: + 'country_code' in params ? params['country_code'] : '', + }; + + let dataStr = ''; + + Object.keys(data).forEach(function (key, index) { + if (this[key] != '') { + dataStr += key + '=' + encodeURIComponent(this[key]) + '&'; + } + }, data); + + dataStr = dataStr.substring(0, dataStr.length - 1); + + let options = { + hostname: 'api.fraudlabspro.com', + port: 443, + path: '/v1/verification/send', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(dataStr), + }, + }; + + let d = ''; + let req = https.request(options, function (res) { + res.on('data', (chunk) => (d = d + chunk)); + res.on('end', function () { + callback(null, res, JSON.parse(d)); + }); + }); + + req.write(dataStr); + req.end(); + req.on('error', function (e) { + callback(e); + }); + } + + verifyOTP(params, callback) { + let data = { + key: this.apiKey, + format: FORMAT, + source: SOURCE, + source_version: VERSION, + + tran_id: 'tran_id' in params ? params['tran_id'] : '', + otp: 'otp' in params ? params['otp'] : '', + }; + + let dataStr = ''; + + Object.keys(data).forEach(function (key, index) { + if (this[key] != '') { + dataStr += key + '=' + encodeURIComponent(this[key]) + '&'; + } + }, data); + + dataStr = dataStr.substring(0, dataStr.length - 1); + + let options = { + hostname: 'api.fraudlabspro.com', + port: 443, + path: '/v1/verification/result', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': Buffer.byteLength(dataStr), + }, + }; + + let d = ''; + let req = https.request(options, function (res) { + res.on('data', (chunk) => (d = d + chunk)); + res.on('end', function () { + callback(null, res, JSON.parse(d)); + }); + }); + + req.write(dataStr); + req.end(); + req.on('error', function (e) { + callback(e); + }); + } +} + +module.exports = { + FraudValidation: FraudValidation, + SMSVerification: SMSVerification, +}; diff --git a/src/test.js b/src/test.js new file mode 100644 index 0000000..5273e29 --- /dev/null +++ b/src/test.js @@ -0,0 +1,42 @@ +// const {FraudValidation, SMSVerification} = require("fraudlabspro-nodejs"); +// const {FraudValidation, SMSVerification} = require("./fraudlabspro.js"); +// const {FraudValidation} = require("./fraudlabspro.js"); +// const {SMSVerification} = require("./fraudlabspro.js"); + +// var flp = new FraudValidation('YOUR API KEY'); +// var sms = new SMSVerification('YOUR API KEY'); + +// params = { + // ip: '8.8.8.8' +// }; +// flp.validate(params, flpResults); + +// params = { + // id: '20210716AZ1ZIC', + // action: 'REJECT', +// }; +// flp.feedback(params, flpResults); + +// params = { + // id: '20210716AZ1ZIC', + // id_type: 'fraudlabspro_id', +// }; +// flp.getTransaction(params, flpResults); + +// params = { + // tel: '+1234567890', + // mesg: 'Hello, your OTP is .', +// }; +// sms.sendSMS(params, flpResults); + +// params = { + // tran_id: 'fG8Ee2w88DBD3HjzBz0', + // otp: '649114', +// }; +// sms.verifyOTP(params, flpResults); + +function flpResults(err, res, data) { + if (!err && res.statusCode == 200) { + console.log(data); + } +}