'use strict';
var analytics = require('../lib/analytics');
var isBrowserSupported = require('./shared/supports-venmo');
var constants = require('./shared/constants');
var errors = require('./shared/errors');
var querystring = require('../lib/querystring');
var methods = require('../lib/methods');
var convertMethodsToError = require('../lib/convert-methods-to-error');
var wrapPromise = require('@braintree/wrap-promise');
var BraintreeError = require('../lib/braintree-error');
var Promise = require('../lib/promise');
var VERSION = process.env.npm_package_version;
function Venmo(options) {
var configuration;
this._client = options.client;
configuration = this._client.getConfiguration();
this._isDebug = configuration.isDebug;
this._assetsUrl = configuration.gatewayConfiguration.assetsUrl + '/web/' + VERSION;
this._allowNewBrowserTab = options.allowNewBrowserTab !== false;
this._profileId = options.profileId;
this._deepLinkReturnUrl = options.deepLinkReturnUrl;
}
Venmo.prototype._initialize = function () {
var params = {};
var currentUrl = this._deepLinkReturnUrl || global.location.href.replace(global.location.hash, '');
var configuration = this._client.getConfiguration();
var venmoConfiguration = configuration.gatewayConfiguration.payWithVenmo;
var analyticsMetadata = this._client.getConfiguration().analyticsMetadata;
var braintreeData = {
_meta: {
version: analyticsMetadata.sdkVersion,
integration: analyticsMetadata.integration,
platform: analyticsMetadata.platform,
sessionId: analyticsMetadata.sessionId
}
};
params['x-success'] = currentUrl + '#venmoSuccess=1';
params['x-cancel'] = currentUrl + '#venmoCancel=1';
params['x-error'] = currentUrl + '#venmoError=1';
params.ua = global.navigator.userAgent;
params.braintree_merchant_id = this._profileId || venmoConfiguration.merchantId;
params.braintree_access_token = venmoConfiguration.accessToken;
params.braintree_environment = venmoConfiguration.environment;
params.braintree_sdk_data = btoa(JSON.stringify(braintreeData));
this._url = constants.VENMO_OPEN_URL + '?' + querystring.stringify(params);
return Promise.resolve(this);
};
Venmo.prototype.isBrowserSupported = function () {
return isBrowserSupported.isBrowserSupported({
allowNewBrowserTab: this._allowNewBrowserTab
});
};
Venmo.prototype.hasTokenizationResult = function () {
var params = getFragmentParameters();
return typeof (params.venmoSuccess || params.venmoError || params.venmoCancel) !== 'undefined';
};
Venmo.prototype.tokenize = function () {
var self = this;
if (this._tokenizationInProgress === true) {
return Promise.reject(new BraintreeError(errors.VENMO_TOKENIZATION_REQUEST_ACTIVE));
}
if (this.hasTokenizationResult()) {
return this._processResults();
}
return new Promise(function (resolve, reject) {
self._tokenizationInProgress = true;
self._previousHash = global.location.hash;
if (self._deepLinkReturnUrl) {
global.location = self._url;
} else {
global.open(self._url);
}
self._visibilityChangeListener = function () {
if (!global.document.hidden) {
self._tokenizationInProgress = false;
setTimeout(function () {
self._processResults().then(resolve).catch(reject).then(function () {
global.location.hash = self._previousHash;
self._removeVisibilityEventListener();
delete self._visibilityChangeListener;
});
}, constants.PROCESS_RESULTS_DELAY);
}
};
setTimeout(function () {
global.document.addEventListener(documentVisibilityChangeEventName(), self._visibilityChangeListener);
}, constants.DOCUMENT_VISIBILITY_CHANGE_EVENT_DELAY);
});
};
Venmo.prototype.teardown = function () {
this._removeVisibilityEventListener();
convertMethodsToError(this, methods(Venmo.prototype));
return Promise.resolve();
};
Venmo.prototype._removeVisibilityEventListener = function () {
global.document.removeEventListener(documentVisibilityChangeEventName(), this._visibilityChangeListener);
};
Venmo.prototype._processResults = function () {
var self = this;
var params = getFragmentParameters();
return new Promise(function (resolve, reject) {
if (params.venmoSuccess) {
analytics.sendEvent(self._client, 'venmo.appswitch.handle.success');
resolve(formatTokenizePayload(params));
} else if (params.venmoError) {
analytics.sendEvent(self._client, 'venmo.appswitch.handle.error');
reject(new BraintreeError({
type: errors.VENMO_APP_FAILED.type,
code: errors.VENMO_APP_FAILED.code,
message: errors.VENMO_APP_FAILED.message,
details: {
originalError: {
message: decodeURIComponent(params.errorMessage),
code: params.errorCode
}
}
}));
} else if (params.venmoCancel) {
analytics.sendEvent(self._client, 'venmo.appswitch.handle.cancel');
reject(new BraintreeError(errors.VENMO_APP_CANCELED));
} else {
analytics.sendEvent(self._client, 'venmo.appswitch.cancel-or-unavailable');
reject(new BraintreeError(errors.VENMO_CANCELED));
}
clearFragmentParameters();
});
};
function getFragmentParameters() {
var keyValuesArray = global.location.hash.substring(1).split('&');
return keyValuesArray.reduce(function (toReturn, keyValue) {
var parts = keyValue.split('=');
var key = decodeURIComponent(parts[0]);
var value = decodeURIComponent(parts[1]);
toReturn[key] = value;
return toReturn;
}, {});
}
function clearFragmentParameters() {
if (typeof global.history.replaceState === 'function' && global.location.hash) {
history.pushState({}, '', global.location.href.slice(0, global.location.href.indexOf('#')));
}
}
function formatTokenizePayload(fragmentParams) {
return {
nonce: fragmentParams.paymentMethodNonce,
type: 'VenmoAccount',
details: {
username: fragmentParams.username
}
};
}
function documentVisibilityChangeEventName() {
var visibilityChange;
if (typeof global.document.hidden !== 'undefined') {
visibilityChange = 'visibilitychange';
} else if (typeof global.document.msHidden !== 'undefined') {
visibilityChange = 'msvisibilitychange';
} else if (typeof global.document.webkitHidden !== 'undefined') {
visibilityChange = 'webkitvisibilitychange';
}
return visibilityChange;
}
module.exports = wrapPromise.wrapPrototype(Venmo);