iin-checker
Advanced tools
Comparing version 0.1.9 to 0.6.0
# Changelog | ||
## **0.2.0** | ||
- Updating dependencies to current stable versions and updating tests to match. | ||
## **0.1.9** | ||
@@ -4,0 +7,0 @@ - [**#25**](https://github.com/Shortbreaks/iinChecker/issues/25) Switched the order of provider checking to get better API output |
module.exports = [ | ||
{ | ||
name: "PAYOUT", | ||
domain: "https://bins.payout.com", | ||
path: "/api/v1/bins/", | ||
map: function( returnedData, nullValue ) { | ||
return { | ||
iin: returnedData.bin, | ||
brand: returnedData.brand, | ||
issuer: returnedData.issuer, | ||
type: returnedData.type || nullValue, | ||
category: nullValue, | ||
country: returnedData.country_code | ||
}; | ||
} | ||
}, | ||
{ | ||
name: "RIBBON", | ||
@@ -11,6 +26,6 @@ domain: "https://bins.ribbon.co", | ||
issuer: returnedData.issuer, | ||
type: ( returnedData.type ? returnedData.type : nullValue ), | ||
type: returnedData.type || nullValue, | ||
category: nullValue, | ||
country: returnedData.country_code | ||
} | ||
}; | ||
} | ||
@@ -27,8 +42,8 @@ }, | ||
issuer: returnedData.bank, | ||
type: returnedData.card_type, | ||
type: returnedData.card_type || nullValue, | ||
category: returnedData.card_category, | ||
country: returnedData.country_code | ||
} | ||
}; | ||
} | ||
} | ||
] | ||
]; |
@@ -14,43 +14,43 @@ /* jslint node: true */ | ||
// project configuration | ||
grunt.initConfig( { | ||
jshint: { | ||
options: { | ||
jshintrc: '.jshintrc' | ||
}, | ||
core: { | ||
src: ['Gruntfile.js', 'lib/**/*.js'] | ||
}, | ||
test: { | ||
src: ['test/**/*.js'] | ||
}, | ||
json: { | ||
src: ['package.json', 'lib/**/*.json', 'test/**/*.json'] | ||
} | ||
}, | ||
jscs: { | ||
options: { | ||
config: '.jscsrc' | ||
}, | ||
files: { | ||
src: ['<%= jshint.core.src %>', '<%= jshint.test.src %>'] | ||
} | ||
}, | ||
mochaTest: { | ||
options: { | ||
reporter: 'spec' | ||
}, | ||
src: ['test/**/*.js'] | ||
} | ||
} ); | ||
// project configuration | ||
grunt.initConfig( { | ||
jshint: { | ||
options: { | ||
jshintrc: '.jshintrc' | ||
}, | ||
core: { | ||
src: ['Gruntfile.js', 'lib/**/*.js'] | ||
}, | ||
test: { | ||
src: ['test/**/*.js'] | ||
}, | ||
json: { | ||
src: ['package.json', 'lib/**/*.json', 'test/**/*.json'] | ||
} | ||
}, | ||
jscs: { | ||
options: { | ||
config: '.jscsrc' | ||
}, | ||
files: { | ||
src: ['<%= jshint.core.src %>', '<%= jshint.test.src %>'] | ||
} | ||
}, | ||
mochaTest: { | ||
options: { | ||
reporter: 'spec' | ||
}, | ||
src: ['test/**/*.js'] | ||
} | ||
} ); | ||
// load tasks from the specified grunt plugins... | ||
grunt.loadNpmTasks( 'grunt-contrib-jshint' ); | ||
grunt.loadNpmTasks( 'grunt-jscs' ); | ||
grunt.loadNpmTasks( 'grunt-mocha-test' ); | ||
// load tasks from the specified grunt plugins... | ||
grunt.loadNpmTasks( 'grunt-contrib-jshint' ); | ||
grunt.loadNpmTasks( 'grunt-jscs' ); | ||
grunt.loadNpmTasks( 'grunt-mocha-test' ); | ||
// register task alias' | ||
grunt.registerTask( 'default', ['jshint', 'jscs'] ); | ||
grunt.registerTask( 'test', ['mochaTest'] ); | ||
// register task alias' | ||
grunt.registerTask( 'default', ['jshint', 'jscs'] ); | ||
grunt.registerTask( 'test', ['mochaTest'] ); | ||
}; | ||
}; |
10
index.js
@@ -1,8 +0,2 @@ | ||
/** | ||
* @name /index.js | ||
* @description Nodejs style iinChecker include | ||
* @author Simon Wood <simon.wood@holidayextras.com> | ||
*/ | ||
module.exports = require( './lib/iinChecker' ); | ||
'use strict'; | ||
module.exports = require( './lib/iinChecker' ); |
@@ -6,3 +6,4 @@ { | ||
"PARAMETER_IIN_IS_NOT_LONG_ENOUGH" : "Parameter \"iin\" in not long enough (6 characters)", | ||
"PARAMETER_IIN_IS_INVALID" : "Parameter \"iin\" is invalid", | ||
"PARAMETER_CALLBACK_NOT_FUNCTION": "Parameter \"callback\" is not [function]" | ||
} |
@@ -0,148 +1,299 @@ | ||
'use strict'; | ||
( function() { | ||
// get some stuff we need to support IIN Checker | ||
var _ = require( 'lodash' ); | ||
var request = require( 'request' ); | ||
var EventEmitter = require( 'events' ).EventEmitter; | ||
/** | ||
* @name /lib/iinChecker.js | ||
* @description Issuer identification number checker which returns details about a credit/debit card | ||
* @author Simon Wood <simon.wood@holidayextras.com> | ||
*/ | ||
var iinChecker = function( iinOptions ) { | ||
// Load all of our providers into an array that we can loop over. | ||
this.providers = require( '../configs/providers' ); | ||
( function() { | ||
// get some stuff we need to support IIN Checker | ||
var _ = require( 'lodash' ); | ||
var request = require( 'request' ); | ||
// Load all of our providers into an array that we can loop over. | ||
var providers = require( '../configs/providers' ); | ||
// default options | ||
this.options = { | ||
language: 'en', | ||
cache: false, | ||
timeout: 1000 | ||
}; | ||
var iinChecker = function( inOptions ) { | ||
// default options | ||
this.options = { | ||
language: 'en' | ||
}; | ||
// if there's any overriding options, blat them over the defaults | ||
this.options = _.extend( this.options, iinOptions ); | ||
// if there's any overriding options, blat them over the defaults | ||
this.options = _.extend( this.options, inOptions ); | ||
// Define our constants for comparison | ||
this.nullValue = 'UNKNOWN'; /* Value incase services are offline or return null */ | ||
this.brands = { | ||
VISA: 'VISA', | ||
MASTERCARD: 'MASTERCARD', | ||
AMEX: 'AMERICAN EXPRESS', | ||
DISCOVER: 'DISCOVER', | ||
DINERS: 'DINERS CLUB', | ||
JCB: 'JCB', | ||
MAESTRO: 'MAESTRO', | ||
LASER: 'LASER', | ||
UNKNOWN: this.nullValue | ||
}; | ||
// DANKORT what do we do with this? | ||
// CHINA UNION PAY | ||
// SOLO | ||
// ELECTRON ??? Don't support? Visa Electron | ||
// Define our constants for comparison | ||
this.nullValue = 'UNKNOWN'; /* Value incase services are offline or return null */ | ||
this.brands = { | ||
VISA: 'VISA', | ||
MASTERCARD: 'MASTERCARD', | ||
AMEX: 'AMERICAN EXPRESS', | ||
DISCOVER: 'DISCOVER', | ||
DINERS: 'DINERS CLUB', | ||
JCB: 'JCB', | ||
MAESTRO: 'MAESTRO', | ||
LASER: 'LASER', | ||
UNKNOWN: this.nullValue | ||
}; | ||
// DANKORT what do we do with this? | ||
// CHINA UNION PAY | ||
// SOLO | ||
// ELECTRON ??? Don't support? Visa Electron | ||
// DINERS has been added for RegEx, but both Robbin and BinList return these cards as DISCOVER | ||
// TODO: Change this later to be consitent across RegEx and providers | ||
// DINERS has been added for RegEx, but both Robbin and BinList return these cards as DISCOVER | ||
// TODO: Change this later to be consitent across RegEx and providers | ||
this.types = { | ||
DEBIT: 'DEBIT', | ||
CREDIT: 'CREDIT', | ||
UNKNOWN: this.nullValue | ||
}; | ||
this.types = { | ||
DEBIT: 'DEBIT', | ||
CREDIT: 'CREDIT', | ||
UNKNOWN: this.nullValue | ||
}; | ||
// now fetch the language settings based on the requested language | ||
this.options.messages = require( './i18n/' + this.options.language ); // ISO 639‑1 | ||
// now fetch the language settings based on the requested language | ||
this.options.messages = require( './i18n/' + this.options.language ); // ISO 639‑1 | ||
this.isCacheable = function( cardInfo ) { | ||
var self = this; | ||
// we don't have a cache | ||
if ( !self.options.cache ) { | ||
return false; | ||
} | ||
// we don't want to cache cards we don't know the brand for | ||
if ( !cardInfo.brand || cardInfo.brand === self.brands.UNKNOWN ) { | ||
return false; | ||
} | ||
this.makeRequest = function( iin, providerCount, callback ) { | ||
var self = this; | ||
var cardInfo; | ||
var providerDetails = providers[providerCount]; | ||
request( { url: providerDetails.domain + providerDetails.path + iin, json: true }, function( error, response, body ) { | ||
if ( !error && response.statusCode === 200 ) { | ||
// Remap the reply to match our schema | ||
cardInfo = providerDetails.map( body, self.nullValue ); | ||
// send the results back a-la-node | ||
callback( null, cardInfo ); | ||
} else { | ||
if( ++providerCount < providers.length ) { | ||
self.makeRequest( iin, providerCount, callback ); | ||
} else { | ||
// Maybe one last attempt here with RegEx? If that does not work then error | ||
var patterns = require( '../configs/patterns' ); | ||
// we don't want to cache cards we don't know the type of | ||
if ( !cardInfo.type || cardInfo.type === this.nullValue ) { | ||
return false; | ||
} | ||
// Set out null info object | ||
cardInfo = { | ||
iin: iin, | ||
brand: null, | ||
issuer: self.nullValue, | ||
type: self.nullValue, | ||
category: self.nullValue, | ||
country: self.nullValue | ||
}; | ||
// we can cache this card | ||
return true; | ||
}; | ||
_.each( patterns, function( pattern ) { | ||
var regex = new RegExp( pattern.expression ); | ||
if( !cardInfo.brand && regex.test( iin ) ) { | ||
cardInfo.brand = self.brands[pattern.name]; | ||
} | ||
} ); | ||
this.flipBrandWhereNecessary = function( cardInfo ) { | ||
var self = this; | ||
var firstNumber = parseInt( cardInfo.iin.charAt(0), 10 ); | ||
if ( cardInfo.brand === self.brands.MASTERCARD && firstNumber === 4 ) { | ||
cardInfo.brand = self.brands.VISA; | ||
} else if ( cardInfo.brand === self.brands.VISA && firstNumber === 5 ) { | ||
cardInfo.brand = self.brands.MASTERCARD; | ||
} | ||
return cardInfo; | ||
}; | ||
}; | ||
// See if RegEx worked | ||
if ( cardInfo.brand && cardInfo.brand !== self.brands.UNKNOWN ) { | ||
callback( null, cardInfo ); | ||
} else { | ||
// Return the err in the error callback, or if no error send back the http status code | ||
callback( error || response.statusCode ); | ||
} | ||
} | ||
} | ||
} ); | ||
}; | ||
}; | ||
// create a shorthand then export the IinChecker object for Nodejs | ||
exports = module.exports = iinChecker; | ||
// create a shorthand then export the IinChecker object for Nodejs | ||
exports = module.exports = iinChecker; | ||
/** | ||
* Lookup a card by its IIN and return a card object | ||
* | ||
* @param {String} iin the number to check | ||
* @param {Function} callback function to return the card details/error | ||
* @return {Boolean} returns true unless there is no callback supplied | ||
*/ | ||
iinChecker.prototype.lookup = function( iin, callback ) { | ||
var self = this; | ||
var emitter = new EventEmitter(); | ||
/** | ||
* Lookup a card by its IIN and return a card object | ||
* | ||
* @param {String} iin | ||
* @param {Function} callback | ||
* @return {Object} | ||
*/ | ||
iinChecker.prototype.lookup = function( iin, callback ) { | ||
try { | ||
function doRequest( iinToLookup, provider ) { | ||
var cardInfo; | ||
if ( _.isUndefined( iin ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_UNDEFINED ); | ||
} else { | ||
if ( _.isEmpty( iin ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_EMPTY ); | ||
} else { | ||
// convert input to string incase a int is passed in | ||
iin = String( iin ); | ||
var _request = request( { url: provider.domain + provider.path + iinToLookup, json: true, timeout: self.options.timeout }, function( error, response, body ) { | ||
// the provider errored or our iin was bad | ||
if ( error || response.statusCode !== 200 ) { | ||
// fire off an event so we can handle the failed request | ||
emitter.emit( 'requestFailed', iinToLookup, _request ); | ||
return false; | ||
} | ||
// Remap the reply to match our schema | ||
cardInfo = provider.map( body, self.nullValue ); | ||
// we have some issues with binlist's correctness, some of their binranges | ||
// starting with 5 are being returned as VISA when they are actually MASTERCARD | ||
cardInfo = self.flipBrandWhereNecessary( cardInfo ); | ||
// if caching is on, provider request is only attempted if card details were not | ||
// in the cache now we have the details set it. | ||
if ( self.isCacheable( cardInfo ) ) { | ||
self.options.cache.set( iinToLookup, cardInfo ); | ||
} | ||
// fire off an event so we know that we have completed our request | ||
emitter.emit( 'requestComplete', cardInfo ); | ||
return true; | ||
}); | ||
// First up. Make sure we are passing a number in. | ||
if( _.isNaN( parseInt( iin ) ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_NOT_A_NUMBER ); | ||
} | ||
// fire off an event so we know that the request has started | ||
emitter.emit( 'requestStarted', _request, iinToLookup ); | ||
} | ||
// Now make sure that we are passing in 6 characters | ||
if( iin.length !== 6 ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_NOT_LONG_ENOUGH ); | ||
} | ||
// Loop through the providers and make a request to each of them | ||
function doLookup( providersToCheck, iinToCheck ) { | ||
providersToCheck.forEach( function( element ) { | ||
doRequest( iinToCheck, element ); | ||
}); | ||
} | ||
} | ||
} | ||
if ( !_.isFunction( callback ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_CALLBACK_NOT_FUNCTION ); | ||
} | ||
this.makeRequest( iin, 0, callback ); | ||
} catch ( err ) { | ||
// Return the err in the error callback, if not possible return it. | ||
if ( callback ) { | ||
callback( err ); | ||
} else { | ||
return err; | ||
} | ||
} | ||
}; | ||
} )(); | ||
// Do a RegEx lookup on a iin | ||
function doRegex( iinToLookup ) { | ||
var cardInfo; | ||
var patterns = require( '../configs/patterns' ); | ||
// Set out null info object | ||
cardInfo = { | ||
iin: iinToLookup, | ||
brand: self.nullValue, | ||
issuer: self.nullValue, | ||
type: self.nullValue, | ||
category: self.nullValue, | ||
country: self.nullValue | ||
}; | ||
_.each( patterns, function( pattern ) { | ||
var regex = new RegExp( pattern.expression ); | ||
if ( cardInfo.brand === self.nullValue && regex.test( iinToLookup ) ) { | ||
cardInfo.brand = self.brands[pattern.name]; | ||
} | ||
} ); | ||
// See if RegEx worked | ||
if ( cardInfo.brand && cardInfo.brand !== self.brands.UNKNOWN ) { | ||
// Our RegEx has work, so we fire off an event so we know about it | ||
emitter.emit( 'regexResult', cardInfo ); | ||
} else { | ||
// The RegEx was unable to figure out what the card was so we will fire off an event so we know about it and deal with it | ||
emitter.emit( 'returnError', new TypeError(self.options.messages.PARAMETER_IIN_IS_INVALID), iinToLookup ); | ||
} | ||
} | ||
// Bind our listeners here so we can handle events | ||
function bindListeners( listenerCallback ) { | ||
// we need to keep track of any requests we have | ||
var currentRequests = []; | ||
function stopListening() { | ||
emitter.removeAllListeners(); | ||
} | ||
function clearRequestQueue() { | ||
_.invokeMap( currentRequests, 'abort' ); | ||
} | ||
// listen to the "requestStarted" event - here we add requests into our "currentRequests" queue so we can keep track of them | ||
emitter.on( 'requestStarted', function( theRequest ) { | ||
// add this request to our queue | ||
currentRequests.push( theRequest ); | ||
}); | ||
// listen to the "requestComplete" event - the request has completed successfully if we have enough information | ||
// we can stop listening to any more events and call the callback with the resulting cardInfo | ||
emitter.on( 'requestComplete', function( cardInfo ) { | ||
// is this the event we're interested in?... | ||
if ( cardInfo.iin === iin ) { | ||
// ...yes, do we have what we need?... | ||
if ( cardInfo.brand && cardInfo.brand !== self.brands.UNKNOWN ) { | ||
//...yes we do! So we can stop listening to events | ||
stopListening(); | ||
// we also don't care about any other requests that may be running | ||
clearRequestQueue(); | ||
// finally fire off the callback with the card details | ||
listenerCallback( null, cardInfo ); | ||
return true; | ||
} | ||
} | ||
return true; | ||
}); | ||
// listen to the "requestFailed" event - our request failed, so either the iin we have is bad or the provider is unavailable | ||
emitter.on( 'requestFailed', function( iinToLookup, theRequest ) { | ||
// make sure we are listening to a relevant event | ||
if ( iinToLookup === iin ) { | ||
// ok, our request failed we should remove it from the "currentRequests" queue | ||
var index = currentRequests.indexOf( theRequest ); | ||
if ( index > -1 ) { | ||
currentRequests.splice( index, 1 ); | ||
} | ||
// if we have no requests the the queue then we should do a RegEx lookup as a last resort | ||
if ( currentRequests.length === 0 ) { | ||
doRegex( iin ); | ||
} | ||
} | ||
}); | ||
// listen to the "regexResult" event - we have a result from | ||
emitter.on( 'regexResult', function( cardInfo ) { | ||
if ( cardInfo.iin === iin ) { | ||
// we don't want to worry about any more events | ||
stopListening(); | ||
// now clean up any requests so we're not waiting around | ||
clearRequestQueue(); | ||
// everything else has failed and we're left with the RegEx result - let's just send that back | ||
return listenerCallback( null, cardInfo ); | ||
} | ||
return true; | ||
}); | ||
emitter.on( 'returnError', function( error, iinToLookup ) { | ||
if ( iinToLookup === iin ) { | ||
// we don't want to worry about any more events | ||
stopListening(); | ||
clearRequestQueue(); | ||
// if we've made it here then we can only return and error | ||
return listenerCallback( error ); | ||
} | ||
return true; | ||
}); | ||
} | ||
try { | ||
if ( _.isUndefined( iin ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_UNDEFINED ); | ||
} else { | ||
if ( _.isEmpty( iin ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_EMPTY ); | ||
} else { | ||
// convert input to string in case a int is passed in | ||
iin = String( iin ); | ||
// First up. Make sure we are passing a number in. | ||
if ( _.isNaN( parseInt( iin, 10 ) ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_NOT_A_NUMBER ); | ||
} | ||
// Now make sure that we are passing in 6 characters | ||
if ( iin.length !== 6 ) { | ||
throw new TypeError( this.options.messages.PARAMETER_IIN_IS_NOT_LONG_ENOUGH ); | ||
} | ||
} | ||
} | ||
if ( !_.isFunction( callback ) ) { | ||
throw new TypeError( this.options.messages.PARAMETER_CALLBACK_NOT_FUNCTION ); | ||
} | ||
bindListeners( callback ); | ||
// if cache is turned on attempt to get card details from cache | ||
if ( self.options.cache ) { | ||
self.options.cache.get( iin ) | ||
.then( function( data ) { | ||
// card details from cache | ||
callback( null, data ); | ||
return true; | ||
} ) | ||
.catch( function() { | ||
// attempt to get from the providers if not in cache | ||
doLookup( self.providers, iin ); | ||
} ); | ||
} else { | ||
// we are not using the cache, so do a lookup | ||
doLookup( self.providers, iin ); | ||
} | ||
} catch ( err ) { | ||
// Return the err in the error callback, if not possible return it. | ||
if ( callback ) { | ||
callback( err ); | ||
return false; | ||
} | ||
return err; | ||
} | ||
return true; | ||
}; | ||
} )(); |
{ | ||
"name": "iin-checker", | ||
"description": "Issuer identification number checker which returns details about a credit/debit card", | ||
"version": "0.1.9", | ||
"version": "0.6.0", | ||
"homepage": "https://github.com/Shortbreaks/iinChecker", | ||
@@ -20,19 +20,24 @@ "author": "Simon Wood <simon.wood@holidayextras.com> (https://github.com/Shortbreaks)", | ||
"scripts": { | ||
"test": "grunt test" | ||
"test": "node_modules/deployment-helpers/nodeApps/preRelease.sh && node_modules/.bin/make-up lib config controllers flows plugins test && istanbul cover _mocha -- test/**/*Test.js -R spec" | ||
}, | ||
"devDependencies": { | ||
"chai": "^1.9.1", | ||
"coveralls": "^2.11.1", | ||
"grunt": "~0.4.3", | ||
"grunt-contrib-jshint": "^0.10.0", | ||
"grunt-jscs": "^0.8.1", | ||
"grunt-mocha-test": "^0.12.2", | ||
"istanbul": "^0.3.0", | ||
"mocha": "^2.0.1", | ||
"nock": "^0.48.2" | ||
"chai": "3.2.0", | ||
"coveralls": "2.11.3", | ||
"deployment-helpers": "git+https://github.com/holidayextras/deployment-helpers.git", | ||
"dirty-chai": "^1.2.2", | ||
"grunt": "0.4.5", | ||
"grunt-contrib-jshint": "0.11.2", | ||
"grunt-jscs": "2.0.0", | ||
"grunt-mocha-test": "0.12.7", | ||
"istanbul": "0.3.17", | ||
"make-up": ">=9.1.0", | ||
"mocha": "2.2.5", | ||
"nock": "8.0.0", | ||
"q": "^1.4.1", | ||
"sinon": "1.12.2" | ||
}, | ||
"dependencies": { | ||
"lodash": "^2.4.1", | ||
"request": "^2.40.0" | ||
"lodash": "4.13.1", | ||
"request": "2.72.0" | ||
} | ||
} |
# IIN Checker for payment cards | ||
[![Circle CI](https://circleci.com/gh/holidayextras/iinChecker/tree/master.svg?style=svg&circle-token=af8da07bbe8bddd209990d0f9f0c0a2f39db99df)](https://circleci.com/gh/holidayextras/iinChecker) | ||
[![Dependency status](https://david-dm.org/holidayextras/iinChecker/status.png)](https://david-dm.org/holidayextras/iinChecker#info=dependencies&view=table) | ||
[![Dev Dependency Status](https://david-dm.org/holidayextras/iinChecker/dev-status.png)](https://david-dm.org/holidayextras/iinChecker#info=devDependencies&view=table) | ||
[![Build Status](https://travis-ci.org/Shortbreaks/iinChecker.png)](https://travis-ci.org/Shortbreaks/iinChecker) | ||
[![Coverage Status](https://coveralls.io/repos/Shortbreaks/iinChecker/badge.png?branch=master)](https://coveralls.io/r/Shortbreaks/iinChecker?branch=master) | ||
[![Dependency status](https://david-dm.org/Shortbreaks/iinChecker/status.png)](https://david-dm.org/Shortbreaks/iinChecker#info=dependencies&view=table) | ||
[![Dev Dependency Status](https://david-dm.org/Shortbreaks/iinChecker/dev-status.png)](https://david-dm.org/Shortbreaks/iinChecker#info=devDependencies&view=table) | ||
[![NPM](https://nodei.co/npm/iin-checker.png)](https://nodei.co/npm/iin-checker/) | ||
@@ -34,13 +32,28 @@ | ||
var IinChecker = require( 'iin-checker' ); | ||
// Initialise with default options no caching | ||
var iin = new IinChecker( {} ); | ||
// Initialise with caching | ||
var iin = new IinChecker( { | ||
cache: { | ||
set: function( iin, cardDetails ) {...}, | ||
get: function( iin ) {..} | ||
} | ||
} ); | ||
iin.lookup( '543210', function( err, result ) { | ||
if ( err ) { | ||
console.log( 'Error:', err ); | ||
} else { | ||
console.log( 'Result:', result ); | ||
} | ||
if ( err ) { | ||
console.log( 'Error:', err ); | ||
} else { | ||
console.log( 'Result:', result ); | ||
} | ||
} ); | ||
``` | ||
### Caching | ||
Caching is turned off by default. | ||
It can be turned on by passing in options a cache object with your functions to set and get the cache'. | ||
### Card Type Detection | ||
@@ -55,8 +68,8 @@ | ||
iin.lookup( '543210', function( err, result ) { | ||
if ( err ) { | ||
console.log( 'Error:', err ); | ||
} else { | ||
var isDebit = ( result.type === iin.types.DEBIT ) | ||
console.log( 'Debit?:', isDebit ); | ||
} | ||
if ( err ) { | ||
console.log( 'Error:', err ); | ||
} else { | ||
var isDebit = ( result.type === iin.types.DEBIT ) | ||
console.log( 'Debit?:', isDebit ); | ||
} | ||
} ); | ||
@@ -76,8 +89,8 @@ ``` | ||
iin.lookup( '543210', function( err, result ) { | ||
if ( err ) { | ||
console.log( 'Error:', err ); | ||
} else { | ||
var isMastercard = ( result.brand === iin.brands.MASTERCARD ) | ||
console.log( 'Mastercard?:', isMastercard ); | ||
} | ||
if ( err ) { | ||
console.log( 'Error:', err ); | ||
} else { | ||
var isMastercard = ( result.brand === iin.brands.MASTERCARD ) | ||
console.log( 'Mastercard?:', isMastercard ); | ||
} | ||
} ); | ||
@@ -92,5 +105,4 @@ ``` | ||
## License | ||
Copyright (c) 2014 Shortbreaks | ||
Copyright (c) 2016 Holiday Extras Ltd | ||
Licensed under the MIT license. | ||
@@ -97,0 +109,0 @@ |
@@ -11,4 +11,3 @@ { | ||
"latitude": "38", | ||
"longitude": "-97", | ||
"query_time": "321.45us" | ||
"longitude": "-97" | ||
} |
@@ -11,4 +11,3 @@ { | ||
"latitude": "53", | ||
"longitude": "-8", | ||
"query_time": "285.736us" | ||
"longitude": "-8" | ||
} |
@@ -11,4 +11,3 @@ { | ||
"latitude": "54", | ||
"longitude": "-2", | ||
"query_time": "289.586us" | ||
"longitude": "-2" | ||
} |
@@ -7,3 +7,4 @@ { | ||
"type": "CREDIT", | ||
"country_code": "US" | ||
"country_code": "US", | ||
"is_prepaid": false | ||
} |
@@ -7,3 +7,4 @@ { | ||
"type": "DEBIT", | ||
"country_code": "IE" | ||
"country_code": "IE", | ||
"is_prepaid": false | ||
} |
@@ -7,3 +7,4 @@ { | ||
"type": "CREDIT", | ||
"country_code": "GB" | ||
"country_code": "GB", | ||
"is_prepaid": false | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
45526
37
853
112
14
1
+ Addedansi-regex@2.1.1(transitive)
+ Addedansi-styles@2.2.1(transitive)
+ Addedassert-plus@0.2.0(transitive)
+ Addedasync@2.6.4(transitive)
+ Addedaws-sign2@0.6.0(transitive)
+ Addedbl@1.1.2(transitive)
+ Addedboom@2.10.1(transitive)
+ Addedcaseless@0.11.0(transitive)
+ Addedchalk@1.1.3(transitive)
+ Addedcommander@2.20.3(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addedcryptiles@2.0.5(transitive)
+ Addedescape-string-regexp@1.0.5(transitive)
+ Addedform-data@1.0.1(transitive)
+ Addedgenerate-function@2.3.1(transitive)
+ Addedgenerate-object-property@1.2.0(transitive)
+ Addedhar-validator@2.0.6(transitive)
+ Addedhas-ansi@2.0.0(transitive)
+ Addedhawk@3.1.3(transitive)
+ Addedhoek@2.16.3(transitive)
+ Addedhttp-signature@1.1.1(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-my-ip-valid@1.0.1(transitive)
+ Addedis-my-json-valid@2.20.6(transitive)
+ Addedis-property@1.0.2(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedjsonpointer@5.0.1(transitive)
+ Addedlodash@4.13.14.17.21(transitive)
+ Addednode-uuid@1.4.8(transitive)
+ Addedoauth-sign@0.8.2(transitive)
+ Addedpinkie@2.0.4(transitive)
+ Addedpinkie-promise@2.0.1(transitive)
+ Addedprocess-nextick-args@1.0.7(transitive)
+ Addedqs@6.1.2(transitive)
+ Addedreadable-stream@2.0.6(transitive)
+ Addedrequest@2.72.0(transitive)
+ Addedsntp@1.0.9(transitive)
+ Addedstring_decoder@0.10.31(transitive)
+ Addedstringstream@0.0.6(transitive)
+ Addedstrip-ansi@3.0.1(transitive)
+ Addedsupports-color@2.0.0(transitive)
+ Addedtough-cookie@2.2.2(transitive)
+ Addedtunnel-agent@0.4.3(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedxtend@4.0.2(transitive)
- Removedajv@6.12.6(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedaws-sign2@0.7.0(transitive)
- Removedcaseless@0.12.0(transitive)
- Removedfast-deep-equal@3.1.3(transitive)
- Removedfast-json-stable-stringify@2.1.0(transitive)
- Removedform-data@2.3.3(transitive)
- Removedhar-schema@2.0.0(transitive)
- Removedhar-validator@5.1.5(transitive)
- Removedhttp-signature@1.2.0(transitive)
- Removedjson-schema-traverse@0.4.1(transitive)
- Removedlodash@2.4.2(transitive)
- Removedoauth-sign@0.9.0(transitive)
- Removedperformance-now@2.1.0(transitive)
- Removedpsl@1.15.0(transitive)
- Removedpunycode@2.3.1(transitive)
- Removedqs@6.5.3(transitive)
- Removedrequest@2.88.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedtough-cookie@2.5.0(transitive)
- Removedtunnel-agent@0.6.0(transitive)
- Removeduri-js@4.4.1(transitive)
- Removeduuid@3.4.0(transitive)
Updatedlodash@4.13.1
Updatedrequest@2.72.0