UNPKG

braintree-web

Version:

A suite of tools for integrating Braintree in the browser

152 lines (131 loc) 5.5 kB
"use strict"; var wrapPromise = require("@braintree/wrap-promise"); var BraintreeError = require("../../lib/braintree-error"); var sepaErrors = require("../shared/errors"); var constants = require("../shared/constants"); var mandates = require("./mandate"); var hasMissingOption = require("../shared/has-missing-option"); var analytics = require("../../lib/analytics"); var VERSION = "3.117.1"; var assign = require("../../lib/assign").assign; /** * @class * @param {object} options see {@link module:braintree-web/sepa.create|sepa.create} * @description <strong>Do not use this constructor directly. Use {@link module:braintree-web/sepa.create|braintree-web.sepa.create} instead.</strong> * @classdesc This class represents a SEPA component produced by {@link module:braintree-web/sepa.create|braintree-web.sepa.create}. Instances provide methods for tokenizing SEPA payments. */ function SEPA(options) { var getConfiguration = options.client.getConfiguration(); this._client = options.client; this._assetsUrl = getConfiguration.gatewayConfiguration.assetsUrl + "/web/" + VERSION; this._isDebug = getConfiguration.isDebug; if (options.redirectUrl) { this._returnUrl = options.redirectUrl; this._cancelUrl = options.redirectUrl + "?cancel=1"; this._isRedirectFlow = true; } else { this._returnUrl = this._assetsUrl + "/html/redirect-frame.html?success=1"; this._cancelUrl = this._assetsUrl + "/html/redirect-frame.html?cancel=1"; } if (options.tokenizePayload) { this.tokenizePayload = options.tokenizePayload; } analytics.sendEvent(this._client, "sepa.component.initialized"); } /** * SEPA tokenize payload. * @typedef SEPA~tokenizePayload * @property {string} nonce The payment nonce. * @property {string} ibanLastFour The last four digits of the customer's IBAN. * @property {string} mandateType The specified mandateType used. * @property {string} customerId The provided customer id. */ /** * @public * @param {object} options All options for intiating the SEPA payment flow. * @param {string} [options.accountHolderName] The account holder name. * @param {string} [options.customerId] The customer's id. * @param {string} [options.iban] The customer's International Bank Account Number. * @param {string} [options.mandateType] Specify ONE_OFF or RECURRENT payment. * @param {string} [options.countryCode] The customer's country code. * @param {string} [options.merchantAccountId] The merchant's account id. * @param {callback} [callback] The first argument is an error object, where the second is a {@link SEPA~tokenizePayload|tokenizePayload} * @returns {(Promise<tokenizePayload|error>)} Returns a promise if no callback is provided. * * @example * button.addEventListener('click', function () { * var tokenizeInputs = { * accountHolderName: "some-accnt-holder-name", * customerId: "a-customer-id", * iban: "a-full-iban", * mandateType: "ONE_OFF", * countryCode: "LI", * merchantAccountId: "a-merchant-account-id" * } * sepaInstance.tokenize(tokenizeInputs).then(function (payload) { * // Submit payload.nonce to your server * }).catch(function(tokenizationErr) { * // Handle errors in the flow * }) * }) */ SEPA.prototype.tokenize = function (options) { var self = this; var popupPromise; var createMandateOptions = assign( { cancelUrl: self._cancelUrl, returnUrl: self._returnUrl }, options ); if (!options || hasMissingOption(options, constants.REQUIRED_OPTIONS)) { analytics.sendEvent(self._client, "sepa.input-validation.missing-options"); return Promise.reject( new BraintreeError(sepaErrors.SEPA_TOKENIZE_MISSING_REQUIRED_OPTION) ); } if (!constants.MANDATE_TYPE_ENUM.includes(options.mandateType)) { analytics.sendEvent(self._client, "sepa.input-validation.invalid-mandate"); return Promise.reject( new BraintreeError(sepaErrors.SEPA_INVALID_MANDATE_TYPE) ); } popupPromise = mandates .createMandate(self._client, createMandateOptions) .then(function (mandateResponse) { analytics.sendEvent(self._client, "sepa.create-mandate.success"); if (self._isRedirectFlow) { return mandates.redirectPage(mandateResponse.approvalUrl); } options.last4 = mandateResponse.last4; options.bankReferenceToken = mandateResponse.bankReferenceToken; return mandates.openPopup(self._client, { approvalUrl: mandateResponse.approvalUrl, assetsUrl: self._assetsUrl, }); }); // Must be outside of .then() to return from top-level function if (self._isRedirectFlow) { return Promise.resolve(); } // At this point, we know the promise came from the popup flow return popupPromise .then(function () { analytics.sendEvent(self._client, "sepa.mandate.approved"); return mandates.handleApproval(self._client, { bankReferenceToken: options.bankReferenceToken, last4: options.last4, customerId: options.customerId, mandateType: options.mandateType, merchantAccountId: options.merchantAccountId, }); }) .then(function (approval) { analytics.sendEvent(self._client, "sepa.tokenization.success"); return Promise.resolve(approval); }) .catch(function (err) { analytics.sendEvent(self._client, "sepa." + err.details + ".failed"); return Promise.reject(err); }); }; module.exports = wrapPromise.wrapPrototype(SEPA);