Skip to content

Commit fc90eb9

Browse files
committed
Release braintree-web 3.111.0 source
1 parent 7f9146b commit fc90eb9

File tree

8 files changed

+274
-34
lines changed

8 files changed

+274
-34
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# CHANGELOG
22

3+
## 3.111.0
4+
5+
- Local Payment Methods
6+
- Add Full Page Redirect
7+
38
## 3.110.0
49

510
- SEPA

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "braintree-web",
3-
"version": "3.110.0",
3+
"version": "3.111.0",
44
"license": "MIT",
55
"main": "src/index.js",
66
"private": true,

src/local-payment/external/constants.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ module.exports = {
55
"givenName",
66
"surname",
77
"currencyCode",
8-
"onPaymentStart",
98
"paymentType",
109
"amount",
1110
"fallback",
@@ -45,7 +44,6 @@ module.exports = {
4544
"givenName",
4645
"surname",
4746
"currencyCode",
48-
"onPaymentStart",
4947
"paymentType",
5048
"amount",
5149
],

src/local-payment/external/local-payment.js

Lines changed: 74 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var querystring = require("../../lib/querystring");
1515
var wrapPromise = require("@braintree/wrap-promise");
1616
var constants = require("./constants");
1717
var errors = require("../shared/errors");
18+
var assign = require("../../lib/assign").assign;
1819

1920
var DEFAULT_WINDOW_WIDTH = 1282;
2021
var DEFAULT_WINDOW_HEIGHT = 720;
@@ -43,6 +44,10 @@ function LocalPayment(options) {
4344
this._authorizationInProgress = false;
4445
this._paymentType = "unknown";
4546
this._merchantAccountId = options.merchantAccountId;
47+
if (options.redirectUrl) {
48+
this._redirectUrl = options.redirectUrl;
49+
this._isRedirectFlow = true;
50+
}
4651
}
4752

4853
LocalPayment.prototype._initialize = function () {
@@ -76,12 +81,12 @@ LocalPayment.prototype._initialize = function () {
7681
/**
7782
* Options used for most local payment types.
7883
* @typedef {object} LocalPayment~StartPaymentOptions
79-
* @property {object} fallback Configuration for what to do when app switching back from a Bank app on a mobile device.
84+
* @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.
8085
* @property {string} fallback.buttonText The text to display in a button to redirect back to the merchant page.
8186
* @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.
8287
* @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.
8388
* @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.
84-
* @property {object} [windowOptions] The options for configuring the window that is opened when starting the payment.
89+
* @property {object} [windowOptions] The options for configuring the window that is opened when starting the payment. Only applicable to the popup flow.
8590
* @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.
8691
* @property {number} [windowOptions.height=720] The height in pixels of the window opened when starting the payment.
8792
* @property {string} amount The amount to authorize for the transaction.
@@ -409,10 +414,17 @@ LocalPayment.prototype.startPayment = function (options) {
409414
promise,
410415
billingAddress,
411416
windowOptions,
412-
onPaymentStartPromise;
417+
onPaymentStartPromise,
418+
serviceId,
419+
cancelUrl,
420+
returnUrl;
413421
var self = this; // eslint-disable-line no-invalid-this
414-
var serviceId = this._frameService._serviceId; // eslint-disable-line no-invalid-this
415422

423+
if (self._isRedirectFlow) {
424+
options.redirectUrl = self._redirectUrl;
425+
} else {
426+
serviceId = self._frameService._serviceId;
427+
}
416428
// In order to provide the merchant with appropriate error messaging,
417429
// more robust validation is being done on the client-side, since some
418430
// option names are mapped to legacy names for the sake of the API.
@@ -448,18 +460,6 @@ LocalPayment.prototype.startPayment = function (options) {
448460
},
449461
birthDate: options.birthDate,
450462
blikOptions: options.blikOptions,
451-
cancelUrl: querystring.queryify(
452-
self._assetsUrl +
453-
"/html/local-payment-redirect-frame" +
454-
useMin(self._isDebug) +
455-
".html",
456-
{
457-
channel: serviceId,
458-
r: fallback.cancelUrl || fallback.url,
459-
t: fallback.cancelButtonText || fallback.buttonText,
460-
c: 1, // indicating we went through the cancel flow
461-
}
462-
),
463463
city: address.locality,
464464
correlationId: options.correlationId,
465465
countryCode: address.countryCode,
@@ -486,7 +486,29 @@ LocalPayment.prototype.startPayment = function (options) {
486486
phoneCountryCode: options.phoneCountryCode,
487487
postalCode: address.postalCode,
488488
recurrent: options.recurrent,
489-
returnUrl: querystring.queryify(
489+
shippingAmount: options.shippingAmount,
490+
state: address.region,
491+
};
492+
493+
if (self._isRedirectFlow) {
494+
cancelUrl = querystring.queryify(self._redirectUrl, {
495+
wasCanceled: true,
496+
});
497+
returnUrl = self._redirectUrl;
498+
} else {
499+
cancelUrl = querystring.queryify(
500+
self._assetsUrl +
501+
"/html/local-payment-redirect-frame" +
502+
useMin(self._isDebug) +
503+
".html",
504+
{
505+
channel: serviceId,
506+
r: fallback.cancelUrl || fallback.url,
507+
t: fallback.cancelButtonText || fallback.buttonText,
508+
c: 1, // indicating we went through the cancel flow
509+
}
510+
);
511+
returnUrl = querystring.queryify(
490512
self._assetsUrl +
491513
"/html/local-payment-redirect-frame" +
492514
useMin(self._isDebug) +
@@ -496,13 +518,13 @@ LocalPayment.prototype.startPayment = function (options) {
496518
r: fallback.url,
497519
t: fallback.buttonText,
498520
}
499-
),
500-
shippingAmount: options.shippingAmount,
501-
state: address.region,
502-
};
521+
);
522+
}
523+
assign(params, { cancelUrl: cancelUrl, returnUrl: returnUrl });
503524

504525
self._paymentType = options.paymentType.toLowerCase();
505-
if (self._authorizationInProgress) {
526+
527+
if (self._authorizationInProgress && !self._isRedirectFlow) {
506528
analytics.sendEvent(
507529
self._client,
508530
self._paymentType + ".local-payment.start-payment.error.already-opened"
@@ -519,7 +541,7 @@ LocalPayment.prototype.startPayment = function (options) {
519541

520542
// For deferred payment types, the popup window should not be opened,
521543
// since the actual payment will be done outside of this session.
522-
if (!isDeferredPaymentTypeOptions(options)) {
544+
if (!isDeferredPaymentTypeOptions(options) && !self._isRedirectFlow) {
523545
self._startPaymentCallback = self._createStartPaymentCallback(
524546
function (val) {
525547
promise.resolve(val);
@@ -547,10 +569,17 @@ LocalPayment.prototype.startPayment = function (options) {
547569
.then(function (response) {
548570
var redirectUrl = response.paymentResource.redirectUrl;
549571

550-
analytics.sendEvent(
551-
self._client,
552-
self._paymentType + ".local-payment.start-payment.opened"
553-
);
572+
if (self._isRedirectFlow) {
573+
analytics.sendEvent(
574+
self._client,
575+
self._paymentType + ".local-payment.start-payment.redirected"
576+
);
577+
} else {
578+
analytics.sendEvent(
579+
self._client,
580+
self._paymentType + ".local-payment.start-payment.opened"
581+
);
582+
}
554583
self._startPaymentOptions = options;
555584

556585
if (isDeferredPaymentTypeOptions(options)) {
@@ -575,6 +604,8 @@ LocalPayment.prototype.startPayment = function (options) {
575604
promise.resolve();
576605
}
577606
}
607+
} else if (self._isRedirectFlow) {
608+
window.location.href = response.paymentResource.redirectUrl;
578609
} else {
579610
options.onPaymentStart(
580611
{ paymentId: response.paymentResource.paymentToken },
@@ -587,7 +618,9 @@ LocalPayment.prototype.startPayment = function (options) {
587618
.catch(function (err) {
588619
var status = err.details && err.details.httpStatus;
589620

590-
self._frameService.close();
621+
if (!self._isRedirectFlow) {
622+
self._frameService.close();
623+
}
591624
self._authorizationInProgress = false;
592625

593626
if (status === 422) {
@@ -936,6 +969,12 @@ function hasMissingBlikOptions(options) {
936969
var i, option, oneClick;
937970
var blikOptions = options.blikOptions || {};
938971

972+
if (!options.redirectUrl) {
973+
constants.REQUIRED_OPTIONS_FOR_BLIK_SEAMLESS_PAYMENT_TYPE.push(
974+
"onPaymentStart"
975+
);
976+
}
977+
939978
for (
940979
i = 0;
941980
i < constants.REQUIRED_OPTIONS_FOR_BLIK_SEAMLESS_PAYMENT_TYPE.length;
@@ -1035,6 +1074,10 @@ function hasMissingOption(options) {
10351074
return hasMissingBlikOptions(options);
10361075
}
10371076
} else {
1077+
if (!options.redirectUrl) {
1078+
constants.REQUIRED_OPTIONS_FOR_START_PAYMENT.push("onPaymentStart");
1079+
}
1080+
10381081
for (i = 0; i < constants.REQUIRED_OPTIONS_FOR_START_PAYMENT.length; i++) {
10391082
option = constants.REQUIRED_OPTIONS_FOR_START_PAYMENT[i];
10401083

@@ -1072,7 +1115,9 @@ function hasMissingOption(options) {
10721115
LocalPayment.prototype.teardown = function () {
10731116
var self = this; // eslint-disable-line no-invalid-this
10741117

1075-
self._frameService.teardown();
1118+
if (!self._isRedirectFlow) {
1119+
self._frameService.teardown();
1120+
}
10761121

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

src/local-payment/index.js

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var VERSION = process.env.npm_package_version;
1313
var wrapPromise = require("@braintree/wrap-promise");
1414
var BraintreeError = require("../lib/braintree-error");
1515
var errors = require("./shared/errors");
16+
var parse = require("../lib/querystring").parse;
1617

1718
/**
1819
* @static
@@ -21,6 +22,7 @@ var errors = require("./shared/errors");
2122
* @param {Client} [options.client] A {@link Client} instance.
2223
* @param {string} [options.authorization] A tokenizationKey or clientToken. Can be used in place of `options.client`.
2324
* @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.
25+
* @param {redirectUrl} When provided, triggers full page redirect flow instead of popup flow.
2426
* @param {callback} callback The second argument, `data`, is the {@link LocalPayment} instance.
2527
* @example <caption>Using the local payment component to set up an iDEAL button</caption>
2628
* var idealButton = document.querySelector('.ideal-button');
@@ -102,7 +104,7 @@ function create(options) {
102104
});
103105
})
104106
.then(function (client) {
105-
var localPaymentInstance;
107+
var localPaymentInstance, params;
106108
var config = client.getConfiguration();
107109

108110
options.client = client;
@@ -116,6 +118,26 @@ function create(options) {
116118
analytics.sendEvent(client, "local-payment.initialized");
117119

118120
localPaymentInstance = new LocalPayment(options);
121+
if (options.redirectUrl) {
122+
params = parse(window.location.href);
123+
124+
if (params.token || params.wasCanceled) {
125+
return localPaymentInstance
126+
.tokenize(params)
127+
.then(function (payload) {
128+
localPaymentInstance.tokenizePayload = payload;
129+
130+
return localPaymentInstance;
131+
})
132+
.catch(function (err) {
133+
console.log("Error while tokenizing: ", err);
134+
135+
return localPaymentInstance;
136+
});
137+
}
138+
139+
return localPaymentInstance;
140+
}
119141

120142
return localPaymentInstance._initialize();
121143
});

0 commit comments

Comments
 (0)