UNPKG

braintree-web

Version:

A suite of tools for integrating Braintree in the browser

1,689 lines (1,560 loc) 67.8 kB
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}(g.braintree || (g.braintree = {})).dataCollector = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PromiseGlobal = void 0; var promise_polyfill_1 = __importDefault(_dereq_("promise-polyfill")); var PromiseGlobal = // eslint-disable-next-line no-undef typeof Promise !== "undefined" ? Promise : promise_polyfill_1.default; exports.PromiseGlobal = PromiseGlobal; },{"promise-polyfill":9}],2:[function(_dereq_,module,exports){ "use strict"; var promise_1 = _dereq_("./lib/promise"); var scriptPromiseCache = {}; function loadScript(options) { var scriptLoadPromise; var stringifiedOptions = JSON.stringify(options); if (!options.forceScriptReload) { scriptLoadPromise = scriptPromiseCache[stringifiedOptions]; if (scriptLoadPromise) { return scriptLoadPromise; } } var script = document.createElement("script"); var attrs = options.dataAttributes || {}; var container = options.container || document.head; script.src = options.src; script.id = options.id || ""; script.async = true; if (options.crossorigin) { script.setAttribute("crossorigin", "" + options.crossorigin); } Object.keys(attrs).forEach(function (key) { script.setAttribute("data-" + key, "" + attrs[key]); }); scriptLoadPromise = new promise_1.PromiseGlobal(function (resolve, reject) { script.addEventListener("load", function () { resolve(script); }); script.addEventListener("error", function () { reject(new Error(options.src + " failed to load.")); }); script.addEventListener("abort", function () { reject(new Error(options.src + " has aborted.")); }); container.appendChild(script); }); scriptPromiseCache[stringifiedOptions] = scriptLoadPromise; return scriptLoadPromise; } loadScript.clearCache = function () { scriptPromiseCache = {}; }; module.exports = loadScript; },{"./lib/promise":1}],3:[function(_dereq_,module,exports){ module.exports = _dereq_("./dist/load-script"); },{"./dist/load-script":2}],4:[function(_dereq_,module,exports){ "use strict"; var GlobalPromise = (typeof Promise !== "undefined" ? Promise // eslint-disable-line no-undef : null); var ExtendedPromise = /** @class */ (function () { function ExtendedPromise(options) { var _this = this; if (typeof options === "function") { this._promise = new ExtendedPromise.Promise(options); return; } this._promise = new ExtendedPromise.Promise(function (resolve, reject) { _this._resolveFunction = resolve; _this._rejectFunction = reject; }); options = options || {}; this._onResolve = options.onResolve || ExtendedPromise.defaultOnResolve; this._onReject = options.onReject || ExtendedPromise.defaultOnReject; if (ExtendedPromise.shouldCatchExceptions(options)) { this._promise.catch(function () { // prevents unhandled promise rejection warning // in the console for extended promises that // that catch the error in an asynchronous manner }); } this._resetState(); } ExtendedPromise.defaultOnResolve = function (result) { return ExtendedPromise.Promise.resolve(result); }; ExtendedPromise.defaultOnReject = function (err) { return ExtendedPromise.Promise.reject(err); }; ExtendedPromise.setPromise = function (PromiseClass) { ExtendedPromise.Promise = PromiseClass; }; ExtendedPromise.shouldCatchExceptions = function (options) { if (options.hasOwnProperty("suppressUnhandledPromiseMessage")) { return Boolean(options.suppressUnhandledPromiseMessage); } return Boolean(ExtendedPromise.suppressUnhandledPromiseMessage); }; // start Promise methods documented in: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#Methods ExtendedPromise.all = function (args) { return ExtendedPromise.Promise.all(args); }; ExtendedPromise.allSettled = function (args) { return ExtendedPromise.Promise.allSettled(args); }; ExtendedPromise.race = function (args) { return ExtendedPromise.Promise.race(args); }; ExtendedPromise.reject = function (arg) { return ExtendedPromise.Promise.reject(arg); }; ExtendedPromise.resolve = function (arg) { return ExtendedPromise.Promise.resolve(arg); }; ExtendedPromise.prototype.then = function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return (_a = this._promise).then.apply(_a, args); }; ExtendedPromise.prototype.catch = function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return (_a = this._promise).catch.apply(_a, args); }; ExtendedPromise.prototype.resolve = function (arg) { var _this = this; if (this.isFulfilled) { return this; } this._setResolved(); ExtendedPromise.Promise.resolve() .then(function () { return _this._onResolve(arg); }) .then(function (argForResolveFunction) { _this._resolveFunction(argForResolveFunction); }) .catch(function (err) { _this._resetState(); _this.reject(err); }); return this; }; ExtendedPromise.prototype.reject = function (arg) { var _this = this; if (this.isFulfilled) { return this; } this._setRejected(); ExtendedPromise.Promise.resolve() .then(function () { return _this._onReject(arg); }) .then(function (result) { _this._setResolved(); _this._resolveFunction(result); }) .catch(function (err) { return _this._rejectFunction(err); }); return this; }; ExtendedPromise.prototype._resetState = function () { this.isFulfilled = false; this.isResolved = false; this.isRejected = false; }; ExtendedPromise.prototype._setResolved = function () { this.isFulfilled = true; this.isResolved = true; this.isRejected = false; }; ExtendedPromise.prototype._setRejected = function () { this.isFulfilled = true; this.isResolved = false; this.isRejected = true; }; ExtendedPromise.Promise = GlobalPromise; return ExtendedPromise; }()); module.exports = ExtendedPromise; },{}],5:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function deferred(fn) { return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } setTimeout(function () { try { fn.apply(void 0, args); } catch (err) { /* eslint-disable no-console */ console.log("Error in callback function"); console.log(err); /* eslint-enable no-console */ } }, 1); }; } exports.deferred = deferred; },{}],6:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function once(fn) { var called = false; return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (!called) { called = true; fn.apply(void 0, args); } }; } exports.once = once; },{}],7:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable consistent-return */ function promiseOrCallback(promise, callback) { if (!callback) { return promise; } promise.then(function (data) { return callback(null, data); }).catch(function (err) { return callback(err); }); } exports.promiseOrCallback = promiseOrCallback; },{}],8:[function(_dereq_,module,exports){ "use strict"; var deferred_1 = _dereq_("./lib/deferred"); var once_1 = _dereq_("./lib/once"); var promise_or_callback_1 = _dereq_("./lib/promise-or-callback"); function wrapPromise(fn) { // eslint-disable-next-line @typescript-eslint/no-explicit-any return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var callback; var lastArg = args[args.length - 1]; if (typeof lastArg === "function") { callback = args.pop(); callback = once_1.once(deferred_1.deferred(callback)); } // I know, I know, this looks bad. But it's a quirk of the library that // we need to allow passing the this context to the original function // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore: this has an implicit any return promise_or_callback_1.promiseOrCallback(fn.apply(this, args), callback); // eslint-disable-line no-invalid-this }; } wrapPromise.wrapPrototype = function (target, options) { if (options === void 0) { options = {}; } var ignoreMethods = options.ignoreMethods || []; var includePrivateMethods = options.transformPrivateMethods === true; var methods = Object.getOwnPropertyNames(target.prototype).filter(function (method) { var isNotPrivateMethod; var isNonConstructorFunction = method !== "constructor" && typeof target.prototype[method] === "function"; var isNotAnIgnoredMethod = ignoreMethods.indexOf(method) === -1; if (includePrivateMethods) { isNotPrivateMethod = true; } else { isNotPrivateMethod = method.charAt(0) !== "_"; } return (isNonConstructorFunction && isNotPrivateMethod && isNotAnIgnoredMethod); }); methods.forEach(function (method) { var original = target.prototype[method]; target.prototype[method] = wrapPromise(original); }); return target; }; module.exports = wrapPromise; },{"./lib/deferred":5,"./lib/once":6,"./lib/promise-or-callback":7}],9:[function(_dereq_,module,exports){ 'use strict'; /** * @this {Promise} */ function finallyConstructor(callback) { var constructor = this.constructor; return this.then( function(value) { // @ts-ignore return constructor.resolve(callback()).then(function() { return value; }); }, function(reason) { // @ts-ignore return constructor.resolve(callback()).then(function() { // @ts-ignore return constructor.reject(reason); }); } ); } function allSettled(arr) { var P = this; return new P(function(resolve, reject) { if (!(arr && typeof arr.length !== 'undefined')) { return reject( new TypeError( typeof arr + ' ' + arr + ' is not iterable(cannot read property Symbol(Symbol.iterator))' ) ); } var args = Array.prototype.slice.call(arr); if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { then.call( val, function(val) { res(i, val); }, function(e) { args[i] = { status: 'rejected', reason: e }; if (--remaining === 0) { resolve(args); } } ); return; } } args[i] = { status: 'fulfilled', value: val }; if (--remaining === 0) { resolve(args); } } for (var i = 0; i < args.length; i++) { res(i, args[i]); } }); } // Store setTimeout reference so promise-polyfill will be unaffected by // other code modifying setTimeout (like sinon.useFakeTimers()) var setTimeoutFunc = setTimeout; function isArray(x) { return Boolean(x && typeof x.length !== 'undefined'); } function noop() {} // Polyfill for Function.prototype.bind function bind(fn, thisArg) { return function() { fn.apply(thisArg, arguments); }; } /** * @constructor * @param {Function} fn */ function Promise(fn) { if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); if (typeof fn !== 'function') throw new TypeError('not a function'); /** @type {!number} */ this._state = 0; /** @type {!boolean} */ this._handled = false; /** @type {Promise|undefined} */ this._value = undefined; /** @type {!Array<!Function>} */ this._deferreds = []; doResolve(fn, this); } function handle(self, deferred) { while (self._state === 3) { self = self._value; } if (self._state === 0) { self._deferreds.push(deferred); return; } self._handled = true; Promise._immediateFn(function() { var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { (self._state === 1 ? resolve : reject)(deferred.promise, self._value); return; } var ret; try { ret = cb(self._value); } catch (e) { reject(deferred.promise, e); return; } resolve(deferred.promise, ret); }); } function resolve(self, newValue) { try { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); if ( newValue && (typeof newValue === 'object' || typeof newValue === 'function') ) { var then = newValue.then; if (newValue instanceof Promise) { self._state = 3; self._value = newValue; finale(self); return; } else if (typeof then === 'function') { doResolve(bind(then, newValue), self); return; } } self._state = 1; self._value = newValue; finale(self); } catch (e) { reject(self, e); } } function reject(self, newValue) { self._state = 2; self._value = newValue; finale(self); } function finale(self) { if (self._state === 2 && self._deferreds.length === 0) { Promise._immediateFn(function() { if (!self._handled) { Promise._unhandledRejectionFn(self._value); } }); } for (var i = 0, len = self._deferreds.length; i < len; i++) { handle(self, self._deferreds[i]); } self._deferreds = null; } /** * @constructor */ function Handler(onFulfilled, onRejected, promise) { this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; this.onRejected = typeof onRejected === 'function' ? onRejected : null; this.promise = promise; } /** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. */ function doResolve(fn, self) { var done = false; try { fn( function(value) { if (done) return; done = true; resolve(self, value); }, function(reason) { if (done) return; done = true; reject(self, reason); } ); } catch (ex) { if (done) return; done = true; reject(self, ex); } } Promise.prototype['catch'] = function(onRejected) { return this.then(null, onRejected); }; Promise.prototype.then = function(onFulfilled, onRejected) { // @ts-ignore var prom = new this.constructor(noop); handle(this, new Handler(onFulfilled, onRejected, prom)); return prom; }; Promise.prototype['finally'] = finallyConstructor; Promise.all = function(arr) { return new Promise(function(resolve, reject) { if (!isArray(arr)) { return reject(new TypeError('Promise.all accepts an array')); } var args = Array.prototype.slice.call(arr); if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { try { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { then.call( val, function(val) { res(i, val); }, reject ); return; } } args[i] = val; if (--remaining === 0) { resolve(args); } } catch (ex) { reject(ex); } } for (var i = 0; i < args.length; i++) { res(i, args[i]); } }); }; Promise.allSettled = allSettled; Promise.resolve = function(value) { if (value && typeof value === 'object' && value.constructor === Promise) { return value; } return new Promise(function(resolve) { resolve(value); }); }; Promise.reject = function(value) { return new Promise(function(resolve, reject) { reject(value); }); }; Promise.race = function(arr) { return new Promise(function(resolve, reject) { if (!isArray(arr)) { return reject(new TypeError('Promise.race accepts an array')); } for (var i = 0, len = arr.length; i < len; i++) { Promise.resolve(arr[i]).then(resolve, reject); } }); }; // Use polyfill for setImmediate for performance gains Promise._immediateFn = // @ts-ignore (typeof setImmediate === 'function' && function(fn) { // @ts-ignore setImmediate(fn); }) || function(fn) { setTimeoutFunc(fn, 0); }; Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { if (typeof console !== 'undefined' && console) { console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console } }; module.exports = Promise; },{}],10:[function(_dereq_,module,exports){ "use strict"; /** * @name BraintreeError.Data Collector - Creation Error Codes * @description Errors that occur when [creating the Data Collector component](./module-braintree-web_data-collector.html#.create). * @property {MERCHANT} DATA_COLLECTOR_KOUNT_NOT_ENABLED Occurs when Kount is enabled in creation options but is not enabled on the Braintree control panel. * @property {MERCHANT} DATA_COLLECTOR_KOUNT_ERROR Occurs when Kount errors while setting up. * @property {MERCHANT} DATA_COLLECTOR_REQUIRES_CREATE_OPTIONS Occurs when Kount or PayPal Fraudnet could not be enabled. */ var BraintreeError = _dereq_("../lib/braintree-error"); module.exports = { DATA_COLLECTOR_KOUNT_NOT_ENABLED: { type: BraintreeError.types.MERCHANT, code: "DATA_COLLECTOR_KOUNT_NOT_ENABLED", message: "Kount is not enabled for this merchant.", }, DATA_COLLECTOR_KOUNT_ERROR: { type: BraintreeError.types.MERCHANT, code: "DATA_COLLECTOR_KOUNT_ERROR", }, DATA_COLLECTOR_REQUIRES_CREATE_OPTIONS: { type: BraintreeError.types.MERCHANT, code: "DATA_COLLECTOR_REQUIRES_CREATE_OPTIONS", message: "Data Collector must be created with Kount and/or PayPal.", }, }; },{"../lib/braintree-error":17}],11:[function(_dereq_,module,exports){ "use strict"; var FRAUDNET_FNCLS = _dereq_("../lib/constants").FRAUDNET_FNCLS; var FRAUDNET_SOURCE = _dereq_("../lib/constants").FRAUDNET_SOURCE; var FRAUDNET_URL = _dereq_("../lib/constants").FRAUDNET_URL; var loadScript = _dereq_("../lib/assets").loadScript; var Promise = _dereq_("../lib/promise"); var cachedSessionId; function setup(options) { var fraudNet = new Fraudnet(); options = options || {}; if (!options.sessionId && cachedSessionId) { fraudNet.sessionId = cachedSessionId; return Promise.resolve(fraudNet); } return fraudNet.initialize(options); } function clearSessionIdCache() { cachedSessionId = null; } function Fraudnet() {} Fraudnet.prototype.initialize = function (options) { var environment = options.environment; var self = this; this.sessionId = options.sessionId || _generateSessionId(); if (!options.sessionId) { cachedSessionId = this.sessionId; } this._beaconId = _generateBeaconId(this.sessionId); this._parameterBlock = _createParameterBlock( this.sessionId, this._beaconId, environment ); return loadScript({ src: FRAUDNET_URL, }) .then(function (block) { self._thirdPartyBlock = block; return self; }) .catch(function () { // if the fraudnet script fails to load // we just resolve with nothing // and data collector ignores it return null; }); }; Fraudnet.prototype.teardown = function () { removeElementIfOnPage(document.querySelector('iframe[title="ppfniframe"]')); removeElementIfOnPage(document.querySelector('iframe[title="pbf"]')); removeElementIfOnPage(this._parameterBlock); removeElementIfOnPage(this._thirdPartyBlock); }; function removeElementIfOnPage(element) { if (element && element.parentNode) { element.parentNode.removeChild(element); } } function _generateSessionId() { var i; var id = ""; for (i = 0; i < 32; i++) { id += Math.floor(Math.random() * 16).toString(16); } return id; } function _generateBeaconId(sessionId) { var timestamp = new Date().getTime() / 1000; return ( "https://b.stats.paypal.com/counter.cgi" + "?i=127.0.0.1" + "&p=" + sessionId + "&t=" + timestamp + "&a=14" ); } function _createParameterBlock(sessionId, beaconId, environment) { var el = document.body.appendChild(document.createElement("script")); var config = { f: sessionId, s: FRAUDNET_SOURCE, b: beaconId, }; // for some reason, the presence of the sandbox // attribute in a production environment causes // some weird behavior with what url paths are // hit, so instead, we only apply this attribute // when it is not a production environment if (environment !== "production") { config.sandbox = true; } el.type = "application/json"; el.setAttribute("fncls", FRAUDNET_FNCLS); el.text = JSON.stringify(config); return el; } module.exports = { setup: setup, clearSessionIdCache: clearSessionIdCache, }; },{"../lib/assets":15,"../lib/constants":19,"../lib/promise":26}],12:[function(_dereq_,module,exports){ "use strict"; /** @module braintree-web/data-collector */ var kount = _dereq_("./kount"); var fraudnet = _dereq_("./fraudnet"); var BraintreeError = _dereq_("../lib/braintree-error"); var basicComponentVerification = _dereq_("../lib/basic-component-verification"); var createDeferredClient = _dereq_("../lib/create-deferred-client"); var createAssetsUrl = _dereq_("../lib/create-assets-url"); var methods = _dereq_("../lib/methods"); var convertMethodsToError = _dereq_("../lib/convert-methods-to-error"); var VERSION = "3.87.0"; var Promise = _dereq_("../lib/promise"); var wrapPromise = _dereq_("@braintree/wrap-promise"); var errors = _dereq_("./errors"); /** * @class * @global * @name DataCollector * @description <strong>Do not use this constructor directly. Use {@link module:braintree-web/data-collector.create|braintree-web.data-collector.create} instead.</strong> * @classdesc This class is used for fraud integration with PayPal and Kount. Instances of this class have {@link DataCollector#deviceData|deviceData} which is used to correlate user sessions with server transactions. */ /** * @memberof DataCollector * @name deviceData * @type string * @description JSON string to pass with server transactions. * @instance */ /** * @memberof DataCollector * @name rawDeviceData * @type object * @description The device data as an object instead of a string. * @instance */ /** * @memberof DataCollector * @name teardown * @function * @description Cleanly remove anything set up by {@link module:braintree-web/data-collector.create|create}. * @param {callback} [callback] Called on completion. If no callback is provided, `teardown` returns a promise. * @instance * @example * dataCollectorInstance.teardown(); * @example <caption>With callback</caption> * dataCollectorInstance.teardown(function () { * // teardown is complete * }); * @returns {(Promise|void)} Returns a promise if no callback is provided. */ /** * @memberof DataCollector * @name getDeviceData * @function * @description Resolves with device data once it is ready. * @param {object} [options] Options for how device data is resolved. * @param {boolean} [options.raw=false] When set to true, the device data will resolve as an object instead of a JSON string. * @param {callback} [callback] Called on completion. If no callback is provided, `getDeviceData` returns a promise. * @instance * @example * dataCollectorInstance.getDeviceData(); * @example <caption>Without options</caption> * dataCollectorInstance.getDeviceData().then(function (deviceData) { * // typeof deviceData === 'string' * // pass onto your server with the payment method nonce * }); * @example <caption>With options</caption> * dataCollectorInstance.getDeviceData({ * raw: true * }).then(function (deviceData) { * // typeof deviceData === 'object' * // for if you'd like to parse the data before sending it to your server * }); * @returns {(Promise|void)} Returns a promise if no callback is provided. */ /** * @static * @function create * @description Creates a DataCollector instance and collects device data based on your merchant configuration. We recommend that you call this method as early as possible, e.g. as soon as your website loads. If that's too early, call it at the beginning of customer checkout. * **Note:** To use your own Kount ID, contact our support team ([support@braintreepayments.com](mailto:support@braintreepayments.com) or [877.434.2894](tel:877.434.2894)). * @param {object} options Creation options: * @param {Client} [options.client] A {@link Client} instance. * @param {string} [options.authorization] A tokenizationKey or clientToken. Can be used in place of `options.client`. * @param {boolean} [options.useDeferredClient] Used in conjunction with `authorization`, allows the Data Collector instance to be available right away by fetching the client configuration in the background. When this option is used, {@link GooglePayment#getDeviceData} must be used to collect the device data. * @param {boolean} [options.kount] Kount fraud data collection will occur if the merchant configuration has it enabled. * **Note:** the data sent to Kount is asynchronous and may not have completed by the time the data collector create call is complete. In most cases, this will not matter, but if you create the data collector instance and immediately navigate away from the page, the device information may fail to be sent to Kount. * @param {boolean} [options.paypal] *Deprecated:* PayPal fraud data collection will occur when the DataCollector instance is created. * @param {string} [options.riskCorrelationId] Pass a custom risk correlation id when creating the data collector. * @param {string} [options.clientMetadataId] Deprecated. Use `options.riskCorrelationId` instead. * @param {string} [options.correlationId] Deprecated. Use `options.riskCorrelationId` instead. * @param {callback} [callback] The second argument, `data`, is the {@link DataCollector} instance. * @returns {(Promise|void)} Returns a promise that resolves the {@link DataCollector} instance if no callback is provided. */ function create(options) { var name = "Data Collector"; var result = { _instances: [], }; var data; return basicComponentVerification .verify({ name: name, client: options.client, authorization: options.authorization, }) .then(function () { result._instantiatedWithAClient = !options.useDeferredClient; result._createPromise = createDeferredClient .create({ authorization: options.authorization, client: options.client, debug: options.debug, assetsUrl: createAssetsUrl.create(options.authorization), name: name, }) .then(function (client) { var kountInstance; var config = client.getConfiguration(); if (options.kount === true && config.gatewayConfiguration.kount) { try { kountInstance = kount.setup({ environment: config.gatewayConfiguration.environment, merchantId: config.gatewayConfiguration.kount.kountMerchantId, }); } catch (err) { return Promise.reject( new BraintreeError({ type: errors.DATA_COLLECTOR_KOUNT_ERROR.type, code: errors.DATA_COLLECTOR_KOUNT_ERROR.code, message: err.message, }) ); } data = kountInstance.deviceData; result._instances.push(kountInstance); } else { data = {}; } return Promise.resolve(client); }) .then(function (client) { return fraudnet .setup({ sessionId: options.riskCorrelationId || options.clientMetadataId || options.correlationId, environment: client.getConfiguration().gatewayConfiguration.environment, }) .then(function (fraudnetInstance) { if (fraudnetInstance) { data.correlation_id = fraudnetInstance.sessionId; // eslint-disable-line camelcase result._instances.push(fraudnetInstance); } }); }) .then(function () { if (result._instances.length === 0) { // NEXT_MAJOR_VERSION either this should error with a specific error that // no data collector instances could be set up, or we should just swallow // the error and document that no device data will be returned if // data collector cannot be instantiated. We can't change the error code here // without possibly breaking merchant integrations relying on this inccorrect // behavior. return Promise.reject( new BraintreeError(errors.DATA_COLLECTOR_REQUIRES_CREATE_OPTIONS) ); } result.deviceData = JSON.stringify(data); result.rawDeviceData = data; return result; }); result.teardown = createTeardownMethod(result); result.getDeviceData = createGetDeviceDataMethod(result); if (result._instantiatedWithAClient) { return result._createPromise; } return result; }); } function createTeardownMethod(result) { return wrapPromise(function teardown() { return result._createPromise.then(function () { result._instances.forEach(function (instance) { if (instance) { instance.teardown(); } }); convertMethodsToError(result, methods(result)); }); }); } function createGetDeviceDataMethod(result) { return wrapPromise(function getDeviceData(options) { options = options || {}; return result._createPromise.then(function () { if (options.raw) { return Promise.resolve(result.rawDeviceData); } return Promise.resolve(result.deviceData); }); }); } module.exports = { create: wrapPromise(create), /** * @description The current version of the SDK, i.e. `{@pkg version}`. * @type {string} */ VERSION: VERSION, }; },{"../lib/basic-component-verification":16,"../lib/braintree-error":17,"../lib/convert-methods-to-error":20,"../lib/create-assets-url":21,"../lib/create-deferred-client":22,"../lib/methods":25,"../lib/promise":26,"./errors":10,"./fraudnet":11,"./kount":13,"@braintree/wrap-promise":8}],13:[function(_dereq_,module,exports){ "use strict"; var sjcl = _dereq_("./vendor/sjcl"); var camelCaseToSnakeCase = _dereq_("../lib/camel-case-to-snake-case"); var QA_URL = "https://assets.qa.braintreepayments.com/data"; var IFRAME_ID_PREFIX = "braintreeDataFrame-"; var environmentUrls = { development: QA_URL, qa: QA_URL, sandbox: "https://assets.braintreegateway.com/sandbox/data", production: "https://assets.braintreegateway.com/data", }; var cachedDeviceData = {}; function setup(o) { var options = o != null ? o : {}; return new Kount(options); } function Kount(options) { var previouslyInitializedDeviceData = Kount.getCachedDeviceData( options.merchantId ); if (previouslyInitializedDeviceData) { this.deviceData = previouslyInitializedDeviceData; this._isCached = true; return; } this._currentEnvironment = this._initializeEnvironment(options); sjcl.random.startCollectors(); this._deviceSessionId = this._generateDeviceSessionId(); this.deviceData = this._getDeviceData(); Kount.setCachedDeviceData(options.merchantId, this.deviceData); this._iframe = this._setupIFrame(); } Kount.getCachedDeviceData = function (merchantId) { return cachedDeviceData[merchantId]; }; Kount.setCachedDeviceData = function (merchantId, data) { cachedDeviceData[merchantId] = data; }; Kount.prototype.teardown = function () { if (!this._isCached) { sjcl.random.stopCollectors(); this._removeIframe(); } }; Kount.prototype._removeIframe = function () { this._iframe.parentNode.removeChild(this._iframe); }; Kount.prototype._getDeviceData = function () { return camelCaseToSnakeCase({ deviceSessionId: this._deviceSessionId, fraudMerchantId: this._currentEnvironment.id, }); }; Kount.prototype._generateDeviceSessionId = function () { var bits, hexString; bits = sjcl.random.randomWords(4, 0); hexString = sjcl.codec.hex.fromBits(bits); return hexString; }; Kount.prototype._setupIFrame = function () { var params, iframe; var self = this; params = "?m=" + this._currentEnvironment.id + "&s=" + this._deviceSessionId; iframe = document.createElement("iframe"); iframe.width = 1; iframe.id = IFRAME_ID_PREFIX + this._deviceSessionId; iframe.height = 1; iframe.frameBorder = 0; iframe.scrolling = "no"; iframe.style.position = "fixed"; iframe.style.left = "-999999px"; iframe.style.top = "-999999px"; iframe.title = "Braintree-Kount-iframe"; iframe.setAttribute("aria-hidden", "true"); document.body.appendChild(iframe); setTimeout(function () { iframe.src = self._currentEnvironment.url + "/logo.htm" + params; iframe.innerHTML = '<img src="' + self._currentEnvironment.url + "/logo.gif" + params + '" alt="" />'; }, 10); return iframe; }; Kount.prototype._initializeEnvironment = function (options) { var url = environmentUrls[options.environment]; if (url == null) { throw new Error( options.environment + " is not a valid environment for kount.environment" ); } return { url: url, name: options.environment, id: options.merchantId, }; }; module.exports = { setup: setup, Kount: Kount, environmentUrls: environmentUrls, }; },{"../lib/camel-case-to-snake-case":18,"./vendor/sjcl":14}],14:[function(_dereq_,module,exports){ "use strict"; var sjcl = { cipher: {}, hash: {}, keyexchange: {}, mode: {}, misc: {}, codec: {}, exception: { corrupt: function (a) { this.toString = function () { return "CORRUPT: " + this.message; }; this.message = a; }, invalid: function (a) { this.toString = function () { return "INVALID: " + this.message; }; this.message = a; }, bug: function (a) { this.toString = function () { return "BUG: " + this.message; }; this.message = a; }, notReady: function (a) { this.toString = function () { return "NOT READY: " + this.message; }; this.message = a; }, }, }; sjcl.cipher.aes = function (a) { this.l[0][0][0] || this.G(); var b, c, d, e, f = this.l[0][4], g = this.l[1]; b = a.length; var k = 1; if (4 !== b && 6 !== b && 8 !== b) throw new sjcl.exception.invalid("invalid aes key size"); this.b = [(d = a.slice(0)), (e = [])]; for (a = b; a < 4 * b + 28; a++) { c = d[a - 1]; if (0 === a % b || (8 === b && 4 === a % b)) (c = (f[c >>> 24] << 24) ^ (f[(c >> 16) & 255] << 16) ^ (f[(c >> 8) & 255] << 8) ^ f[c & 255]), 0 === a % b && ((c = (c << 8) ^ (c >>> 24) ^ (k << 24)), (k = (k << 1) ^ (283 * (k >> 7)))); d[a] = d[a - b] ^ c; } for (b = 0; a; b++, a--) (c = d[b & 3 ? a : a - 4]), (e[b] = 4 >= a || 4 > b ? c : g[0][f[c >>> 24]] ^ g[1][f[(c >> 16) & 255]] ^ g[2][f[(c >> 8) & 255]] ^ g[3][f[c & 255]]); }; sjcl.cipher.aes.prototype = { encrypt: function (a) { return t(this, a, 0); }, decrypt: function (a) { return t(this, a, 1); }, l: [ [[], [], [], [], []], [[], [], [], [], []], ], G: function () { var a = this.l[0], b = this.l[1], c = a[4], d = b[4], e, f, g, k = [], l = [], p, n, h, m; for (e = 0; 0x100 > e; e++) l[(k[e] = (e << 1) ^ (283 * (e >> 7))) ^ e] = e; for (f = g = 0; !c[f]; f ^= p || 1, g = l[g] || 1) for ( h = g ^ (g << 1) ^ (g << 2) ^ (g << 3) ^ (g << 4), h = (h >> 8) ^ (h & 255) ^ 99, c[f] = h, d[h] = f, n = k[(e = k[(p = k[f])])], m = (0x1010101 * n) ^ (0x10001 * e) ^ (0x101 * p) ^ (0x1010100 * f), n = (0x101 * k[h]) ^ (0x1010100 * h), e = 0; 4 > e; e++ ) (a[e][f] = n = (n << 24) ^ (n >>> 8)), (b[e][h] = m = (m << 24) ^ (m >>> 8)); for (e = 0; 5 > e; e++) (a[e] = a[e].slice(0)), (b[e] = b[e].slice(0)); }, }; function t(a, b, c) { if (4 !== b.length) throw new sjcl.exception.invalid("invalid aes block size"); var d = a.b[c], e = b[0] ^ d[0], f = b[c ? 3 : 1] ^ d[1], g = b[2] ^ d[2]; b = b[c ? 1 : 3] ^ d[3]; var k, l, p, n = d.length / 4 - 2, h, m = 4, q = [0, 0, 0, 0]; k = a.l[c]; a = k[0]; var r = k[1], v = k[2], w = k[3], x = k[4]; for (h = 0; h < n; h++) (k = a[e >>> 24] ^ r[(f >> 16) & 255] ^ v[(g >> 8) & 255] ^ w[b & 255] ^ d[m]), (l = a[f >>> 24] ^ r[(g >> 16) & 255] ^ v[(b >> 8) & 255] ^ w[e & 255] ^ d[m + 1]), (p = a[g >>> 24] ^ r[(b >> 16) & 255] ^ v[(e >> 8) & 255] ^ w[f & 255] ^ d[m + 2]), (b = a[b >>> 24] ^ r[(e >> 16) & 255] ^ v[(f >> 8) & 255] ^ w[g & 255] ^ d[m + 3]), (m += 4), (e = k), (f = l), (g = p); for (h = 0; 4 > h; h++) (q[c ? 3 & -h : h] = (x[e >>> 24] << 24) ^ (x[(f >> 16) & 255] << 16) ^ (x[(g >> 8) & 255] << 8) ^ x[b & 255] ^ d[m++]), (k = e), (e = f), (f = g), (g = b), (b = k); return q; } sjcl.bitArray = { bitSlice: function (a, b, c) { a = sjcl.bitArray.M(a.slice(b / 32), 32 - (b & 31)).slice(1); return void 0 === c ? a : sjcl.bitArray.clamp(a, c - b); }, extract: function (a, b, c) { var d = Math.floor((-b - c) & 31); return ( (((b + c - 1) ^ b) & -32 ? (a[(b / 32) | 0] << (32 - d)) ^ (a[(b / 32 + 1) | 0] >>> d) : a[(b / 32) | 0] >>> d) & ((1 << c) - 1) ); }, concat: function (a, b) { if (0 === a.length || 0 === b.length) return a.concat(b); var c = a[a.length - 1], d = sjcl.bitArray.getPartial(c); return 32 === d ? a.concat(b) : sjcl.bitArray.M(b, d, c | 0, a.slice(0, a.length - 1)); }, bitLength: function (a) { var b = a.length; return 0 === b ? 0 : 32 * (b - 1) + sjcl.bitArray.getPartial(a[b - 1]); }, clamp: function (a, b) { if (32 * a.length < b) return a; a = a.slice(0, Math.ceil(b / 32)); var c = a.length; b = b & 31; 0 < c && b && (a[c - 1] = sjcl.bitArray.partial( b, a[c - 1] & (2147483648 >> (b - 1)), 1 )); return a; }, partial: function (a, b, c) { return 32 === a ? b : (c ? b | 0 : b << (32 - a)) + 0x10000000000 * a; }, getPartial: function (a) { return Math.round(a / 0x10000000000) || 32; }, equal: function (a, b) { if (sjcl.bitArray.bitLength(a) !== sjcl.bitArray.bitLength(b)) return !1; var c = 0, d; for (d = 0; d < a.length; d++) c |= a[d] ^ b[d]; return 0 === c; }, M: function (a, b, c, d) { var e; e = 0; for (void 0 === d && (d = []); 32 <= b; b -= 32) d.push(c), (c = 0); if (0 === b) return d.concat(a); for (e = 0; e < a.length; e++) d.push(c | (a[e] >>> b)), (c = a[e] << (32 - b)); e = a.length ? a[a.length - 1] : 0; a = sjcl.bitArray.getPartial(e); d.push(sjcl.bitArray.partial((b + a) & 31, 32 < b + a ? c : d.pop(), 1)); return d; }, Y: function (a, b) { return [a[0] ^ b[0], a[1] ^ b[1], a[2] ^ b[2], a[3] ^ b[3]]; }, byteswapM: function (a) { var b, c; for (b = 0; b < a.length; ++b) (c = a[b]), (a[b] = (c >>> 24) | ((c >>> 8) & 0xff00) | ((c & 0xff00) << 8) | (c << 24)); return a; }, }; sjcl.codec.utf8String = { fromBits: function (a) { var b = "", c = sjcl.bitArray.bitLength(a), d, e; for (d = 0; d < c / 8; d++) 0 === (d & 3) && (e = a[d / 4]), (b += String.fromCharCode(((e >>> 8) >>> 8) >>> 8)), (e <<= 8); return decodeURIComponent(escape(b)); }, toBits: function (a) { a = unescape(encodeURIComponent(a)); var b = [], c, d = 0; for (c = 0; c < a.length; c++) (d = (d << 8) | a.charCodeAt(c)), 3 === (c & 3) && (b.push(d), (d = 0)); c & 3 && b.push(sjcl.bitArray.partial(8 * (c & 3), d)); return b; }, }; sjcl.codec.hex = { fromBits: function (a) { var b = "", c; for (c = 0; c < a.length; c++) b += ((a[c] | 0) + 0xf00000000000).toString(16).substr(4); return b.substr(0, sjcl.bitArray.bitLength(a) / 4); }, toBits: function (a) { var b, c = [], d; a = a.replace(/\s|0x/g, ""); d = a.length; a = a + "00000000"; for (b = 0; b < a.length; b += 8) c.push(parseInt(a.substr(b, 8), 16) ^ 0); return sjcl.bitArray.clamp(c, 4 * d); }, }; sjcl.hash.sha256 = function (a) { this.b[0] || this.G(); a ? ((this.u = a.u.slice(0)), (this.o = a.o.slice(0)), (this.h = a.h)) : this.reset(); }; sjcl.hash.sha256.hash = function (a) { return new sjcl.hash.sha256().update(a).finalize(); }; sjcl.hash.sha256.prototype = { blockSize: 512, reset: function () { this.u = this.K.slice(0); this.o = []; this.h = 0; return this; }, update: function (a) { "string" === typeof a && (a = sjcl.codec.utf8String.toBits(a)); var b, c = (this.o = sjcl.bitArray.concat(this.o, a)); b = this.h; a = this.h = b + sjcl.bitArray.bitLength(a); if (0x1fffffffffffff < a) throw new sjcl.exception.invalid("Cannot hash more than 2^53 - 1 bits"); if ("undefined" !== typeof Uint32Array) { var d = new Uint32Array(c), e = 0; for (b = 512 + b - ((512 + b) & 0x1ff); b <= a; b += 512) u(this, d.subarray(16 * e, 16 * (e + 1))), (e += 1); c.splice(0, 16 * e); } else for (b = 512 + b - ((512 + b) & 0x1ff); b <= a; b += 512) u(this, c.splice(0, 16)); return this; }, finalize: function () { var a, b = this.o, c = this.u, b = sjcl.bitArray.concat(b, [sjcl.bitArray.partial(1, 1)]); for (a = b.length + 2; a & 15; a++) b.push(0); b.push(Math.floor(this.h / 0x100000000)); for (b.push(this.h | 0); b.length; ) u(this, b.splice(0, 16)); this.reset(); return c; }, K: [], b: [], G: function () { function a(a) { return (0x100000000 * (a - Math.floor(a))) | 0; } for (var b = 0, c = 2, d, e; 64 > b; c++) { e = !0; for (d = 2; d * d <= c; d++) if (0 === c % d) { e = !1; break; } e && (8 > b && (this.K[b] = a(Math.pow(c, 0.5))), (this.b[b] = a(Math.pow(c, 1 / 3))), b++); } }, }; function u(a, b) { var c, d, e, f = a.u, g = a.b, k = f[0], l = f[1], p = f[2], n = f[3], h = f[4], m = f[5], q = f[6], r = f[7]; for (c = 0; 64 > c; c++) 16 > c ? (d = b[c]) : ((d = b[(c + 1) & 15]), (e = b[(c + 14) & 15]), (d = b[c & 15] = (((d >>> 7) ^ (d >>> 18) ^ (d >>> 3) ^ (d << 25) ^ (d << 14)) + ((e >>> 17) ^ (e >>> 19) ^ (e >>> 10) ^ (e << 15) ^ (e << 13)) + b[c & 15] + b[(c + 9) & 15]) | 0)), (d = d + r + ((h >>> 6) ^ (h >>> 11) ^ (h >>> 25) ^ (h << 26) ^ (h << 21) ^ (h << 7)) + (q ^ (h & (m ^ q))) + g[c]), (r = q), (q = m), (m = h), (h = (n + d) | 0), (n = p), (p = l), (l = k), (k = (d + ((l & p) ^ (n & (l ^ p))) + ((l >>> 2) ^ (l >>> 13) ^ (l >>> 22) ^ (l << 30) ^ (l << 19) ^ (l << 10))) | 0); f[0] = (f[0] + k) | 0; f[1] = (f[1] + l) | 0; f[2] = (f[2] + p) | 0; f[3] = (f[3] + n) | 0; f[4] = (f[4] + h) | 0; f[5] = (f[5] + m) | 0; f[6] = (f[6] + q) | 0; f[7] = (f[7] + r) | 0; } sjcl.prng = function (a) { this.c = [new sjcl.hash.sha256()]; this.i = [0]; this.H = 0; this.v = {}; this.F = 0; this.J = {}; this.L = this.f = this.j = this.T = 0; this.b = [0, 0, 0, 0, 0, 0, 0, 0]; this.g = [0, 0, 0, 0]; this.C = void 0; this.D = a; this.s = !1; this.B = { progress: {}, seeded: {} }; this.m = this.S = 0; this.w = 1; this.A = 2; this.O = 0x10000; this.I = [0, 48, 64, 96, 128, 192, 0x100, 384, 512, 768, 1024]; this.P = 3e4; this.N = 80; }; sjcl.prng.prototype = { randomWords: function (a, b) { var c = [], d; d = this.isReady(b); var e; if (d === this.m) throw new sjcl.exception.notReady("generator isn't seeded"); if (d & this.A) { d = !(d & this.w); e = []; var f = 0, g; this.L = e[0] = new Date().valueOf() + this.P; for (g = 0; 16 > g; g++) e.push((0x100000000 * Math.random()) | 0); for ( g = 0; g < this.c.length && ((e = e.concat(this.c[g].finalize())), (f += this.i[g]), (this.i[g] = 0), d || !(this.H & (1 << g))); g++ ); this.H >= 1 << this.c.length && (this.c.push(new sjcl.hash.sha256()), this.i.push(0)); this.f -= f; f > this.j && (this.j = f); this.H++; this.b = sjcl.hash.sha256.hash(this.b.concat(e)); this.C = new sjcl.cipher.aes(this.b); for ( d = 0; 4 > d && ((this.g[d] = (this.g[d] + 1) | 0), !this.g[d]); d++ ); } for (d = 0; d < a; d += 4) 0 === (d + 1) % this.O && y(this), (e = z(this)), c.push(e[0], e[1], e[2], e[3]); y(this); return c.slice(0, a); }, setDefaultParanoia: function (a, b) { if ( 0 === a && "Setting paranoia=0 will ruin your security; use it only for testing" !== b ) throw new sjcl.exception.invalid( "Setting paranoia=0 will ruin your security; use it only for testing" ); this.D = a; }, addEntropy: function (a, b, c) { c = c || "user"; var d, e, f = new Date().valueOf(), g = this.v[c], k = this.isReady(), l = 0; d = this.J[c]; void 0 === d && (d = this.J[c] = this.T++); void 0 === g && (g = this.v[c] = 0); this.v[c] = (this.v[c] + 1) % this.c.length; switch (typeof a) { case "number": void 0 === b && (b = 1); this.c[g].update([d, this.F++, 1, b, f, 1, a | 0]); break; case "object": c = Object.prototype.toString.call(a); if ("[object Uint32Array]" === c) { e = []; for (c = 0; c < a.length; c++) e.push(a[c]); a = e; } else for ( "[object Array]" !== c && (l = 1), c = 0; c < a.length && !l; c++ ) "number" !== typeof a[c] && (l = 1);