UNPKG

braintree-web

Version:

A suite of tools for integrating Braintree in the browser

4,416 lines • 153 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 = {})).localPayment = 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 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.type) {
        script.setAttribute("type", "".concat(options.type));
    }
    if (options.crossorigin) {
        script.setAttribute("crossorigin", "".concat(options.crossorigin));
    }
    Object.keys(attrs).forEach(function (key) {
        script.setAttribute("data-".concat(key), "".concat(attrs[key]));
    });
    scriptLoadPromise = new Promise(function (resolve, reject) {
        script.addEventListener("load", function () {
            resolve(script);
        });
        script.addEventListener("error", function () {
            reject(new Error("".concat(options.src, " failed to load.")));
        });
        script.addEventListener("abort", function () {
            reject(new Error("".concat(options.src, " has aborted.")));
        });
        container.appendChild(script);
    });
    scriptPromiseCache[stringifiedOptions] = scriptLoadPromise;
    return scriptLoadPromise;
}
loadScript.clearCache = function () {
    scriptPromiseCache = {};
};
module.exports = loadScript;

},{}],2:[function(_dereq_,module,exports){
module.exports = _dereq_("./dist/load-script");

},{"./dist/load-script":1}],3:[function(_dereq_,module,exports){
"use strict";
module.exports = function isAndroid(ua) {
    ua = ua || window.navigator.userAgent;
    return /Android/i.test(ua);
};

},{}],4:[function(_dereq_,module,exports){
"use strict";
var isEdge = _dereq_("./is-edge");
var isSamsung = _dereq_("./is-samsung");
var isDuckDuckGo = _dereq_("./is-duckduckgo");
var isOpera = _dereq_("./is-opera");
var isSilk = _dereq_("./is-silk");
module.exports = function isChrome(ua) {
    ua = ua || window.navigator.userAgent;
    return ((ua.indexOf("Chrome") !== -1 || ua.indexOf("CriOS") !== -1) &&
        !isEdge(ua) &&
        !isSamsung(ua) &&
        !isDuckDuckGo(ua) &&
        !isOpera(ua) &&
        !isSilk(ua));
};

},{"./is-duckduckgo":5,"./is-edge":6,"./is-opera":13,"./is-samsung":14,"./is-silk":15}],5:[function(_dereq_,module,exports){
"use strict";
module.exports = function isDuckDuckGo(ua) {
    ua = ua || window.navigator.userAgent;
    return ua.indexOf("DuckDuckGo/") !== -1;
};

},{}],6:[function(_dereq_,module,exports){
"use strict";
module.exports = function isEdge(ua) {
    ua = ua || window.navigator.userAgent;
    return ua.indexOf("Edge/") !== -1 || ua.indexOf("Edg/") !== -1;
};

},{}],7:[function(_dereq_,module,exports){
"use strict";
module.exports = function isIosFirefox(ua) {
    ua = ua || window.navigator.userAgent;
    return /FxiOS/i.test(ua);
};

},{}],8:[function(_dereq_,module,exports){
"use strict";
var isIos = _dereq_("./is-ios");
function isGoogleSearchApp(ua) {
    return /\bGSA\b/.test(ua);
}
module.exports = function isIosGoogleSearchApp(ua) {
    ua = ua || window.navigator.userAgent;
    return isIos(ua) && isGoogleSearchApp(ua);
};

},{"./is-ios":11}],9:[function(_dereq_,module,exports){
"use strict";
var isIos = _dereq_("./is-ios");
var isIosGoogleSearchApp = _dereq_("./is-ios-google-search-app");
module.exports = function isIosWebview(ua) {
    ua = ua || window.navigator.userAgent;
    if (isIos(ua)) {
        // The Google Search iOS app is technically a webview and doesn't support popups.
        if (isIosGoogleSearchApp(ua)) {
            return true;
        }
        // Historically, a webview could be identified by the presence of AppleWebKit and _no_ presence of Safari after.
        return /.+AppleWebKit(?!.*Safari)/i.test(ua);
    }
    return false;
};

},{"./is-ios":11,"./is-ios-google-search-app":8}],10:[function(_dereq_,module,exports){
"use strict";
var isIosWebview = _dereq_("./is-ios-webview");
module.exports = function isIosWKWebview(ua, statusBarVisible) {
    statusBarVisible =
        typeof statusBarVisible !== "undefined"
            ? statusBarVisible
            : window.statusbar.visible;
    return isIosWebview(ua) && statusBarVisible;
};

},{"./is-ios-webview":9}],11:[function(_dereq_,module,exports){
"use strict";
var isIpadOS = _dereq_("./is-ipados");
module.exports = function isIos(ua, checkIpadOS, document) {
    if (checkIpadOS === void 0) { checkIpadOS = true; }
    ua = ua || window.navigator.userAgent;
    var iOsTest = /iPhone|iPod|iPad/i.test(ua);
    return checkIpadOS ? iOsTest || isIpadOS(ua, document) : iOsTest;
};

},{"./is-ipados":12}],12:[function(_dereq_,module,exports){
"use strict";
module.exports = function isIpadOS(ua, document) {
    ua = ua || window.navigator.userAgent;
    document = document || window.document;
    // "ontouchend" is used to determine if a browser is on an iPad, otherwise
    // user-agents for iPadOS behave/identify as a desktop browser
    return /Mac|iPad/i.test(ua) && "ontouchend" in document;
};

},{}],13:[function(_dereq_,module,exports){
"use strict";
module.exports = function isOpera(ua) {
    ua = ua || window.navigator.userAgent;
    return (ua.indexOf("OPR/") !== -1 ||
        ua.indexOf("Opera/") !== -1 ||
        ua.indexOf("OPT/") !== -1);
};

},{}],14:[function(_dereq_,module,exports){
"use strict";
module.exports = function isSamsungBrowser(ua) {
    ua = ua || window.navigator.userAgent;
    return /SamsungBrowser/i.test(ua);
};

},{}],15:[function(_dereq_,module,exports){
"use strict";
module.exports = function isSilk(ua) {
    ua = ua || window.navigator.userAgent;
    return ua.indexOf("Silk/") !== -1;
};

},{}],16:[function(_dereq_,module,exports){
"use strict";
var MINIMUM_SUPPORTED_CHROME_IOS_VERSION = 48;
var isAndroid = _dereq_("./is-android");
var isIosFirefox = _dereq_("./is-ios-firefox");
var isIosWebview = _dereq_("./is-ios-webview");
var isChrome = _dereq_("./is-chrome");
var isSamsungBrowser = _dereq_("./is-samsung");
var isDuckDuckGo = _dereq_("./is-duckduckgo");
function isUnsupportedIosChrome(ua) {
    ua = ua || window.navigator.userAgent;
    var match = ua.match(/CriOS\/(\d+)\./);
    if (!match) {
        return false;
    }
    var version = parseInt(match[1], 10);
    return version < MINIMUM_SUPPORTED_CHROME_IOS_VERSION;
}
function isOperaMini(ua) {
    ua = ua || window.navigator.userAgent;
    return ua.indexOf("Opera Mini") > -1;
}
function isAndroidWebview(ua) {
    var androidWebviewRegExp = /Version\/[\d.]+/i;
    ua = ua || window.navigator.userAgent;
    if (isAndroid(ua)) {
        return (androidWebviewRegExp.test(ua) && !isOperaMini(ua) && !isDuckDuckGo(ua));
    }
    return false;
}
function isOldSamsungBrowserOrSamsungWebview(ua) {
    return !isChrome(ua) && !isSamsungBrowser(ua) && /samsung/i.test(ua);
}
module.exports = function supportsPopups(ua) {
    ua = ua || window.navigator.userAgent;
    return !(isIosWebview(ua) ||
        isIosFirefox(ua) ||
        isAndroidWebview(ua) ||
        isOperaMini(ua) ||
        isUnsupportedIosChrome(ua) ||
        isOldSamsungBrowserOrSamsungWebview(ua));
};

},{"./is-android":3,"./is-chrome":4,"./is-duckduckgo":5,"./is-ios-firefox":7,"./is-ios-webview":9,"./is-samsung":14}],17:[function(_dereq_,module,exports){
module.exports = _dereq_("./dist/is-ios-wkwebview");

},{"./dist/is-ios-wkwebview":10}],18:[function(_dereq_,module,exports){
module.exports = _dereq_("./dist/is-ios");

},{"./dist/is-ios":11}],19:[function(_dereq_,module,exports){
module.exports = _dereq_("./dist/supports-popups");

},{"./dist/supports-popups":16}],20:[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;

},{}],21:[function(_dereq_,module,exports){
"use strict";
var set_attributes_1 = _dereq_("./lib/set-attributes");
var default_attributes_1 = _dereq_("./lib/default-attributes");
var assign_1 = _dereq_("./lib/assign");
module.exports = function createFrame(options) {
    if (options === void 0) { options = {}; }
    var iframe = document.createElement("iframe");
    var config = (0, assign_1.assign)({}, default_attributes_1.defaultAttributes, options);
    if (config.style && typeof config.style !== "string") {
        (0, assign_1.assign)(iframe.style, config.style);
        delete config.style;
    }
    (0, set_attributes_1.setAttributes)(iframe, config);
    if (!iframe.getAttribute("id")) {
        iframe.id = iframe.name;
    }
    return iframe;
};

},{"./lib/assign":22,"./lib/default-attributes":23,"./lib/set-attributes":24}],22:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.assign = void 0;
function assign(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
target) {
    var objs = [];
    for (var _i = 1; _i < arguments.length; _i++) {
        objs[_i - 1] = arguments[_i];
    }
    objs.forEach(function (obj) {
        if (typeof obj !== "object") {
            return;
        }
        Object.keys(obj).forEach(function (key) {
            target[key] = obj[key];
        });
    });
    return target;
}
exports.assign = assign;

},{}],23:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.defaultAttributes = void 0;
exports.defaultAttributes = {
    src: "about:blank",
    frameBorder: 0,
    allowtransparency: true,
    scrolling: "no",
};

},{}],24:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setAttributes = void 0;
function setAttributes(element, 
// eslint-disable-next-line @typescript-eslint/no-explicit-any
attributes) {
    for (var key in attributes) {
        if (attributes.hasOwnProperty(key)) {
            var value = attributes[key];
            if (value == null) {
                element.removeAttribute(key);
            }
            else {
                element.setAttribute(key, value);
            }
        }
    }
}
exports.setAttributes = setAttributes;

},{}],25:[function(_dereq_,module,exports){
"use strict";

function uuid() {
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
    var r = (Math.random() * 16) | 0;
    var v = c === "x" ? r : (r & 0x3) | 0x8;

    return v.toString(16);
  });
}

module.exports = uuid;

},{}],26:[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;

},{}],27:[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;

},{}],28:[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;

},{}],29:[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":26,"./lib/once":27,"./lib/promise-or-callback":28}],30:[function(_dereq_,module,exports){
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
    typeof define === 'function' && define.amd ? define(['exports'], factory) :
    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.loadAxo = {}));
})(this, (function (exports) { 'use strict';

    /*! *****************************************************************************
    Copyright (c) Microsoft Corporation.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    PERFORMANCE OF THIS SOFTWARE.
    ***************************************************************************** */
    /* global Reflect, Promise */


    function __awaiter(thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
            function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }

    function __generator(thisArg, body) {
        var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
        return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f) throw new TypeError("Generator is already executing.");
            while (_) try {
                if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
                if (y = 0, t) op = [op[0] & 2, t.value];
                switch (op[0]) {
                    case 0: case 1: t = op; break;
                    case 4: _.label++; return { value: op[1], done: false };
                    case 5: _.label++; y = op[1]; op = [0]; continue;
                    case 7: op = _.ops.pop(); _.trys.pop(); continue;
                    default:
                        if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                        if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                        if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                        if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                        if (t[2]) _.ops.pop();
                        _.trys.pop(); continue;
                }
                op = body.call(thisArg, _);
            } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
            if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
        }
    }

    var dist = {};

    var scriptPromiseCache = {};
    function loadScript$1(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.type) {
            script.setAttribute("type", "".concat(options.type));
        }
        if (options.crossorigin) {
            script.setAttribute("crossorigin", "".concat(options.crossorigin));
        }
        Object.keys(attrs).forEach(function (key) {
            script.setAttribute("data-".concat(key), "".concat(attrs[key]));
        });
        scriptLoadPromise = new Promise(function (resolve, reject) {
            script.addEventListener("load", function () {
                resolve(script);
            });
            script.addEventListener("error", function () {
                reject(new Error("".concat(options.src, " failed to load.")));
            });
            script.addEventListener("abort", function () {
                reject(new Error("".concat(options.src, " has aborted.")));
            });
            container.appendChild(script);
        });
        scriptPromiseCache[stringifiedOptions] = scriptLoadPromise;
        return scriptLoadPromise;
    }
    loadScript$1.clearCache = function () {
        scriptPromiseCache = {};
    };
    var loadScript_1$1 = loadScript$1;

    var loadStylesheet$1 = function loadStylesheet(options) {
        var stylesheet = document.querySelector("link[href=\"".concat(options.href, "\"]"));
        if (stylesheet) {
            return Promise.resolve(stylesheet);
        }
        stylesheet = document.createElement("link");
        var container = options.container || document.head;
        stylesheet.setAttribute("rel", "stylesheet");
        stylesheet.setAttribute("type", "text/css");
        stylesheet.setAttribute("href", options.href);
        stylesheet.setAttribute("id", options.id);
        if (container.firstChild) {
            container.insertBefore(stylesheet, container.firstChild);
        }
        else {
            container.appendChild(stylesheet);
        }
        return Promise.resolve(stylesheet);
    };

    Object.defineProperty(dist, "__esModule", { value: true });
    dist.loadStylesheet = loadScript_1 = dist.loadScript = void 0;
    var loadScript = loadScript_1$1;
    var loadScript_1 = dist.loadScript = loadScript;
    var loadStylesheet = loadStylesheet$1;
    dist.loadStylesheet = loadStylesheet;

    var CDNX_PROD = "https://www.paypalobjects.com";
    var ASSET_NAME = {
        minified: "axo.min",
        unminified: "axo",
    };
    var FL_NAMESPACE = "fastlane";
    var ASSET_PATH = "connect-boba";
    var LOCALE_PATH = "".concat(ASSET_PATH, "/locales/");
    var constants = {
        AXO_ASSET_NAME: ASSET_NAME,
        AXO_ASSET_PATH: ASSET_PATH,
        LOCALE_PATH: LOCALE_PATH,
        CDNX_PROD: CDNX_PROD,
    };

    var AxoSupportedPlatforms = {
        BT: "BT",
        PPCP: "PPCP",
    };

    /**
     * Checks if the current environment is an AMD environment.
     *
     * @returns {boolean} True if the environment is AMD, false otherwise.
     */
    function isAmdEnv() {
        return typeof window.define === "function" && !!window.define.amd;
    }
    /**
     * Checks if the current environment is a RequireJS environment.
     *
     * @returns {boolean} True if the environment is RequireJS, false otherwise.
     */
    function isRequireJsEnv() {
        return (isAmdEnv() &&
            typeof window.requirejs === "function" &&
            typeof window.requirejs.config === "function");
    }

    /**
     * Safely loads BT modules by checking if the module already exists and verifying if versions mismatch
     *
     * @param loadConfig <BtModuleLoadConfig> Configuration of BT Module to load
     * @param version <string> version that should be passed from the client getVersion
     * @returns Promise<HTMLScriptElement>
     * @returns Promise<true> when BT module with same version already exists
     * @returns Promise.reject(err) when BT module already exists but versions mismatch or empty version passed in
     */
    function safeLoadBtModule(loadConfig, version, minified) {
        var _a, _b;
        if (minified === void 0) { minified = true; }
        return __awaiter(this, void 0, void 0, function () {
            var bt, existingVersion;
            return __generator(this, function (_c) {
                bt = getBraintree();
                if (bt && bt[loadConfig.module]) {
                    if (version && ((_a = bt[loadConfig.module]) === null || _a === void 0 ? void 0 : _a.VERSION) !== version) {
                        existingVersion = (_b = bt[loadConfig.module]) === null || _b === void 0 ? void 0 : _b.VERSION;
                        throw new Error("".concat(loadConfig.module, " already loaded with version ").concat(existingVersion, " cannot load version ").concat(version));
                    }
                    else {
                        return [2 /*return*/, true];
                    }
                }
                if (!version) {
                    throw new Error("Attempted to load ".concat(loadConfig.module, " without specifying version"));
                }
                return [2 /*return*/, loadBtModule(loadConfig, version, minified)];
            });
        });
    }
    /**
     * Reads the version and to load the correct version of Bt module
     *
     * @param loadConfig <BtModuleLoadConfig> Configuration of BT Module to load
     * @param version <string> Bt module version
     * @returns Promise<HTMLScriptElement> or
     */
    function loadBtModule(loadConfig, version, minified) {
        if (minified === void 0) { minified = true; }
        if (isAmdEnv()) {
            var module_1 = minified
                ? loadConfig.amdModule.minified
                : loadConfig.amdModule.unminified;
            return new Promise(function (resolve, reject) {
                // eslint-disable-next-line @typescript-eslint/ban-ts-comment
                // @ts-ignore
                window.require([module_1], resolve, reject);
            });
        }
        var script = minified
            ? loadConfig.script.minified
            : loadConfig.script.unminified;
        return loadScript_1({
            id: "".concat(loadConfig.id, "-").concat(version),
            src: "https://js.braintreegateway.com/web/".concat(version, "/js/").concat(script),
        });
    }
    /**
     * Looks for the Braintree web sdk on the window object
     *
     * @returns Braintree web sdk
     */
    function getBraintree() {
        return window === null || window === void 0 ? void 0 : window.braintree;
    }

    var _a, _b;
    /**
     * Maps to the BT module namespace created on the window.braintree object
     */
    var BtModule = {
        Client: "client",
        HostedCardFields: "hostedFields",
    };
    var BT_NAMESPACE = "braintree";
    var BT_ASSET_NAME = (_a = {},
        _a[BtModule.Client] = "client",
        _a[BtModule.HostedCardFields] = "hosted-fields",
        _a);
    var btModulesLoadConfig = (_b = {},
        _b[BtModule.Client] = {
            id: "client",
            module: BtModule.Client,
            amdModule: {
                unminified: "".concat(BT_NAMESPACE, "/").concat(BT_ASSET_NAME[BtModule.Client]),
                minified: "".concat(BT_NAMESPACE, "/").concat(BT_ASSET_NAME[BtModule.Client], ".min"),
            },
            script: {
                unminified: "".concat(BT_ASSET_NAME[BtModule.Client], ".js"),
                minified: "".concat(BT_ASSET_NAME[BtModule.Client], ".min.js"),
            },
        },
        _b[BtModule.HostedCardFields] = {
            id: "hcf",
            module: BtModule.HostedCardFields,
            amdModule: {
                unminified: "".concat(BT_NAMESPACE, "/").concat(BT_ASSET_NAME[BtModule.HostedCardFields]),
                minified: "".concat(BT_NAMESPACE, "/").concat(BT_ASSET_NAME[BtModule.HostedCardFields], ".min"),
            },
            script: {
                unminified: "".concat(BT_ASSET_NAME[BtModule.HostedCardFields], ".js"),
                minified: "".concat(BT_ASSET_NAME[BtModule.HostedCardFields], ".min.js"),
            },
        },
        _b);

    /**
     * Loads accelerated checkout components.
     * @param options object with a minified parameter to determine if the script that is loaded should be minified or not (defaults to true if)
     * @returns an object with metadata with a localeUrl parameter to be read by AXO SDK
     */
    function loadAxo(options) {
        return __awaiter(this, void 0, void 0, function () {
            var btSdkVersion, minified, assetUrl, localeUrl;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        performance.mark("pp_axo_sdk_init_invoked");
                        btSdkVersion = options.btSdkVersion, minified = options.minified;
                        assetUrl = getAssetsUrl(options);
                        localeUrl = getLocaleUrl(options);
                        if (!(options.platform === AxoSupportedPlatforms.BT)) return [3 /*break*/, 2];
                        return [4 /*yield*/, Promise.all([
                                safeLoadBtModule(btModulesLoadConfig.hostedFields, btSdkVersion, minified),
                                loadAXOScript(assetUrl, minified),
                            ])];
                    case 1:
                        _a.sent();
                        return [3 /*break*/, 5];
                    case 2:
                        if (!(options.platform === AxoSupportedPlatforms.PPCP)) return [3 /*break*/, 4];
                        return [4 /*yield*/, Promise.all([
                                safeLoadBtModule(btModulesLoadConfig.client, btSdkVersion, minified),
                                safeLoadBtModule(btModulesLoadConfig.hostedFields, btSdkVersion, minified),
                                loadAXOScript(assetUrl, minified),
                            ])];
                    case 3:
                        _a.sent();
                        return [3 /*break*/, 5];
                    case 4: throw new Error("unsupported axo platform");
                    case 5: return [2 /*return*/, { metadata: { localeUrl: localeUrl } }];
                }
            });
        });
    }
    /**
     * Reads the url and to load the axo bundle script
     * @param url (Required) string url for the correct axo asset
     * @returns Promise<HTMLScriptElement>
     */
    function loadAXOScript(url, minified) {
        var _a;
        if (minified === void 0) { minified = true; }
        if (isAmdEnv()) {
            // AMD environment
            if (isRequireJsEnv()) {
                // Let's configure RequireJS
                requirejs.config({
                    paths: (_a = {},
                        _a[FL_NAMESPACE] = url,
                        _a),
                });
            }
            var moduleName_1 = "".concat(FL_NAMESPACE, "/").concat(minified
                ? constants.AXO_ASSET_NAME.minified
                : constants.AXO_ASSET_NAME.unminified);
            return new Promise(function (resolve, reject) {
                window.require([moduleName_1], resolve, reject);
            });
        }
        // Not an AMD environment
        return loadScript_1({
            id: "axo-id",
            src: url,
            forceScriptReload: true,
        });
    }
    /**
     * Prepends the domain to the asset url
     * @param options object with assetUrl and bundleid parameters to determine which URL to return
     * @returns full domain and assets URL as string
     */
    function generateAssetUrl(_a) {
        var assetUrl = _a.assetUrl, bundleId = _a.bundleId;
        return bundleId
            ? "https://cdn-".concat(bundleId, ".static.engineering.dev.paypalinc.com/").concat(assetUrl)
            : "".concat(constants.CDNX_PROD, "/").concat(assetUrl);
    }
    /**
     * Retrieves either the minified or unminified assets URL as specified
     * @param options (Optional) object with a minified and metadata with bundleIdOverride parameters to determine which URL to return
     * @returns assets URL as string
     */
    function getAssetsUrl(options) {
        var _a;
        var assetName = (options === null || options === void 0 ? void 0 : options.minified) !== false
            ? constants.AXO_ASSET_NAME.minified
            : constants.AXO_ASSET_NAME.unminified;
        var assetUrl = isAmdEnv()
            ? constants.AXO_ASSET_PATH
            : "".concat(constants.AXO_ASSET_PATH, "/").concat(assetName, ".js");
        return generateAssetUrl({
            assetUrl: assetUrl,
            bundleId: (_a = options === null || options === void 0 ? void 0 : options.metadata) === null || _a === void 0 ? void 0 : _a.bundleIdOverride,
        });
    }
    /**
     * Retrieves the Locales URL, the path to our language files
     * @param options (Optional) object with a minified and metadata with bundleIdOverride parameters to determine which URL to return
     * @returns locale URL as string
     */
    function getLocaleUrl(options) {
        var _a;
        return generateAssetUrl({
            assetUrl: constants.LOCALE_PATH,
            bundleId: (_a = options === null || options === void 0 ? void 0 : options.metadata) === null || _a === void 0 ? void 0 : _a.bundleIdOverride,
        });
    }

    exports.constants = constants;
    exports.loadAxo = loadAxo;

}));

},{}],31:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Framebus = void 0;
var lib_1 = _dereq_("./lib");
var DefaultPromise = (typeof window !== "undefined" &&
    window.Promise);
var Framebus = /** @class */ (function () {
    function Framebus(options) {
        if (options === void 0) { options = {}; }
        this.origin = options.origin || "*";
        this.channel = options.channel || "";
        this.verifyDomain = options.verifyDomain;
        // if a targetFrames configuration is not passed in,
        // the default behavior is to broadcast the payload
        // to the top level window or to the frame itself.
        // By default, the broadcast function will loop through
        // all the known siblings and children of the window.
        // If a targetFrames array is passed, it will instead
        // only broadcast to those specified targetFrames
        this.targetFrames = options.targetFrames || [];
        this.limitBroadcastToFramesArray = Boolean(options.targetFrames);
        this.isDestroyed = false;
        this.listeners = [];
        this.hasAdditionalChecksForOnListeners = Boolean(this.verifyDomain || this.limitBroadcastToFramesArray);
    }
    Framebus.setPromise = function (PromiseGlobal) {
        Framebus.Promise = PromiseGlobal;
    };
    Framebus.target = function (options) {
        return new Framebus(options);
    };
    Framebus.prototype.addTargetFrame = function (frame) {
        if (!this.limitBroadcastToFramesArray) {
            return;
        }
        this.targetFrames.push(frame);
    };
    Framebus.prototype.include = function (childWindow) {
        if (childWindow == null) {
            return false;
        }
        if (childWindow.Window == null) {
            return false;
        }
        if (childWindow.constructor !== childWindow.Window) {
            return false;
        }
        lib_1.childWindows.push(childWindow);
        return true;
    };
    Framebus.prototype.target = function (options) {
        return Framebus.target(options);
    };
    Framebus.prototype.emit = function (eventName, data, reply) {
        if (this.isDestroyed) {
            return false;
        }
        var origin = this.origin;
        eventName = this.namespaceEvent(eventName);
        if ((0, lib_1.isntString)(eventName)) {
            return false;
        }
        if ((0, lib_1.isntString)(origin)) {
            return false;
        }
        if (typeof data === "function") {
            reply = data;
            data = undefined; // eslint-disable-line no-undefined
        }
        var payload = (0, lib_1.packagePayload)(eventName, origin, data, reply);
        if (!payload) {
            return false;
        }
        if (this.limitBroadcastToFramesArray) {
            this.targetFramesAsWindows().forEach(function (frame) {
                (0, lib_1.sendMessage)(frame, payload, origin);
            });
        }
        else {
            (0, lib_1.broadcast)(payload, {
                origin: origin,
                frame: window.top || window.self,
            });
        }
        return true;
    };
    Framebus.prototype.emitAsPromise = function (eventName, data) {
        var _this = this;
        return new Framebus.Promise(function (resolve, reject) {
            var didAttachListener = _this.emit(eventName, data, function (payload) {
                resolve(payload);
            });
            if (!didAttachListener) {
                reject(new Error("Listener not added for \"".concat(eventName, "\"")));
            }
        });
    };
    Framebus.prototype.on = function (eventName, originalHandler) {
        if (this.isDestroyed) {
            return false;
        }
        // eslint-disable-next-line @typescript-eslint/no-this-alias
        var self = this;
        var origin = this.origin;
        var handler = originalHandler;
        eventName = this.namespaceEvent(eventName);
        if ((0, lib_1.subscriptionArgsInvalid)(eventName, handler, origin)) {
            return false;
        }
        if (this.hasAdditionalChecksForOnListeners) {
            /* eslint-disable no-invalid-this, @typescript-eslint/ban-ts-comment */
            handler = function () {
                var args = [];
                for (var _i = 0; _i < arguments.length; _i++) {
                    args[_i] = arguments[_i];
                }
                // @ts-ignore
                if (!self.passesVerifyDomainCheck(this && this.origin)) {
                    return;
                }
                // @ts-ignore
                if (!self.hasMatchingTargetFrame(this && this.source)) {
                    return;
                }
                originalHandler.apply(void 0, args);
            };
            /* eslint-enable no-invalid-this, @typescript-eslint/ban-ts-comment */
        }
        this.listeners.push({
            eventName: eventName,
            handler: handler,
            originalHandler: originalHandler,
        });
        lib_1.subscribers[origin] = lib_1.subscribers[origin] || {};
        lib_1.subscribers[origin][eventName] = lib_1.subscribers[origin][eventName] || [];
        lib_1.subscribers[origin][eventName].push(handler);
        return true;
    };
    Framebus.prototype.off = function (eventName, originalHandler) {
        var handler = originalHandler;
        if (this.isDestroyed) {
            return false;
        }
        if (this.hasAdditionalChecksForOnListeners) {
            for (var i = 0; i < this.listeners.length; i++) {
                var listener = this.listeners[i];
                if (listener.originalHandler === originalHandler) {
                    handler = listener.handler;
                }
            }
        }
        eventName = this.namespaceEvent(eventName);
        var origin = this.origin;
        if ((0, lib_1.subscriptionArgsInvalid)(eventName, handler, origin)) {
            return false;
        }
        var subscriberList = lib_1.subscribers[origin] && lib_1.subscribers[origin][eventName];
        if (!subscriberList) {
            return false;
        }
        for (var i = 0; i < subscriberList.length; i++) {
            if (subscriberList[i] === handler) {
                subscriberList.splice(i, 1);
                return true;
            }
        }
        return false;
    };
    Framebus.prototype.teardown = function () {
        if (this.isDestroyed) {
            return;
        }
        this.isDestroyed = true;
        for (var i = 0; i < this.listeners.length; i++) {
            var listener = this.listeners[i];
            this.off(listener.eventName, listener.handler);
        }
        this.listeners.length = 0;
    };
    Framebus.prototype.passesVerifyDomainCheck = function (origin) {
        if (!this.verifyDomain) {
            // always pass this check if no verifyDomain option was set
            return true;
        }
        return this.checkOrigin(origin);
    };
    Framebus.prototype.targetFramesAsWindows = function () {
        if (!this.limitBroadcastToFramesArray) {
            return [];
        }
        return this.targetFrames
            .map(function (frame) {
            // we can't pull off the contentWindow
            // when the iframe is originally added
            // to the array, because if it is not
            // in the DOM at that time, it will have
            // a contentWindow of `null`
            if (frame instanceof HTMLIFrameElement) {
                return frame.contentWindow;
            }
            return frame;
        })
            .filter(function (win) {
            // just in case an iframe element
            // was removed from the DOM
            // and the contentWindow property
            // is null
            return win;
        });
    };
    Framebus.prototype.hasMatchingTargetFrame = function (source) {
        if (!this.limitBroadcastToFramesArray) {
            // always pass this check if we aren't limiting to the target frames
            return true;
        }
        var matchingFrame = this.targetFramesAsWindows().find(function (frame) {
            return frame === source;
        });
        return Boolean(matchingFrame);
    };
    Framebus.prototype.checkOrigin = function (postMessageOrigin) {
        var merchantHost;
        var a = document.createElement("a");
        a.href = location.href;
        if (a.protocol === "https:") {
            merchantHost = a.host.replace(/:443$/, "");
        }
        else if (a.protocol === "http:") {
            merchantHost = a.host.replace(/:80$/, "");
        }
        else {
            merchantHost = a.host;
        }
        var merchantOrigin = a.protocol + "//" + merchantHost;
        if (merchantOrigin === postMessageOrigin) {
            return true;
        }
        if (this.verifyDomain) {
            return this.verifyDomain(postMessageOrigin);
        }
        return true;
    };
    Framebus.prototype.namespaceEvent = function (eventName) {
        if (!this.channel) {
            return eventName;
        }
        return "".concat(this.channel, ":").concat(eventName);
    };
    Framebus.Promise = DefaultPromise;
    return Framebus;
}());
exports.Framebus = Framebus;

},{"./lib":39}],32:[function(_dereq_,module,exports){
"use strict";
var lib_1 = _dereq_("./lib");
var framebus_1 = _dereq_("./framebus");
(0, lib_1.attach)();
module.exports = framebus_1.Framebus;

},{"./framebus":31,"./lib":39}],33:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.detach = exports.attach = void 0;
var _1 = _dereq_("./");
var isAttached = false;
function attach() {
    if (isAttached || typeof window === "undefined") {
        return;
    }
    isAttached = true;
    window.addEventListener("message", _1.onMessage, false);
}
exports.attach = attach;
// removeIf(production)
function detach() {
    isAttached = false;
    window.removeEventListener("message", _1.onMessage, false);
}
exports.detach = detach;
// endRemoveIf(production)

},{"./":39}],34:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.broadcastToChildWindows = void 0;
var _1 = _dereq_("./");
function broadcastToChildWindows(payload, origin, source) {
    for (var i = _1.childWindows.length - 1; i >= 0; i--) {
        var childWindow = _1.childWindows[i];
        if (childWindow.closed) {
            _1.childWindows.splice(i, 1);
        }
        else if (source !== childWindow) {
            (0, _1.broadcast)(payload, {
                origin: origin,
                frame: childWindow.top,
            });
        }
    }
}
exports.broadcastToChildWindows = broadcastToChildWindows;

},{"./":39}],35:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.broadcast = void 0;
var _1 = _dereq_("./");
function broadcast(payload, options) {
    var i = 0;
    var frameToBroadcastTo;
    var origin = options.origin, frame = options.frame;
    try {
        frame.postMessage(payload, origin);
        if ((0, _1.hasOpener)(frame) && frame.opener.top !== window.top) {
            broadcast(payload, {
                origin: origin,
                frame: frame.opener.top,
            });
        }
        // previously, our max value was frame.frames.length
        // but frames.length inherits from window.length
        // which can be overwritten if a developer does
        // `var length = value;` outside of a function
        // scope, it'll prevent us from looping through
        // all the frames. With this, we loop through
        // until there are no longer any frames
        // eslint-disable-next-line no-cond-assign
        while ((frameToBroadcastTo = frame.frames[i])) {
            broadcast(payload, {
                origin: origin,
                frame: frameToBroadcastTo,
            });
            i++;
        }
    }
    catch (_) {
        /* ignored */
    }
}
exports.broadcast = broadcast;

},{"./":39}],36:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.subscribers = exports.childWindows = exports.prefix = void 0;
exports.prefix = "/*framebus*/";
exports.childWindows = [];
exports.subscribers = {};

},{}],37:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.dispatch = void 0;
var _1 = _dereq_("./");
function dispatch(origin, event, data, reply, e) {
    if (!_1.subscribers[origin]) {
        return;
    }
    if (!_1.subscribers[origin][event]) {
        return;
    }
    var args = [];
    if (data) {
        args.push(data);
    }
    if (reply) {
        args.push(reply);
    }
    for (var i = 0; i < _1.subscribers[origin][event].length; i++) {
        _1.subscribers[origin][event][i].apply(e, args);
    }
}
exports.dispatch = dispatch;

},{"./":39}],38:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasOpener = void 0;
function hasOpener(frame) {
    if (frame.top !== frame) {
        return false;
    }
    if (frame.opener == null) {
        return false;
    }
    if (frame.opener === frame) {
        return false;
    }
    if (frame.opener.closed === true) {
        return false;
    }
    return true;
}
exports.hasOpener = hasOpener;

},{}],39:[function(_dereq_,module,exports){
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", { value: true });
__exportStar(_dereq_("./attach"), exports);
__exportStar(_dereq_("./broadcast-to-child-windows"), exports);
__exportStar(_dereq_("./broadcast"), exports);
__exportStar(_dereq_("./constants"), exports);
__exportStar(_dereq_("./dispatch"), exports);
__exportStar(_dereq_("./has-opener"), exports);
__exportStar(_dereq_("./is-not-string"), exports);
__exportStar(_dereq_("./message"), exports);
__exportStar(_dereq_("./package-payload"), exports);
__exportStar(_dereq_("./send-message"), exports);
__exportStar(_dereq_("./subscribe-replier"), exports);
__exportStar(_dereq_("./subscription-args-invalid"), exports);
__exportStar(_dereq_("./types"), exports);
__exportStar(_dereq_("./unpack-payload"), exports);

},{"./attach":33,"./broadcast":35,"./broadcast-to-child-windows":34,"./constants":36,"./dispatch":37,"./has-opener":38,"./is-not-string":40,"./message":41,"./package-payload":42,"./send-message":43,"./subscribe-replier":44,"./subscription-args-invalid":45,"./types":46,"./unpack-payload":47}],40:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isntString = void 0;
function isntString(str) {
    return typeof str !== "string";
}
exports.isntString = isntString;

},{}],41:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.onMessage = void 0;
var _1 = _dereq_("./");
function onMessage(e) {
    if ((0, _1.isntString)(e.data)) {
        return;
    }
    var payload = (0, _1.unpackPayload)(e);
    if (!payload) {
        return;
    }
    var data = payload.eventData;
    var reply = payload.reply;
    (0, _1.dispatch)("*", payload.event, data, reply, e);
    (0, _1.dispatch)(e.origin, payload.event, data, reply, e);
    (0, _1.broadcastToChildWindows)(e.data, payload.origin, e.source);
}
exports.onMessage = onMessage;

},{"./":39}],42:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.packagePayload = void 0;
var _1 = _dereq_("./");
function packagePayload(event, origin, data, reply) {
    var packaged;
    var payload = {
        event: event,
        origin: origin,
    };
    if (typeof reply === "function") {
        payload.reply = (0, _1.subscribeReplier)(reply, origin);
    }
    payload.eventData = data;
    try {
        packaged = _1.prefix + JSON.stringify(payload);
    }
    catch (e) {
        throw new Error("Could not stringify event: ".concat(e.message));
    }
    return packaged;
}
exports.packagePayload = packagePayload;

},{"./":39}],43:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.sendMessage = void 0;
/**
 * A basic function for wrapping the sending of postMessages to frames.
 */
function sendMessage(frame, payload, origin) {
    try {
        frame.postMessage(payload, origin);
    }
    catch (error) {
        /* ignored */
    }
}
exports.sendMessage = sendMessage;

},{}],44:[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.subscribeReplier = void 0;
var framebus_1 = _dereq_("../framebus");
var uuid_1 = __importDefault(_dereq_("@braintree/uuid"));
function subscribeReplier(fn, origin) {
    var uuid = (0, uuid_1.default)();
    function replier(data, replyOriginHandler) {
        fn(data, replyOriginHandler);
        framebus_1.Framebus.target({
            origin: origin,
        }).off(uuid, replier);
    }
    framebus_1.Framebus.target({
        origin: origin,
    }).on(uuid, replier);
    return uuid;
}
exports.subscribeReplier = subscribeReplier;

},{"../framebus":31,"@braintree/uuid":25}],45:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.subscriptionArgsInvalid = void 0;
var _1 = _dereq_("./");
function subscriptionArgsInvalid(event, fn, origin) {
    if ((0, _1.isntString)(event)) {
        return true;
    }
    if (typeof fn !== "function") {
        return true;
    }
    return (0, _1.isntString)(origin);
}
exports.subscriptionArgsInvalid = subscriptionArgsInvalid;

},{"./":39}],46:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });

},{}],47:[function(_dereq_,module,exports){
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unpackPayload = void 0;
var _1 = _dereq_("./");
function unpackPayload(e) {
    var payload;
    if (e.data.slice(0, _1.prefix.length) !== _1.prefix) {
        return false;
    }
    try {
        payload = JSON.parse(e.data.slice(_1.prefix.length));
    }
    catch (err) {
        return false;
    }
    if (payload.reply) {
        var replyOrigin_1 = e.origin;
        var replySource_1 = e.source;
        var replyEvent_1 = payload.reply;
        payload.reply = function reply(replyData) {
            if (!replySource_1) {
                return;
            }
            var replyPayload = (0, _1.packagePayload)(replyEvent_1, replyOrigin_1, replyData);
            if (!replyPayload) {
                return;
            }
            replySource_1.postMessage(replyPayload, replyOrigin_1);
        };
    }
    return payload;
}
exports.unpackPayload = unpackPayload;

},{"./":39}],48:[function(_dereq_,module,exports){
"use strict";

var createAuthorizationData = _dereq_("./create-authorization-data");
var jsonClone = _dereq_("./json-clone");
var constants = _dereq_("./constants");

function addMetadata(configuration, data) {
  var key;
  var attrs = data ? jsonClone(data) : {};
  var authAttrs = createAuthorizationData(configuration.authorization).attrs;
  var _meta = jsonClone(configuration.analyticsMetadata);

  attrs.braintreeLibraryVersion = constants.BRAINTREE_LIBRARY_VERSION;

  for (key in attrs._meta) {
    if (attrs._meta.hasOwnProperty(key)) {
      _meta[key] = attrs._meta[key];
    }
  }

  attrs._meta = _meta;

  if (authAttrs.tokenizationKey) {
    attrs.tokenizationKey = authAttrs.tokenizationKey;
  } else {
    attrs.authorizationFingerprint = authAttrs.authorizationFingerprint;
  }

  return attrs;
}

function addEventMetadata(clientInstanceOrPromise) {
  var configuration = clientInstanceOrPromise.getConfiguration();
  var authAttrs = createAuthorizationData(configuration.authorization).attrs;
  var isProd = configuration.gatewayConfiguration.environment === "production";

  /* eslint-disable camelcase */
  var metadata = {
    api_integration_type: configuration.analyticsMetadata.integrationType,
    app_id: window.location.host,
    c_sdk_ver: constants.VERSION,
    component: "braintreeclientsdk",
    merchant_sdk_env: isProd ? "production" : "sandbox",
    merchant_id: configuration.gatewayConfiguration.merchantId,
    event_source: "web",
    platform: constants.PLATFORM,
    platform_version: window.navigator.userAgent,
    session_id: configuration.analyticsMetadata.sessionId,
    client_session_id: configuration.analyticsMetadata.sessionId,
    tenant_name: "braintree",
  };

  if (authAttrs.tokenizationKey) {
    metadata.tokenization_key = authAttrs.tokenizationKey;
  } else {
    metadata.auth_fingerprint = authAttrs.authorizationFingerprint;
  }
  /* eslint-enable camelcase */

  return metadata;
}

module.exports = {
  addMetadata: addMetadata,
  addEventMetadata: addEventMetadata,
};

},{"./constants":54,"./create-authorization-data":58,"./json-clone":74}],49:[function(_dereq_,module,exports){
"use strict";

var constants = _dereq_("./constants");
var metadata = _dereq_("./add-metadata");
var assign = _dereq_("./assign").assign;

function sendPaypalEvent(clientInstanceOrPromise, eventName, callback) {
  return sendPaypalEventPlusFields(
    clientInstanceOrPromise,
    eventName,
    {},
    callback
  );
}

function sendPaypalEventPlusFields(
  clientInstanceOrPromise,
  eventName,
  extraFields,
  callback
) {
  var timestamp = Date.now();

  return Promise.resolve(clientInstanceOrPromise)
    .then(function (client) {
      var request = client._request;
      var url = constants.ANALYTICS_URL;
      var qualifiedEvent = constants.ANALYTICS_PREFIX + eventName;
      var configuration = client.getConfiguration();
      var isProd =
        configuration.gatewayConfiguration.environment === "production";
      var data = {
        events: [],
        tracking: [],
      };
      var trackingMeta = metadata.addEventMetadata(client, data);

      trackingMeta.event_name = qualifiedEvent; // eslint-disable-line camelcase
      trackingMeta.t = timestamp; // eslint-disable-line camelcase

      data.events = [
        {
          level: "info",
          event: qualifiedEvent,
          payload: {
            env: isProd ? "production" : "sandbox",
            timestamp: timestamp,
          },
        },
      ];
      data.tracking = [trackingMeta];

      if (extraFields && typeof extraFields === "object") {
        data.tracking = [appendExtraFieldsTo(trackingMeta, extraFields)];
      }

      return request(
        {
          url: url,
          method: "post",
          data: data,
          timeout: constants.ANALYTICS_REQUEST_TIMEOUT_MS,
        },
        callback
      );
    })
    .catch(function (err) {
      if (callback) {
        callback(err);
      }
    });
}

function appendExtraFieldsTo(trackingMeta, extraFields) {
  var result = {};
  var allowedExtraFields = assign({}, extraFields);

  Object.keys(allowedExtraFields).forEach(function (field) {
    if (constants.ALLOWED_EXTRA_EVENT_FIELDS.indexOf(field) === -1) {
      delete allowedExtraFields[field];
    }
  });

  result = assign(trackingMeta, allowedExtraFields);

  return result;
}

module.exports = {
  sendEvent: sendPaypalEvent,
  sendEventPlus: sendPaypalEventPlusFields,
};

},{"./add-metadata":48,"./assign":51,"./constants":54}],50:[function(_dereq_,module,exports){
"use strict";

var loadScript = _dereq_("@braintree/asset-loader/load-script");
var loadConnectScript = _dereq_("@paypal/accelerated-checkout-loader");

module.exports = {
  loadScript: loadScript,
  loadFastlane: loadConnectScript.loadAxo,
};

},{"@braintree/asset-loader/load-script":2,"@paypal/accelerated-checkout-loader":30}],51:[function(_dereq_,module,exports){
"use strict";

var assignNormalized =
  typeof Object.assign === "function" ? Object.assign : assignPolyfill;

function assignPolyfill(destination) {
  var i, source, key;

  for (i = 1; i < arguments.length; i++) {
    source = arguments[i];
    for (key in source) {
      if (source.hasOwnProperty(key)) {
        destination[key] = source[key];
      }
    }
  }

  return destination;
}

module.exports = {
  assign: assignNormalized,
  _assign: assignPolyfill,
};

},{}],52:[function(_dereq_,module,exports){
"use strict";

var BraintreeError = _dereq_("./braintree-error");
var sharedErrors = _dereq_("./errors");
var VERSION = "3.118.2";

function basicComponentVerification(options) {
  var client, authorization, name;

  if (!options) {
    return Promise.reject(
      new BraintreeError({
        type: sharedErrors.INVALID_USE_OF_INTERNAL_FUNCTION.type,
        code: sharedErrors.INVALID_USE_OF_INTERNAL_FUNCTION.code,
        message:
          "Options must be passed to basicComponentVerification function.",
      })
    );
  }

  name = options.name;
  client = options.client;
  authorization = options.authorization;

  if (!client && !authorization) {
    return Promise.reject(
      new BraintreeError({
        type: sharedErrors.INSTANTIATION_OPTION_REQUIRED.type,
        code: sharedErrors.INSTANTIATION_OPTION_REQUIRED.code,
        // NEXT_MAJOR_VERSION in major version, we expose passing in authorization for all components
        // instead of passing in a client instance. Leave this a silent feature for now.
        message: "options.client is required when instantiating " + name + ".",
      })
    );
  }

  if (!authorization && client.getVersion() !== VERSION) {
    return Promise.reject(
      new BraintreeError({
        type: sharedErrors.INCOMPATIBLE_VERSIONS.type,
        code: sharedErrors.INCOMPATIBLE_VERSIONS.code,
        message:
          "Client (version " +
          client.getVersion() +
          ") and " +
          name +
          " (version " +
          VERSION +
          ") components must be from the same SDK version.",
      })
    );
  }

  return Promise.resolve();
}

module.exports = {
  verify: basicComponentVerification,
};

},{"./braintree-error":53,"./errors":61}],53:[function(_dereq_,module,exports){
"use strict";

var enumerate = _dereq_("./enumerate");

/**
 * @class
 * @global
 * @param {object} options Construction options
 * @classdesc This class is used to report error conditions, frequently as the first parameter to callbacks throughout the Braintree SDK.
 * @description <strong>You cannot use this constructor directly. Interact with instances of this class through {@link callback callbacks}.</strong>
 */
function BraintreeError(options) {
  if (!BraintreeError.types.hasOwnProperty(options.type)) {
    throw new Error(options.type + " is not a valid type.");
  }

  if (!options.code) {
    throw new Error("Error code required.");
  }

  if (!options.message) {
    throw new Error("Error message required.");
  }

  this.name = "BraintreeError";

  /**
   * @type {string}
   * @description A code that corresponds to specific errors.
   */
  this.code = options.code;

  /**
   * @type {string}
   * @description A short description of the error.
   */
  this.message = options.message;

  /**
   * @type {BraintreeError.types}
   * @description The type of error.
   */
  this.type = options.type;

  /**
   * @type {object=}
   * @description Additional information about the error, such as an underlying network error response.
   */
  this.details = options.details;
}

BraintreeError.prototype = Object.create(Error.prototype);
BraintreeError.prototype.constructor = BraintreeError;

/**
 * Enum for {@link BraintreeError} types.
 * @name BraintreeError.types
 * @enum
 * @readonly
 * @memberof BraintreeError
 * @property {string} CUSTOMER An error caused by the customer.
 * @property {string} MERCHANT An error that is actionable by the merchant.
 * @property {string} NETWORK An error due to a network problem.
 * @property {string} INTERNAL An error caused by Braintree code.
 * @property {string} UNKNOWN An error where the origin is unknown.
 */
BraintreeError.types = enumerate([
  "CUSTOMER",
  "MERCHANT",
  "NETWORK",
  "INTERNAL",
  "UNKNOWN",
]);

BraintreeError.findRootError = function (err) {
  if (
    err instanceof BraintreeError &&
    err.details &&
    err.details.originalError
  ) {
    return BraintreeError.findRootError(err.details.originalError);
  }

  return err;
};

module.exports = BraintreeError;

},{"./enumerate":60}],54:[function(_dereq_,module,exports){
"use strict";

var VERSION = "3.118.2";
var PLATFORM = "web";

var CLIENT_API_URLS = {
  production: "https://api.braintreegateway.com:443",
  sandbox: "https://api.sandbox.braintreegateway.com:443",
};

var ASSETS_URLS = {
  production: "https://assets.braintreegateway.com",
  sandbox: "https://assets.braintreegateway.com",
};

var GRAPHQL_URLS = {
  production: "https://payments.braintree-api.com/graphql",
  sandbox: "https://payments.sandbox.braintree-api.com/graphql",
};

// endRemoveIf(production)

module.exports = {
  ANALYTICS_PREFIX: PLATFORM + ".",
  ANALYTICS_REQUEST_TIMEOUT_MS: 2000,
  ANALYTICS_URL: "https://www.paypal.com/xoplatform/logger/api/logger",
  ASSETS_URLS: ASSETS_URLS,
  CLIENT_API_URLS: CLIENT_API_URLS,
  FRAUDNET_SOURCE: "BRAINTREE_SIGNIN",
  FRAUDNET_FNCLS: "fnparams-dede7cc5-15fd-4c75-a9f4-36c430ee3a99",
  FRAUDNET_URL: "https://c.paypal.com/da/r/fb.js",
  BUS_CONFIGURATION_REQUEST_EVENT: "BUS_CONFIGURATION_REQUEST",
  GRAPHQL_URLS: GRAPHQL_URLS,
  INTEGRATION_TIMEOUT_MS: 60000,
  VERSION: VERSION,
  INTEGRATION: "custom",
  SOURCE: "client",
  PLATFORM: PLATFORM,
  BRAINTREE_LIBRARY_VERSION: "braintree/" + PLATFORM + "/" + VERSION,
  ALLOWED_EXTRA_EVENT_FIELDS: ["paypal_context_id"],
};

},{}],55:[function(_dereq_,module,exports){
"use strict";

var BraintreeError = _dereq_("./braintree-error");
var sharedErrors = _dereq_("./errors");

module.exports = function (instance, methodNames) {
  methodNames.forEach(function (methodName) {
    instance[methodName] = function () {
      throw new BraintreeError({
        type: sharedErrors.METHOD_CALLED_AFTER_TEARDOWN.type,
        code: sharedErrors.METHOD_CALLED_AFTER_TEARDOWN.code,
        message: methodName + " cannot be called after teardown.",
      });
    };
  });
};

},{"./braintree-error":53,"./errors":61}],56:[function(_dereq_,module,exports){
"use strict";

var BraintreeError = _dereq_("./braintree-error");

function convertToBraintreeError(originalErr, btErrorObject) {
  if (originalErr instanceof BraintreeError) {
    return originalErr;
  }

  return new BraintreeError({
    type: btErrorObject.type,
    code: btErrorObject.code,
    message: btErrorObject.message,
    details: {
      originalError: originalErr,
    },
  });
}

module.exports = convertToBraintreeError;

},{"./braintree-error":53}],57:[function(_dereq_,module,exports){
"use strict";

// endRemoveIf(production)
var ASSETS_URLS = _dereq_("./constants").ASSETS_URLS;

function createAssetsUrl(authorization) {
  // endRemoveIf(production)

  return ASSETS_URLS.production;
}
/* eslint-enable */

module.exports = {
  create: createAssetsUrl,
};

},{"./constants":54}],58:[function(_dereq_,module,exports){
"use strict";

var atob = _dereq_("../lib/vendor/polyfill").atob;
var CLIENT_API_URLS = _dereq_("../lib/constants").CLIENT_API_URLS;

function _isTokenizationKey(str) {
  return /^[a-zA-Z0-9]+_[a-zA-Z0-9]+_[a-zA-Z0-9_]+$/.test(str);
}

function _parseTokenizationKey(tokenizationKey) {
  var tokens = tokenizationKey.split("_");
  var environment = tokens[0];
  var merchantId = tokens.slice(2).join("_");

  return {
    merchantId: merchantId,
    environment: environment,
  };
}

function createAuthorizationData(authorization) {
  var parsedClientToken, parsedTokenizationKey;
  var data = {
    attrs: {},
    configUrl: "",
  };

  if (_isTokenizationKey(authorization)) {
    parsedTokenizationKey = _parseTokenizationKey(authorization);
    data.environment = parsedTokenizationKey.environment;
    data.attrs.tokenizationKey = authorization;
    data.configUrl =
      CLIENT_API_URLS[parsedTokenizationKey.environment] +
      "/merchants/" +
      parsedTokenizationKey.merchantId +
      "/client_api/v1/configuration";
  } else {
    parsedClientToken = JSON.parse(atob(authorization));
    data.environment = parsedClientToken.environment;
    data.attrs.authorizationFingerprint =
      parsedClientToken.authorizationFingerprint;
    data.configUrl = parsedClientToken.configUrl;
    data.graphQL = parsedClientToken.graphQL;
  }

  return data;
}

module.exports = createAuthorizationData;

},{"../lib/constants":54,"../lib/vendor/polyfill":78}],59:[function(_dereq_,module,exports){
"use strict";

var BraintreeError = _dereq_("./braintree-error");
var assets = _dereq_("./assets");
var sharedErrors = _dereq_("./errors");

var VERSION = "3.118.2";

function createDeferredClient(options) {
  var promise = Promise.resolve();

  if (options.client) {
    return Promise.resolve(options.client);
  }

  if (!(window.braintree && window.braintree.client)) {
    promise = assets
      .loadScript({
        src: options.assetsUrl + "/web/" + VERSION + "/js/client.min.js",
      })
      .catch(function (err) {
        return Promise.reject(
          new BraintreeError({
            type: sharedErrors.CLIENT_SCRIPT_FAILED_TO_LOAD.type,
            code: sharedErrors.CLIENT_SCRIPT_FAILED_TO_LOAD.code,
            message: sharedErrors.CLIENT_SCRIPT_FAILED_TO_LOAD.message,
            details: {
              originalError: err,
            },
          })
        );
      });
  }

  return promise.then(function () {
    if (window.braintree.client.VERSION !== VERSION) {
      return Promise.reject(
        new BraintreeError({
          type: sharedErrors.INCOMPATIBLE_VERSIONS.type,
          code: sharedErrors.INCOMPATIBLE_VERSIONS.code,
          message:
            "Client (version " +
            window.braintree.client.VERSION +
            ") and " +
            options.name +
            " (version " +
            VERSION +
            ") components must be from the same SDK version.",
        })
      );
    }

    return window.braintree.client.create({
      authorization: options.authorization,
      debug: options.debug,
    });
  });
}

module.exports = {
  create: createDeferredClient,
};

},{"./assets":50,"./braintree-error":53,"./errors":61}],60:[function(_dereq_,module,exports){
"use strict";

function enumerate(values, prefix) {
  prefix = prefix == null ? "" : prefix;

  return values.reduce(function (enumeration, value) {
    enumeration[value] = prefix + value;

    return enumeration;
  }, {});
}

module.exports = enumerate;

},{}],61:[function(_dereq_,module,exports){
"use strict";

/**
 * @name BraintreeError.Shared Internal Error Codes
 * @ignore
 * @description These codes should never be experienced by the merchant directly.
 * @property {INTERNAL} INVALID_USE_OF_INTERNAL_FUNCTION Occurs when the client is created without a gateway configuration. Should never happen.
 */

/**
 * @name BraintreeError.Shared Errors - Component Creation Error Codes
 * @description Errors that occur when creating components.
 * @property {MERCHANT} INSTANTIATION_OPTION_REQUIRED Occurs when a component is created that is missing a required option.
 * @property {MERCHANT} INCOMPATIBLE_VERSIONS Occurs when a component is created with a client with a different version than the component.
 * @property {NETWORK} CLIENT_SCRIPT_FAILED_TO_LOAD Occurs when a component attempts to load the Braintree client script, but the request fails.
 */

/**
 * @name BraintreeError.Shared Errors - Component Instance Error Codes
 * @description Errors that occur when using instances of components.
 * @property {MERCHANT} METHOD_CALLED_AFTER_TEARDOWN Occurs when a method is called on a component instance after it has been torn down.
 */

var BraintreeError = _dereq_("./braintree-error");

module.exports = {
  INVALID_USE_OF_INTERNAL_FUNCTION: {
    type: BraintreeError.types.INTERNAL,
    code: "INVALID_USE_OF_INTERNAL_FUNCTION",
  },
  INSTANTIATION_OPTION_REQUIRED: {
    type: BraintreeError.types.MERCHANT,
    code: "INSTANTIATION_OPTION_REQUIRED",
  },
  INCOMPATIBLE_VERSIONS: {
    type: BraintreeError.types.MERCHANT,
    code: "INCOMPATIBLE_VERSIONS",
  },
  CLIENT_SCRIPT_FAILED_TO_LOAD: {
    type: BraintreeError.types.NETWORK,
    code: "CLIENT_SCRIPT_FAILED_TO_LOAD",
    message: "Braintree client script could not be loaded.",
  },
  METHOD_CALLED_AFTER_TEARDOWN: {
    type: BraintreeError.types.MERCHANT,
    code: "METHOD_CALLED_AFTER_TEARDOWN",
  },
};

},{"./braintree-error":53}],62:[function(_dereq_,module,exports){
"use strict";

var Popup = _dereq_("./strategies/popup");
var PopupBridge = _dereq_("./strategies/popup-bridge");
var Modal = _dereq_("./strategies/modal");
var Bus = _dereq_("framebus");
var events = _dereq_("../shared/events");
var errors = _dereq_("../shared/errors");
var constants = _dereq_("../shared/constants");
var uuid = _dereq_("@braintree/uuid");
var iFramer = _dereq_("@braintree/iframer");
var BraintreeError = _dereq_("../../braintree-error");
var browserDetection = _dereq_("../shared/browser-detection");
var assign = _dereq_("./../../assign").assign;
var BUS_CONFIGURATION_REQUEST_EVENT =
  _dereq_("../../constants").BUS_CONFIGURATION_REQUEST_EVENT;

var REQUIRED_CONFIG_KEYS = ["name", "dispatchFrameUrl", "openFrameUrl"];

function noop() {}

function _validateFrameConfiguration(options) {
  if (!options) {
    throw new Error("Valid configuration is required");
  }

  REQUIRED_CONFIG_KEYS.forEach(function (key) {
    if (!options.hasOwnProperty(key)) {
      throw new Error("A valid frame " + key + " must be provided");
    }
  });

  if (!/^[\w_]+$/.test(options.name)) {
    throw new Error("A valid frame name must be provided");
  }
}

function FrameService(options) {
  _validateFrameConfiguration(options);

  this._serviceId = uuid().replace(/-/g, "");

  this._options = {
    name: options.name + "_" + this._serviceId,
    dispatchFrameUrl: options.dispatchFrameUrl,
    openFrameUrl: options.openFrameUrl,
    height: options.height,
    width: options.width,
    top: options.top,
    left: options.left,
  };
  this.state = options.state || {};

  this._bus = new Bus({ channel: this._serviceId });
  this._setBusEvents();
}

FrameService.prototype.initialize = function (callback) {
  var dispatchFrameReadyHandler = function () {
    callback();
    this._bus.off(events.DISPATCH_FRAME_READY, dispatchFrameReadyHandler);
  }.bind(this);

  this._bus.on(events.DISPATCH_FRAME_READY, dispatchFrameReadyHandler);
  this._writeDispatchFrame();
};

FrameService.prototype._writeDispatchFrame = function () {
  var frameName = constants.DISPATCH_FRAME_NAME + "_" + this._serviceId;
  var frameSrc = this._options.dispatchFrameUrl;

  this._dispatchFrame = iFramer({
    "aria-hidden": true,
    name: frameName,
    title: frameName,
    src: frameSrc,
    class: constants.DISPATCH_FRAME_CLASS,
    height: 0,
    width: 0,
    style: {
      position: "absolute",
      left: "-9999px",
    },
  });

  document.body.appendChild(this._dispatchFrame);
};

FrameService.prototype._setBusEvents = function () {
  this._bus.on(
    events.DISPATCH_FRAME_REPORT,
    function (res, reply) {
      if (this._onCompleteCallback) {
        this._onCompleteCallback.call(null, res.err, res.payload);
      }
      this._frame.close();

      this._onCompleteCallback = null;

      if (reply) {
        reply();
      }
    }.bind(this)
  );

  this._bus.on(
    BUS_CONFIGURATION_REQUEST_EVENT,
    function (reply) {
      reply(this.state);
    }.bind(this)
  );
};

FrameService.prototype.open = function (options, callback) {
  options = options || {};
  this._frame = this._getFrameForEnvironment(options);

  this._frame.initialize(callback);

  if (this._frame instanceof PopupBridge) {
    // Frameservice loads a spinner then redirects to the final destination url.
    // For Popupbridge it doesn't have the same rules around popups since it's deferred to the mobile side
    // therefore, skips the regular open path and instead uses `#redirect` to handle things
    return;
  }

  assign(this.state, options.state);

  this._onCompleteCallback = callback;
  this._frame.open();

  if (this.isFrameClosed()) {
    this._cleanupFrame();

    if (callback) {
      callback(new BraintreeError(errors.FRAME_SERVICE_FRAME_OPEN_FAILED));
    }

    return;
  }
  this._pollForPopupClose();
};

FrameService.prototype.redirect = function (url) {
  if (this._frame && !this.isFrameClosed()) {
    this._frame.redirect(url);
  }
};

FrameService.prototype.close = function () {
  if (!this.isFrameClosed()) {
    this._frame.close();
  }
};

FrameService.prototype.focus = function () {
  if (!this.isFrameClosed()) {
    this._frame.focus();
  }
};

FrameService.prototype.createHandler = function (options) {
  options = options || {};

  return {
    close: function () {
      if (options.beforeClose) {
        options.beforeClose();
      }

      this.close();
    }.bind(this),
    focus: function () {
      if (options.beforeFocus) {
        options.beforeFocus();
      }

      this.focus();
    }.bind(this),
  };
};

FrameService.prototype.createNoopHandler = function () {
  return {
    close: noop,
    focus: noop,
  };
};

FrameService.prototype.teardown = function () {
  this.close();
  this._dispatchFrame.parentNode.removeChild(this._dispatchFrame);
  this._dispatchFrame = null;
  this._cleanupFrame();
};

FrameService.prototype.isFrameClosed = function () {
  return this._frame == null || this._frame.isClosed();
};

FrameService.prototype._cleanupFrame = function () {
  this._frame = null;
  clearInterval(this._popupInterval);
  this._popupInterval = null;
};

FrameService.prototype._pollForPopupClose = function () {
  this._popupInterval = setInterval(
    function () {
      if (this.isFrameClosed()) {
        this._cleanupFrame();
        if (this._onCompleteCallback) {
          this._onCompleteCallback(
            new BraintreeError(errors.FRAME_SERVICE_FRAME_CLOSED)
          );
        }
      }
    }.bind(this),
    constants.POPUP_POLL_INTERVAL
  );

  return this._popupInterval;
};

FrameService.prototype._getFrameForEnvironment = function (options) {
  var usePopup = browserDetection.supportsPopups();
  var popupBridgeExists = Boolean(window.popupBridge);

  var initOptions = assign({}, this._options, options);

  if (popupBridgeExists) {
    return new PopupBridge(initOptions);
  } else if (usePopup) {
    return new Popup(initOptions);
  }

  return new Modal(initOptions);
};

module.exports = FrameService;

},{"../../braintree-error":53,"../../constants":54,"../shared/browser-detection":69,"../shared/constants":70,"../shared/errors":71,"../shared/events":72,"./../../assign":51,"./strategies/modal":64,"./strategies/popup":67,"./strategies/popup-bridge":65,"@braintree/iframer":21,"@braintree/uuid":25,"framebus":32}],63:[function(_dereq_,module,exports){
"use strict";

var FrameService = _dereq_("./frame-service");

/**
 * @ignore
 * @function create
 * Initializing FrameService should be done at the point when the component is created, so it is ready whenever a component needs to open a popup window.
 * Browsers have varying rules around what constitutes and async action worth blocking a popup for, but the likes of Safari
 * will block the popup if `frameService#create` is invoked during any asynchronous process (such as an API request to tokenize payment details).
 *
 * The process of setting up the dispatch frame and subsequent framebus communications via event listeners are considered async by Safari's standards.
 *
 * @param {object} options The options provided to frameservice
 * @param {string} options.name The name to use for identifying the various pieces associated with frameservice.
 * @param {string} options.dispatchFrameUrl The static asset to load for use as the dispatch frame. This allows for secure communication between the iframe and the popup, since they are on the same asset domain (usually checkout.paypal.com or assets.braintreegateway.com)
 * @param {string} options.openFrameUrl The url to load in the popup. Sometimes it is the case that you'll need info that comes _after_ the popup loads in which case we load the `landing-frame` that's a loading spinner then redirect to the proper/final destination. See the PayPal component for an example.
 * Otherwise if all the info needed is ready up-front, then you can forego a landing frame and go straight to the final destination.
 * @param {string} [options.height] The desired popup height.
 * @param {string} [options.width] The desired popup width.
 * @param {string} [options.top] The desired top value of the popup for positioning.
 * @param {string} [options.left] The desired left value of the popup for positioning.
 * @param {object} [options.state] Seems to be dead code, but allows for injecting data in to popup. NEXT_MAJOR_VERSION remove this param if no usage exists.
 * @param {function} callback The function to invoke once the frameservice is created and ready to use. FrameService instance is returned.
 */
module.exports = {
  create: function createFrameService(options, callback) {
    var frameService = new FrameService(options);

    frameService.initialize(function () {
      callback(frameService);
    });
  },
};

},{"./frame-service":62}],64:[function(_dereq_,module,exports){
"use strict";

var iFramer = _dereq_("@braintree/iframer");
var assign = _dereq_("../../../assign").assign;
var browserDetection = _dereq_("../../shared/browser-detection");

var ELEMENT_STYLES = {
  position: "fixed",
  top: 0,
  left: 0,
  bottom: 0,
  padding: 0,
  margin: 0,
  border: 0,
  outline: "none",
  zIndex: 20001,
  background: "#FFFFFF",
};

function noop() {}

/**
 *
 * We should not ever really use the Modal. Modals are _like_  popups, but the key difference is that the customer can't actually verify it's app domain and thus secure/valid. Old PP sdk (./src/paypal) uses this
 * to get info from webviews (e.g. facebook).
 */

function Modal(options) {
  this._closed = null;
  this._frame = null;
  this._options = options || {};
  this._container = this._options.container || document.body;
}

Modal.prototype.initialize = noop;

Modal.prototype.open = function () {
  var iframerConfig = {
    src: this._options.openFrameUrl,
    name: this._options.name,
    scrolling: "yes",
    height: "100%",
    width: "100%",
    style: assign({}, ELEMENT_STYLES),
    title: "Lightbox Frame",
  };

  if (browserDetection.isIos()) {
    // WKWebView has buggy behavior when scrolling a fixed position modal. The workaround is to lock scrolling in
    // the background. When modal is closed, we restore scrolling and return to the previous scroll position.
    if (browserDetection.isIosWKWebview()) {
      this._lockScrolling();
      // Allows WKWebView to scroll all the way down to bottom
      iframerConfig.style = {};
    }

    this._el = document.createElement("div");

    assign(this._el.style, ELEMENT_STYLES, {
      height: "100%",
      width: "100%",
      overflow: "auto",
      "-webkit-overflow-scrolling": "touch",
    });

    this._frame = iFramer(iframerConfig);
    this._el.appendChild(this._frame);
  } else {
    this._el = this._frame = iFramer(iframerConfig);
  }
  this._closed = false;

  this._container.appendChild(this._el);
};

Modal.prototype.focus = noop;

Modal.prototype.close = function () {
  this._container.removeChild(this._el);
  this._frame = null;
  this._closed = true;
  if (browserDetection.isIosWKWebview()) {
    this._unlockScrolling();
  }
};

Modal.prototype.isClosed = function () {
  return Boolean(this._closed);
};

Modal.prototype.redirect = function (redirectUrl) {
  this._frame.src = redirectUrl;
};

Modal.prototype._unlockScrolling = function () {
  document.body.style.overflow = this._savedBodyProperties.overflowStyle;
  document.body.style.position = this._savedBodyProperties.positionStyle;
  window.scrollTo(
    this._savedBodyProperties.left,
    this._savedBodyProperties.top
  );
  delete this._savedBodyProperties;
};

Modal.prototype._lockScrolling = function () {
  var doc = document.documentElement;

  // From https://stackoverflow.com/questions/9538868/prevent-body-from-scrolling-when-a-modal-is-opened#comment65626743_24727206
  this._savedBodyProperties = {
    left: (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0),
    top: (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0),
    overflowStyle: document.body.style.overflow,
    positionStyle: document.body.style.position,
  };
  document.body.style.overflow = "hidden";
  document.body.style.position = "fixed";
  window.scrollTo(0, 0);
};

module.exports = Modal;

},{"../../../assign":51,"../../shared/browser-detection":69,"@braintree/iframer":21}],65:[function(_dereq_,module,exports){
"use strict";

var BraintreeError = _dereq_("../../../braintree-error");
var errors = _dereq_("../../shared/errors");

function noop() {}

function PopupBridge(options) {
  this._closed = null;
  this._options = options;
}

PopupBridge.prototype.initialize = function (callback) {
  var self = this;

  window.popupBridge.onComplete = function (err, payload) {
    var popupDismissed = !payload && !err;

    self._closed = true;

    if (err || popupDismissed) {
      // User clicked "Done" button of browser view
      callback(new BraintreeError(errors.FRAME_SERVICE_FRAME_CLOSED));

      return;
    }
    // User completed popup flow (includes success and cancel cases)
    callback(null, payload);
  };
};

PopupBridge.prototype.open = function (options) {
  var url;

  options = options || {};
  url = options.openFrameUrl || this._options.openFrameUrl;

  this._closed = false;
  window.popupBridge.open(url);
};

PopupBridge.prototype.focus = noop;

PopupBridge.prototype.close = noop;

PopupBridge.prototype.isClosed = function () {
  return Boolean(this._closed);
};

PopupBridge.prototype.redirect = function (redirectUrl) {
  this.open({ openFrameUrl: redirectUrl });
};

module.exports = PopupBridge;

},{"../../../braintree-error":53,"../../shared/errors":71}],66:[function(_dereq_,module,exports){
"use strict";

var constants = _dereq_("../../../shared/constants");
var position = _dereq_("./position");

function calculatePosition(type, userDefinedPosition, size) {
  if (typeof userDefinedPosition !== "undefined") {
    return userDefinedPosition;
  }

  return position[type](size);
}

module.exports = function composePopupOptions(options) {
  var height = options.height || constants.DEFAULT_POPUP_HEIGHT;
  var width = options.width || constants.DEFAULT_POPUP_WIDTH;
  var top = calculatePosition("top", options.top, height);
  var left = calculatePosition("left", options.left, width);

  return [
    constants.POPUP_BASE_OPTIONS,
    "height=" + height,
    "width=" + width,
    "top=" + top,
    "left=" + left,
  ].join(",");
};

},{"../../../shared/constants":70,"./position":68}],67:[function(_dereq_,module,exports){
"use strict";

var composeOptions = _dereq_("./compose-options");

function noop() {}

function Popup(options) {
  this._frame = null;
  this._options = options || {};
}

Popup.prototype.initialize = noop;

Popup.prototype.open = function () {
  this._frame = window.open(
    this._options.openFrameUrl,
    this._options.name,
    composeOptions(this._options)
  );
};

Popup.prototype.focus = function () {
  this._frame.focus();
};

Popup.prototype.close = function () {
  if (this._frame.closed) {
    return;
  }
  this._frame.close();
};

Popup.prototype.isClosed = function () {
  return !this._frame || Boolean(this._frame.closed);
};

Popup.prototype.redirect = function (redirectUrl) {
  this._frame.location.href = redirectUrl;
};

module.exports = Popup;

},{"./compose-options":66}],68:[function(_dereq_,module,exports){
"use strict";

function top(height) {
  var windowHeight =
    window.outerHeight || document.documentElement.clientHeight;
  var windowTop = window.screenY == null ? window.screenTop : window.screenY;

  return center(windowHeight, height, windowTop);
}

function left(width) {
  var windowWidth = window.outerWidth || document.documentElement.clientWidth;
  var windowLeft = window.screenX == null ? window.screenLeft : window.screenX;

  return center(windowWidth, width, windowLeft);
}

function center(windowMetric, popupMetric, offset) {
  return (windowMetric - popupMetric) / 2 + offset;
}

module.exports = {
  top: top,
  left: left,
  center: center,
};

},{}],69:[function(_dereq_,module,exports){
"use strict";

module.exports = {
  isIos: _dereq_("@braintree/browser-detection/is-ios"),
  isIosWKWebview: _dereq_("@braintree/browser-detection/is-ios-wkwebview"),
  supportsPopups: _dereq_("@braintree/browser-detection/supports-popups"),
};

},{"@braintree/browser-detection/is-ios":18,"@braintree/browser-detection/is-ios-wkwebview":17,"@braintree/browser-detection/supports-popups":19}],70:[function(_dereq_,module,exports){
"use strict";

module.exports = {
  DISPATCH_FRAME_NAME: "dispatch",
  DISPATCH_FRAME_CLASS: "braintree-dispatch-frame",
  POPUP_BASE_OPTIONS: "resizable,scrollbars",
  DEFAULT_POPUP_WIDTH: 450,
  DEFAULT_POPUP_HEIGHT: 535,
  POPUP_POLL_INTERVAL: 100,
  POPUP_CLOSE_TIMEOUT: 100,
};

},{}],71:[function(_dereq_,module,exports){
"use strict";

/**
 * @name BraintreeError.Popup Related Error Codes
 * @ignore
 * @description Errors that occur when using a component that opens a popup window.
 * @property {INTERNAL} FRAME_SERVICE_FRAME_CLOSED - Occurs when the frame is closed before tokenization can occur.
 * @property {INTERNAL} FRAME_SERVICE_FRAME_OPEN_FAILED - Occurs when the popup could not be opened.
 */

var BraintreeError = _dereq_("../../braintree-error");

module.exports = {
  FRAME_SERVICE_FRAME_CLOSED: {
    type: BraintreeError.types.INTERNAL,
    code: "FRAME_SERVICE_FRAME_CLOSED",
    message: "Frame closed before tokenization could occur.",
  },
  FRAME_SERVICE_FRAME_OPEN_FAILED: {
    type: BraintreeError.types.INTERNAL,
    code: "FRAME_SERVICE_FRAME_OPEN_FAILED",
    message: "Frame failed to open.",
  },
};

},{"../../braintree-error":53}],72:[function(_dereq_,module,exports){
"use strict";

var enumerate = _dereq_("../../enumerate");

module.exports = enumerate(
  ["DISPATCH_FRAME_READY", "DISPATCH_FRAME_REPORT"],
  "frameService:"
);

},{"../../enumerate":60}],73:[function(_dereq_,module,exports){
"use strict";

module.exports = function inIframe(win) {
  win = win || window;

  try {
    return win.self !== win.top;
  } catch (e) {
    return true;
  }
};

},{}],74:[function(_dereq_,module,exports){
"use strict";

module.exports = function (value) {
  return JSON.parse(JSON.stringify(value));
};

},{}],75:[function(_dereq_,module,exports){
"use strict";

module.exports = function (obj) {
  return Object.keys(obj).filter(function (key) {
    return typeof obj[key] === "function";
  });
};

},{}],76:[function(_dereq_,module,exports){
"use strict";

function _notEmpty(obj) {
  var key;

  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      return true;
    }
  }

  return false;
}

/* eslint-disable no-mixed-operators */
function _isArray(value) {
  return (
    (value &&
      typeof value === "object" &&
      typeof value.length === "number" &&
      Object.prototype.toString.call(value) === "[object Array]") ||
    false
  );
}
/* eslint-enable no-mixed-operators */

function hasQueryParams(url) {
  url = url || window.location.href;

  return /\?/.test(url);
}

function parse(url) {
  var query, params;

  url = url || window.location.href;

  if (!hasQueryParams(url)) {
    return {};
  }

  query = url.split("?")[1] || "";
  query = query.replace(/#.*$/, "").split("&");

  params = query.reduce(function (toReturn, keyValue) {
    var parts = keyValue.split("=");
    var key = decodeURIComponent(parts[0]);
    var value = decodeURIComponent(parts[1]);

    toReturn[key] = value;

    return toReturn;
  }, {});

  return params;
}

function stringify(params, namespace) {
  var k, v, p;
  var query = [];

  for (p in params) {
    if (!params.hasOwnProperty(p)) {
      continue;
    }

    v = params[p];

    if (namespace) {
      if (_isArray(params)) {
        k = namespace + "[]";
      } else {
        k = namespace + "[" + p + "]";
      }
    } else {
      k = p;
    }
    if (typeof v === "object") {
      query.push(stringify(v, k));
    } else {
      query.push(encodeURIComponent(k) + "=" + encodeURIComponent(v));
    }
  }

  return query.join("&");
}

function queryify(url, params) {
  url = url || "";

  if (params != null && typeof params === "object" && _notEmpty(params)) {
    url += url.indexOf("?") === -1 ? "?" : "";
    url += url.indexOf("=") !== -1 ? "&" : "";
    url += stringify(params);
  }

  return url;
}

module.exports = {
  parse: parse,
  stringify: stringify,
  queryify: queryify,
  hasQueryParams: hasQueryParams,
};

},{}],77:[function(_dereq_,module,exports){
"use strict";

function useMin(isDebug) {
  return isDebug ? "" : ".min";
}

module.exports = useMin;

},{}],78:[function(_dereq_,module,exports){
"use strict";

// NEXT_MAJOR_VERSION old versions of IE don't have atob, in the
// next major version, we're dropping support for those versions
// so we can eliminate the need to have this atob polyfill
var atobNormalized = typeof atob === "function" ? atob : atobPolyfill;

function atobPolyfill(base64String) {
  var a, b, c, b1, b2, b3, b4, i;
  var base64Matcher = new RegExp(
    "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})([=]{1,2})?$"
  );
  var characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  var result = "";

  if (!base64Matcher.test(base64String)) {
    throw new Error("Non base64 encoded input passed to window.atob polyfill");
  }

  i = 0;
  do {
    b1 = characters.indexOf(base64String.charAt(i++));
    b2 = characters.indexOf(base64String.charAt(i++));
    b3 = characters.indexOf(base64String.charAt(i++));
    b4 = characters.indexOf(base64String.charAt(i++));

    a = ((b1 & 0x3f) << 2) | ((b2 >> 4) & 0x3);
    b = ((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf);
    c = ((b3 & 0x3) << 6) | (b4 & 0x3f);

    result +=
      String.fromCharCode(a) +
      (b ? String.fromCharCode(b) : "") +
      (c ? String.fromCharCode(c) : "");
  } while (i < base64String.length);

  return result;
}

module.exports = {
  atob: function (base64String) {
    return atobNormalized.call(window, base64String);
  },
  _atob: atobPolyfill,
};

},{}],79:[function(_dereq_,module,exports){
"use strict";

module.exports = {
  REQUIRED_OPTIONS_FOR_START_PAYMENT: [
    "givenName",
    "surname",
    "currencyCode",
    "paymentType",
    "amount",
    "fallback",
  ],
  REQUIRED_OPTIONS_FOR_PAY_UPON_INVOICE_PAYMENT_TYPE: [
    "givenName",
    "surname",
    "currencyCode",
    "onPaymentStart",
    "paymentType",
    "amount",
    "address",
    "billingAddress",
    "birthDate",
    "email",
    "locale",
    "customerServiceInstructions",
    "correlationId",
    "phone",
    "phoneCountryCode",
    "lineItems",
  ],
  REQUIRED_OPTIONS_FOR_ADDRESS: [
    "streetAddress",
    "locality",
    "postalCode",
    "countryCode",
  ],
  REQUIRED_OPTIONS_FOR_LINE_ITEMS: [
    "category",
    "name",
    "quantity",
    "unitAmount",
    "unitTaxAmount",
  ],
  REQUIRED_OPTIONS_FOR_BLIK_SEAMLESS_PAYMENT_TYPE: [
    "givenName",
    "surname",
    "currencyCode",
    "paymentType",
    "amount",
  ],
  REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_LEVEL_0: ["authCode"],
  REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_ONE_CLICK_FIRST: [
    "authCode",
    "consumerReference",
    "aliasLabel",
  ],
  REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_ONE_CLICK_SUBSEQUENT: [
    "consumerReference",
    "aliasKey",
  ],
};

},{}],80:[function(_dereq_,module,exports){
"use strict";

var frameService = _dereq_("../../lib/frame-service/external");
var BraintreeError = _dereq_("../../lib/braintree-error");
var useMin = _dereq_("../../lib/use-min");
var VERSION = "3.118.2";
var INTEGRATION_TIMEOUT_MS =
  _dereq_("../../lib/constants").INTEGRATION_TIMEOUT_MS;
var analytics = _dereq_("../../lib/analytics");
var methods = _dereq_("../../lib/methods");
var convertMethodsToError = _dereq_("../../lib/convert-methods-to-error");
var convertToBraintreeError = _dereq_("../../lib/convert-to-braintree-error");
var ExtendedPromise = _dereq_("@braintree/extended-promise");
var querystring = _dereq_("../../lib/querystring");
var wrapPromise = _dereq_("@braintree/wrap-promise");
var constants = _dereq_("./constants");
var errors = _dereq_("../shared/errors");
var assign = _dereq_("../../lib/assign").assign;
var inIframe = _dereq_("../../lib/in-iframe");

var DEFAULT_WINDOW_WIDTH = 1282;
var DEFAULT_WINDOW_HEIGHT = 720;

ExtendedPromise.suppressUnhandledPromiseMessage = true;

/**
 * @class
 * @param {object} options see {@link module:braintree-web/local-payment.create|local-payment.create}
 * @classdesc This class represents a LocalPayment component. Instances of this class can open a LocalPayment window for paying with alternate payments local to a specific country. Any additional UI, such as disabling the page while authentication is taking place, is up to the developer.
 *
 * @description <strong>Do not use this constructor directly. Use {@link module:braintree-web/local-payment.create|braintree-web.local-payment.create} instead.</strong>
 */
function LocalPayment(options) {
  this._client = options.client;
  this._assetsUrl =
    options.client.getConfiguration().gatewayConfiguration.assetsUrl +
    "/web/" +
    VERSION;
  this._isDebug = options.client.getConfiguration().isDebug;
  this._loadingFrameUrl =
    this._assetsUrl +
    "/html/local-payment-landing-frame" +
    useMin(this._isDebug) +
    ".html";
  this._authorizationInProgress = false;
  this._paymentType = "unknown";
  this._merchantAccountId = options.merchantAccountId;
  if (options.redirectUrl) {
    this._redirectUrl = options.redirectUrl;
    this._isRedirectFlow = true;
  }
}

LocalPayment.prototype._initialize = function () {
  var self = this;
  var client = this._client;
  var failureTimeout = setTimeout(function () {
    analytics.sendEvent(client, "local-payment.load.timed-out");
  }, INTEGRATION_TIMEOUT_MS);

  return new Promise(function (resolve) {
    frameService.create(
      {
        name: "localpaymentlandingpage",
        dispatchFrameUrl:
          self._assetsUrl +
          "/html/dispatch-frame" +
          useMin(self._isDebug) +
          ".html",
        openFrameUrl: self._loadingFrameUrl,
      },
      function (service) {
        self._frameService = service;
        clearTimeout(failureTimeout);
        analytics.sendEvent(client, "local-payment.load.succeeded");
        resolve(self);
      }
    );
  });
};

/**
 * Options used for most local payment types.
 * @typedef {object} LocalPayment~StartPaymentOptions
 * @property {object} fallback Configuration for what to do when app switching back from a Bank app on a mobile device. Only applicable to the popup flow.
 * @property {string} fallback.buttonText The text to display in a button to redirect back to the merchant page.
 * @property {string} fallback.url The url to redirect to when the redirect button is pressed. Query params will be added to the url to process the data returned from the bank.
 * @property {string} fallback.cancelButtonText The text to display in a button to redirect back to the merchant page when the customer cancels. If no `cancelButtonText` is provided, `buttonText` will be used.
 * @property {string} fallback.cancelUrl The url to redirect to when the redirect button is pressed when the customer cancels. Query params will be added to the url to check the state of the payment. If no `cancelUrl` is provided, `url` will be used.
 * @property {object} [windowOptions] The options for configuring the window that is opened when starting the payment. Only applicable to the popup flow.
 * @property {number} [windowOptions.width=1282] The width in pixels of the window opened when starting the payment. The default width size is this large to allow various banking partner landing pages to display the QR Code to be scanned by the bank's mobile app. Many will not display the QR code when the window size is smaller than a standard desktop screen.
 * @property {number} [windowOptions.height=720] The height in pixels of the window opened when starting the payment.
 * @property {string} amount The amount to authorize for the transaction.
 * @property {string} currencyCode The currency to process the payment (three-character ISO-4217).
 * @property {string} [displayName] The merchant name displayed inside of the window that is opened when starting the payment.
 * @property {string} paymentType The type of local payment. See https://developer.paypal.com/braintree/docs/guides/local-payment-methods/client-side-custom
 * @property {string} paymentTypeCountryCode The country code of the local payment. This value must be one of the supported country codes for a given local payment type listed {@link https://developer.paypal.com/braintree/docs/guides/local-payment-methods/client-side-custom/javascript/v3#render-local-payment-method-buttons|here}. For local payments supported in multiple countries, this value may determine which banks are presented to the customer.
 * @property {string} email Payer email of the customer.
 * @property {string} givenName First name of the customer.
 * @property {string} surname Last name of the customer.
 * @property {string} phone Phone number of the customer.
 * @property {boolean} recurrent Enable recurrent payment.
 * @property {string} customerId The customer's id in merchant's system (required for recurrent payments).
 * @property {boolean} shippingAddressRequired Indicates whether or not the payment needs to be shipped. For digital goods, this should be false. Defaults to false.
 * @property {object} address The shipping address.
 * @property {string} address.streetAddress Line 1 of the Address (eg. number, street, etc). An error will occur if this address is not valid.
 * @property {string} address.extendedAddress Line 2 of the Address (eg. suite, apt #, etc.). An error will occur if this address is not valid.
 * @property {string} address.locality Customer's city.
 * @property {string} address.region Customer's region or state.
 * @property {string} address.postalCode Customer's postal code.
 * @property {string} address.countryCode Customer's country code (two-character ISO 3166-1 code).
 * @property {function} onPaymentStart A function that will be called with two parameters: an object containing the  `paymentId` and a `continueCallback` that must be called to launch the flow. You can use method to do any preprocessing on your server before the flow begins..
 */

/**
 * Options used for the Pay Upon Invoice local payment type.
 * @typedef {object} LocalPayment~StartPaymentPayUponInvoiceOptions
 * @property {string} amount The amount to authorize for the transaction.
 * @property {string} currencyCode The currency to process the payment (three-character ISO-4217).
 * @property {string} [displayName] The merchant name displayed inside of the window that is opened when starting the payment.
 * @property {string} paymentType The type of local payment. Must be `pay_upon_invoice`.
 * @property {string} [paymentTypeCountryCode] The country code of the local payment. This value must be one of the supported country codes for a given local payment type listed {@link https://developer.paypal.com/braintree/docs/guides/local-payment-methods/client-side-custom/javascript/v3#render-local-payment-method-buttons|here}. For local payments supported in multiple countries, this value may determine which banks are presented to the customer.
 * @property {string} email Payer email of the customer.
 * @property {string} givenName First name of the customer.
 * @property {string} surname Last name of the customer.
 * @property {string} phone Phone number of the customer.
 * @property {string} phoneCountryCode The country calling code.
 * @property {string} birthDate The birth date of the customer in `YYYY-MM-DD` format.
 * @property {object} address The shipping address.
 * @property {string} address.streetAddress Line 1 of the Address (eg. number, street, etc). An error will occur if this address is not valid.
 * @property {string} [address.extendedAddress] Line 2 of the Address (eg. suite, apt #, etc.). An error will occur if this address is not valid.
 * @property {string} address.locality Customer's city.
 * @property {string} [address.region] Customer's region or state.
 * @property {string} address.postalCode Customer's postal code.
 * @property {string} address.countryCode Customer's country code (two-character ISO 3166-1 code).
 * @property {string} [shippingAmount] The shipping fee for all items. This value can not be a negative number.
 * @property {string} [discountAmount] The discount for all items. This value can not be a negative number.
 * @property {object} billingAddress The billing address.
 * @property {string} billingAddress.streetAddress Line 1 of the Address (eg. number, street, etc). An error will occur if this address is not valid.
 * @property {string} [billingAddress.extendedAddress] Line 2 of the Address (eg. suite, apt #, etc.). An error will occur if this address is not valid.
 * @property {string} billingAddress.locality Customer's city.
 * @property {string} [billingAddress.region] Customer's region or state.
 * @property {string} billingAddress.postalCode Customer's postal code.
 * @property {string} billingAddress.countryCode Customer's country code (two-character ISO 3166-1 code).
 * @property {object[]} lineItems List of line items.
 * @property {string} lineItems.category The item category type: `'DIGITAL_GOODS'`, `'PHYSICAL_GOODS'`, or `'DONATION'`.
 * @property {string} lineItems.name Item name. Maximum 127 characters.
 * @property {string} lineItems.quantity Number of units of the item purchased. This value must be a whole number and can't be negative or zero.
 * @property {string} lineItems.unitAmount Per-unit price of the item. Can include up to 2 decimal places. This value can't be negative or zero.
 * @property {string} lineItems.unitTaxAmount Per-unit tax price of the item. Can include up to 2 decimal places. This value can't be negative.
 * @property {string} locale The BCP 47-formatted locale. PayPal supports a five-character code. For example, `en-DE`, `da-DK`, `he-IL`, `id-ID`, `ja-JP`, `no-NO`, `pt-BR`, `ru-RU`, `sv-SE`, `th-TH`, `zh-CN`, `zh-HK`, or `zh-TW`.
 * @property {string} customerServiceInstructions Instructions for how to contact the merchant's customer service. Maximum 4,000 characters.
 * @property {string} correlationId Used to correlate user sessions with server transactions.
 * @property {function} onPaymentStart A function that will be called with an object containing the `paymentId`. The `continueCallback` is not provided as it is not needed for this use case.
 */

/**
 * Options used for the seamless/oneclick BLIK local payment type.
 * @typedef {object} LocalPayment~StartPaymentOptions
 * @property {string} amount The amount to authorize for the transaction.
 * @property {string} currencyCode The currency to process the payment (three-character ISO-4217).
 * @property {string} [displayName] The merchant name displayed inside of the window that is opened when starting the payment.
 * @property {string} paymentType The type of local payment. Must be `blik`.
 * @property {string} paymentTypeCountryCode The country code of the local payment. This value must be one of the supported country codes for a given local payment type listed {@link https://developer.paypal.com/braintree/docs/guides/local-payment-methods/client-side-custom/javascript/v3#render-local-payment-method-buttons|here}. For local payments supported in multiple countries, this value may determine which banks are presented to the customer.
 * @property {string} email Payer email of the customer.
 * @property {string} givenName First name of the customer.
 * @property {string} surname Last name of the customer.
 * @property {string} phone Phone number of the customer.
 * @property {boolean} shippingAddressRequired Indicates whether or not the payment needs to be shipped. For digital goods, this should be false. Defaults to false.
 * @property {object} address The shipping address.
 * @property {string} address.streetAddress Line 1 of the Address (eg. number, street, etc). An error will occur if this address is not valid.
 * @property {string} address.extendedAddress Line 2 of the Address (eg. suite, apt #, etc.). An error will occur if this address is not valid.
 * @property {string} address.locality Customer's city.
 * @property {string} address.region Customer's region or state.
 * @property {string} address.postalCode Customer's postal code.
 * @property {string} address.countryCode Customer's country code (two-character ISO 3166-1 code).
 * @property {object} blikOptions Blik seamless/oneclick specific options. Should contain only one object: `level_0` or `oneClick`.
 * @property {object} blikOptions.level_0 Blik seamless specific options.
 * @property {string} blikOptions.level_0.authCode 6-digit code used to authenticate a consumer within BLIK.
 * @property {object} blikOptions.oneClick Blik oneclick specific options.
 * @property {string} blikOptions.oneClick.authCode 6-digit code used to authenticate a consumer within BLIK.
 * @property {string} blikOptions.oneClick.consumerReference The merchant generated, unique reference serving as a primary identifier for accounts connected between Blik and a merchant.
 * @property {string} blikOptions.oneClick.aliasLabel A bank defined identifier used as a display name to allow the payer to differentiate between multiple registered bank accounts.
 * @property {string} blikOptions.oneClick.aliasKey A Blik-defined identifier for a specific Blik-enabled bank account that is associated with a given merchant. Used only in conjunction with a Consumer Reference.
 * @property {function} onPaymentStart A function that will be called with an object containing the `paymentId`. The `continueCallback` is not provided as it is not needed for this use case.
 */

/**
 * Launches the local payment flow and returns a nonce payload. Only one local payment flow should be active at a time. One way to achieve this is to disable your local payment button while the flow is open.
 * @public
 * @function
 * @param {LocalPayment~StartPaymentOptions|LocalPayment~StartPaymentPayUponInvoiceOptions} options Options for initiating the local payment payment flow.
 * @param {callback} callback The second argument, <code>data</code>, is a {@link LocalPayment~startPaymentPayload|startPaymentPayload}. If no callback is provided, the method will return a Promise that resolves with a {@link LocalPayment~startPaymentPayload|startPaymentPayload}.
 * @returns {(Promise|void)} Returns a promise if no callback is provided.
 * @example
 * localPaymentInstance.startPayment({
 *   paymentType: 'ideal',
 *   paymentTypeCountryCode: 'NL',
 *   fallback: {
 *     buttonText: 'Return to Merchant',
 *     url: 'https://example.com/my-checkout-page'
 *   },
 *   amount: '10.00',
 *   currencyCode: 'EUR',
 *   givenName: 'Joe',
 *   surname: 'Doe',
 *   address: {
 *     countryCode: 'NL'
 *   },
 *   onPaymentStart: function (data, continueCallback) {
 *     // Do any preprocessing before starting the flow
 *     // data.paymentId is the ID of the localPayment
 *     continueCallback();
 *   }
 * }).then(function (payload) {
 *   // Submit payload.nonce to your server
 * }).catch(function (startPaymentError) {
 *   // Handle flow errors or premature flow closure
 *   console.error('Error!', startPaymentError);
 * });
 * @example <caption>Pay Upon Invoice</caption>
 * localPaymentInstance.startPayment({
 *   paymentType: 'pay_upon_invoice',
 *   amount: '100.00',
 *   currencyCode: 'EUR',
 *   givenName: 'Max',
 *   surname: 'Mustermann',
 *   address: { // This is used as the shipping address.
 *     streetAddress: 'Taunusanlage 12',
 *     locality: 'Frankfurt',
 *     postalCode: '60325',
 *     countryCode: 'DE',
 *   },
 *   billingAddress: {
 *     streetAddress: 'Schönhauser Allee 84',
 *     locality: 'Berlin',
 *     postalCode: '10439',
 *     countryCode: 'DE'
 *   },
 *   birthDate: '1990-01-01',
 *   email: 'buyer@example.com',
 *   locale: 'en-DE',
 *   customerServiceInstructions: 'Customer service phone is +49 6912345678.',
 *   lineItems: [{
 *     category: 'PHYSICAL_GOODS',
 *     name: 'Basketball Shoes',
 *     quantity: '1',
 *     unitAmount: '81.00',
 *     unitTaxAmount: '19.00',
 *   }],
 *   phone: '6912345678',
 *   phoneCountryCode: '49',
 *   correlationId: correlationId,
 *   onPaymentStart: function (data) {
 *     // NOTE: It is critical here to store data.paymentId on your server
 *     //       so it can be mapped to a webhook sent by Braintree once the
 *     //       buyer completes their payment.
 *     console.log('Payment ID:', data.paymentId);
 *   },
 * }).catch(function (err) {
 *   // Handle any error calling startPayment.
 *   console.error(err);
 * });
 * @example <caption>BLIK seamless</caption>
 * localPaymentInstance.startPayment({
 *   paymentType: 'blik',
 *   paymentTypeCountryCode: 'PL',
 *   amount: '10.00',
 *   currencyCode: 'PLN',
 *   givenName: 'Joe',
 *   surname: 'Doe',
 *   phone: '1234566789',
 *   address: {
 *     streetAddress: 'Mokotowska 1234',
 *     locality: 'Warsaw',
 *     postalCode: '02-697',
 *     countryCode: 'PL',
 *   },
 *   blikOptions: {
 *     level_0: {
 *       authCode: "123456",
 *     },
 *   },
 *   onPaymentStart: function (data) {
 *     // NOTE: It is critical here to store data.paymentId on your server
 *     //       so it can be mapped to a webhook sent by Braintree once the
 *     //       buyer completes their payment.
 *     console.log('Payment ID:', data.paymentId);
 *   },
 * }).catch(function (err) {
 *   // Handle any error calling startPayment.
 *   console.error(err);
 * });
 * @example <caption>BLIK oneclick first payment</caption>
 * localPaymentInstance.startPayment({
 *   paymentType: 'blik',
 *   paymentTypeCountryCode: 'PL',
 *   amount: '10.00',
 *   currencyCode: 'PLN',
 *   givenName: 'Joe',
 *   surname: 'Doe',
 *   phone: '1234566789',
 *   address: {
 *     streetAddress: 'Mokotowska 1234',
 *     locality: 'Warsaw',
 *     postalCode: '02-697',
 *     countryCode: 'PL',
 *   },
 *   blikOptions: {
 *     oneClick: {
 *       authCode: "123456",
 *       consumerReference: "ABCde123",
 *       aliasLabel: "my uniq alias",
 *     },
 *   },
 *   onPaymentStart: function (data) {
 *     // NOTE: It is critical here to store data.paymentId on your server
 *     //       so it can be mapped to a webhook sent by Braintree once the
 *     //       buyer completes their payment.
 *     console.log('Payment ID:', data.paymentId);
 *   },
 * }).catch(function (err) {
 *   // Handle any error calling startPayment.
 *   console.error(err);
 * });
 * @example <caption>BLIK oneclick subsequent payment</caption>
 * localPaymentInstance.startPayment({
 *   paymentType: 'blik',
 *   paymentTypeCountryCode: 'PL',
 *   amount: '10.00',
 *   currencyCode: 'PLN',
 *   givenName: 'Joe',
 *   surname: 'Doe',
 *   phone: '1234566789',
 *   address: {
 *     streetAddress: 'Mokotowska 1234',
 *     locality: 'Warsaw',
 *     postalCode: '02-697',
 *     countryCode: 'PL',
 *   },
 *   blikOptions: {
 *     oneClick: {
 *       consumerReference: "ABCde123",
 *       aliasKey: "123456789",
 *     },
 *   },
 *   onPaymentStart: function (data) {
 *     // NOTE: It is critical here to store data.paymentId on your server
 *     //       so it can be mapped to a webhook sent by Braintree once the
 *     //       buyer completes their payment.
 *     console.log('Payment ID:', data.paymentId);
 *   },
 * }).catch(function (err) {
 *   // Handle any error calling startPayment.
 *   console.error(err);
 * });
 * @example <caption>MB WAY</caption>
 * localPaymentInstance.startPayment({
 *   paymentType: 'mbway',
 *   amount: '10.00',
 *   currencyCode: 'EUR',
 *   givenName: 'Joe',
 *   surname: 'Doe',
 *   phone: '1234566789',
 *   phoneCountryCode: '351'
 *   address: {
 *     streetAddress: 'Rua Escura 12',
 *     locality: 'Porto',
 *     postalCode: '4465-283',
 *     countryCode: 'PT',
 *   },
 *   onPaymentStart: function (data) {
 *     // NOTE: It is critical here to store data.paymentId on your server
 *     //       so it can be mapped to a webhook sent by Braintree once the
 *     //       buyer completes their payment.
 *     console.log('Payment ID:', data.paymentId);
 *   },
 * }).catch(function (err) {
 *   // Handle any error calling startPayment.
 *   console.error(err);
 * });
 * @example <caption>BANCOMAT PAY</caption>
 * localPaymentInstance.startPayment({
 *   paymentType: 'bancomatpay',
 *   amount: '10.00',
 *   currencyCode: 'EUR',
 *   givenName: 'Joe',
 *   surname: 'Doe',
 *   phone: '1234566789',
 *   phoneCountryCode: '49'
 *   address: {
 *     streetAddress: 'Via del Corso 12',
 *     locality: 'Roma',
 *     postalCode: '00100',
 *     countryCode: 'IT',
 *   },
 *   onPaymentStart: function (data) {
 *     // NOTE: It is critical here to store data.paymentId on your server
 *     //       so it can be mapped to a webhook sent by Braintree once the
 *     //       buyer completes their payment.
 *     console.log('Payment ID:', data.paymentId);
 *   },
 * }).catch(function (err) {
 *   // Handle any error calling startPayment.
 *   console.error(err);
 * });
 */
LocalPayment.prototype.startPayment = function (options) {
  var missingOption,
    missingError,
    address,
    fallback,
    params,
    promise,
    billingAddress,
    windowOptions,
    onPaymentStartPromise,
    serviceId,
    cancelUrl,
    returnUrl;
  var self = this; // eslint-disable-line no-invalid-this

  if (self._isRedirectFlow) {
    options.redirectUrl = self._redirectUrl;
  } else {
    serviceId = self._frameService._serviceId;
  }
  // In order to provide the merchant with appropriate error messaging,
  // more robust validation is being done on the client-side, since some
  // option names are mapped to legacy names for the sake of the API.
  // For example, if `billingAddress.streetAddress` was missing, then
  // the API error response would say that `billing_address.line1` was
  // missing. This client-side validation will correctly tell the
  // merchant that `billingAddress.streetAddress` was missing.
  missingOption = hasMissingOption(options);
  if (missingOption) {
    missingError = new BraintreeError(
      errors.LOCAL_PAYMENT_START_PAYMENT_MISSING_REQUIRED_OPTION
    );
    if (typeof missingOption === "string") {
      missingError.details = "Missing required '" + missingOption + "' option.";
    }

    return Promise.reject(missingError);
  }
  windowOptions = options.windowOptions || {};
  address = options.address || {};
  fallback = options.fallback || {};
  billingAddress = options.billingAddress || {};
  params = {
    amount: options.amount,
    billingAddress: {
      line1: billingAddress.streetAddress,
      line2: billingAddress.extendedAddress,
      city: billingAddress.locality,
      state: billingAddress.region,
      postalCode: billingAddress.postalCode,
      countryCode: billingAddress.countryCode,
    },
    birthDate: options.birthDate,
    blikOptions: options.blikOptions,
    city: address.locality,
    correlationId: options.correlationId,
    countryCode: address.countryCode,
    currencyIsoCode: options.currencyCode,
    discountAmount: options.discountAmount,
    experienceProfile: {
      brandName: options.displayName,
      customerServiceInstructions: options.customerServiceInstructions,
      locale: options.locale,
      noShipping: !options.shippingAddressRequired,
    },
    firstName: options.givenName,
    fundingSource: options.paymentType,
    intent: "sale",
    lastName: options.surname,
    line1: address.streetAddress,
    line2: address.extendedAddress,
    lineItems: options.lineItems,
    merchantAccountId: self._merchantAccountId,
    merchantOrPartnerCustomerId: options.customerId,
    payerEmail: options.email,
    paymentTypeCountryCode: options.paymentTypeCountryCode,
    phone: options.phone,
    phoneCountryCode: options.phoneCountryCode,
    postalCode: address.postalCode,
    recurrent: options.recurrent,
    shippingAmount: options.shippingAmount,
    state: address.region,
  };

  if (self._isRedirectFlow) {
    cancelUrl = querystring.queryify(self._redirectUrl, {
      wasCanceled: true,
    });
    returnUrl = self._redirectUrl;
  } else {
    cancelUrl = querystring.queryify(
      self._assetsUrl +
        "/html/local-payment-redirect-frame" +
        useMin(self._isDebug) +
        ".html",
      {
        channel: serviceId,
        r: fallback.cancelUrl || fallback.url,
        t: fallback.cancelButtonText || fallback.buttonText,
        c: 1, // indicating we went through the cancel flow
      }
    );
    returnUrl = querystring.queryify(
      self._assetsUrl +
        "/html/local-payment-redirect-frame" +
        useMin(self._isDebug) +
        ".html",
      {
        channel: serviceId,
        r: fallback.url,
        t: fallback.buttonText,
      }
    );
  }
  assign(params, { cancelUrl: cancelUrl, returnUrl: returnUrl });

  self._paymentType = options.paymentType.toLowerCase();

  if (self._authorizationInProgress && !self._isRedirectFlow) {
    analytics.sendEvent(
      self._client,
      self._paymentType + ".local-payment.start-payment.error.already-opened"
    );

    return Promise.reject(
      new BraintreeError(errors.LOCAL_PAYMENT_ALREADY_IN_PROGRESS)
    );
  }

  self._authorizationInProgress = true;

  promise = new ExtendedPromise();

  // For deferred payment types, the popup window should not be opened,
  // since the actual payment will be done outside of this session.
  if (!isDeferredPaymentTypeOptions(options) && !self._isRedirectFlow) {
    self._startPaymentCallback = self._createStartPaymentCallback(
      function (val) {
        promise.resolve(val);
      },
      function (err) {
        promise.reject(err);
      }
    );

    self._frameService.open(
      {
        width: windowOptions.width || DEFAULT_WINDOW_WIDTH,
        height: windowOptions.height || DEFAULT_WINDOW_HEIGHT,
      },
      self._startPaymentCallback
    );
  }

  self._client
    .request({
      method: "post",
      endpoint: "local_payments/create",
      data: params,
    })
    .then(function (response) {
      var redirectUrl = response.paymentResource.redirectUrl;

      if (self._isRedirectFlow) {
        analytics.sendEvent(
          self._client,
          self._paymentType + ".local-payment.start-payment.redirected"
        );
      } else {
        analytics.sendEvent(
          self._client,
          self._paymentType + ".local-payment.start-payment.opened"
        );
      }
      self._startPaymentOptions = options;

      if (isDeferredPaymentTypeOptions(options)) {
        self._authorizationInProgress = false;

        if (typeof redirectUrl === "string" && redirectUrl.length) {
          promise.reject(
            new BraintreeError(
              errors.LOCAL_PAYMENT_START_PAYMENT_DEFERRED_PAYMENT_FAILED
            )
          );
        } else {
          onPaymentStartPromise = options.onPaymentStart({
            paymentId: response.paymentResource.paymentToken,
          });

          if (onPaymentStartPromise instanceof Promise) {
            onPaymentStartPromise.then(function () {
              promise.resolve();
            });
          } else {
            promise.resolve();
          }
        }
      } else {
        if (typeof options.onPaymentStart === "function") {
          options.onPaymentStart(
            { paymentId: response.paymentResource.paymentToken },
            function () {
              if (!self._isRedirectFlow) {
                self._frameService.redirect(
                  response.paymentResource.redirectUrl
                );
              }
            }
          );
        }
        if (self._isRedirectFlow) {
          if (inIframe()) {
            window.top.location.href = response.paymentResource.redirectUrl;
          } else {
            window.location.href = response.paymentResource.redirectUrl;
          }
        }
      }
    })
    .catch(function (err) {
      var status = err.details && err.details.httpStatus;

      if (!self._isRedirectFlow) {
        self._frameService.close();
      }
      self._authorizationInProgress = false;

      if (status === 422) {
        promise.reject(
          new BraintreeError({
            type: errors.LOCAL_PAYMENT_INVALID_PAYMENT_OPTION.type,
            code: errors.LOCAL_PAYMENT_INVALID_PAYMENT_OPTION.code,
            message: errors.LOCAL_PAYMENT_INVALID_PAYMENT_OPTION.message,
            details: {
              originalError: err,
            },
          })
        );

        return;
      }

      promise.reject(
        convertToBraintreeError(err, {
          type: errors.LOCAL_PAYMENT_START_PAYMENT_FAILED.type,
          code: errors.LOCAL_PAYMENT_START_PAYMENT_FAILED.code,
          message: errors.LOCAL_PAYMENT_START_PAYMENT_FAILED.message,
        })
      );
    });

  return promise;
};

/**
 * Manually tokenizes params for a local payment received from PayPal.When app switching back from a mobile application (such as a bank application for an iDEAL payment), the window may lose context with the parent page. In that case, a fallback url is used, and this method can be used to finish the flow.
 * @public
 * @function
 * @param {object} [params] All options for tokenizing local payment parameters. If no params are passed in, the params will be pulled off of the query string of the page.
 * @param {string} params.btLpToken The token representing the local payment. Aliased to `token` if `btLpToken` is not present.
 * @param {string} params.btLpPaymentId The payment id for the local payment. Aliased to `paymentId` if `btLpPaymentId` is not present.
 * @param {string} params.btLpPayerId The payer id for the local payment. Aliased to `PayerID` if `btLpPayerId` is not present.
 * @param {callback} [callback] The second argument, <code>data</code>, is a {@link LocalPayment~startPaymentPayload|startPaymentPayload}. If no callback is provided, the method will return a Promise that resolves with a {@link LocalPayment~startPaymentPayload|startPaymentPayload}.
 * @example
 * localPaymentInstance.tokenize().then(function (payload) {
 *   // send payload.nonce to your server
 * }).catch(function (err) {
 *   // handle tokenization error
 * });
 * @returns {(Promise|void)} Returns a promise if no callback is provided.
 */
LocalPayment.prototype.tokenize = function (params) {
  var self = this;
  var client = this._client;

  params = params || querystring.parse();

  // iOS Safari parses query params by adding the params inside an object called: queryItems
  if (params.queryItems) {
    params = params.queryItems;
  }

  if (params.c || params.wasCanceled) {
    return Promise.reject(
      new BraintreeError({
        type: errors.LOCAL_PAYMENT_CANCELED.type,
        code: errors.LOCAL_PAYMENT_CANCELED.code,
        message: errors.LOCAL_PAYMENT_CANCELED.message,
        details: {
          originalError: {
            errorcode: params.errorcode,
            token: params.btLpToken,
          },
        },
      })
    );
  } else if (params.errorcode) {
    return Promise.reject(
      new BraintreeError({
        type: errors.LOCAL_PAYMENT_START_PAYMENT_FAILED.type,
        code: errors.LOCAL_PAYMENT_START_PAYMENT_FAILED.code,
        message: errors.LOCAL_PAYMENT_START_PAYMENT_FAILED.message,
        details: {
          originalError: {
            errorcode: params.errorcode,
            token: params.btLpToken,
          },
        },
      })
    );
  }

  return client
    .request({
      endpoint: "payment_methods/paypal_accounts",
      method: "post",
      data: this._formatTokenizeData(params),
    })
    .then(function (response) {
      var payload = self._formatTokenizePayload(response);

      if (window.popupBridge) {
        analytics.sendEvent(
          client,
          self._paymentType + ".local-payment.tokenization.success-popupbridge"
        );
      } else {
        analytics.sendEvent(
          client,
          self._paymentType + ".local-payment.tokenization.success"
        );
      }

      return payload;
    })
    .catch(function (err) {
      analytics.sendEvent(
        client,
        self._paymentType + ".local-payment.tokenization.failed"
      );

      return Promise.reject(
        convertToBraintreeError(err, {
          type: errors.LOCAL_PAYMENT_TOKENIZATION_FAILED.type,
          code: errors.LOCAL_PAYMENT_TOKENIZATION_FAILED.code,
          message: errors.LOCAL_PAYMENT_TOKENIZATION_FAILED.message,
        })
      );
    });
};

/**
 * Closes the LocalPayment window if it is open.
 * @public
 * @example
 * localPaymentInstance.closeWindow();
 * @returns {void}
 */
LocalPayment.prototype.closeWindow = function () {
  if (this._authoriztionInProgress) {
    analytics.sendEvent(
      this._client,
      this._paymentType + ".local-payment.start-payment.closed.by-merchant"
    );
  }
  this._frameService.close();
};

/**
 * Focuses the LocalPayment window if it is open.
 * @public
 * @example
 * localPaymentInstance.focusWindow();
 * @returns {void}
 */
LocalPayment.prototype.focusWindow = function () {
  this._frameService.focus();
};

LocalPayment.prototype._createStartPaymentCallback = function (
  resolve,
  reject
) {
  var self = this;
  var client = this._client;

  return function (err, params) {
    self._authorizationInProgress = false;
    if (err) {
      if (err.code === "FRAME_SERVICE_FRAME_CLOSED") {
        if (params && params.errorcode === "processing_error") {
          // something failed within the payment window (rather than when
          // tokenizing with Braintree)
          analytics.sendEvent(
            client,
            self._paymentType + ".local-payment.failed-in-window"
          );
          reject(new BraintreeError(errors.LOCAL_PAYMENT_START_PAYMENT_FAILED));

          return;
        }

        // its possible to have a query param with errorcode=payment_error, which
        // indicates that the customer cancelled the flow from within the UI,
        // but as there's no meaningful difference to the merchant whether the
        // customer closes via the UI or by manually closing the window, we
        // don't differentiate these
        analytics.sendEvent(
          client,
          self._paymentType + ".local-payment.tokenization.closed.by-user"
        );
        reject(new BraintreeError(errors.LOCAL_PAYMENT_WINDOW_CLOSED));
      } else if (
        err.code &&
        err.code.indexOf("FRAME_SERVICE_FRAME_OPEN_FAILED") > -1
      ) {
        reject(
          new BraintreeError({
            code: errors.LOCAL_PAYMENT_WINDOW_OPEN_FAILED.code,
            type: errors.LOCAL_PAYMENT_WINDOW_OPEN_FAILED.type,
            message: errors.LOCAL_PAYMENT_WINDOW_OPEN_FAILED.message,
            details: {
              originalError: err,
            },
          })
        );
      }
    } else if (params) {
      if (!window.popupBridge) {
        self._frameService.redirect(self._loadingFrameUrl);
      }

      self
        .tokenize(params)
        .then(resolve)
        .catch(reject)
        .then(function () {
          self._frameService.close();
        });
    }
  };
};

LocalPayment.prototype._formatTokenizePayload = function (response) {
  var payload;
  var account = {};

  if (response.paypalAccounts) {
    account = response.paypalAccounts[0];
  }

  payload = {
    nonce: account.nonce,
    details: {},
    type: account.type,
  };

  if (account.details) {
    if (account.details.payerInfo) {
      payload.details = account.details.payerInfo;
    }
    if (account.details.correlationId) {
      payload.correlationId = account.details.correlationId;
    }
  }

  return payload;
};

/**
 * Checks if required tokenization parameters are available in querystring for manual tokenization requests.
 * @public
 * @function
 * @example
 * // if query string contains
 * // ?btLpToken=token&btLpPaymentId=payment-id&btLpPayerId=payer-id
 * localPaymentInstance.hasTokenizationParams(); // true
 *
 * // if query string has token: (full page redirect flow)
 * // ?token=abcdefg123456789
 * localPaymentInstance.hasTokenizationParams(); // true
 *
 * // if query string is missing required params
 * localPaymentInstance.hasTokenizationParams(); // false
 *
 * if (localPaymentInstance.hasTokenizationParams()) {
 *   localPaymentInstance.tokenize();
 * }
 * @returns {Boolean} Returns a Boolean value for the state of the query string.
 */
LocalPayment.prototype.hasTokenizationParams = function () {
  var params = querystring.parse();

  if (params.errorcode || params.token) {
    return true;
  }

  return Boolean(
    params.btLpToken && params.btLpPaymentId && params.btLpPayerId
  );
};

LocalPayment.prototype._formatTokenizeData = function (params) {
  var clientConfiguration = this._client.getConfiguration();
  var gatewayConfiguration = clientConfiguration.gatewayConfiguration;
  var data = {
    merchantAccountId: this._merchantAccountId,
    paypalAccount: {
      correlationId: params.btLpToken || params.token,
      paymentToken: params.btLpPaymentId || params.paymentId,
      payerId: params.btLpPayerId || params.PayerID,
      unilateral: gatewayConfiguration.paypal.unvettedMerchant,
      intent: "sale",
    },
  };

  return data;
};

// Some payment types are deferred. Meaning, the actual payment will
// occur at a later time outside of this session. For example, with
// Pay Upon Invoice, the customer will later receive an email that will
// be used to make the actual payment through RatePay. This function
// will return `true` if the given options contain `paymentType` of
// a deferred payment type; and/or some payments, like blik, may have
// specific extra options to be treated as deferred. Otherwise, it
// will return `false`.
function isDeferredPaymentTypeOptions(options) {
  var blikOptions = options.blikOptions || {};
  var paymentType =
    typeof options.paymentType === "string"
      ? options.paymentType.toLowerCase()
      : options.paymentType;

  if (paymentType === "blik") {
    return (
      blikOptions.hasOwnProperty("level_0") ||
      blikOptions.hasOwnProperty("oneClick")
    );
  }

  return ["pay_upon_invoice", "mbway", "bancomatpay"].includes(paymentType);
}

function hasMissingAddressOption(options) {
  var i, option;

  for (i = 0; i < constants.REQUIRED_OPTIONS_FOR_ADDRESS.length; i++) {
    option = constants.REQUIRED_OPTIONS_FOR_ADDRESS[i];
    if (!options.hasOwnProperty(option)) {
      return option;
    }
  }

  return false;
}

function hasMissingLineItemsOption(items) {
  var i, j, item, option;

  for (j = 0; j < items.length; j++) {
    item = items[j];
    for (i = 0; i < constants.REQUIRED_OPTIONS_FOR_LINE_ITEMS.length; i++) {
      option = constants.REQUIRED_OPTIONS_FOR_LINE_ITEMS[i];
      if (!item.hasOwnProperty(option)) {
        return option;
      }
    }
  }

  return false;
}

function hasMissingBlikOptions(options) {
  var i, option, oneClick;
  var blikOptions = options.blikOptions || {};

  if (!options.redirectUrl) {
    constants.REQUIRED_OPTIONS_FOR_BLIK_SEAMLESS_PAYMENT_TYPE.push(
      "onPaymentStart"
    );
  }

  for (
    i = 0;
    i < constants.REQUIRED_OPTIONS_FOR_BLIK_SEAMLESS_PAYMENT_TYPE.length;
    i++
  ) {
    option = constants.REQUIRED_OPTIONS_FOR_BLIK_SEAMLESS_PAYMENT_TYPE[i];
    if (!options.hasOwnProperty(option)) {
      return option;
    }
  }

  if (blikOptions.hasOwnProperty("level_0")) {
    for (
      i = 0;
      i < constants.REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_LEVEL_0.length;
      i++
    ) {
      option = constants.REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_LEVEL_0[i];

      // eslint-disable-next-line camelcase
      if (!blikOptions.level_0.hasOwnProperty(option)) {
        return "blikOptions.level_0." + option;
      }
    }
  } else if (blikOptions.hasOwnProperty("oneClick")) {
    oneClick = blikOptions.oneClick || {};

    if (oneClick.hasOwnProperty("aliasKey")) {
      for (
        i = 0;
        i <
        constants.REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_ONE_CLICK_SUBSEQUENT.length;
        i++
      ) {
        option =
          constants.REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_ONE_CLICK_SUBSEQUENT[i];

        if (!oneClick.hasOwnProperty(option)) {
          return "blikOptions.oneClick." + option;
        }
      }
    } else {
      for (
        i = 0;
        i < constants.REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_ONE_CLICK_FIRST.length;
        i++
      ) {
        option = constants.REQUIRED_OPTIONS_FOR_BLIK_OPTIONS_ONE_CLICK_FIRST[i];

        if (!oneClick.hasOwnProperty(option)) {
          return "blikOptions.oneClick." + option;
        }
      }
    }
  }

  return false;
}

// This will return the name of the first missing required option that
// is found or `true` if `options` itself is not defined. Otherwise, it
// will return `false`.
function hasMissingOption(options) {
  var i, option, missingAddressOption, missingLineItemOption, paymentType;

  if (!options) {
    return true;
  }

  if (isDeferredPaymentTypeOptions(options)) {
    paymentType = options.paymentType || "";

    if (paymentType.toLowerCase() === "pay_upon_invoice") {
      for (
        i = 0;
        i < constants.REQUIRED_OPTIONS_FOR_PAY_UPON_INVOICE_PAYMENT_TYPE.length;
        i++
      ) {
        option =
          constants.REQUIRED_OPTIONS_FOR_PAY_UPON_INVOICE_PAYMENT_TYPE[i];
        if (!options.hasOwnProperty(option)) {
          return option;
        }
        if (option === "address" || option === "billingAddress") {
          missingAddressOption = hasMissingAddressOption(options[option]);
          if (missingAddressOption) {
            return option + "." + missingAddressOption;
          }
        } else if (option === "lineItems") {
          missingLineItemOption = hasMissingLineItemsOption(options[option]);
          if (missingLineItemOption) {
            return option + "." + missingLineItemOption;
          }
        }
      }
    } else if (paymentType.toLowerCase() === "blik") {
      return hasMissingBlikOptions(options);
    }
  } else {
    if (!options.redirectUrl) {
      constants.REQUIRED_OPTIONS_FOR_START_PAYMENT.push("onPaymentStart");
    }

    for (i = 0; i < constants.REQUIRED_OPTIONS_FOR_START_PAYMENT.length; i++) {
      option = constants.REQUIRED_OPTIONS_FOR_START_PAYMENT[i];

      if (!options.hasOwnProperty(option)) {
        return option;
      }
    }

    if (!options.fallback.url) {
      return "fallback.url";
    }
    if (!options.fallback.buttonText) {
      return "fallback.buttonText";
    }
    if (options.recurrent === true && !options.customerId) {
      return "customerId";
    }
  }

  return false;
}

/**
 * Cleanly remove anything set up by {@link module:braintree-web/local-payment.create|create}.
 * @public
 * @param {callback} [callback] Called on completion.
 * @example
 * localPaymentInstance.teardown();
 * @example <caption>With callback</caption>
 * localPaymentInstance.teardown(function () {
 *   // teardown is complete
 * });
 * @returns {(Promise|void)} Returns a promise if no callback is provided.
 */
LocalPayment.prototype.teardown = function () {
  var self = this; // eslint-disable-line no-invalid-this

  if (!self._isRedirectFlow) {
    self._frameService.teardown();
  }

  convertMethodsToError(self, methods(LocalPayment.prototype));

  analytics.sendEvent(self._client, "local-payment.teardown-completed");

  return Promise.resolve();
};

module.exports = wrapPromise.wrapPrototype(LocalPayment);

},{"../../lib/analytics":49,"../../lib/assign":51,"../../lib/braintree-error":53,"../../lib/constants":54,"../../lib/convert-methods-to-error":55,"../../lib/convert-to-braintree-error":56,"../../lib/frame-service/external":63,"../../lib/in-iframe":73,"../../lib/methods":75,"../../lib/querystring":76,"../../lib/use-min":77,"../shared/errors":82,"./constants":79,"@braintree/extended-promise":20,"@braintree/wrap-promise":29}],81:[function(_dereq_,module,exports){
"use strict";
/**
 * @module braintree-web/local-payment
 * @description A component to integrate with local payment methods. *This component is currently in beta and is subject to change.*
 */

var analytics = _dereq_("../lib/analytics");
var basicComponentVerification = _dereq_("../lib/basic-component-verification");
var createDeferredClient = _dereq_("../lib/create-deferred-client");
var createAssetsUrl = _dereq_("../lib/create-assets-url");
var LocalPayment = _dereq_("./external/local-payment");
var VERSION = "3.118.2";
var wrapPromise = _dereq_("@braintree/wrap-promise");
var BraintreeError = _dereq_("../lib/braintree-error");
var errors = _dereq_("./shared/errors");
var parse = _dereq_("../lib/querystring").parse;

/**
 * @static
 * @function create
 * @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 {string} [options.merchantAccountId] A non-default merchant account ID to use for tokenization and creation of the authorizing transaction. Braintree strongly recommends specifying this parameter.
 * @param {string} [options.redirectUrl] When provided, triggers full page redirect flow instead of popup flow.
 * @param {callback} callback The second argument, `data`, is the {@link LocalPayment} instance.
 * @example <caption>Using the local payment component to set up an iDEAL button</caption>
 * var idealButton = document.querySelector('.ideal-button');
 *
 * braintree.client.create({
 *   authorization: CLIENT_AUTHORIZATION
 * }, function (clientErr, clientInstance) {
 *   if (clientErr) {
 *     console.error('Error creating client:', clientErr);
 *     return;
 *   }
 *
 *   braintree.localPayment.create({
 *     client: clientInstance,
 *     merchantAccountId: 'merchantAccountEUR',
 *   }, function (localPaymentErr, localPaymentInstance) {
 *     if (localPaymentErr) {
 *       console.error('Error creating local payment component:', localPaymentErr);
 *       return;
 *     }
 *
 *     idealButton.removeAttribute('disabled');
 *
 *     // When the button is clicked, attempt to start the payment flow.
 *     idealButton.addEventListener('click', function (event) {
 *       // Because this opens a popup, this has to be called as a result of
 *       // customer action, like clicking a button. You cannot call this at any time.
 *       localPaymentInstance.startPayment({
 *         paymentType: 'ideal',
 *         amount: '10.67',
 *         city: 'Den Haag',
 *         countryCode: 'NL',
 *         firstName: 'Test',
 *         lastName: 'McTester',
 *         line1: '123 of 456 Fake Lane',
 *         line2: 'Apartment 789',
 *         payerEmail: 'payer@example.com',
 *         phone: '123456789',
 *         postalCode: '1234 AA',
 *         currencyCode: 'EUR',
 *         onPaymentStart: function (data, continueCallback) {
 *           // Do any preprocessing to store the ID and setup webhook
 *           // Call start to initiate the popup
 *           continueCallback();
 *         }
 **       }, function (startPaymentErr, payload) {
 *         if (startPaymentErr) {
 *           if (startPaymentErr.type !== 'CUSTOMER') {
 *             console.error('Error starting payment:', startPaymentErr);
 *           }
 *           return;
 *         }
 *
 *         idealButton.setAttribute('disabled', true);
 *
 *         console.log(payload.paymentId);
 *       });
 *     }, false);
 *   });
 * });
 * @returns {(Promise|void)} Returns a promise if no callback is provided.
 */
function create(options) {
  var name = "Local Payment";

  return basicComponentVerification
    .verify({
      name: name,
      client: options.client,
      authorization: options.authorization,
    })
    .then(function () {
      return createDeferredClient.create({
        authorization: options.authorization,
        client: options.client,
        debug: options.debug,
        assetsUrl: createAssetsUrl.create(options.authorization),
        name: name,
      });
    })
    .then(function (client) {
      var localPaymentInstance, params;
      var config = client.getConfiguration();

      options.client = client;

      if (config.gatewayConfiguration.paypalEnabled !== true) {
        return Promise.reject(
          new BraintreeError(errors.LOCAL_PAYMENT_NOT_ENABLED)
        );
      }

      analytics.sendEvent(client, "local-payment.initialized");

      localPaymentInstance = new LocalPayment(options);
      if (options.redirectUrl) {
        params = parse(window.location.href);

        if (params.token || params.wasCanceled) {
          return localPaymentInstance
            .tokenize(params)
            .then(function (payload) {
              localPaymentInstance.tokenizePayload = payload;

              return localPaymentInstance;
            })
            .catch(function (err) {
              console.log("Error while tokenizing: ", err);

              return localPaymentInstance;
            });
        }

        return localPaymentInstance;
      }

      return localPaymentInstance._initialize();
    });
}

module.exports = {
  create: wrapPromise(create),
  /**
   * @description The current version of the SDK, i.e. `{@pkg version}`.
   * @type {string}
   */
  VERSION: VERSION,
};

},{"../lib/analytics":49,"../lib/basic-component-verification":52,"../lib/braintree-error":53,"../lib/create-assets-url":57,"../lib/create-deferred-client":59,"../lib/querystring":76,"./external/local-payment":80,"./shared/errors":82,"@braintree/wrap-promise":29}],82:[function(_dereq_,module,exports){
"use strict";

/**
 * @name BraintreeError.LocalPayment - Creation Error Codes
 * @description Errors that occur when [creating the Local Payment component](./module-braintree-web_local-payment.html#.create).
 * @property {MERCHANT} LOCAL_PAYMENT_NOT_ENABLED Occurs when Local Payment is not enabled on the Braintree control panel.
 */

/**
 * @name BraintreeError.LocalPayment - startPayment Error Codes
 * @description Errors that occur when using the [`startPayment` method](./LocalPayment.html#startPayment).
 * @property {MERCHANT} LOCAL_PAYMENT_START_PAYMENT_MISSING_REQUIRED_OPTION Occurs when a startPayment is missing a required option.
 * @property {MERCHANT} LOCAL_PAYMENT_ALREADY_IN_PROGRESS Occurs when a startPayment call is already in progress.
 * @property {MERCHANT} LOCAL_PAYMENT_INVALID_PAYMENT_OPTION Occurs when a startPayment call has an invalid option.
 * @property {NETWORK} LOCAL_PAYMENT_START_PAYMENT_FAILED Occurs when a startPayment call fails.
 * @property {NETWORK} LOCAL_PAYMENT_TOKENIZATION_FAILED Occurs when a startPayment call fails to tokenize the result from authorization.
 * @property {CUSTOMER} LOCAL_PAYMENT_CANCELED Occurs when the customer cancels the Local Payment.
 * @property {CUSTOMER} LOCAL_PAYMENT_WINDOW_CLOSED Occurs when the customer closes the Local Payment window.
 * @property {MERCHANT} LOCAL_PAYMENT_WINDOW_OPEN_FAILED Occurs when the Local Payment window fails to open. Usually because `startPayment` was not called as a direct result of a user action.
 */

var BraintreeError = _dereq_("../../lib/braintree-error");

module.exports = {
  LOCAL_PAYMENT_NOT_ENABLED: {
    type: BraintreeError.types.MERCHANT,
    code: "LOCAL_PAYMENT_NOT_ENABLED",
    message: "LocalPayment is not enabled for this merchant.",
  },
  LOCAL_PAYMENT_ALREADY_IN_PROGRESS: {
    type: BraintreeError.types.MERCHANT,
    code: "LOCAL_PAYMENT_ALREADY_IN_PROGRESS",
    message: "LocalPayment payment is already in progress.",
  },
  LOCAL_PAYMENT_CANCELED: {
    type: BraintreeError.types.CUSTOMER,
    code: "LOCAL_PAYMENT_CANCELED",
    message: "Customer canceled the LocalPayment before authorizing.",
  },
  LOCAL_PAYMENT_WINDOW_CLOSED: {
    type: BraintreeError.types.CUSTOMER,
    code: "LOCAL_PAYMENT_WINDOW_CLOSED",
    message: "Customer closed LocalPayment window before authorizing.",
  },
  LOCAL_PAYMENT_WINDOW_OPEN_FAILED: {
    type: BraintreeError.types.MERCHANT,
    code: "LOCAL_PAYMENT_WINDOW_OPEN_FAILED",
    message:
      "LocalPayment window failed to open; make sure startPayment was called in response to a user action.",
  },
  LOCAL_PAYMENT_START_PAYMENT_FAILED: {
    type: BraintreeError.types.NETWORK,
    code: "LOCAL_PAYMENT_START_PAYMENT_FAILED",
    message: "LocalPayment startPayment failed.",
  },
  LOCAL_PAYMENT_START_PAYMENT_MISSING_REQUIRED_OPTION: {
    type: BraintreeError.types.MERCHANT,
    code: "LOCAL_PAYMENT_START_PAYMENT_MISSING_REQUIRED_OPTION",
    message: "Missing required option for startPayment.",
  },
  LOCAL_PAYMENT_START_PAYMENT_DEFERRED_PAYMENT_FAILED: {
    type: BraintreeError.types.UNKNOWN,
    code: "LOCAL_PAYMENT_START_PAYMENT_DEFERRED_PAYMENT_FAILED",
    message: "LocalPayment startPayment deferred payment failed.",
  },
  LOCAL_PAYMENT_TOKENIZATION_FAILED: {
    type: BraintreeError.types.NETWORK,
    code: "LOCAL_PAYMENT_TOKENIZATION_FAILED",
    message: "Could not tokenize user's local payment method.",
  },
  LOCAL_PAYMENT_INVALID_PAYMENT_OPTION: {
    type: BraintreeError.types.MERCHANT,
    code: "LOCAL_PAYMENT_INVALID_PAYMENT_OPTION",
    message: "Local payment options are invalid.",
  },
};

},{"../../lib/braintree-error":53}]},{},[81])(81)
});