UNPKG

braintree-web

Version:

A suite of tools for integrating Braintree in the browser

1,559 lines (1,396 loc) 56 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 = {})).applePay = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(_dereq_,module,exports){ "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PromiseGlobal = void 0; var promise_polyfill_1 = __importDefault(_dereq_("promise-polyfill")); var PromiseGlobal = // eslint-disable-next-line no-undef typeof Promise !== "undefined" ? Promise : promise_polyfill_1.default; exports.PromiseGlobal = PromiseGlobal; },{"promise-polyfill":9}],2:[function(_dereq_,module,exports){ "use strict"; var promise_1 = _dereq_("./lib/promise"); var scriptPromiseCache = {}; function loadScript(options) { var scriptLoadPromise; var stringifiedOptions = JSON.stringify(options); if (!options.forceScriptReload) { scriptLoadPromise = scriptPromiseCache[stringifiedOptions]; if (scriptLoadPromise) { return scriptLoadPromise; } } var script = document.createElement("script"); var attrs = options.dataAttributes || {}; var container = options.container || document.head; script.src = options.src; script.id = options.id || ""; script.async = true; if (options.crossorigin) { script.setAttribute("crossorigin", "" + options.crossorigin); } Object.keys(attrs).forEach(function (key) { script.setAttribute("data-" + key, "" + attrs[key]); }); scriptLoadPromise = new promise_1.PromiseGlobal(function (resolve, reject) { script.addEventListener("load", function () { resolve(script); }); script.addEventListener("error", function () { reject(new Error(options.src + " failed to load.")); }); script.addEventListener("abort", function () { reject(new Error(options.src + " has aborted.")); }); container.appendChild(script); }); scriptPromiseCache[stringifiedOptions] = scriptLoadPromise; return scriptLoadPromise; } loadScript.clearCache = function () { scriptPromiseCache = {}; }; module.exports = loadScript; },{"./lib/promise":1}],3:[function(_dereq_,module,exports){ module.exports = _dereq_("./dist/load-script"); },{"./dist/load-script":2}],4:[function(_dereq_,module,exports){ "use strict"; var GlobalPromise = (typeof Promise !== "undefined" ? Promise // eslint-disable-line no-undef : null); var ExtendedPromise = /** @class */ (function () { function ExtendedPromise(options) { var _this = this; if (typeof options === "function") { this._promise = new ExtendedPromise.Promise(options); return; } this._promise = new ExtendedPromise.Promise(function (resolve, reject) { _this._resolveFunction = resolve; _this._rejectFunction = reject; }); options = options || {}; this._onResolve = options.onResolve || ExtendedPromise.defaultOnResolve; this._onReject = options.onReject || ExtendedPromise.defaultOnReject; if (ExtendedPromise.shouldCatchExceptions(options)) { this._promise.catch(function () { // prevents unhandled promise rejection warning // in the console for extended promises that // that catch the error in an asynchronous manner }); } this._resetState(); } ExtendedPromise.defaultOnResolve = function (result) { return ExtendedPromise.Promise.resolve(result); }; ExtendedPromise.defaultOnReject = function (err) { return ExtendedPromise.Promise.reject(err); }; ExtendedPromise.setPromise = function (PromiseClass) { ExtendedPromise.Promise = PromiseClass; }; ExtendedPromise.shouldCatchExceptions = function (options) { if (options.hasOwnProperty("suppressUnhandledPromiseMessage")) { return Boolean(options.suppressUnhandledPromiseMessage); } return Boolean(ExtendedPromise.suppressUnhandledPromiseMessage); }; // start Promise methods documented in: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise#Methods ExtendedPromise.all = function (args) { return ExtendedPromise.Promise.all(args); }; ExtendedPromise.allSettled = function (args) { return ExtendedPromise.Promise.allSettled(args); }; ExtendedPromise.race = function (args) { return ExtendedPromise.Promise.race(args); }; ExtendedPromise.reject = function (arg) { return ExtendedPromise.Promise.reject(arg); }; ExtendedPromise.resolve = function (arg) { return ExtendedPromise.Promise.resolve(arg); }; ExtendedPromise.prototype.then = function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return (_a = this._promise).then.apply(_a, args); }; ExtendedPromise.prototype.catch = function () { var _a; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } return (_a = this._promise).catch.apply(_a, args); }; ExtendedPromise.prototype.resolve = function (arg) { var _this = this; if (this.isFulfilled) { return this; } this._setResolved(); ExtendedPromise.Promise.resolve() .then(function () { return _this._onResolve(arg); }) .then(function (argForResolveFunction) { _this._resolveFunction(argForResolveFunction); }) .catch(function (err) { _this._resetState(); _this.reject(err); }); return this; }; ExtendedPromise.prototype.reject = function (arg) { var _this = this; if (this.isFulfilled) { return this; } this._setRejected(); ExtendedPromise.Promise.resolve() .then(function () { return _this._onReject(arg); }) .then(function (result) { _this._setResolved(); _this._resolveFunction(result); }) .catch(function (err) { return _this._rejectFunction(err); }); return this; }; ExtendedPromise.prototype._resetState = function () { this.isFulfilled = false; this.isResolved = false; this.isRejected = false; }; ExtendedPromise.prototype._setResolved = function () { this.isFulfilled = true; this.isResolved = true; this.isRejected = false; }; ExtendedPromise.prototype._setRejected = function () { this.isFulfilled = true; this.isResolved = false; this.isRejected = true; }; ExtendedPromise.Promise = GlobalPromise; return ExtendedPromise; }()); module.exports = ExtendedPromise; },{}],5:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function deferred(fn) { return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } setTimeout(function () { try { fn.apply(void 0, args); } catch (err) { /* eslint-disable no-console */ console.log("Error in callback function"); console.log(err); /* eslint-enable no-console */ } }, 1); }; } exports.deferred = deferred; },{}],6:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function once(fn) { var called = false; return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } if (!called) { called = true; fn.apply(void 0, args); } }; } exports.once = once; },{}],7:[function(_dereq_,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* eslint-disable consistent-return */ function promiseOrCallback(promise, callback) { if (!callback) { return promise; } promise.then(function (data) { return callback(null, data); }).catch(function (err) { return callback(err); }); } exports.promiseOrCallback = promiseOrCallback; },{}],8:[function(_dereq_,module,exports){ "use strict"; var deferred_1 = _dereq_("./lib/deferred"); var once_1 = _dereq_("./lib/once"); var promise_or_callback_1 = _dereq_("./lib/promise-or-callback"); function wrapPromise(fn) { // eslint-disable-next-line @typescript-eslint/no-explicit-any return function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var callback; var lastArg = args[args.length - 1]; if (typeof lastArg === "function") { callback = args.pop(); callback = once_1.once(deferred_1.deferred(callback)); } // I know, I know, this looks bad. But it's a quirk of the library that // we need to allow passing the this context to the original function // eslint-disable-next-line @typescript-eslint/ban-ts-ignore // @ts-ignore: this has an implicit any return promise_or_callback_1.promiseOrCallback(fn.apply(this, args), callback); // eslint-disable-line no-invalid-this }; } wrapPromise.wrapPrototype = function (target, options) { if (options === void 0) { options = {}; } var ignoreMethods = options.ignoreMethods || []; var includePrivateMethods = options.transformPrivateMethods === true; var methods = Object.getOwnPropertyNames(target.prototype).filter(function (method) { var isNotPrivateMethod; var isNonConstructorFunction = method !== "constructor" && typeof target.prototype[method] === "function"; var isNotAnIgnoredMethod = ignoreMethods.indexOf(method) === -1; if (includePrivateMethods) { isNotPrivateMethod = true; } else { isNotPrivateMethod = method.charAt(0) !== "_"; } return (isNonConstructorFunction && isNotPrivateMethod && isNotAnIgnoredMethod); }); methods.forEach(function (method) { var original = target.prototype[method]; target.prototype[method] = wrapPromise(original); }); return target; }; module.exports = wrapPromise; },{"./lib/deferred":5,"./lib/once":6,"./lib/promise-or-callback":7}],9:[function(_dereq_,module,exports){ 'use strict'; /** * @this {Promise} */ function finallyConstructor(callback) { var constructor = this.constructor; return this.then( function(value) { // @ts-ignore return constructor.resolve(callback()).then(function() { return value; }); }, function(reason) { // @ts-ignore return constructor.resolve(callback()).then(function() { // @ts-ignore return constructor.reject(reason); }); } ); } function allSettled(arr) { var P = this; return new P(function(resolve, reject) { if (!(arr && typeof arr.length !== 'undefined')) { return reject( new TypeError( typeof arr + ' ' + arr + ' is not iterable(cannot read property Symbol(Symbol.iterator))' ) ); } var args = Array.prototype.slice.call(arr); if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { then.call( val, function(val) { res(i, val); }, function(e) { args[i] = { status: 'rejected', reason: e }; if (--remaining === 0) { resolve(args); } } ); return; } } args[i] = { status: 'fulfilled', value: val }; if (--remaining === 0) { resolve(args); } } for (var i = 0; i < args.length; i++) { res(i, args[i]); } }); } // Store setTimeout reference so promise-polyfill will be unaffected by // other code modifying setTimeout (like sinon.useFakeTimers()) var setTimeoutFunc = setTimeout; function isArray(x) { return Boolean(x && typeof x.length !== 'undefined'); } function noop() {} // Polyfill for Function.prototype.bind function bind(fn, thisArg) { return function() { fn.apply(thisArg, arguments); }; } /** * @constructor * @param {Function} fn */ function Promise(fn) { if (!(this instanceof Promise)) throw new TypeError('Promises must be constructed via new'); if (typeof fn !== 'function') throw new TypeError('not a function'); /** @type {!number} */ this._state = 0; /** @type {!boolean} */ this._handled = false; /** @type {Promise|undefined} */ this._value = undefined; /** @type {!Array<!Function>} */ this._deferreds = []; doResolve(fn, this); } function handle(self, deferred) { while (self._state === 3) { self = self._value; } if (self._state === 0) { self._deferreds.push(deferred); return; } self._handled = true; Promise._immediateFn(function() { var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected; if (cb === null) { (self._state === 1 ? resolve : reject)(deferred.promise, self._value); return; } var ret; try { ret = cb(self._value); } catch (e) { reject(deferred.promise, e); return; } resolve(deferred.promise, ret); }); } function resolve(self, newValue) { try { // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.'); if ( newValue && (typeof newValue === 'object' || typeof newValue === 'function') ) { var then = newValue.then; if (newValue instanceof Promise) { self._state = 3; self._value = newValue; finale(self); return; } else if (typeof then === 'function') { doResolve(bind(then, newValue), self); return; } } self._state = 1; self._value = newValue; finale(self); } catch (e) { reject(self, e); } } function reject(self, newValue) { self._state = 2; self._value = newValue; finale(self); } function finale(self) { if (self._state === 2 && self._deferreds.length === 0) { Promise._immediateFn(function() { if (!self._handled) { Promise._unhandledRejectionFn(self._value); } }); } for (var i = 0, len = self._deferreds.length; i < len; i++) { handle(self, self._deferreds[i]); } self._deferreds = null; } /** * @constructor */ function Handler(onFulfilled, onRejected, promise) { this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null; this.onRejected = typeof onRejected === 'function' ? onRejected : null; this.promise = promise; } /** * Take a potentially misbehaving resolver function and make sure * onFulfilled and onRejected are only called once. * * Makes no guarantees about asynchrony. */ function doResolve(fn, self) { var done = false; try { fn( function(value) { if (done) return; done = true; resolve(self, value); }, function(reason) { if (done) return; done = true; reject(self, reason); } ); } catch (ex) { if (done) return; done = true; reject(self, ex); } } Promise.prototype['catch'] = function(onRejected) { return this.then(null, onRejected); }; Promise.prototype.then = function(onFulfilled, onRejected) { // @ts-ignore var prom = new this.constructor(noop); handle(this, new Handler(onFulfilled, onRejected, prom)); return prom; }; Promise.prototype['finally'] = finallyConstructor; Promise.all = function(arr) { return new Promise(function(resolve, reject) { if (!isArray(arr)) { return reject(new TypeError('Promise.all accepts an array')); } var args = Array.prototype.slice.call(arr); if (args.length === 0) return resolve([]); var remaining = args.length; function res(i, val) { try { if (val && (typeof val === 'object' || typeof val === 'function')) { var then = val.then; if (typeof then === 'function') { then.call( val, function(val) { res(i, val); }, reject ); return; } } args[i] = val; if (--remaining === 0) { resolve(args); } } catch (ex) { reject(ex); } } for (var i = 0; i < args.length; i++) { res(i, args[i]); } }); }; Promise.allSettled = allSettled; Promise.resolve = function(value) { if (value && typeof value === 'object' && value.constructor === Promise) { return value; } return new Promise(function(resolve) { resolve(value); }); }; Promise.reject = function(value) { return new Promise(function(resolve, reject) { reject(value); }); }; Promise.race = function(arr) { return new Promise(function(resolve, reject) { if (!isArray(arr)) { return reject(new TypeError('Promise.race accepts an array')); } for (var i = 0, len = arr.length; i < len; i++) { Promise.resolve(arr[i]).then(resolve, reject); } }); }; // Use polyfill for setImmediate for performance gains Promise._immediateFn = // @ts-ignore (typeof setImmediate === 'function' && function(fn) { // @ts-ignore setImmediate(fn); }) || function(fn) { setTimeoutFunc(fn, 0); }; Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) { if (typeof console !== 'undefined' && console) { console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console } }; module.exports = Promise; },{}],10:[function(_dereq_,module,exports){ "use strict"; var BraintreeError = _dereq_("../lib/braintree-error"); var analytics = _dereq_("../lib/analytics"); var errors = _dereq_("./errors"); var Promise = _dereq_("../lib/promise"); var methods = _dereq_("../lib/methods"); var convertMethodsToError = _dereq_("../lib/convert-methods-to-error"); var wrapPromise = _dereq_("@braintree/wrap-promise"); /** * @typedef {object} ApplePay~tokenizePayload * @property {string} nonce The payment method nonce. * @property {object} details Additional details. * @property {string} details.cardType Type of card, ex: Visa, MasterCard. * @property {string} details.cardHolderName The name of the card holder. * @property {string} details.dpanLastTwo Last two digits of card number. * @property {string} description A human-readable description. * @property {string} type The payment method type, always `ApplePayCard`. * @property {object} binData Information about the card based on the bin. * @property {string} binData.commercial Possible values: 'Yes', 'No', 'Unknown'. * @property {string} binData.countryOfIssuance The country of issuance. * @property {string} binData.debit Possible values: 'Yes', 'No', 'Unknown'. * @property {string} binData.durbinRegulated Possible values: 'Yes', 'No', 'Unknown'. * @property {string} binData.healthcare Possible values: 'Yes', 'No', 'Unknown'. * @property {string} binData.issuingBank The issuing bank. * @property {string} binData.payroll Possible values: 'Yes', 'No', 'Unknown'. * @property {string} binData.prepaid Possible values: 'Yes', 'No', 'Unknown'. * @property {string} binData.productId The product id. */ /** * An Apple Pay Payment Authorization Event object. * @typedef {object} ApplePayPaymentAuthorizedEvent * @external ApplePayPaymentAuthorizedEvent * @see {@link https://developer.apple.com/reference/applepayjs/applepaypaymentauthorizedevent ApplePayPaymentAuthorizedEvent} */ /** * An Apple Pay Payment Request object. * @typedef {object} ApplePayPaymentRequest * @external ApplePayPaymentRequest * @see {@link https://developer.apple.com/reference/applepayjs/1916082-applepay_js_data_types/paymentrequest PaymentRequest} */ /** * @class * @param {object} options Options * @description <strong>You cannot use this constructor directly. Use {@link module:braintree-web/apple-pay.create|braintree.applePay.create} instead.</strong> * @classdesc This class represents an Apple Pay component. Instances of this class have methods for validating the merchant server and tokenizing payments. */ function ApplePay(options) { this._instantiatedWithClient = Boolean(!options.useDeferredClient); this._client = options.client; this._createPromise = options.createPromise; if (this._client) { this._setMerchantIdentifier(); } } ApplePay.prototype._waitForClient = function () { if (this._client) { return Promise.resolve(); } return this._createPromise.then( function (client) { this._client = client; this._setMerchantIdentifier(); }.bind(this) ); }; ApplePay.prototype._setMerchantIdentifier = function () { var applePayConfig = this._client.getConfiguration().gatewayConfiguration.applePayWeb; if (!applePayConfig) { return; } /** * @name ApplePay#merchantIdentifier * @description A special merchant ID which represents the merchant association with Braintree. Required when using `ApplePaySession.canMakePaymentsWithActiveCard`. * @example * var promise = ApplePaySession.canMakePaymentsWithActiveCard(applePayInstance.merchantIdentifier); * promise.then(function (canMakePaymentsWithActiveCard) { * if (canMakePaymentsWithActiveCard) { * // Set up Apple Pay buttons * } * }); */ Object.defineProperty(this, "merchantIdentifier", { value: applePayConfig.merchantIdentifier, configurable: false, writable: false, }); }; /** * Merges a payment request with Braintree defaults to return an {external:ApplePayPaymentRequest}. * * The following properties are assigned to `paymentRequest` if not already defined. Their default values come from the Braintree gateway. * - `countryCode` * - `currencyCode` * - `merchantCapabilities` * - `supportedNetworks` * @public * @param {external:ApplePayPaymentRequest} paymentRequest The payment request details to apply on top of those from Braintree. * @returns {external:ApplePayPaymentRequest|Promise} The decorated `paymentRequest` object. If `useDeferredClient` is used along with an `authorization`, this method will return a promise that resolves with the `paymentRequest` object. * @example * var applePay = require('braintree-web/apple-pay'); * * applePay.create({client: clientInstance}, function (applePayErr, applePayInstance) { * if (applePayErr) { * // Handle error here * return; * } * * var paymentRequest = applePayInstance.createPaymentRequest({ * total: { * label: 'My Company', * amount: '19.99' * } * }); * * var session = new ApplePaySession(3, paymentRequest); * * // ... * @example <caption>With deferred client</caption> * var applePay = require('braintree-web/apple-pay'); * * applePay.create({ * authorization: 'client-token-or-tokenization-key', * useDeferredClient: true * }, function (applePayErr, applePayInstance) { * if (applePayErr) { * // Handle error here * return; * } * * applePayInstance.createPaymentRequest({ * total: { * label: 'My Company', * amount: '19.99' * } * }).then(function (paymentRequest) { * var session = new ApplePaySession(3, paymentRequest); * * // ... * }); */ ApplePay.prototype.createPaymentRequest = function (paymentRequest) { if (this._instantiatedWithClient) { return this._createPaymentRequestSynchronously(paymentRequest); } return this._waitForClient().then( function () { return this._createPaymentRequestSynchronously(paymentRequest); }.bind(this) ); }; ApplePay.prototype._createPaymentRequestSynchronously = function ( paymentRequest ) { var applePay = this._client.getConfiguration().gatewayConfiguration.applePayWeb; var defaults = { countryCode: applePay.countryCode, currencyCode: applePay.currencyCode, merchantCapabilities: applePay.merchantCapabilities || ["supports3DS"], supportedNetworks: applePay.supportedNetworks.map(function (network) { return network === "mastercard" ? "masterCard" : network; }), }; return Object.assign({}, defaults, paymentRequest); }; /** * Validates your merchant website, as required by `ApplePaySession` before payment can be authorized. * @public * @param {object} options Options * @param {string} options.validationURL The validationURL from an `ApplePayValidateMerchantEvent`. * @param {string} options.displayName The canonical name for your store. Use a non-localized name. This parameter should be a UTF-8 string that is a maximum of 128 characters. The system may display this name to the user. * @param {callback} [callback] The second argument, <code>data</code>, is the Apple Pay merchant session object. If no callback is provided, `performValidation` returns a promise. * Pass the merchant session to your Apple Pay session's `completeMerchantValidation` method. * @returns {(Promise|void)} Returns a promise if no callback is provided. * @example * var applePay = require('braintree-web/apple-pay'); * * applePay.create({client: clientInstance}, function (applePayErr, applePayInstance) { * if (applePayErr) { * // Handle error here * return; * } * * var paymentRequest = applePayInstance.createPaymentRequest({ * total: { * label: 'My Company', * amount: '19.99' * } * }); * var session = new ApplePaySession(3, paymentRequest); * * session.onvalidatemerchant = function (event) { * applePayInstance.performValidation({ * validationURL: event.validationURL, * displayName: 'My Great Store' * }, function (validationErr, validationData) { * if (validationErr) { * console.error(validationErr); * session.abort(); * return; * } * * session.completeMerchantValidation(validationData); * }); * }; * }); */ ApplePay.prototype.performValidation = function (options) { var self = this; if (!options || !options.validationURL) { return Promise.reject( new BraintreeError(errors.APPLE_PAY_VALIDATION_URL_REQUIRED) ); } return this._waitForClient() .then(function () { var applePayWebSession = { validationUrl: options.validationURL, domainName: options.domainName || window.location.hostname, merchantIdentifier: options.merchantIdentifier || self.merchantIdentifier, }; if (options.displayName != null) { applePayWebSession.displayName = options.displayName; } return self._client.request({ method: "post", endpoint: "apple_pay_web/sessions", data: { _meta: { source: "apple-pay" }, applePayWebSession: applePayWebSession, }, }); }) .then(function (response) { analytics.sendEvent(self._client, "applepay.performValidation.succeeded"); return Promise.resolve(response); }) .catch(function (err) { analytics.sendEvent(self._client, "applepay.performValidation.failed"); if (err.code === "CLIENT_REQUEST_ERROR") { return Promise.reject( new BraintreeError({ type: errors.APPLE_PAY_MERCHANT_VALIDATION_FAILED.type, code: errors.APPLE_PAY_MERCHANT_VALIDATION_FAILED.code, message: errors.APPLE_PAY_MERCHANT_VALIDATION_FAILED.message, details: { originalError: err.details.originalError, }, }) ); } return Promise.reject( new BraintreeError({ type: errors.APPLE_PAY_MERCHANT_VALIDATION_NETWORK.type, code: errors.APPLE_PAY_MERCHANT_VALIDATION_NETWORK.code, message: errors.APPLE_PAY_MERCHANT_VALIDATION_NETWORK.message, details: { originalError: err, }, }) ); }); }; /** * Tokenizes an Apple Pay payment. This will likely be called in your `ApplePaySession`'s `onpaymentauthorized` callback. * @public * @param {object} options Options * @param {object} options.token The `payment.token` property of an {@link external:ApplePayPaymentAuthorizedEvent}. * @param {callback} [callback] The second argument, <code>data</code>, is a {@link ApplePay~tokenizePayload|tokenizePayload}. If no callback is provided, `tokenize` returns a promise that resolves with a {@link ApplePay~tokenizePayload|tokenizePayload}. * @returns {(Promise|void)} Returns a promise if no callback is provided. * @example * var applePay = require('braintree-web/apple-pay'); * * applePay.create({client: clientInstance}, function (applePayErr, applePayInstance) { * if (applePayErr) { * // Handle error here * return; * } * * var paymentRequest = applePayInstance.createPaymentRequest({ * total: { * label: 'My Company', * amount: '19.99' * } * }); * var session = new ApplePaySession(3, paymentRequest); * * session.onpaymentauthorized = function (event) { * applePayInstance.tokenize({ * token: event.payment.token * }, function (tokenizeErr, tokenizedPayload) { * if (tokenizeErr) { * session.completePayment(ApplePaySession.STATUS_FAILURE); * return; * } * // Send the tokenizedPayload to your server here! * * // Once the transaction is complete, call completePayment * // to close the Apple Pay sheet * session.completePayment(ApplePaySession.STATUS_SUCCESS); * }); * }; * * // ... * }); */ ApplePay.prototype.tokenize = function (options) { var self = this; if (!options.token) { return Promise.reject( new BraintreeError(errors.APPLE_PAY_PAYMENT_TOKEN_REQUIRED) ); } return this._waitForClient() .then(function () { return self._client.request({ method: "post", endpoint: "payment_methods/apple_payment_tokens", data: { _meta: { source: "apple-pay", }, applePaymentToken: Object.assign({}, options.token, { // The gateway requires this key to be base64-encoded. paymentData: btoa(JSON.stringify(options.token.paymentData)), }), }, }); }) .then(function (response) { analytics.sendEvent(self._client, "applepay.tokenize.succeeded"); return Promise.resolve(response.applePayCards[0]); }) .catch(function (err) { analytics.sendEvent(self._client, "applepay.tokenize.failed"); return Promise.reject( new BraintreeError({ type: errors.APPLE_PAY_TOKENIZATION.type, code: errors.APPLE_PAY_TOKENIZATION.code, message: errors.APPLE_PAY_TOKENIZATION.message, details: { originalError: err, }, }) ); }); }; /** * Cleanly tear down anything set up by {@link module:braintree-web/apple-pay.create|create}. * @public * @param {callback} [callback] Called once teardown is complete. No data is returned if teardown completes successfully. * @example * applePayInstance.teardown(); * @example <caption>With callback</caption> * applePayInstance.teardown(function () { * // teardown is complete * }); * @returns {(Promise|void)} Returns a promise if no callback is provided. */ ApplePay.prototype.teardown = function () { convertMethodsToError(this, methods(ApplePay.prototype)); return Promise.resolve(); }; module.exports = wrapPromise.wrapPrototype(ApplePay); },{"../lib/analytics":14,"../lib/braintree-error":17,"../lib/convert-methods-to-error":19,"../lib/methods":26,"../lib/promise":27,"./errors":11,"@braintree/wrap-promise":8}],11:[function(_dereq_,module,exports){ "use strict"; /** * @name BraintreeError.Apple Pay - Creation Error Codes * @description Errors that occur when [creating the Apple Pay component](./module-braintree-web_apple-pay.html#.create). * @property {MERCHANT} APPLE_PAY_NOT_ENABLED Occurs when the authorization used is not authorized to process Apple Pay. */ /** * @name BraintreeError.Apple Pay - performValidation Error Codes * @description Errors that occur when [validating](./ApplePay.html#performValidation). * @property {MERCHANT} APPLE_PAY_VALIDATION_URL_REQUIRED Occurs when the `validationURL` option is not passed in. * @property {MERCHANT} APPLE_PAY_MERCHANT_VALIDATION_FAILED Occurs when the website domain has not been registered in the Braintree control panel. * @property {NETWORK} APPLE_PAY_MERCHANT_VALIDATION_NETWORK Occurs when an unknown network error occurs. */ /** * @name BraintreeError.Apple Pay - tokenize Error Codes * @description Errors that occur when [tokenizing](./ApplePay.html#tokenize). * @property {MERCHANT} APPLE_PAY_PAYMENT_TOKEN_REQUIRED Occurs when the `token` option is not passed in. * @property {NETWORK} APPLE_PAY_TOKENIZATION Occurs when an unknown network error occurs. */ var BraintreeError = _dereq_("../lib/braintree-error"); module.exports = { APPLE_PAY_NOT_ENABLED: { type: BraintreeError.types.MERCHANT, code: "APPLE_PAY_NOT_ENABLED", message: "Apple Pay is not enabled for this merchant.", }, APPLE_PAY_VALIDATION_URL_REQUIRED: { type: BraintreeError.types.MERCHANT, code: "APPLE_PAY_VALIDATION_URL_REQUIRED", message: "performValidation must be called with a validationURL.", }, APPLE_PAY_MERCHANT_VALIDATION_NETWORK: { type: BraintreeError.types.NETWORK, code: "APPLE_PAY_MERCHANT_VALIDATION_NETWORK", message: "A network error occurred when validating the Apple Pay merchant.", }, APPLE_PAY_MERCHANT_VALIDATION_FAILED: { type: BraintreeError.types.MERCHANT, code: "APPLE_PAY_MERCHANT_VALIDATION_FAILED", message: "Make sure you have registered your domain name in the Braintree Control Panel.", }, APPLE_PAY_PAYMENT_TOKEN_REQUIRED: { type: BraintreeError.types.MERCHANT, code: "APPLE_PAY_PAYMENT_TOKEN_REQUIRED", message: "tokenize must be called with a payment token.", }, APPLE_PAY_TOKENIZATION: { type: BraintreeError.types.NETWORK, code: "APPLE_PAY_TOKENIZATION", message: "A network error occurred when processing the Apple Pay payment.", }, }; },{"../lib/braintree-error":17}],12:[function(_dereq_,module,exports){ "use strict"; /** * @module braintree-web/apple-pay * @description Accept Apple Pay on the Web. *This component is currently in beta and is subject to change.* */ var ApplePay = _dereq_("./apple-pay"); var analytics = _dereq_("../lib/analytics"); var BraintreeError = _dereq_("../lib/braintree-error"); var basicComponentVerification = _dereq_("../lib/basic-component-verification"); var createAssetsUrl = _dereq_("../lib/create-assets-url"); var createDeferredClient = _dereq_("../lib/create-deferred-client"); var Promise = _dereq_("../lib/promise"); var errors = _dereq_("./errors"); var VERSION = "3.87.0"; var wrapPromise = _dereq_("@braintree/wrap-promise"); /** * @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 {boolean} [options.useDeferredClient] Used in conjunction with `authorization`, allows the Apple Pay instance to be available right away by fetching the client configuration in the background. When this option is used, {@link ApplePay#createPaymentRequest} will return a promise that resolves with the configuration instead of returning synchronously. * @param {callback} [callback] The second argument, `data`, is the {@link ApplePay} instance. If no callback is provided, `create` returns a promise that resolves with the {@link ApplePay} instance. * @returns {(Promise|void)} Returns a promise if no callback is provided. */ function create(options) { var name = "Apple Pay"; return basicComponentVerification .verify({ name: name, client: options.client, authorization: options.authorization, }) .then(function () { var applePayInstance; var createPromise = createDeferredClient .create({ authorization: options.authorization, client: options.client, debug: options.debug, assetsUrl: createAssetsUrl.create(options.authorization), name: name, }) .then(function (client) { if (!client.getConfiguration().gatewayConfiguration.applePayWeb) { return Promise.reject( new BraintreeError(errors.APPLE_PAY_NOT_ENABLED) ); } analytics.sendEvent(client, "applepay.initialized"); return client; }); options.createPromise = createPromise; applePayInstance = new ApplePay(options); if (!options.useDeferredClient) { return createPromise.then(function (client) { applePayInstance._client = client; return applePayInstance; }); } return applePayInstance; }); } module.exports = { create: wrapPromise(create), /** * @description The current version of the SDK, i.e. `{@pkg version}`. * @type {string} */ VERSION: VERSION, }; },{"../lib/analytics":14,"../lib/basic-component-verification":16,"../lib/braintree-error":17,"../lib/create-assets-url":20,"../lib/create-deferred-client":22,"../lib/promise":27,"./apple-pay":10,"./errors":11,"@braintree/wrap-promise":8}],13:[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; } module.exports = addMetadata; },{"./constants":18,"./create-authorization-data":21,"./json-clone":25}],14:[function(_dereq_,module,exports){ "use strict"; var Promise = _dereq_("./promise"); var constants = _dereq_("./constants"); var addMetadata = _dereq_("./add-metadata"); function sendAnalyticsEvent(clientInstanceOrPromise, kind, callback) { var timestamp = Date.now(); // milliseconds return Promise.resolve(clientInstanceOrPromise) .then(function (client) { var timestampInPromise = Date.now(); var configuration = client.getConfiguration(); var request = client._request; var url = configuration.gatewayConfiguration.analytics.url; var data = { analytics: [ { kind: constants.ANALYTICS_PREFIX + kind, isAsync: Math.floor(timestampInPromise / 1000) !== Math.floor(timestamp / 1000), timestamp: timestamp, }, ], }; request( { url: url, method: "post", data: addMetadata(configuration, data), timeout: constants.ANALYTICS_REQUEST_TIMEOUT_MS, }, callback ); }) .catch(function (err) { // for all non-test cases, we don't provide a callback, // so this error will always be swallowed. In this case, // that's fine, it should only error when the deferred // client fails to set up, in which case we don't want // that error to report over and over again via these // deferred analytics events if (callback) { callback(err); } }); } module.exports = { sendEvent: sendAnalyticsEvent, }; },{"./add-metadata":13,"./constants":18,"./promise":27}],15:[function(_dereq_,module,exports){ "use strict"; var loadScript = _dereq_("@braintree/asset-loader/load-script"); module.exports = { loadScript: loadScript, }; },{"@braintree/asset-loader/load-script":3}],16:[function(_dereq_,module,exports){ "use strict"; var BraintreeError = _dereq_("./braintree-error"); var Promise = _dereq_("./promise"); var sharedErrors = _dereq_("./errors"); var VERSION = "3.87.0"; 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":17,"./errors":24,"./promise":27}],17:[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":23}],18:[function(_dereq_,module,exports){ "use strict"; var VERSION = "3.87.0"; 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, 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, }; },{}],19:[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":17,"./errors":24}],20:[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":18}],21:[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":18,"../lib/vendor/polyfill":28}],22:[function(_dereq_,module,exports){ "use strict"; var BraintreeError = _dereq_("./braintree-error"); var Promise = _dereq_("./promise"); var assets = _dereq_("./assets"); var sharedErrors = _dereq_("./errors"); var VERSION = "3.87.0"; function createDeferredClient(options) { var promise = Promise.resolve(); if (options.client) { return