Wondering what‚Äôs next for npm?Check out our public roadmap! ¬Ľ

    yield-siftscience

    0.2.1¬†‚Äʬ†Public¬†‚Äʬ†Published

    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:

    • {string} api_key (get your api key)
    • {string} [account_id] (required for device fingerprinting api, get your account id)
    • {string} [partner_id] (required for partner api, get your partner id)
    • {string[]} [custom_events] (ex: ['referral_code_redeemed', 'contacted_customer_support', ...])
    • {function} [global_callback] (ex: function(err, response) { ... } - can be used to override promise and make regular callback on all requests)
    • {string[]} [abuse_types] (default: [] - specify an array of sift science products. This parameter restricts the list of score or workflow decision retrieved to the specific products requested. more info. Possible values: Array with one or more of - ['payment_abuse','promo_abuse','content_abuse','account_abuse','legacy'])
    • {boolean} [return_score] (default: false - can be used to return score from sift science synchronously more info)
    • {boolean} [return_workflow_status] (default: false - can be used to return workflow status from sift science synchronously more info)
    • {object} [webhooks] (default: {} - see webhooks for usage)
    • {boolean} [return_action] DEPRECATED (default: false - can be used to get extra params from sift science responses more info)

    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

    Install

    npm i yield-siftscience

    DownloadsWeekly Downloads

    340

    Version

    0.2.1

    License

    MIT

    Homepage

    otothea.com

    Last publish

    Collaborators

    • avatar