swell-js 3.12.0 → 3.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.js CHANGED
@@ -246,7 +246,7 @@ function _request() {
246
246
 
247
247
  if (typeof window !== 'undefined') {
248
248
  window.swell = {
249
- version: '3.12.0'
249
+ version: '3.13.0'
250
250
  };
251
251
  }
252
252
 
package/dist/currency.js CHANGED
@@ -110,9 +110,11 @@ function methods(request, opt) {
110
110
  var formatRate = params.rate || rate;
111
111
  var formatLocale = params.locale || this.locale;
112
112
  var formatDecimals = typeof params.decimals === 'number' ? params.decimals : decimals;
113
+ var _params$convert = params.convert,
114
+ convert = _params$convert === void 0 ? true : _params$convert;
113
115
  var formatAmount = amount;
114
116
 
115
- if ((type === 'display' || params.rate) && typeof formatAmount === 'number' && typeof formatRate === 'number') {
117
+ if (convert && (type === 'display' || params.rate) && typeof formatAmount === 'number' && typeof formatRate === 'number') {
116
118
  // Convert the price currency into the display currency
117
119
  formatAmount = this.applyRounding(amount * formatRate, state);
118
120
  }
package/dist/payment.js CHANGED
@@ -12,6 +12,12 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
12
12
 
13
13
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
14
14
 
15
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
16
+
17
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
18
+
19
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
20
+
15
21
  var get = require('lodash/get');
16
22
 
17
23
  var toLower = require('lodash/toLower');
@@ -42,6 +48,9 @@ var _require3 = require('./utils/quickpay'),
42
48
  var _require4 = require('./utils/paysafecard'),
43
49
  createPaysafecardPayment = _require4.createPaysafecardPayment;
44
50
 
51
+ var _require5 = require('./utils/klarna'),
52
+ createKlarnaSession = _require5.createKlarnaSession;
53
+
45
54
  var LOADING_SCRIPTS = {};
46
55
  var CARD_ELEMENTS = {};
47
56
  var API = {};
@@ -605,7 +614,7 @@ function _stripeElements() {
605
614
  case 0:
606
615
  publishable_key = payMethods.card.publishable_key;
607
616
  stripe = window.Stripe(publishable_key);
608
- elements = stripe.elements();
617
+ elements = stripe.elements(params.config);
609
618
 
610
619
  createElement = function createElement(type) {
611
620
  var elementParams = get(params, "card[".concat(type, "]")) || params.card || params.ideal;
@@ -652,7 +661,7 @@ function payPalButton(_x16, _x17, _x18, _x19) {
652
661
 
653
662
  function _payPalButton() {
654
663
  _payPalButton = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee11(request, cart, payMethods, params) {
655
- var paypal, _params$paypal, locale, style, elementId, onError, onSuccess;
664
+ var paypal, _params$paypal, locale, style, elementId, onError, onSuccess, _getTotalsDueRemainin, totalDue;
656
665
 
657
666
  return _regenerator["default"].wrap(function _callee11$(_context11) {
658
667
  while (1) {
@@ -678,6 +687,16 @@ function _payPalButton() {
678
687
  return isFunction(successHandler) && successHandler();
679
688
  };
680
689
 
690
+ _getTotalsDueRemainin = getTotalsDueRemaining(cart), totalDue = _getTotalsDueRemainin.totalDue;
691
+
692
+ if (totalDue > 0) {
693
+ _context11.next = 9;
694
+ break;
695
+ }
696
+
697
+ throw new Error('Invalid PayPal button amount. Value should be greater than zero.');
698
+
699
+ case 9:
681
700
  paypal.Buttons({
682
701
  locale: locale || 'en_US',
683
702
  style: style || {
@@ -693,7 +712,7 @@ function _payPalButton() {
693
712
  intent: 'AUTHORIZE',
694
713
  purchase_units: [{
695
714
  amount: {
696
- value: cart.grand_total,
715
+ value: +totalDue.toFixed(2),
697
716
  currency_code: cart.currency
698
717
  }
699
718
  }]
@@ -704,10 +723,11 @@ function _payPalButton() {
704
723
  var payer = authorization.payer;
705
724
  var shipping = get(authorization, 'purchase_units[0].shipping');
706
725
  var authorizationID = get(authorization, 'purchase_units[0].payments.authorizations[0].id');
707
- return cartApi.methods(request).update({
726
+ return cartApi.methods(request).update(_objectSpread(_objectSpread({}, !cart.account_logged_in && {
708
727
  account: {
709
728
  email: payer.email_address
710
- },
729
+ }
730
+ }), {}, {
711
731
  billing: {
712
732
  method: 'paypal',
713
733
  paypal: {
@@ -723,12 +743,12 @@ function _payPalButton() {
723
743
  zip: shipping.address.postal_code,
724
744
  country: shipping.address.country_code
725
745
  }
726
- });
746
+ }));
727
747
  }).then(onSuccess)["catch"](onError);
728
748
  }
729
749
  }, onError).render(elementId || '#paypal-button');
730
750
 
731
- case 7:
751
+ case 10:
732
752
  case "end":
733
753
  return _context11.stop();
734
754
  }
@@ -830,7 +850,7 @@ function paymentTokenize(_x24, _x25, _x26, _x27) {
830
850
 
831
851
  function _paymentTokenize() {
832
852
  _paymentTokenize = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee13(request, params, payMethods, cart) {
833
- var onError, stripe, paymentMethod, currency, amount, stripeCustomer, intent, _yield$stripe$confirm, paymentIntent, error, _intent, _yield$createIDealPay, _error, _paymentMethod, _currency, _amount, _intent2, publishable_key, _stripe, settings, _yield$createKlarnaSo, _error2, source, _publishable_key, _stripe2, _yield$createBanconta, _error3, _source, _intent3;
853
+ var onError, stripe, paymentMethod, currency, amount, stripeCustomer, intent, _yield$stripe$confirm, paymentIntent, error, _intent, _yield$createIDealPay, _error, _paymentMethod, _currency, _amount, _intent2, session, publishable_key, _stripe, settings, _yield$createKlarnaSo, _error2, source, _publishable_key, _stripe2, _yield$createBanconta, _error3, _source, _intent3;
834
854
 
835
855
  return _regenerator["default"].wrap(function _callee13$(_context13) {
836
856
  while (1) {
@@ -999,7 +1019,7 @@ function _paymentTokenize() {
999
1019
  createQuickpayCard(methods(request).authorizeGateway)["catch"](onError);
1000
1020
 
1001
1021
  case 48:
1002
- _context13.next = 121;
1022
+ _context13.next = 128;
1003
1023
  break;
1004
1024
 
1005
1025
  case 50:
@@ -1092,44 +1112,59 @@ function _paymentTokenize() {
1092
1112
  return _context13.abrupt("return", _context13.t5);
1093
1113
 
1094
1114
  case 75:
1095
- _context13.next = 121;
1115
+ _context13.next = 128;
1096
1116
  break;
1097
1117
 
1098
1118
  case 77:
1099
1119
  if (!(params.klarna && payMethods.klarna)) {
1100
- _context13.next = 97;
1120
+ _context13.next = 104;
1121
+ break;
1122
+ }
1123
+
1124
+ if (!(payMethods.klarna.gateway === 'klarna')) {
1125
+ _context13.next = 85;
1101
1126
  break;
1102
1127
  }
1103
1128
 
1129
+ _context13.next = 81;
1130
+ return createKlarnaSession(cart, methods(request).createIntent)["catch"](function (err) {
1131
+ return onError(err);
1132
+ });
1133
+
1134
+ case 81:
1135
+ session = _context13.sent;
1136
+ return _context13.abrupt("return", session && window.location.replace(session.redirect_url));
1137
+
1138
+ case 85:
1104
1139
  if (!(payMethods.card && payMethods.card.gateway === 'stripe')) {
1105
- _context13.next = 95;
1140
+ _context13.next = 102;
1106
1141
  break;
1107
1142
  }
1108
1143
 
1109
1144
  if (window.Stripe) {
1110
- _context13.next = 82;
1145
+ _context13.next = 89;
1111
1146
  break;
1112
1147
  }
1113
1148
 
1114
- _context13.next = 82;
1149
+ _context13.next = 89;
1115
1150
  return loadScript('stripe-js', 'https://js.stripe.com/v3/');
1116
1151
 
1117
- case 82:
1152
+ case 89:
1118
1153
  publishable_key = payMethods.card.publishable_key;
1119
1154
  _stripe = window.Stripe(publishable_key);
1120
1155
  _context13.t6 = toSnake;
1121
- _context13.next = 87;
1156
+ _context13.next = 94;
1122
1157
  return settingsApi.methods(request, options).get();
1123
1158
 
1124
- case 87:
1159
+ case 94:
1125
1160
  _context13.t7 = _context13.sent;
1126
1161
  settings = (0, _context13.t6)(_context13.t7);
1127
- _context13.next = 91;
1162
+ _context13.next = 98;
1128
1163
  return createKlarnaSource(_stripe, _objectSpread(_objectSpread({}, cart), {}, {
1129
1164
  settings: settings.store
1130
1165
  }));
1131
1166
 
1132
- case 91:
1167
+ case 98:
1133
1168
  _yield$createKlarnaSo = _context13.sent;
1134
1169
  _error2 = _yield$createKlarnaSo.error;
1135
1170
  source = _yield$createKlarnaSo.source;
@@ -1143,36 +1178,36 @@ function _paymentTokenize() {
1143
1178
  return onError(err);
1144
1179
  }));
1145
1180
 
1146
- case 95:
1147
- _context13.next = 121;
1181
+ case 102:
1182
+ _context13.next = 128;
1148
1183
  break;
1149
1184
 
1150
- case 97:
1185
+ case 104:
1151
1186
  if (!(params.bancontact && payMethods.bancontact)) {
1152
- _context13.next = 112;
1187
+ _context13.next = 119;
1153
1188
  break;
1154
1189
  }
1155
1190
 
1156
1191
  if (!(payMethods.card && payMethods.card.gateway === 'stripe')) {
1157
- _context13.next = 110;
1192
+ _context13.next = 117;
1158
1193
  break;
1159
1194
  }
1160
1195
 
1161
1196
  if (window.Stripe) {
1162
- _context13.next = 102;
1197
+ _context13.next = 109;
1163
1198
  break;
1164
1199
  }
1165
1200
 
1166
- _context13.next = 102;
1201
+ _context13.next = 109;
1167
1202
  return loadScript('stripe-js', 'https://js.stripe.com/v3/');
1168
1203
 
1169
- case 102:
1204
+ case 109:
1170
1205
  _publishable_key = payMethods.card.publishable_key;
1171
1206
  _stripe2 = window.Stripe(_publishable_key);
1172
- _context13.next = 106;
1207
+ _context13.next = 113;
1173
1208
  return createBancontactSource(_stripe2, cart);
1174
1209
 
1175
- case 106:
1210
+ case 113:
1176
1211
  _yield$createBanconta = _context13.sent;
1177
1212
  _error3 = _yield$createBanconta.error;
1178
1213
  _source = _yield$createBanconta.source;
@@ -1186,31 +1221,31 @@ function _paymentTokenize() {
1186
1221
  return onError(err);
1187
1222
  }));
1188
1223
 
1189
- case 110:
1190
- _context13.next = 121;
1224
+ case 117:
1225
+ _context13.next = 128;
1191
1226
  break;
1192
1227
 
1193
- case 112:
1228
+ case 119:
1194
1229
  if (!(params.paysafecard && payMethods.paysafecard)) {
1195
- _context13.next = 121;
1230
+ _context13.next = 128;
1196
1231
  break;
1197
1232
  }
1198
1233
 
1199
- _context13.next = 115;
1234
+ _context13.next = 122;
1200
1235
  return createPaysafecardPayment(cart, methods(request).createIntent)["catch"](onError);
1201
1236
 
1202
- case 115:
1237
+ case 122:
1203
1238
  _intent3 = _context13.sent;
1204
1239
 
1205
1240
  if (_intent3) {
1206
- _context13.next = 118;
1241
+ _context13.next = 125;
1207
1242
  break;
1208
1243
  }
1209
1244
 
1210
1245
  return _context13.abrupt("return");
1211
1246
 
1212
- case 118:
1213
- _context13.next = 120;
1247
+ case 125:
1248
+ _context13.next = 127;
1214
1249
  return cartApi.methods(request, options).update({
1215
1250
  billing: {
1216
1251
  method: 'paysafecard',
@@ -1222,10 +1257,10 @@ function _paymentTokenize() {
1222
1257
  }
1223
1258
  });
1224
1259
 
1225
- case 120:
1260
+ case 127:
1226
1261
  return _context13.abrupt("return", window.location.replace(_intent3.redirect.auth_url));
1227
1262
 
1228
- case 121:
1263
+ case 128:
1229
1264
  case "end":
1230
1265
  return _context13.stop();
1231
1266
  }
@@ -1247,7 +1282,7 @@ function _handleRedirect3() {
1247
1282
  switch (_context14.prev = _context14.next) {
1248
1283
  case 0:
1249
1284
  onError = function onError(error) {
1250
- var errorHandler = get(params, 'card.onError') || get(params, 'paysafecard.onError');
1285
+ var errorHandler = get(params, 'card.onError') || get(params, 'paysafecard.onError') || get(params, 'klarna.onError');
1251
1286
 
1252
1287
  if (isFunction(errorHandler)) {
1253
1288
  return errorHandler(error);
@@ -1257,7 +1292,7 @@ function _handleRedirect3() {
1257
1292
  };
1258
1293
 
1259
1294
  onSuccess = function onSuccess(result) {
1260
- var successHandler = get(params, 'card.onSuccess') || get(params, 'paysafecard.onSuccess');
1295
+ var successHandler = get(params, 'card.onSuccess') || get(params, 'paysafecard.onSuccess') || get(params, 'klarna.onSuccess');
1261
1296
 
1262
1297
  if (isFunction(successHandler)) {
1263
1298
  return successHandler(result);
@@ -1280,12 +1315,12 @@ function _handleRedirect3() {
1280
1315
 
1281
1316
  case 8:
1282
1317
  result = _context14.sent;
1283
- _context14.next = 15;
1318
+ _context14.next = 21;
1284
1319
  break;
1285
1320
 
1286
1321
  case 11:
1287
1322
  if (!(gateway === 'paysafecard')) {
1288
- _context14.next = 15;
1323
+ _context14.next = 17;
1289
1324
  break;
1290
1325
  }
1291
1326
 
@@ -1294,27 +1329,41 @@ function _handleRedirect3() {
1294
1329
 
1295
1330
  case 14:
1296
1331
  result = _context14.sent;
1332
+ _context14.next = 21;
1333
+ break;
1297
1334
 
1298
- case 15:
1335
+ case 17:
1336
+ if (!(gateway === 'klarna_direct')) {
1337
+ _context14.next = 21;
1338
+ break;
1339
+ }
1340
+
1341
+ _context14.next = 20;
1342
+ return handleDirectKlarnaRedirectAction(request, cart, params, queryParams);
1343
+
1344
+ case 20:
1345
+ result = _context14.sent;
1346
+
1347
+ case 21:
1299
1348
  if (result) {
1300
- _context14.next = 19;
1349
+ _context14.next = 25;
1301
1350
  break;
1302
1351
  }
1303
1352
 
1304
1353
  return _context14.abrupt("return");
1305
1354
 
1306
- case 19:
1355
+ case 25:
1307
1356
  if (!result.error) {
1308
- _context14.next = 23;
1357
+ _context14.next = 29;
1309
1358
  break;
1310
1359
  }
1311
1360
 
1312
1361
  return _context14.abrupt("return", onError(result.error));
1313
1362
 
1314
- case 23:
1363
+ case 29:
1315
1364
  return _context14.abrupt("return", onSuccess(result));
1316
1365
 
1317
- case 24:
1366
+ case 30:
1318
1367
  case "end":
1319
1368
  return _context14.stop();
1320
1369
  }
@@ -1477,6 +1526,109 @@ function _handlePaysafecardRedirectAction() {
1477
1526
  return _handlePaysafecardRedirectAction.apply(this, arguments);
1478
1527
  }
1479
1528
 
1529
+ function handleDirectKlarnaRedirectAction(_x37, _x38, _x39, _x40) {
1530
+ return _handleDirectKlarnaRedirectAction.apply(this, arguments);
1531
+ }
1532
+
1533
+ function _handleDirectKlarnaRedirectAction() {
1534
+ _handleDirectKlarnaRedirectAction = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee17(request, cart, params, queryParams) {
1535
+ var authorization_token;
1536
+ return _regenerator["default"].wrap(function _callee17$(_context17) {
1537
+ while (1) {
1538
+ switch (_context17.prev = _context17.next) {
1539
+ case 0:
1540
+ authorization_token = queryParams.authorization_token;
1541
+
1542
+ if (authorization_token) {
1543
+ _context17.next = 3;
1544
+ break;
1545
+ }
1546
+
1547
+ return _context17.abrupt("return", {
1548
+ error: {
1549
+ message: 'We are unable to authenticate your payment method. Please choose a different payment method and try again.'
1550
+ }
1551
+ });
1552
+
1553
+ case 3:
1554
+ _context17.next = 5;
1555
+ return cartApi.methods(request, options).update({
1556
+ billing: {
1557
+ method: 'klarna',
1558
+ klarna: {
1559
+ token: authorization_token
1560
+ }
1561
+ }
1562
+ });
1563
+
1564
+ case 5:
1565
+ return _context17.abrupt("return", {
1566
+ success: true
1567
+ });
1568
+
1569
+ case 6:
1570
+ case "end":
1571
+ return _context17.stop();
1572
+ }
1573
+ }
1574
+ }, _callee17);
1575
+ }));
1576
+ return _handleDirectKlarnaRedirectAction.apply(this, arguments);
1577
+ }
1578
+
1579
+ function getTotalsDueRemaining(cart) {
1580
+ var grand_total = cart.grand_total,
1581
+ account = cart.account,
1582
+ account_credit_amount = cart.account_credit_amount,
1583
+ giftcards = cart.giftcards;
1584
+ var totalDue = grand_total;
1585
+ var totalRemaining = 0;
1586
+ var totalRemainingGiftcard = 0;
1587
+ var totalRemainingAccount = 0;
1588
+
1589
+ if (giftcards && giftcards.length > 0) {
1590
+ var _iterator = _createForOfIteratorHelper(giftcards),
1591
+ _step;
1592
+
1593
+ try {
1594
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
1595
+ var gc = _step.value;
1596
+ totalDue -= gc.amount;
1597
+ }
1598
+ } catch (err) {
1599
+ _iterator.e(err);
1600
+ } finally {
1601
+ _iterator.f();
1602
+ }
1603
+
1604
+ if (totalDue < 0) {
1605
+ totalRemainingGiftcard = -totalDue;
1606
+ }
1607
+ }
1608
+
1609
+ var accountCreditAmount = typeof account_credit_amount === 'number' ? account_credit_amount : account && account.balance;
1610
+
1611
+ if (accountCreditAmount > 0) {
1612
+ totalDue -= accountCreditAmount;
1613
+
1614
+ if (totalDue < 0) {
1615
+ totalRemainingAccount = -totalDue - totalRemainingGiftcard;
1616
+ }
1617
+ }
1618
+
1619
+ if (totalDue < 0) {
1620
+ totalRemaining = -totalDue;
1621
+ totalDue = 0;
1622
+ }
1623
+
1624
+ return {
1625
+ totalDue: totalDue,
1626
+ totalRemaining: totalRemaining,
1627
+ totalRemainingGiftcard: totalRemainingGiftcard,
1628
+ totalRemainingAccount: totalRemainingAccount
1629
+ };
1630
+ }
1631
+
1480
1632
  module.exports = {
1481
1633
  methods: methods
1482
1634
  };
@@ -0,0 +1,143 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+
5
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
6
+
7
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
8
+
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+
11
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
12
+
13
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
14
+
15
+ var _require = require('lodash'),
16
+ map = _require.map,
17
+ get = _require.get,
18
+ reduce = _require.reduce,
19
+ toNumber = _require.toNumber;
20
+
21
+ var addressFieldsMap = {
22
+ given_name: 'first_name',
23
+ family_name: 'last_name',
24
+ city: 'city',
25
+ country: 'country',
26
+ phone: 'phone',
27
+ postal_code: 'zip',
28
+ street_address: 'address1',
29
+ street_address2: 'address2',
30
+ region: 'state'
31
+ };
32
+
33
+ var mapFields = function mapFields(fieldsMap, data) {
34
+ return reduce(fieldsMap, function (acc, srcKey, destKey) {
35
+ var value = data[srcKey];
36
+
37
+ if (value) {
38
+ acc[destKey] = value;
39
+ }
40
+
41
+ return acc;
42
+ }, {});
43
+ };
44
+
45
+ var mapAddressFields = function mapAddressFields(cart, addressField) {
46
+ return _objectSpread(_objectSpread({}, mapFields(addressFieldsMap, cart[addressField])), {}, {
47
+ email: get(cart, 'account.email')
48
+ });
49
+ };
50
+
51
+ function getOrderLines(cart) {
52
+ var items = map(cart.items, function (item) {
53
+ return {
54
+ type: 'physical',
55
+ name: get(item, 'product.name'),
56
+ reference: get(item, 'product.sku') || get(item, 'product.slug'),
57
+ quantity: item.quantity,
58
+ unit_price: Math.round(toNumber(item.price - item.discount_each) * 100),
59
+ total_amount: Math.round(toNumber(item.price_total - item.discount_total) * 100),
60
+ tax_rate: 0,
61
+ total_tax_amount: 0
62
+ };
63
+ });
64
+ var tax = get(cart, 'tax_included_total');
65
+ var taxAmount = toNumber(tax) * 100;
66
+
67
+ if (tax) {
68
+ items.push({
69
+ type: 'sales_tax',
70
+ name: 'Taxes',
71
+ quantity: 1,
72
+ unit_price: taxAmount,
73
+ total_amount: taxAmount,
74
+ tax_rate: 0,
75
+ total_tax_amount: 0
76
+ });
77
+ }
78
+
79
+ var shipping = get(cart, 'shipping', {});
80
+ var shippingTotal = get(cart, 'shipment_total', {});
81
+ var shippingAmount = toNumber(shippingTotal) * 100;
82
+
83
+ if (shipping.price) {
84
+ items.push({
85
+ type: 'shipping_fee',
86
+ name: shipping.service_name,
87
+ quantity: 1,
88
+ unit_price: shippingAmount,
89
+ total_amount: shippingAmount,
90
+ tax_rate: 0,
91
+ total_tax_amount: 0
92
+ });
93
+ }
94
+
95
+ return items;
96
+ }
97
+
98
+ function createKlarnaSession(_x, _x2) {
99
+ return _createKlarnaSession.apply(this, arguments);
100
+ }
101
+
102
+ function _createKlarnaSession() {
103
+ _createKlarnaSession = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(cart, createIntent) {
104
+ var returnUrl, successUrl;
105
+ return _regenerator["default"].wrap(function _callee$(_context) {
106
+ while (1) {
107
+ switch (_context.prev = _context.next) {
108
+ case 0:
109
+ returnUrl = "".concat(window.location.origin).concat(window.location.pathname, "?gateway=klarna_direct&sid={{session_id}}");
110
+ successUrl = "".concat(returnUrl, "&authorization_token={{authorization_token}}");
111
+ return _context.abrupt("return", createIntent({
112
+ gateway: 'klarna',
113
+ intent: {
114
+ locale: get(cart, 'settings.locale') || 'en-US',
115
+ purchase_country: get(cart, 'billing.country') || get(cart, 'shipping.country'),
116
+ purchase_currency: cart.currency,
117
+ billing_address: mapAddressFields(cart, 'billing'),
118
+ shipping_address: mapAddressFields(cart, 'shipping'),
119
+ order_amount: Math.round(get(cart, 'grand_total', 0) * 100),
120
+ order_lines: JSON.stringify(getOrderLines(cart)),
121
+ merchant_urls: {
122
+ success: successUrl,
123
+ back: returnUrl,
124
+ cancel: returnUrl,
125
+ error: returnUrl,
126
+ failure: returnUrl
127
+ }
128
+ }
129
+ }));
130
+
131
+ case 3:
132
+ case "end":
133
+ return _context.stop();
134
+ }
135
+ }
136
+ }, _callee);
137
+ }));
138
+ return _createKlarnaSession.apply(this, arguments);
139
+ }
140
+
141
+ module.exports = {
142
+ createKlarnaSession: createKlarnaSession
143
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "swell-js",
3
- "version": "3.12.0",
3
+ "version": "3.13.0",
4
4
  "description": "Swell JS library for client-side stores",
5
5
  "repository": {
6
6
  "type": "git",
package/src/currency.js CHANGED
@@ -62,9 +62,11 @@ function methods(request, opt) {
62
62
  const formatRate = params.rate || rate;
63
63
  const formatLocale = params.locale || this.locale;
64
64
  const formatDecimals = typeof params.decimals === 'number' ? params.decimals : decimals;
65
+ const { convert = true } = params;
65
66
 
66
67
  let formatAmount = amount;
67
68
  if (
69
+ convert &&
68
70
  (type === 'display' || params.rate) &&
69
71
  typeof formatAmount === 'number' &&
70
72
  typeof formatRate === 'number'
@@ -158,6 +158,13 @@ describe('currency', () => {
158
158
  expect(formatted).toEqual('$0.77');
159
159
  });
160
160
 
161
+ it('should not convert amount by selected display currency when convert flag is false', async () => {
162
+ await api.currency.select('USD');
163
+ const formatted = api.currency.format(1, { convert: false });
164
+
165
+ expect(formatted).toEqual('$1.00');
166
+ });
167
+
161
168
  it('should convert amount by selected display currency with rounding (nearest whole)', async () => {
162
169
  const config = api.currency.list().find((curr) => curr.code === 'CNY');
163
170
  config.round = 'nearest';
package/src/payment.js CHANGED
@@ -22,6 +22,7 @@ const {
22
22
  getQuickpayCardDetais,
23
23
  } = require('./utils/quickpay');
24
24
  const { createPaysafecardPayment } = require('./utils/paysafecard');
25
+ const { createKlarnaSession } = require('./utils/klarna');
25
26
 
26
27
  const LOADING_SCRIPTS = {};
27
28
  const CARD_ELEMENTS = {};
@@ -223,7 +224,7 @@ const loadScript = async (id, src) => {
223
224
  async function stripeElements(request, payMethods, params) {
224
225
  const { publishable_key } = payMethods.card;
225
226
  const stripe = window.Stripe(publishable_key);
226
- const elements = stripe.elements();
227
+ const elements = stripe.elements(params.config);
227
228
  const createElement = (type) => {
228
229
  const elementParams = get(params, `card[${type}]`) || params.card || params.ideal;
229
230
  const elementOptions = elementParams.options || {};
@@ -269,6 +270,12 @@ async function payPalButton(request, cart, payMethods, params) {
269
270
  return isFunction(successHandler) && successHandler();
270
271
  };
271
272
 
273
+ const { totalDue } = getTotalsDueRemaining(cart);
274
+
275
+ if (!(totalDue > 0)) {
276
+ throw new Error('Invalid PayPal button amount. Value should be greater than zero.');
277
+ }
278
+
272
279
  paypal
273
280
  .Buttons(
274
281
  {
@@ -287,7 +294,7 @@ async function payPalButton(request, cart, payMethods, params) {
287
294
  purchase_units: [
288
295
  {
289
296
  amount: {
290
- value: cart.grand_total,
297
+ value: +totalDue.toFixed(2),
291
298
  currency_code: cart.currency,
292
299
  },
293
300
  },
@@ -304,9 +311,11 @@ async function payPalButton(request, cart, payMethods, params) {
304
311
  'purchase_units[0].payments.authorizations[0].id',
305
312
  );
306
313
  return cartApi.methods(request).update({
307
- account: {
308
- email: payer.email_address,
309
- },
314
+ ...(!cart.account_logged_in && {
315
+ account: {
316
+ email: payer.email_address,
317
+ },
318
+ }),
310
319
  billing: { method: 'paypal', paypal: { authorization_id: authorizationID } },
311
320
  shipping: {
312
321
  name: shipping.name.full_name,
@@ -526,7 +535,12 @@ async function paymentTokenize(request, params, payMethods, cart) {
526
535
  }
527
536
  }
528
537
  } else if (params.klarna && payMethods.klarna) {
529
- if (payMethods.card && payMethods.card.gateway === 'stripe') {
538
+ if (payMethods.klarna.gateway === 'klarna') {
539
+ const session = await createKlarnaSession(cart, methods(request).createIntent).catch((err) =>
540
+ onError(err),
541
+ );
542
+ return session && window.location.replace(session.redirect_url);
543
+ } else if (payMethods.card && payMethods.card.gateway === 'stripe') {
530
544
  if (!window.Stripe) {
531
545
  await loadScript('stripe-js', 'https://js.stripe.com/v3/');
532
546
  }
@@ -598,14 +612,20 @@ async function paymentTokenize(request, params, payMethods, cart) {
598
612
 
599
613
  async function handleRedirect(request, params, cart) {
600
614
  const onError = (error) => {
601
- const errorHandler = get(params, 'card.onError') || get(params, 'paysafecard.onError');
615
+ const errorHandler =
616
+ get(params, 'card.onError') ||
617
+ get(params, 'paysafecard.onError') ||
618
+ get(params, 'klarna.onError');
602
619
  if (isFunction(errorHandler)) {
603
620
  return errorHandler(error);
604
621
  }
605
622
  throw new Error(error.message);
606
623
  };
607
624
  const onSuccess = (result) => {
608
- const successHandler = get(params, 'card.onSuccess') || get(params, 'paysafecard.onSuccess');
625
+ const successHandler =
626
+ get(params, 'card.onSuccess') ||
627
+ get(params, 'paysafecard.onSuccess') ||
628
+ get(params, 'klarna.onSuccess');
609
629
  if (isFunction(successHandler)) {
610
630
  return successHandler(result);
611
631
  }
@@ -620,6 +640,8 @@ async function handleRedirect(request, params, cart) {
620
640
  result = await handleQuickpayRedirectAction(request, cart, params, queryParams);
621
641
  } else if (gateway === 'paysafecard') {
622
642
  result = await handlePaysafecardRedirectAction(request, cart, params, queryParams);
643
+ } else if (gateway === 'klarna_direct') {
644
+ result = await handleDirectKlarnaRedirectAction(request, cart, params, queryParams);
623
645
  }
624
646
 
625
647
  if (!result) {
@@ -695,6 +717,63 @@ async function handlePaysafecardRedirectAction(request, cart) {
695
717
  }
696
718
  }
697
719
 
720
+ async function handleDirectKlarnaRedirectAction(request, cart, params, queryParams) {
721
+ const { authorization_token } = queryParams;
722
+
723
+ if (!authorization_token) {
724
+ return {
725
+ error: {
726
+ message:
727
+ 'We are unable to authenticate your payment method. Please choose a different payment method and try again.',
728
+ },
729
+ };
730
+ }
731
+
732
+ await cartApi.methods(request, options).update({
733
+ billing: {
734
+ method: 'klarna',
735
+ klarna: {
736
+ token: authorization_token,
737
+ },
738
+ },
739
+ });
740
+ return { success: true };
741
+ }
742
+
743
+ function getTotalsDueRemaining(cart) {
744
+ const { grand_total, account, account_credit_amount, giftcards } = cart;
745
+
746
+ let totalDue = grand_total;
747
+ let totalRemaining = 0;
748
+ let totalRemainingGiftcard = 0;
749
+ let totalRemainingAccount = 0;
750
+
751
+ if (giftcards && giftcards.length > 0) {
752
+ for (let gc of giftcards) {
753
+ totalDue -= gc.amount;
754
+ }
755
+ if (totalDue < 0) {
756
+ totalRemainingGiftcard = -totalDue;
757
+ }
758
+ }
759
+
760
+ const accountCreditAmount =
761
+ typeof account_credit_amount === 'number' ? account_credit_amount : account && account.balance;
762
+ if (accountCreditAmount > 0) {
763
+ totalDue -= accountCreditAmount;
764
+ if (totalDue < 0) {
765
+ totalRemainingAccount = -totalDue - totalRemainingGiftcard;
766
+ }
767
+ }
768
+
769
+ if (totalDue < 0) {
770
+ totalRemaining = -totalDue;
771
+ totalDue = 0;
772
+ }
773
+
774
+ return { totalDue, totalRemaining, totalRemainingGiftcard, totalRemainingAccount };
775
+ }
776
+
698
777
  module.exports = {
699
778
  methods,
700
779
  };
@@ -0,0 +1,104 @@
1
+ const { map, get, reduce, toNumber } = require('lodash');
2
+
3
+ const addressFieldsMap = {
4
+ given_name: 'first_name',
5
+ family_name: 'last_name',
6
+ city: 'city',
7
+ country: 'country',
8
+ phone: 'phone',
9
+ postal_code: 'zip',
10
+ street_address: 'address1',
11
+ street_address2: 'address2',
12
+ region: 'state',
13
+ };
14
+
15
+ const mapFields = (fieldsMap, data) =>
16
+ reduce(
17
+ fieldsMap,
18
+ (acc, srcKey, destKey) => {
19
+ const value = data[srcKey];
20
+ if (value) {
21
+ acc[destKey] = value;
22
+ }
23
+ return acc;
24
+ },
25
+ {},
26
+ );
27
+
28
+ const mapAddressFields = (cart, addressField) => ({
29
+ ...mapFields(addressFieldsMap, cart[addressField]),
30
+ email: get(cart, 'account.email'),
31
+ });
32
+
33
+ function getOrderLines(cart) {
34
+ const items = map(cart.items, (item) => ({
35
+ type: 'physical',
36
+ name: get(item, 'product.name'),
37
+ reference: get(item, 'product.sku') || get(item, 'product.slug'),
38
+ quantity: item.quantity,
39
+ unit_price: Math.round(toNumber(item.price - item.discount_each) * 100),
40
+ total_amount: Math.round(toNumber(item.price_total - item.discount_total) * 100),
41
+ tax_rate: 0,
42
+ total_tax_amount: 0,
43
+ }));
44
+
45
+ const tax = get(cart, 'tax_included_total');
46
+ const taxAmount = toNumber(tax) * 100;
47
+ if (tax) {
48
+ items.push({
49
+ type: 'sales_tax',
50
+ name: 'Taxes',
51
+ quantity: 1,
52
+ unit_price: taxAmount,
53
+ total_amount: taxAmount,
54
+ tax_rate: 0,
55
+ total_tax_amount: 0,
56
+ });
57
+ }
58
+
59
+ const shipping = get(cart, 'shipping', {});
60
+ const shippingTotal = get(cart, 'shipment_total', {});
61
+ const shippingAmount = toNumber(shippingTotal) * 100;
62
+ if (shipping.price) {
63
+ items.push({
64
+ type: 'shipping_fee',
65
+ name: shipping.service_name,
66
+ quantity: 1,
67
+ unit_price: shippingAmount,
68
+ total_amount: shippingAmount,
69
+ tax_rate: 0,
70
+ total_tax_amount: 0,
71
+ });
72
+ }
73
+
74
+ return items;
75
+ }
76
+
77
+ async function createKlarnaSession(cart, createIntent) {
78
+ const returnUrl = `${window.location.origin}${window.location.pathname}?gateway=klarna_direct&sid={{session_id}}`;
79
+ const successUrl = `${returnUrl}&authorization_token={{authorization_token}}`;
80
+
81
+ return createIntent({
82
+ gateway: 'klarna',
83
+ intent: {
84
+ locale: get(cart, 'settings.locale') || 'en-US',
85
+ purchase_country: get(cart, 'billing.country') || get(cart, 'shipping.country'),
86
+ purchase_currency: cart.currency,
87
+ billing_address: mapAddressFields(cart, 'billing'),
88
+ shipping_address: mapAddressFields(cart, 'shipping'),
89
+ order_amount: Math.round(get(cart, 'grand_total', 0) * 100),
90
+ order_lines: JSON.stringify(getOrderLines(cart)),
91
+ merchant_urls: {
92
+ success: successUrl,
93
+ back: returnUrl,
94
+ cancel: returnUrl,
95
+ error: returnUrl,
96
+ failure: returnUrl,
97
+ },
98
+ },
99
+ });
100
+ }
101
+
102
+ module.exports = {
103
+ createKlarnaSession,
104
+ };
@@ -113,6 +113,7 @@ class Sidebar extends React.Component {
113
113
  'Paysafecard',
114
114
  'Square',
115
115
  'Braintree',
116
+ 'Klarna',
116
117
  ],
117
118
  },
118
119
  ].map((item, index) =>
@@ -0,0 +1,101 @@
1
+ import React from 'react';
2
+ import { connect } from 'react-redux';
3
+ import { compose } from 'recompose';
4
+ import { withStyles } from '@material-ui/core/styles';
5
+ import { Card, CardContent, Button } from '@material-ui/core';
6
+ import Info from '../../components/info';
7
+
8
+ const styles = {
9
+ root: {
10
+ display: 'flex',
11
+ flexDirection: 'column',
12
+ },
13
+ input: {
14
+ margin: 20,
15
+ },
16
+ card: {
17
+ marginBottom: 20,
18
+ overflow: 'visible',
19
+ },
20
+ submitContainer: {
21
+ display: 'flex',
22
+ justifyContent: 'space-around',
23
+ },
24
+ button: {
25
+ width: '30%',
26
+ },
27
+ };
28
+
29
+ class Klarna extends React.Component {
30
+ constructor(props) {
31
+ super(props);
32
+ this.state = {
33
+ tokenized: false,
34
+ };
35
+ }
36
+
37
+ componentDidMount() {
38
+ const { api, onError } = this.props;
39
+ api.payment.handleRedirect({
40
+ klarna: { onError, onSuccess: () => this.setState({ tokenized: true }) },
41
+ });
42
+ }
43
+
44
+ onClickTokenize(event) {
45
+ const { api, onError } = this.props;
46
+
47
+ event.preventDefault();
48
+ api.payment.tokenize({
49
+ klarna: {
50
+ onError,
51
+ },
52
+ });
53
+ }
54
+
55
+ render() {
56
+ const {
57
+ classes,
58
+ onOrderSubmit,
59
+ cart: { billing: { method, klarna } = {} },
60
+ } = this.props;
61
+ const { tokenized } = this.state;
62
+
63
+ return (
64
+ <div className={classes.root}>
65
+ <Card classes={{ root: classes.card }}>
66
+ <CardContent>
67
+ {tokenized && <Info title="Billing" source={{ method, klarna }} />}
68
+ <div className={classes.submitContainer}>
69
+ <Button
70
+ id="stripe-submit-button"
71
+ variant="contained"
72
+ color="primary"
73
+ size="small"
74
+ classes={{ root: classes.button }}
75
+ onClick={this.onClickTokenize.bind(this)}
76
+ >
77
+ Tokenize
78
+ </Button>
79
+ <Button
80
+ variant="contained"
81
+ color="secondary"
82
+ size="small"
83
+ disabled={!tokenized}
84
+ classes={{ root: classes.button }}
85
+ onClick={onOrderSubmit}
86
+ >
87
+ Submit
88
+ </Button>
89
+ </div>
90
+ </CardContent>
91
+ </Card>
92
+ </div>
93
+ );
94
+ }
95
+ }
96
+
97
+ const mapStateToProps = ({ api }) => ({
98
+ api,
99
+ });
100
+
101
+ export default compose(connect(mapStateToProps), withStyles(styles))(Klarna);
@@ -24,6 +24,7 @@ import StripeKlarna from './stripe-klarna';
24
24
  import StripeBancontact from './stripe-bancontact';
25
25
  import Quickpay from './quickpay';
26
26
  import Paysafecard from './paysafecard';
27
+ import Klarna from './klarna';
27
28
  import Info from '../../components/info';
28
29
 
29
30
  const styles = {
@@ -186,6 +187,15 @@ class Payment extends React.Component {
186
187
  onError={onError}
187
188
  />
188
189
  );
190
+ case 'klarna':
191
+ return (
192
+ <Klarna
193
+ cart={cart}
194
+ onCartUpdate={onCartUpdate}
195
+ onOrderSubmit={onOrderSubmit}
196
+ onError={onError}
197
+ />
198
+ );
189
199
  case 'square':
190
200
  return <Typography variant="h4">Coming soon</Typography>;
191
201
  case 'braintree':
@@ -1,8 +1,17 @@
1
- import React from 'react';
1
+ import React, { Fragment } from 'react';
2
2
  import { connect } from 'react-redux';
3
3
  import { compose } from 'recompose';
4
4
  import { withStyles } from '@material-ui/core/styles';
5
- import { Card, CardContent, Button } from '@material-ui/core';
5
+ import {
6
+ Card,
7
+ CardContent,
8
+ Button,
9
+ FormControl,
10
+ FormLabel,
11
+ RadioGroup,
12
+ FormControlLabel,
13
+ Radio,
14
+ } from '@material-ui/core';
6
15
 
7
16
  const styles = {
8
17
  root: {
@@ -29,29 +38,84 @@ class Stripe extends React.Component {
29
38
  super(props);
30
39
  this.state = {
31
40
  tokenized: false,
41
+ type: 'card',
42
+ font: 'default',
32
43
  };
44
+
45
+ this.onTokenize = this.onTokenize.bind(this);
46
+ this.onError = this.onError.bind(this);
47
+ this.onClickTokenize = this.onClickTokenize.bind(this);
48
+ this.onChangeType = this.onChangeType.bind(this);
49
+ this.onChangeFont = this.onChangeFont.bind(this);
33
50
  }
34
51
 
35
52
  componentDidMount() {
36
- const { api, onError } = this.props;
37
- api.payment.createElements({
38
- card: {
39
- options: {
40
- style: {
41
- base: {
42
- fontWeight: 500,
43
- fontSize: '16px',
44
- },
45
- },
46
- },
47
- onSuccess: () => {
48
- this.setState({ tokenized: true });
53
+ this.renderStripeElements();
54
+ }
55
+
56
+ componentDidUpdate() {
57
+ this.renderStripeElements();
58
+ }
59
+
60
+ renderStripeElements() {
61
+ const { type, font } = this.state;
62
+ const options = {
63
+ showIcon: true,
64
+ style: {
65
+ base: {
66
+ fontWeight: 500,
67
+ fontSize: '16px',
49
68
  },
50
- onError: (err) => onError(err.message),
69
+ },
70
+ };
71
+
72
+ switch (font) {
73
+ case 'audiowide':
74
+ options.style.base.fontFamily = 'Audiowide';
75
+ break;
76
+ case 'festive':
77
+ options.style.base.fontFamily = 'Festive';
78
+ break;
79
+ default:
80
+ break;
81
+ }
82
+
83
+ this.props.api.payment.createElements({
84
+ config: {
85
+ fonts: [
86
+ {
87
+ cssSrc: 'https://fonts.googleapis.com/css?family=Audiowide',
88
+ },
89
+ {
90
+ cssSrc: 'https://fonts.googleapis.com/css?family=Festive',
91
+ },
92
+ ],
93
+ },
94
+ card: {
95
+ ...(type === 'card'
96
+ ? {
97
+ options,
98
+ }
99
+ : {
100
+ separateElements: true,
101
+ cardNumber: { options },
102
+ cardExpiry: { options },
103
+ cardCvc: { options },
104
+ }),
105
+ onSuccess: this.onTokenize,
106
+ onError: this.onError,
51
107
  },
52
108
  });
53
109
  }
54
110
 
111
+ onTokenize() {
112
+ this.setState({ tokenized: true });
113
+ }
114
+
115
+ onError(err) {
116
+ this.props.onError(err.message);
117
+ }
118
+
55
119
  onClickTokenize(event) {
56
120
  const { api } = this.props;
57
121
 
@@ -59,15 +123,46 @@ class Stripe extends React.Component {
59
123
  api.payment.tokenize();
60
124
  }
61
125
 
126
+ onChangeType(event, type) {
127
+ this.setState({ type });
128
+ }
129
+
130
+ onChangeFont(event, font) {
131
+ this.setState({ font });
132
+ }
133
+
62
134
  render() {
63
135
  const { classes, onOrderSubmit } = this.props;
64
- const { tokenized } = this.state;
136
+ const { tokenized, type } = this.state;
65
137
 
66
138
  return (
67
139
  <div className={classes.root}>
68
140
  <Card classes={{ root: classes.card }}>
69
141
  <CardContent>
70
- <div id="card-element" className={classes.cardInput} />
142
+ <FormControl>
143
+ <FormLabel>Type</FormLabel>
144
+ <RadioGroup defaultValue="card" row onChange={this.onChangeType}>
145
+ <FormControlLabel value="card" control={<Radio />} label="Card" />
146
+ <FormControlLabel value="separate" control={<Radio />} label="Separate elements" />
147
+ </RadioGroup>
148
+ </FormControl>
149
+ <FormControl>
150
+ <FormLabel>Font</FormLabel>
151
+ <RadioGroup defaultValue="default" row onChange={this.onChangeFont}>
152
+ <FormControlLabel value="default" control={<Radio />} label="Default" />
153
+ <FormControlLabel value="audiowide" control={<Radio />} label="Audiowide" />
154
+ <FormControlLabel value="festive" control={<Radio />} label="Festive" />
155
+ </RadioGroup>
156
+ </FormControl>
157
+ {type === 'card' ? (
158
+ <div id="card-element" className={classes.cardInput} />
159
+ ) : (
160
+ <Fragment>
161
+ <div id="cardNumber-element" className={classes.cardInput} />
162
+ <div id="cardExpiry-element" className={classes.cardInput} />
163
+ <div id="cardCvc-element" className={classes.cardInput} />
164
+ </Fragment>
165
+ )}
71
166
  <div className={classes.submitContainer}>
72
167
  <Button
73
168
  id="stripe-submit-button"
@@ -75,7 +170,7 @@ class Stripe extends React.Component {
75
170
  color="primary"
76
171
  size="small"
77
172
  classes={{ root: classes.button }}
78
- onClick={this.onClickTokenize.bind(this)}
173
+ onClick={this.onClickTokenize}
79
174
  >
80
175
  Tokenize
81
176
  </Button>