swell-js 4.0.1 → 4.0.2

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.mjs CHANGED
@@ -135,7 +135,7 @@ const options = {
135
135
  };
136
136
 
137
137
  const api = {
138
- version: '4.0.1',
138
+ version: '4.0.2',
139
139
  options,
140
140
  request,
141
141
 
package/dist/payment.mjs CHANGED
@@ -740,6 +740,68 @@ async function createBancontactSource(stripe, cart) {
740
740
  return await stripe.createSource(sourceObject);
741
741
  }
742
742
 
743
+ function getPaymentRequestData(cart, params) {
744
+ const {
745
+ currency,
746
+ shipping,
747
+ items,
748
+ capture_total,
749
+ shipment_rating,
750
+ shipment_total,
751
+ tax_included_total,
752
+ settings,
753
+ } = cart;
754
+ const { price: shippingPrice, service_name } = shipping || {};
755
+ const { country, name } = settings || {};
756
+ const { require: { shipping: requireShipping } = {} } = params;
757
+
758
+ const stripeCurrency = currency.toLowerCase();
759
+ const displayItems = items.map((item) => ({
760
+ label: get(item, 'product.name', 'Unknown product'),
761
+ amount: stripeAmountByCurrency(
762
+ currency,
763
+ item.price_total - item.discount_total,
764
+ ),
765
+ }));
766
+
767
+ if (tax_included_total) {
768
+ displayItems.push({
769
+ label: 'Taxes',
770
+ amount: stripeAmountByCurrency(currency, tax_included_total),
771
+ });
772
+ }
773
+
774
+ if (shippingPrice && shipment_total) {
775
+ displayItems.push({
776
+ label: service_name,
777
+ amount: stripeAmountByCurrency(currency, shipment_total),
778
+ });
779
+ }
780
+
781
+ let shippingOptions;
782
+ const services = get(shipment_rating, 'services');
783
+ if (Array.isArray(services) && services.length > 0) {
784
+ shippingOptions = services.map((service) => ({
785
+ id: service.id,
786
+ label: service.name,
787
+ detail: service.description,
788
+ amount: stripeAmountByCurrency(currency, service.price),
789
+ }));
790
+ }
791
+
792
+ return {
793
+ country: country || 'US',
794
+ currency: stripeCurrency,
795
+ total: {
796
+ label: name || 'Swell store',
797
+ amount: stripeAmountByCurrency(currency, capture_total),
798
+ pending: true,
799
+ },
800
+ displayItems,
801
+ ...(requireShipping && { shippingOptions }),
802
+ };
803
+ }
804
+
743
805
  function stripeAmountByCurrency(currency, amount) {
744
806
  const zeroDecimalCurrencies = [
745
807
  'BIF', // Burundian Franc
@@ -1209,19 +1271,6 @@ class StripeKlarnaPayment extends Payment {
1209
1271
  }
1210
1272
  }
1211
1273
 
1212
- const VERSION$1 = '2018-10-31';
1213
- const API_VERSION$1 = 2;
1214
- const API_MINOR_VERSION$1 = 0;
1215
- const ALLOWED_CARD_AUTH_METHODS$1 = ['PAN_ONLY', 'CRYPTOGRAM_3DS'];
1216
- const ALLOWED_CARD_NETWORKS$1 = [
1217
- 'AMEX',
1218
- 'DISCOVER',
1219
- 'INTERAC',
1220
- 'JCB',
1221
- 'MASTERCARD',
1222
- 'VISA',
1223
- ];
1224
-
1225
1274
  class StripeGooglePayment extends Payment {
1226
1275
  constructor(request, options, params, methods) {
1227
1276
  if (!methods.card) {
@@ -1237,210 +1286,210 @@ class StripeGooglePayment extends Payment {
1237
1286
  }
1238
1287
 
1239
1288
  get scripts() {
1240
- return ['google-pay'];
1241
- }
1242
-
1243
- get google() {
1244
- if (!window.google) {
1245
- throw new LibraryNotLoadedError('Google');
1246
- }
1247
-
1248
- return window.google;
1289
+ return ['stripe-js'];
1249
1290
  }
1250
1291
 
1251
- get googleClient() {
1252
- if (!StripeGooglePayment.googleClient) {
1253
- if (this.google) {
1254
- this.googleClient = new this.google.payments.api.PaymentsClient({
1255
- environment: isLiveMode(this.method.mode) ? 'PRODUCTION' : 'TEST',
1256
- });
1292
+ get stripe() {
1293
+ if (!StripeGooglePayment.stripe) {
1294
+ if (window.Stripe) {
1295
+ this.stripe = window.Stripe(this.method.publishable_key);
1257
1296
  }
1258
1297
 
1259
- if (!StripeGooglePayment.googleClient) {
1260
- throw new LibraryNotLoadedError('Google client');
1298
+ if (!StripeGooglePayment.stripe) {
1299
+ throw new LibraryNotLoadedError('Stripe');
1261
1300
  }
1262
1301
  }
1263
1302
 
1264
- return StripeGooglePayment.googleClient;
1265
- }
1266
-
1267
- set googleClient(googleClient) {
1268
- StripeGooglePayment.googleClient = googleClient;
1269
- }
1270
-
1271
- get tokenizationSpecification() {
1272
- const publishableKey = this.method.publishable_key;
1273
-
1274
- if (!publishableKey) {
1275
- throw new Error('Stripe publishable key is not defined');
1276
- }
1277
-
1278
- return {
1279
- type: 'PAYMENT_GATEWAY',
1280
- parameters: {
1281
- gateway: 'stripe',
1282
- 'stripe:version': VERSION$1,
1283
- 'stripe:publishableKey': publishableKey,
1284
- },
1285
- };
1286
- }
1287
-
1288
- get cardPaymentMethod() {
1289
- return {
1290
- type: 'CARD',
1291
- tokenizationSpecification: this.tokenizationSpecification,
1292
- parameters: {
1293
- allowedAuthMethods: ALLOWED_CARD_AUTH_METHODS$1,
1294
- allowedCardNetworks: ALLOWED_CARD_NETWORKS$1,
1295
- billingAddressRequired: true,
1296
- billingAddressParameters: {
1297
- format: 'FULL',
1298
- phoneNumberRequired: true,
1299
- },
1300
- },
1301
- };
1303
+ return StripeGooglePayment.stripe;
1302
1304
  }
1303
1305
 
1304
- get allowedPaymentMethods() {
1305
- return [this.cardPaymentMethod];
1306
+ set stripe(stripe) {
1307
+ StripeGooglePayment.stripe = stripe;
1306
1308
  }
1307
1309
 
1308
1310
  async createElements(cart) {
1309
- const {
1310
- elementId = 'googlepay-button',
1311
- locale = 'en',
1312
- style: { color = 'black', type = 'buy', sizeMode = 'fill' } = {},
1313
- } = this.params;
1314
-
1315
- if (!this.method.merchant_id) {
1316
- throw new Error('Google merchant ID is not defined');
1317
- }
1311
+ const { elementId = 'googlepay-button', classes = {} } = this.params;
1318
1312
 
1319
1313
  this.setElementContainer(elementId);
1320
1314
  await this.loadScripts(this.scripts);
1321
1315
 
1322
- const isReadyToPay = await this.googleClient.isReadyToPay({
1323
- apiVersion: API_VERSION$1,
1324
- apiVersionMinor: API_MINOR_VERSION$1,
1325
- allowedPaymentMethods: this.allowedPaymentMethods,
1326
- existingPaymentMethodRequired: true,
1327
- });
1316
+ const paymentRequest = this._createPaymentRequest(cart);
1317
+ const canMakePayment = await paymentRequest.canMakePayment();
1328
1318
 
1329
- if (!isReadyToPay.result) {
1319
+ if (!canMakePayment?.googlePay) {
1330
1320
  throw new Error(
1331
1321
  'This device is not capable of making Google Pay payments',
1332
1322
  );
1333
1323
  }
1334
1324
 
1335
- const paymentRequestData = this._createPaymentRequestData(cart);
1336
-
1337
- this.element = this.googleClient.createButton({
1338
- buttonColor: color,
1339
- buttonType: type,
1340
- buttonSizeMode: sizeMode,
1341
- buttonLocale: locale,
1342
- onClick: this._onClick.bind(this, paymentRequestData),
1325
+ this.element = this.stripe.elements().create('paymentRequestButton', {
1326
+ paymentRequest,
1327
+ style: {
1328
+ paymentRequestButton: this._getButtonStyles(),
1329
+ },
1330
+ classes,
1343
1331
  });
1344
1332
  }
1345
1333
 
1346
1334
  mountElements() {
1347
- const { classes = {} } = this.params;
1348
- const container = this.elementContainer;
1335
+ this.element.mount(`#${this.elementContainer.id}`);
1336
+ }
1349
1337
 
1350
- container.appendChild(this.element);
1338
+ _createPaymentRequest(cart) {
1339
+ const { require: { name, email, shipping, phone } = {} } = this.params;
1351
1340
 
1352
- if (classes.base) {
1353
- container.classList.add(classes.base);
1354
- }
1341
+ const paymentRequest = this.stripe.paymentRequest({
1342
+ requestPayerName: Boolean(name),
1343
+ requestPayerEmail: Boolean(email),
1344
+ requestPayerPhone: Boolean(phone),
1345
+ requestShipping: Boolean(shipping),
1346
+ disableWallets: ['applePay', 'browserCard', 'link'],
1347
+ ...getPaymentRequestData(cart, this.params),
1348
+ });
1349
+
1350
+ paymentRequest.on(
1351
+ 'shippingaddresschange',
1352
+ this._onShippingAddressChange.bind(this),
1353
+ );
1354
+ paymentRequest.on(
1355
+ 'shippingoptionchange',
1356
+ this._onShippingOptionChange.bind(this),
1357
+ );
1358
+ paymentRequest.on('paymentmethod', this._onPaymentMethod.bind(this));
1359
+
1360
+ return paymentRequest;
1355
1361
  }
1356
1362
 
1357
- _createPaymentRequestData(cart) {
1358
- const {
1359
- settings: { name },
1360
- capture_total,
1361
- currency,
1362
- } = cart;
1363
- const { require: { email, shipping, phone } = {} } = this.params;
1363
+ async _onShippingAddressChange(event) {
1364
+ const { shippingAddress, updateWith } = event;
1365
+ const shipping = this._mapShippingAddress(shippingAddress);
1366
+ const cart = await this.updateCart({
1367
+ shipping: { ...shipping, service: null },
1368
+ shipment_rating: null,
1369
+ });
1364
1370
 
1365
- return {
1366
- apiVersion: API_VERSION$1,
1367
- apiVersionMinor: API_MINOR_VERSION$1,
1368
- transactionInfo: {
1369
- currencyCode: currency,
1370
- totalPrice: capture_total.toString(),
1371
- totalPriceStatus: 'ESTIMATED',
1372
- },
1373
- allowedPaymentMethods: this.allowedPaymentMethods,
1374
- emailRequired: Boolean(email),
1375
- shippingAddressRequired: Boolean(shipping),
1376
- shippingAddressParameters: {
1377
- phoneNumberRequired: Boolean(phone),
1378
- },
1379
- merchantInfo: {
1380
- merchantName: name,
1381
- merchantId: this.method.merchant_id,
1382
- },
1383
- };
1371
+ if (cart) {
1372
+ updateWith({
1373
+ status: 'success',
1374
+ ...getPaymentRequestData(cart, this.params),
1375
+ });
1376
+ } else {
1377
+ updateWith({ status: 'invalid_shipping_address' });
1378
+ }
1384
1379
  }
1385
1380
 
1386
- async _onClick(paymentRequestData) {
1387
- try {
1388
- const paymentData = await this.googleClient.loadPaymentData(
1389
- paymentRequestData,
1390
- );
1381
+ async _onShippingOptionChange(event) {
1382
+ const { shippingOption, updateWith } = event;
1383
+ const cart = await this.updateCart({
1384
+ shipping: { service: shippingOption.id },
1385
+ });
1391
1386
 
1392
- if (paymentData) {
1393
- await this._submitPayment(paymentData);
1394
- }
1395
- } catch (error) {
1396
- this.onError(error);
1387
+ if (cart) {
1388
+ updateWith({
1389
+ status: 'success',
1390
+ ...getPaymentRequestData(cart, this.params),
1391
+ });
1392
+ } else {
1393
+ updateWith({ status: 'fail' });
1397
1394
  }
1398
1395
  }
1399
1396
 
1400
- async _submitPayment(paymentData) {
1401
- const { require: { shipping: requireShipping } = {} } = this.params;
1402
- const { email, shippingAddress, paymentMethodData } = paymentData;
1397
+ async _onPaymentMethod(event) {
1403
1398
  const {
1404
- info: { billingAddress },
1405
- tokenizationData,
1406
- } = paymentMethodData;
1407
- const token = JSON.parse(tokenizationData.token);
1408
- const { card } = token;
1399
+ payerEmail,
1400
+ paymentMethod: { id: paymentMethod, card, billing_details },
1401
+ shippingAddress,
1402
+ shippingOption,
1403
+ complete,
1404
+ } = event;
1405
+ const { require: { shipping: requireShipping } = {} } = this.params;
1409
1406
 
1410
1407
  await this.updateCart({
1411
1408
  account: {
1412
- email,
1409
+ email: payerEmail,
1413
1410
  },
1411
+ ...(requireShipping && {
1412
+ shipping: {
1413
+ ...this._mapShippingAddress(shippingAddress),
1414
+ service: shippingOption.id,
1415
+ },
1416
+ }),
1414
1417
  billing: {
1418
+ ...this._mapBillingAddress(billing_details),
1415
1419
  method: 'card',
1416
1420
  card: {
1417
- token: token.id,
1421
+ gateway: 'stripe',
1422
+ token: paymentMethod,
1418
1423
  brand: card.brand,
1419
- last4: card.last4,
1420
1424
  exp_month: card.exp_month,
1421
1425
  exp_year: card.exp_year,
1422
- gateway: 'stripe',
1426
+ last4: card.last4,
1427
+ address_check: card.checks.address_line1_check,
1428
+ zip_check: card.checks.address_postal_code_check,
1429
+ cvc_check: card.checks.cvc_check,
1423
1430
  },
1424
- ...this._mapAddress(billingAddress),
1425
1431
  },
1426
- ...(requireShipping && {
1427
- shipping: this._mapAddress(shippingAddress),
1428
- }),
1429
1432
  });
1430
1433
 
1434
+ complete('success');
1435
+
1431
1436
  this.onSuccess();
1432
1437
  }
1433
1438
 
1434
- _mapAddress(address) {
1439
+ // Provides backward compatibility with Google Pay button options
1440
+ // https://developers.google.com/pay/api/web/reference/request-objects#ButtonOptions
1441
+ _getButtonStyles() {
1442
+ let { style: { color = 'dark', type = 'default', height = '45px' } = {} } =
1443
+ this.params;
1444
+
1445
+ switch (color) {
1446
+ case 'white':
1447
+ color = 'light';
1448
+ break;
1449
+ default:
1450
+ color = 'dark';
1451
+ break;
1452
+ }
1453
+
1454
+ switch (type) {
1455
+ case 'buy':
1456
+ case 'donate':
1457
+ break;
1458
+ default:
1459
+ type = 'default';
1460
+ break;
1461
+ }
1462
+
1435
1463
  return {
1436
- name: address.name,
1437
- address1: address.address1,
1438
- address2: address.address2,
1439
- city: address.locality,
1440
- state: address.administrativeArea,
1464
+ type,
1465
+ height,
1466
+ theme: color,
1467
+ };
1468
+ }
1469
+
1470
+ _mapShippingAddress(address = {}) {
1471
+ return {
1472
+ name: address.recipient,
1473
+ address1: address.addressLine[0],
1474
+ address2: address.addressLine[1],
1475
+ city: address.city,
1476
+ state: address.region,
1441
1477
  zip: address.postalCode,
1442
- country: address.countryCode,
1443
- phone: address.phoneNumber,
1478
+ country: address.country,
1479
+ phone: address.phone,
1480
+ };
1481
+ }
1482
+
1483
+ _mapBillingAddress(address = {}) {
1484
+ return {
1485
+ name: address.name,
1486
+ phone: address.phone,
1487
+ address1: address.address.line1,
1488
+ address2: address.address.line2,
1489
+ city: address.address.city,
1490
+ state: address.address.state,
1491
+ zip: address.address.postal_code,
1492
+ country: address.address.country,
1444
1493
  };
1445
1494
  }
1446
1495
  }
@@ -1541,7 +1590,7 @@ class StripeApplePayment extends Payment {
1541
1590
  requestPayerPhone: Boolean(phone),
1542
1591
  requestShipping: Boolean(shipping),
1543
1592
  disableWallets: ['googlePay', 'browserCard', 'link'],
1544
- ...this._getPaymentRequestData(cart),
1593
+ ...getPaymentRequestData(cart, this.params),
1545
1594
  });
1546
1595
 
1547
1596
  paymentRequest.on(
@@ -1557,65 +1606,6 @@ class StripeApplePayment extends Payment {
1557
1606
  return paymentRequest;
1558
1607
  }
1559
1608
 
1560
- _getPaymentRequestData(cart) {
1561
- const {
1562
- currency,
1563
- shipping,
1564
- items,
1565
- capture_total,
1566
- shipment_rating,
1567
- shipment_total,
1568
- tax_included_total,
1569
- settings,
1570
- } = cart;
1571
-
1572
- const stripeCurrency = currency.toLowerCase();
1573
- const displayItems = items.map((item) => ({
1574
- label: item.product.name,
1575
- amount: stripeAmountByCurrency(
1576
- currency,
1577
- item.price_total - item.discount_total,
1578
- ),
1579
- }));
1580
-
1581
- if (tax_included_total) {
1582
- displayItems.push({
1583
- label: 'Taxes',
1584
- amount: stripeAmountByCurrency(currency, tax_included_total),
1585
- });
1586
- }
1587
-
1588
- if (shipping.price && shipment_total) {
1589
- displayItems.push({
1590
- label: shipping.service_name,
1591
- amount: stripeAmountByCurrency(currency, shipment_total),
1592
- });
1593
- }
1594
-
1595
- const services = shipment_rating && shipment_rating.services;
1596
- let shippingOptions;
1597
- if (services) {
1598
- shippingOptions = services.map((service) => ({
1599
- id: service.id,
1600
- label: service.name,
1601
- detail: service.description,
1602
- amount: stripeAmountByCurrency(currency, service.price),
1603
- }));
1604
- }
1605
-
1606
- return {
1607
- country: settings.country,
1608
- currency: stripeCurrency,
1609
- total: {
1610
- label: settings.name,
1611
- amount: stripeAmountByCurrency(currency, capture_total),
1612
- pending: true,
1613
- },
1614
- displayItems,
1615
- shippingOptions,
1616
- };
1617
- }
1618
-
1619
1609
  async _onShippingAddressChange(event) {
1620
1610
  const { shippingAddress, updateWith } = event;
1621
1611
  const shipping = this._mapShippingAddress(shippingAddress);
@@ -1625,7 +1615,10 @@ class StripeApplePayment extends Payment {
1625
1615
  });
1626
1616
 
1627
1617
  if (cart) {
1628
- updateWith({ status: 'success', ...this._getPaymentRequestData(cart) });
1618
+ updateWith({
1619
+ status: 'success',
1620
+ ...getPaymentRequestData(cart, this.params),
1621
+ });
1629
1622
  } else {
1630
1623
  updateWith({ status: 'invalid_shipping_address' });
1631
1624
  }
@@ -1638,7 +1631,10 @@ class StripeApplePayment extends Payment {
1638
1631
  });
1639
1632
 
1640
1633
  if (cart) {
1641
- updateWith({ status: 'success', ...this._getPaymentRequestData(cart) });
1634
+ updateWith({
1635
+ status: 'success',
1636
+ ...getPaymentRequestData(cart, this.params),
1637
+ });
1642
1638
  } else {
1643
1639
  updateWith({ status: 'fail' });
1644
1640
  }