0.2.1 • Published 7 years ago

yield-siftscience v0.2.1

Weekly downloads
362
License
MIT
Repository
github
Last release
7 years ago

Yield Sift Science - NodeJS

A promise-wrapped helper lib for yielding Sift Science API calls in nodejs.

Also supports regular callbacks.

Table of contents:

INSTALLATION

Using npm:

$ npm install yield-siftscience

USAGE

Require with API Key:

var siftscience = require('yield-siftscience')({
  api_key: 'YOUR_SIFT_SCIENCE_REST_API_KEY'
});

Available Options:

Note: In v204 of the sift science API, return_action is deprecated in favor of the more granular combined use of abuse_types, return_score and return_workflow_status flags. more info

EVENTS API

https://siftscience.com/developers/docs/curl/events-api

Send Event:

var result = yield siftscience.event.create_account({
  '$session_id': session.id,
  '$user_id':    user.id,
  '$user_email': user.email
});
var result = yield siftscience.event.login({
  '$session_id':   session.id,
  '$user_id':      user.id,
  '$login_status': siftscience.CONSTANTS.STATUS.SUCCESS
});

Send Generic Custom Event:

var result = yield siftscience.event.custom_event('referral_code_redeemed', {
  '$session_id': session.id,
  '$user_id':    user.id,
  'code':        'abc123'
});
var result = yield siftscience.event.custom_event('contacted_customer_support', {
  '$session_id': session.id,
  '$user_id':    user.id
});

Inject Custom Events:

Optionally, you can pass in an array of custom event names to add to the lib

var siftscience = require('yield-siftscience')({
  api_key:       'YOUR_SIFT_SCIENCE_REST_API_KEY',
  custom_events: ['referral_code_redeemed', 'contacted_customer_support', ...]
});

Then you could use

var result = yield siftscience.event.referral_code_redeemed({
  '$session_id': session.id,
  '$user_id':    user.id,
  'code':        'abc123'
});
var result = yield siftscience.event.contacted_customer_support({
  '$session_id': session.id,
  '$user_id':    user.id,
});

LABELS API

https://siftscience.com/developers/docs/curl/labels-api

Send Label:

var result = yield siftscience.label(user.id, {
  '$is_bad':      true,
  '$abuse_type':  siftscience.CONSTANTS.ABUSE_TYPE.PAYMENT_ABUSE,
  '$description': 'Because they are spamming and abusing our system',
  '$source':      'manual review',
  '$analyst':     'admin@example.com'
});

Remove Label:

var result = yield siftscience.unlabel(user.id);

DECISION API

https://siftscience.com/developers/docs/curl/decisions-api

Get decision status:

var result = yield siftscience.decision.status(siftscience.CONSTANTS.ENTITY_TYPE.USERS, entity.id)

List decisions:

var result = yield siftscience.decision.list(siftscience.CONSTANTS.ENTITY_TYPE.USER)

Apply decision to user:

var result = yield siftscience.decision.apply(user.id, null, {
  'decision_id': 'user_looks_ok_payment_abuse',
  'source':      siftscience.CONSTANTS.DECISION_SOURCE.MANUAL_REVIEW,
  'analyst':     'analyst@email.com',
  'description': 'applied via the high priority queue, queued user because their risk score exceeded 85'
})

Apply decision to order:

var result = yield siftscience.decision.apply(user.id, order.id, {
  'decision_id': 'user_looks_ok_payment_abuse',
  'source':      siftscience.CONSTANTS.DECISION_SOURCE.AUTOMATED_RULE,
  'description': 'Auto block pending order as score exceeded risk threshold of 90'
})

WORKFLOW API

https://siftscience.com/developers/docs/curl/workflows-api

Get workflow status:

var result = yield siftscience.workflow.status(workflow.id)

SCORE API

https://siftscience.com/developers/docs/curl/score-api

Get Score:

var result = yield siftscience.score(user.id);

DEVICE FINGERPRINTING API

https://siftscience.com/developers/docs/curl/device-fingerprinting-api

JavaScript Snippet:

https://siftscience.com/developers/docs/javascript/javascript-api

Install the following JavaScript snippet on every public-facing page on your site. Do not include this snippet on internal tools or administration systems.

Replace 'UNIQUE_SESSION_ID', 'UNIQUE_USER_ID', and 'INSERT_JS_SNIPPET_KEY_HERE' with proper values

<script type="text/javascript">
  var _user_id = 'UNIQUE_USER_ID';
  var _session_id = 'UNIQUE_SESSION_ID';

  var _sift = window._sift = window._sift || [];
  _sift.push(['_setAccount', 'INSERT_JS_SNIPPET_KEY_HERE']);
  _sift.push(['_setUserId', _user_id]);
  _sift.push(['_setSessionId', _session_id]);
  _sift.push(['_trackPageview']);

  (function() {
    function ls() {
      var e = document.createElement('script');
      e.src = 'https://cdn.siftscience.com/s.js';
      document.body.appendChild(e);
    }
    if (window.attachEvent) {
      window.attachEvent('onload', ls);
    } else {
      window.addEventListener('load', ls, false);
    }
  })();
</script>

Init with Account ID:

An Account ID is required to use the fingerprint api. Get your Account ID

var siftscience = require('yield-siftscience')({
  api_key:    'YOUR_SIFT_SCIENCE_REST_API_KEY',
  account_id: 'YOUR_SIFT_SCIENCE_ACCOUNT_ID'
});

Get Session:

var result = yield siftscience.fingerprint.get_session(session.id);

Get Device:

var result = yield siftscience.fingerprint.get_device(device_fingerprint);

Label Device:

var result = yield siftscience.fingerprint.label_device(device_fingerprint, siftscience.CONSTANTS.DEVICE_LABEL.BAD);

Get Devices:

var result = yield siftscience.fingerprint.get_devices(user.id);

PARTNER API

https://siftscience.com/developers/docs/curl/partner-api

NOTE: I have not tested these as I do not have a partner account with sift science. Please report any bugs.

Init with Account ID and Partner ID (they may be the same thing, I'm not sure):

An Account & Partner ID are required to use the partner api. Get your Account & Partner ID

var siftscience = require('yield-siftscience')({
  api_key:    'YOUR_SIFT_SCIENCE_REST_API_KEY',
  account_id: 'YOUR_SIFT_SCIENCE_ACCOUNT_ID',
  partner_id: 'YOUR_SIFT_SCIENCE_PARTNER_ID'
});

Create Account:

var result = yield siftscience.partner.create_account({
  site_url:      'merchant123.com',
  site_email:    'owner@merchant123.com',
  analyst_email: 'john.doe@merchant123.com',
  password:      's0mepA55word'
});

List Accounts:

var result = yield siftscience.partner.list_accounts();

Configure Notifications:

var result = yield siftscience.partner.configure_notifications({
  email_notification_threshold: 0.5,
  http_notification_threshold:  0.5,
  http_notification_url:       'https://api.partner.com/notify?account=%s'
});

CALLBACKS

Don't know what yielding or promising is? All calls support regular callbacks:

siftscience.score(user.id, function(_err, _response) {
  if (_err) {
    console.log(_err);
  }
  else {
    var score = _response.body;
    console.log(score);
  }
});

You can also inject a global callback for all requests:

var siftscience = require('yield-siftscience')({
  api_key:         'YOUR_SIFT_SCIENCE_REST_API_KEY',
  global_callback: function(_err, _response) {
    if (_err) {
      console.log(_err);
    }
    else {
      var result = _response.body;
      console.log(result);
    }
  }
});

CONSTANTS

siftscience.CONSTANTS = {
  SHIPPING_METHOD: {
    ELECTRONIC: '$electronic',
    PHYSICAL:   '$physical'
  },
  TRANSACTION_TYPE: {
    SALE:       '$sale',
    AUTHORIZE:  '$authorize',
    CAPTURE:    '$capture',
    VOID:       '$void',
    REFUND:     '$refund',
    DEPOSIT:    '$deposit',
    WITHDRAWAL: '$withdrawal',
    TRANSFER:   '$transfer'
  },
  STATUS: {
    SUCCESS: '$success',
    FAILURE: '$failure',
    PENDING: '$pending'
  },
  FAILURE_REASON: {
    ALREADY_USED:   '$already_used',
    INVALID_CODE:   '$invalid_code',
    NOT_APPLICABLE: '$not_applicable',
    EXPIRED:        '$expired'
  },
  SOCIAL_SIGN_ON_TYPE: {
    FACEBOOK: '$facebook',
    GOOGLE:   '$google',
    YAHOO:    '$yahoo',
    TWITTER:  '$twitter',
    OTHER:    '$other',
    LINKEDIN: '$linkedin'
  },
  CONTENT_STATUS: {
    DRAFT:              '$draft',
    PENDING:            '$pending',
    ACTIVE:             '$active',
    PAUSED:             '$paused',
    DELETED_BY_USER:    '$deleted_by_user',
    DELETED_BY_COMPANY: '$deleted_by_company'
  },
  CHARGEBACK_STATE: {
    RECEIVED: '$received',
    ACCEPTED: '$accepted',
    DISPUTED: '$disputed',
    WON:      '$won',
    LOST:     '$lost'
  },
  CHARGEBACK_REASON: {
    FRAUD:                '$fraud',
    DUPLICATE:            '$duplicate',
    PRODUCT_NOT_RECEIVED: '$product_not_received',
    PRODUCT_UNACCEPTABLE: '$product_unacceptable',
    OTHER:                '$other'
  },
  ORDER_STATUS: {
    APPROVED:  '$approved',
    CANCELED:  '$canceled',
    HELD:      '$held',
    FULFILLED: '$fulfilled',
    RETURNED:  '$returned'
  },
  ORDER_CANCEL_REASON: {
    PAYMENT_RISK: '$payment_risk',
    ABUSE:        '$abuse',
    POLICY:       '$policy',
    OTHER:        '$other'
  },
  ORDER_STATUS_SOURCE: {
    AUTOMATED: '$automated',
    MANUAL_REVIEW: '$manual_review'
  },
  VERIFICATION_TYPE: {
    SMS:        '$sms',
    PHONE_CALL: '$phone_call',
    EMAIL:      '$email',
    APP_TFA:    '$app_tfa',
    CAPTCHA:    '$captcha'
  },
  PAYMENT_TYPE: {
    CASH:                     '$cash',
    CHECK:                    '$check',
    CREDIT_CARD:              '$credit_card',
    CRYPTO_CURRENCY:          '$crypto_currency',
    DIGITAL_WALLET:           '$digital_wallet',
    ELECTRONIC_FUND_TRANSFER: '$electronic_fund_transfer',
    FINANCING:                '$financing',
    GIFT_CARD:                '$gift_card',
    INTERAC:                  '$interac', // Deprecated?
    INVOICE:                  '$invoice',
    MONEY_ORDER:              '$money_order',
    MASTERPASS:               '$masterpass', // Deprecated?
    POINTS:                   '$points',
    STORE_CREDIT:             '$store_credit',
    THIRD_PARTY_PROCESSOR:    '$third_party_processor',
    VOUCHER:                  '$voucher'
  },
  RESPONSE_STATUS_MESSAGE: {
    '-4':  'Service currently unavailable. Please try again later.',
    '-3':  'Server-side timeout processing request. Please try again later.',
    '-2':  'Unexpected server-side error',
    '-1':  'Unexpected server-side error',
    '0':   'Success',
    '51':  'Invalid API key',
    '52':  'Invalid characters in field name',
    '53':  'Invalid characters in field value',
    '54':  'Specified user_id has no scoreable events',
    '55':  'Missing required field',
    '56':  'Invalid JSON in request',
    '57':  'Invalid HTTP body',
    '60':  'Rate limited',
    '104': 'Invalid API version',
    '105': 'Not a valid reserved field',
    '111': 'This feature is not enabled in your feature plan.'
  },
  REASON: {
    CHARGEBACK:        '$chargeback',
    SPAM:              '$spam',
    FUNNELING:         '$funneling',
    FAKE:              '$fake',
    REFERRAL:          '$referral',
    DUPLICATE_ACCOUNT: '$duplicate_account'
  },
  DEVICE_LABEL: {
    BAD:     'bad',
    NOT_BAD: 'not_bad'
  },
  DEVICE_PERVASIVENESS: {
    LOW:    'low',
    MEDIUM: 'medium',
    HIGH:   'high'
  },
  ABUSE_TYPE: {
    PAYMENT_ABUSE:   'payment_abuse',
    CONTENT_ABUSE:   'content_abuse',
    PROMOTION_ABUSE: 'promotion_abuse',
    PROMO_ABUSE:     'promo_abuse',
    ACCOUNT_ABUSE:   'account_abuse',
    LEGACY:          'legacy'
  },
  DECISION: {
    PAYMENT_ABUSE:   'payment_abuse',
    PROMOTION_ABUSE: 'promotion_abuse',
    PROMO_ABUSE:     'promo_abuse',
    CONTENT_ABUSE:   'content_abuse',
    ACCOUNT_ABUSE:   'account_abuse',
    LEGACY:          'legacy'
  },
  DECISION_CATEGORY: {
    BLOCK:  'BLOCK',
    WATCH:  'WATCH',
    ACCEPT: 'ACCEPT'
  },
  DECISION_SOURCE: {
    MANUAL_REVIEW:  'MANUAL_REVIEW',
    AUTOMATED_RULE: 'AUTOMATED_RULE',
    CHARGEBACK:     'CHARGEBACK'
  },
  STATE: {
    RUNNING:  'running',
    FINISHED: 'finished',
    FAILED:   'failed'
  },
  ENTITY_TYPE: {
    USERS:  'users',
    ORDERS: 'orders',
    USER:   'user',
    ORDER:  'order'
  },
  APP: {
    DECISION:        'decision',
    REVIEW_QUEUE:    'review_queue',
    USER_SCORER:     'user_scorer',
    ORDER_SCORER:    'order_scorer',
    EVENT_PROCESSOR: 'event_processor'
  },
  ACCOUNT_STATE: {
    ACTIVE:   'ACTIVE',
    DISABLED: 'DISABLED',
    DELETED:  'DELETED'
  }
};

WEBHOOKS

NOTE: Currently only supports express/body-parser

Install Express/Body-Parser:

$ npm install --save express
$ npm install --save body-parser
$ npm install --save yield-siftscience

Example App:

Let's say you have created an action called "Test" with Action ID test

var express    = require('express');
var bodyParser = require('body-parser');

// Require yield-siftscience with a webhooks mapping option
var siftscience = require('yield-siftscience')({
  api_key: 'YOUR_SIFT_SCIENCE_REST_API_KEY',
  webhooks: {
    // This will receive all webhooks, regardless of Action ID
    all: function(req, res, done) {
      console.log('all: ', req.body);
      done();
    },
    // This will receive webhooks with Action ID 'test'
    test: function(req, res, done) {
      console.log('test: ', req.body);
      done();
    }
  }
});

// Set up the webhook listener
var app = express();
app.post('/siftscience', bodyParser.json(), siftscience.webhook.express());

app.listen(config.port);

SIFT SCIENCE DOCUMENTATION

https://siftscience.com/developers/docs/curl/apis-overview

TESTING

Copy Example Config:

$ cp test/config-example.js test/config.js
$ nano test/config.js

Set Sandbox API Key, JS Key, Account ID, Workflow Run ID

module.exports = {
  api_key:         'xxxxxxxxxxxxxxxx',
  js_key:          'xxxxxxxxxx',
  account_id:      'xxxxxxxxxxxxxxxxxxxxxxxx',
  workflow_run_id: 'xxxxxxxxxxxxx',
  host:            'localhost',
  port:            3000
};

Install Dependencies:

$ npm install

Run Test:

$ npm test

Visit Page:

Visiting the test web page will trigger a page view for user_id = '1' and session_id = '1'

http://localhost:3000

NOTE: You will have to run the test a second time if this is your first time visiting the test web page

CHANGE LOG

0.2.1:

  • Add support for decision list api
  • Add support for apply decision api
  • Add many missing CONSTANTS
  • Add $verification event

0.2.0:

  • Update to API v204
  • BREAKING CHANGE: siftscience.unlabel() function signature has changed to support abuse type
  • BREAKING CHANGE: siftscience.score() function signature has changed to support abuse types
  • Add support for decision status api
  • Add support for workflow status api

0.1.2:

  • Add validations for all arguments
  • Update readme with more links to source reference

0.1.1:

  • Found the return_action documentation - MORE INFO
  • Remove support for api version option - will only be supporting the most current version v203
  • Add validations for all init options

0.1.0:

  • BREAKING CHANGE: Consolidate init args into one options arg - see USAGE
  • Add support for return_action in init options - MORE INFO
  • Add support for device fingerprinting api
  • Add support for partner api - NOTE: I do not have a partner account with sift science, this is untested. Please report any bugs.
  • Add CONSTANTS object to siftscience object for things like $reasons and $shipping_method - see LABELS API
  • Add express/body-parser webhook support
  • Add a minimal test package

0.0.9:

  • Add unlabel method to siftscience object
0.2.1

7 years ago

0.2.0

7 years ago

0.1.2

8 years ago

0.1.1

8 years ago

0.1.0

8 years ago

0.0.9

9 years ago

0.0.8

10 years ago

0.0.7

10 years ago

0.0.6

10 years ago

0.0.5

10 years ago

0.0.4

10 years ago

0.0.3

10 years ago

0.0.2

10 years ago

0.0.1

10 years ago