swell-js 5.7.0 → 5.8.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.mjs +1 -1
- package/dist/payment.mjs +397 -239
- package/dist/swell.cjs +398 -240
- package/dist/swell.cjs.map +1 -1
- package/dist/swell.umd.min.js +398 -240
- package/dist/swell.umd.min.js.map +1 -1
- package/package.json +2 -1
package/dist/payment.mjs
CHANGED
|
@@ -782,13 +782,13 @@ function getPaymentRequestData(cart, params) {
|
|
|
782
782
|
tax_included_total,
|
|
783
783
|
settings,
|
|
784
784
|
} = cart;
|
|
785
|
-
const { price: shippingPrice, service_name } = shipping || {};
|
|
785
|
+
const { price: shippingPrice, service, service_name } = shipping || {};
|
|
786
786
|
const { country, name } = settings || {};
|
|
787
787
|
const { require: { shipping: requireShipping } = {} } = params;
|
|
788
788
|
|
|
789
789
|
const stripeCurrency = currency.toLowerCase();
|
|
790
790
|
const displayItems = items.map((item) => ({
|
|
791
|
-
label:
|
|
791
|
+
label: item.product_name || item.product?.name || 'Unknown product',
|
|
792
792
|
amount: stripeAmountByCurrency(
|
|
793
793
|
currency,
|
|
794
794
|
item.price_total - item.discount_total,
|
|
@@ -810,14 +810,21 @@ function getPaymentRequestData(cart, params) {
|
|
|
810
810
|
}
|
|
811
811
|
|
|
812
812
|
let shippingOptions;
|
|
813
|
-
const services =
|
|
814
|
-
if (Array.isArray(services) && services.length > 0) {
|
|
813
|
+
const services = shipment_rating?.services;
|
|
814
|
+
if (requireShipping && Array.isArray(services) && services.length > 0) {
|
|
815
815
|
shippingOptions = services.map((service) => ({
|
|
816
816
|
id: service.id,
|
|
817
817
|
label: service.name,
|
|
818
818
|
detail: service.description,
|
|
819
819
|
amount: stripeAmountByCurrency(currency, service.price),
|
|
820
820
|
}));
|
|
821
|
+
|
|
822
|
+
const index = shippingOptions.findIndex((item) => item.id === service);
|
|
823
|
+
|
|
824
|
+
if (index > 0) {
|
|
825
|
+
// Move selected shipping option to the top
|
|
826
|
+
shippingOptions.unshift(...shippingOptions.splice(index, 1));
|
|
827
|
+
}
|
|
821
828
|
}
|
|
822
829
|
|
|
823
830
|
return {
|
|
@@ -829,7 +836,7 @@ function getPaymentRequestData(cart, params) {
|
|
|
829
836
|
pending: true,
|
|
830
837
|
},
|
|
831
838
|
displayItems,
|
|
832
|
-
...(
|
|
839
|
+
...(shippingOptions && { shippingOptions }),
|
|
833
840
|
};
|
|
834
841
|
}
|
|
835
842
|
|
|
@@ -1377,6 +1384,7 @@ class StripeKlarnaPayment extends Payment {
|
|
|
1377
1384
|
|
|
1378
1385
|
/** @typedef {import('@stripe/stripe-js').Stripe} Stripe */
|
|
1379
1386
|
/** @typedef {import('@stripe/stripe-js').PaymentRequestPaymentMethodEvent} PaymentRequestPaymentMethodEvent */
|
|
1387
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
1380
1388
|
|
|
1381
1389
|
class StripeGooglePayment extends Payment {
|
|
1382
1390
|
constructor(api, options, params, methods) {
|
|
@@ -1444,6 +1452,7 @@ class StripeGooglePayment extends Payment {
|
|
|
1444
1452
|
this.element.mount(`#${this.elementContainer.id}`);
|
|
1445
1453
|
}
|
|
1446
1454
|
|
|
1455
|
+
/** @param {Cart} cart */
|
|
1447
1456
|
_createPaymentRequest(cart) {
|
|
1448
1457
|
const { require: { name, email, shipping, phone } = {} } = this.params;
|
|
1449
1458
|
|
|
@@ -1456,15 +1465,10 @@ class StripeGooglePayment extends Payment {
|
|
|
1456
1465
|
...getPaymentRequestData(cart, this.params),
|
|
1457
1466
|
});
|
|
1458
1467
|
|
|
1459
|
-
paymentRequest
|
|
1460
|
-
'shippingaddresschange',
|
|
1461
|
-
this.
|
|
1462
|
-
|
|
1463
|
-
paymentRequest.on(
|
|
1464
|
-
'shippingoptionchange',
|
|
1465
|
-
this._onShippingOptionChange.bind(this),
|
|
1466
|
-
);
|
|
1467
|
-
paymentRequest.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
1468
|
+
paymentRequest
|
|
1469
|
+
.on('shippingaddresschange', this._onShippingAddressChange.bind(this))
|
|
1470
|
+
.on('shippingoptionchange', this._onShippingOptionChange.bind(this))
|
|
1471
|
+
.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
1468
1472
|
|
|
1469
1473
|
return paymentRequest;
|
|
1470
1474
|
}
|
|
@@ -1472,9 +1476,9 @@ class StripeGooglePayment extends Payment {
|
|
|
1472
1476
|
/** @param {import('@stripe/stripe-js').PaymentRequestShippingAddressEvent} event */
|
|
1473
1477
|
async _onShippingAddressChange(event) {
|
|
1474
1478
|
const { shippingAddress, updateWith } = event;
|
|
1475
|
-
|
|
1479
|
+
|
|
1476
1480
|
const cart = await this.updateCart({
|
|
1477
|
-
shipping:
|
|
1481
|
+
shipping: this._mapShippingAddress(shippingAddress),
|
|
1478
1482
|
shipment_rating: null,
|
|
1479
1483
|
});
|
|
1480
1484
|
|
|
@@ -1514,16 +1518,15 @@ class StripeGooglePayment extends Payment {
|
|
|
1514
1518
|
shippingOption,
|
|
1515
1519
|
complete,
|
|
1516
1520
|
} = event;
|
|
1517
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
1518
1521
|
|
|
1519
1522
|
await this.updateCart({
|
|
1520
1523
|
account: {
|
|
1521
|
-
email: payerEmail,
|
|
1524
|
+
email: payerEmail || billing_details?.email,
|
|
1522
1525
|
},
|
|
1523
|
-
...(
|
|
1526
|
+
...(shippingAddress && {
|
|
1524
1527
|
shipping: {
|
|
1525
1528
|
...this._mapShippingAddress(shippingAddress),
|
|
1526
|
-
service: shippingOption
|
|
1529
|
+
service: shippingOption?.id || undefined,
|
|
1527
1530
|
},
|
|
1528
1531
|
}),
|
|
1529
1532
|
billing: {
|
|
@@ -1537,9 +1540,9 @@ class StripeGooglePayment extends Payment {
|
|
|
1537
1540
|
exp_month: card.exp_month,
|
|
1538
1541
|
exp_year: card.exp_year,
|
|
1539
1542
|
last4: card.last4,
|
|
1540
|
-
address_check: card.checks
|
|
1541
|
-
zip_check: card.checks
|
|
1542
|
-
cvc_check: card.checks
|
|
1543
|
+
address_check: card.checks?.address_line1_check,
|
|
1544
|
+
zip_check: card.checks?.address_postal_code_check,
|
|
1545
|
+
cvc_check: card.checks?.cvc_check,
|
|
1543
1546
|
},
|
|
1544
1547
|
},
|
|
1545
1548
|
});
|
|
@@ -1587,8 +1590,8 @@ class StripeGooglePayment extends Payment {
|
|
|
1587
1590
|
_mapShippingAddress(address = {}) {
|
|
1588
1591
|
return {
|
|
1589
1592
|
name: address.recipient,
|
|
1590
|
-
address1: address.addressLine[0],
|
|
1591
|
-
address2: address.addressLine[1],
|
|
1593
|
+
address1: address.addressLine?.[0],
|
|
1594
|
+
address2: address.addressLine?.[1],
|
|
1592
1595
|
city: address.city,
|
|
1593
1596
|
state: address.region,
|
|
1594
1597
|
zip: address.postalCode,
|
|
@@ -1602,18 +1605,19 @@ class StripeGooglePayment extends Payment {
|
|
|
1602
1605
|
return {
|
|
1603
1606
|
name: address.name,
|
|
1604
1607
|
phone: address.phone,
|
|
1605
|
-
address1: address.address
|
|
1606
|
-
address2: address.address
|
|
1607
|
-
city: address.address
|
|
1608
|
-
state: address.address
|
|
1609
|
-
zip: address.address
|
|
1610
|
-
country: address.address
|
|
1608
|
+
address1: address.address?.line1,
|
|
1609
|
+
address2: address.address?.line2,
|
|
1610
|
+
city: address.address?.city,
|
|
1611
|
+
state: address.address?.state,
|
|
1612
|
+
zip: address.address?.postal_code,
|
|
1613
|
+
country: address.address?.country,
|
|
1611
1614
|
};
|
|
1612
1615
|
}
|
|
1613
1616
|
}
|
|
1614
1617
|
|
|
1615
1618
|
/** @typedef {import('@stripe/stripe-js').Stripe} Stripe */
|
|
1616
1619
|
/** @typedef {import('@stripe/stripe-js').PaymentRequestPaymentMethodEvent} PaymentRequestPaymentMethodEvent */
|
|
1620
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
1617
1621
|
|
|
1618
1622
|
class StripeApplePayment extends Payment {
|
|
1619
1623
|
constructor(api, options, params, methods) {
|
|
@@ -1667,7 +1671,7 @@ class StripeApplePayment extends Payment {
|
|
|
1667
1671
|
const paymentRequest = this._createPaymentRequest(cart);
|
|
1668
1672
|
const canMakePayment = await paymentRequest.canMakePayment();
|
|
1669
1673
|
|
|
1670
|
-
if (!canMakePayment
|
|
1674
|
+
if (!canMakePayment?.applePay) {
|
|
1671
1675
|
throw new Error(
|
|
1672
1676
|
'This device is not capable of making Apple Pay payments',
|
|
1673
1677
|
);
|
|
@@ -1704,6 +1708,7 @@ class StripeApplePayment extends Payment {
|
|
|
1704
1708
|
}
|
|
1705
1709
|
}
|
|
1706
1710
|
|
|
1711
|
+
/** @param {Cart} cart */
|
|
1707
1712
|
_createPaymentRequest(cart) {
|
|
1708
1713
|
const { require: { name, email, shipping, phone } = {} } = this.params;
|
|
1709
1714
|
|
|
@@ -1716,15 +1721,10 @@ class StripeApplePayment extends Payment {
|
|
|
1716
1721
|
...getPaymentRequestData(cart, this.params),
|
|
1717
1722
|
});
|
|
1718
1723
|
|
|
1719
|
-
paymentRequest
|
|
1720
|
-
'shippingaddresschange',
|
|
1721
|
-
this.
|
|
1722
|
-
|
|
1723
|
-
paymentRequest.on(
|
|
1724
|
-
'shippingoptionchange',
|
|
1725
|
-
this._onShippingOptionChange.bind(this),
|
|
1726
|
-
);
|
|
1727
|
-
paymentRequest.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
1724
|
+
paymentRequest
|
|
1725
|
+
.on('shippingaddresschange', this._onShippingAddressChange.bind(this))
|
|
1726
|
+
.on('shippingoptionchange', this._onShippingOptionChange.bind(this))
|
|
1727
|
+
.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
1728
1728
|
|
|
1729
1729
|
return paymentRequest;
|
|
1730
1730
|
}
|
|
@@ -1732,9 +1732,9 @@ class StripeApplePayment extends Payment {
|
|
|
1732
1732
|
/** @param {import('@stripe/stripe-js').PaymentRequestShippingAddressEvent} event */
|
|
1733
1733
|
async _onShippingAddressChange(event) {
|
|
1734
1734
|
const { shippingAddress, updateWith } = event;
|
|
1735
|
-
|
|
1735
|
+
|
|
1736
1736
|
const cart = await this.updateCart({
|
|
1737
|
-
shipping:
|
|
1737
|
+
shipping: this._mapShippingAddress(shippingAddress),
|
|
1738
1738
|
shipment_rating: null,
|
|
1739
1739
|
});
|
|
1740
1740
|
|
|
@@ -1774,16 +1774,15 @@ class StripeApplePayment extends Payment {
|
|
|
1774
1774
|
shippingOption,
|
|
1775
1775
|
complete,
|
|
1776
1776
|
} = event;
|
|
1777
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
1778
1777
|
|
|
1779
1778
|
await this.updateCart({
|
|
1780
1779
|
account: {
|
|
1781
|
-
email: payerEmail,
|
|
1780
|
+
email: payerEmail || billing_details?.email,
|
|
1782
1781
|
},
|
|
1783
|
-
...(
|
|
1782
|
+
...(shippingAddress && {
|
|
1784
1783
|
shipping: {
|
|
1785
1784
|
...this._mapShippingAddress(shippingAddress),
|
|
1786
|
-
service: shippingOption
|
|
1785
|
+
service: shippingOption?.id || undefined,
|
|
1787
1786
|
},
|
|
1788
1787
|
}),
|
|
1789
1788
|
billing: {
|
|
@@ -1797,9 +1796,9 @@ class StripeApplePayment extends Payment {
|
|
|
1797
1796
|
exp_month: card.exp_month,
|
|
1798
1797
|
exp_year: card.exp_year,
|
|
1799
1798
|
last4: card.last4,
|
|
1800
|
-
address_check: card.checks
|
|
1801
|
-
zip_check: card.checks
|
|
1802
|
-
cvc_check: card.checks
|
|
1799
|
+
address_check: card.checks?.address_line1_check,
|
|
1800
|
+
zip_check: card.checks?.address_postal_code_check,
|
|
1801
|
+
cvc_check: card.checks?.cvc_check,
|
|
1803
1802
|
},
|
|
1804
1803
|
},
|
|
1805
1804
|
});
|
|
@@ -1813,8 +1812,8 @@ class StripeApplePayment extends Payment {
|
|
|
1813
1812
|
_mapShippingAddress(address = {}) {
|
|
1814
1813
|
return {
|
|
1815
1814
|
name: address.recipient,
|
|
1816
|
-
address1: address.addressLine[0],
|
|
1817
|
-
address2: address.addressLine[1],
|
|
1815
|
+
address1: address.addressLine?.[0],
|
|
1816
|
+
address2: address.addressLine?.[1],
|
|
1818
1817
|
city: address.city,
|
|
1819
1818
|
state: address.region,
|
|
1820
1819
|
zip: address.postalCode,
|
|
@@ -1828,12 +1827,12 @@ class StripeApplePayment extends Payment {
|
|
|
1828
1827
|
return {
|
|
1829
1828
|
name: address.name,
|
|
1830
1829
|
phone: address.phone,
|
|
1831
|
-
address1: address.address
|
|
1832
|
-
address2: address.address
|
|
1833
|
-
city: address.address
|
|
1834
|
-
state: address.address
|
|
1835
|
-
zip: address.address
|
|
1836
|
-
country: address.address
|
|
1830
|
+
address1: address.address?.line1,
|
|
1831
|
+
address2: address.address?.line2,
|
|
1832
|
+
city: address.address?.city,
|
|
1833
|
+
state: address.address?.state,
|
|
1834
|
+
zip: address.address?.postal_code,
|
|
1835
|
+
country: address.address?.country,
|
|
1837
1836
|
};
|
|
1838
1837
|
}
|
|
1839
1838
|
}
|
|
@@ -2101,6 +2100,44 @@ function getDiscountLabel(discount, cart) {
|
|
|
2101
2100
|
return discount.id;
|
|
2102
2101
|
}
|
|
2103
2102
|
|
|
2103
|
+
/** @type {Map<string, number>} */
|
|
2104
|
+
const CURRENCIES_CENTS = new Map();
|
|
2105
|
+
|
|
2106
|
+
/**
|
|
2107
|
+
* @param {string} currency
|
|
2108
|
+
* @returns {number}
|
|
2109
|
+
*/
|
|
2110
|
+
function getCurrencyCents(currency) {
|
|
2111
|
+
let cents = CURRENCIES_CENTS.get(currency);
|
|
2112
|
+
|
|
2113
|
+
if (cents !== undefined) {
|
|
2114
|
+
return cents;
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
2118
|
+
style: 'currency',
|
|
2119
|
+
currency,
|
|
2120
|
+
});
|
|
2121
|
+
|
|
2122
|
+
const options = formatter.resolvedOptions();
|
|
2123
|
+
const decimals = options.maximumFractionDigits ?? 2;
|
|
2124
|
+
|
|
2125
|
+
cents = 10 ** decimals;
|
|
2126
|
+
|
|
2127
|
+
CURRENCIES_CENTS.set(currency, cents);
|
|
2128
|
+
|
|
2129
|
+
return cents;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* @param {string} currency
|
|
2134
|
+
* @param {number} amount
|
|
2135
|
+
* @returns {number}
|
|
2136
|
+
*/
|
|
2137
|
+
function amountInCents(currency, amount) {
|
|
2138
|
+
return Math.round(amount * getCurrencyCents(currency));
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2104
2141
|
/** @typedef {import('./payment').default} Payment */
|
|
2105
2142
|
/** @typedef {import('../../types').Cart} Cart */
|
|
2106
2143
|
/** @typedef {import('../../types').Address} Address */
|
|
@@ -2188,7 +2225,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
|
|
|
2188
2225
|
this,
|
|
2189
2226
|
cart,
|
|
2190
2227
|
),
|
|
2191
|
-
newTransactionInfo: getTransactionInfo(cart),
|
|
2228
|
+
newTransactionInfo: getTransactionInfo.call(this, cart),
|
|
2192
2229
|
};
|
|
2193
2230
|
}
|
|
2194
2231
|
|
|
@@ -2201,7 +2238,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
|
|
|
2201
2238
|
},
|
|
2202
2239
|
});
|
|
2203
2240
|
|
|
2204
|
-
return { newTransactionInfo: getTransactionInfo(cart) };
|
|
2241
|
+
return { newTransactionInfo: getTransactionInfo.call(this, cart) };
|
|
2205
2242
|
} catch (err) {
|
|
2206
2243
|
return createError(
|
|
2207
2244
|
intermediatePaymentData.callbackTrigger,
|
|
@@ -2223,7 +2260,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
|
|
|
2223
2260
|
|
|
2224
2261
|
return {
|
|
2225
2262
|
newOfferInfo: getOfferInfo(cart),
|
|
2226
|
-
newTransactionInfo: getTransactionInfo(cart),
|
|
2263
|
+
newTransactionInfo: getTransactionInfo.call(this, cart),
|
|
2227
2264
|
};
|
|
2228
2265
|
} catch (err) {
|
|
2229
2266
|
return createError(
|
|
@@ -2323,12 +2360,13 @@ function getDisplayItems(cart) {
|
|
|
2323
2360
|
|
|
2324
2361
|
/**
|
|
2325
2362
|
* Converts cart data to Google Pay transaction information.
|
|
2363
|
+
* @this {Payment}
|
|
2326
2364
|
* @param {Cart} cart - The current cart data
|
|
2327
2365
|
* @returns {google.payments.api.TransactionInfo} Transaction info for Google Pay
|
|
2328
2366
|
*/
|
|
2329
2367
|
function getTransactionInfo(cart) {
|
|
2330
|
-
const {
|
|
2331
|
-
|
|
2368
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
2369
|
+
const { settings, capture_total, currency, shipping } = cart;
|
|
2332
2370
|
|
|
2333
2371
|
return {
|
|
2334
2372
|
countryCode: settings?.country || 'US',
|
|
@@ -2336,7 +2374,7 @@ function getTransactionInfo(cart) {
|
|
|
2336
2374
|
totalPrice: String(capture_total ?? 0),
|
|
2337
2375
|
// Set status to FINAL if shipping has been selected, otherwise ESTIMATED
|
|
2338
2376
|
totalPriceStatus:
|
|
2339
|
-
!
|
|
2377
|
+
!shipmentDelivery || shipping?.service ? 'FINAL' : 'ESTIMATED',
|
|
2340
2378
|
totalPriceLabel: 'Total',
|
|
2341
2379
|
displayItems: getDisplayItems(cart),
|
|
2342
2380
|
};
|
|
@@ -2349,12 +2387,14 @@ function getTransactionInfo(cart) {
|
|
|
2349
2387
|
* @returns {google.payments.api.ShippingOptionParameters | undefined} Shipping options for Google Pay
|
|
2350
2388
|
*/
|
|
2351
2389
|
function getShippingOptionParameters(cart) {
|
|
2352
|
-
const {
|
|
2390
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
2353
2391
|
|
|
2354
|
-
if (!
|
|
2392
|
+
if (!shipmentDelivery) {
|
|
2355
2393
|
return undefined;
|
|
2356
2394
|
}
|
|
2357
2395
|
|
|
2396
|
+
const { shipment_rating, shipping } = cart;
|
|
2397
|
+
|
|
2358
2398
|
if (!shipment_rating?.services?.length) {
|
|
2359
2399
|
// Return placeholder when no shipping services are available
|
|
2360
2400
|
return {
|
|
@@ -2435,20 +2475,11 @@ function createError(intent, reason, message) {
|
|
|
2435
2475
|
};
|
|
2436
2476
|
}
|
|
2437
2477
|
|
|
2478
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
2479
|
+
|
|
2438
2480
|
const API_VERSION$1 = 2;
|
|
2439
2481
|
const API_MINOR_VERSION$1 = 0;
|
|
2440
2482
|
|
|
2441
|
-
const ALLOWED_CARD_AUTH_METHODS = ['PAN_ONLY', 'CRYPTOGRAM_3DS'];
|
|
2442
|
-
|
|
2443
|
-
const ALLOWED_CARD_NETWORKS = [
|
|
2444
|
-
'AMEX',
|
|
2445
|
-
'DISCOVER',
|
|
2446
|
-
'INTERAC',
|
|
2447
|
-
'JCB',
|
|
2448
|
-
'MASTERCARD',
|
|
2449
|
-
'VISA',
|
|
2450
|
-
];
|
|
2451
|
-
|
|
2452
2483
|
class BraintreeGooglePayment extends Payment {
|
|
2453
2484
|
constructor(api, options, params, methods) {
|
|
2454
2485
|
if (!methods.card) {
|
|
@@ -2484,6 +2515,9 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2484
2515
|
if (this.google) {
|
|
2485
2516
|
this.googleClient = new this.google.payments.api.PaymentsClient({
|
|
2486
2517
|
environment: isLiveMode(this.method.mode) ? 'PRODUCTION' : 'TEST',
|
|
2518
|
+
paymentDataCallbacks: {
|
|
2519
|
+
onPaymentDataChanged: onPaymentDataChanged.bind(this),
|
|
2520
|
+
},
|
|
2487
2521
|
});
|
|
2488
2522
|
}
|
|
2489
2523
|
|
|
@@ -2499,31 +2533,12 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2499
2533
|
BraintreeGooglePayment.googleClient = googleClient;
|
|
2500
2534
|
}
|
|
2501
2535
|
|
|
2502
|
-
/** @
|
|
2503
|
-
get cardPaymentMethod() {
|
|
2504
|
-
return {
|
|
2505
|
-
type: 'CARD',
|
|
2506
|
-
parameters: {
|
|
2507
|
-
allowedAuthMethods: ALLOWED_CARD_AUTH_METHODS,
|
|
2508
|
-
allowedCardNetworks: ALLOWED_CARD_NETWORKS,
|
|
2509
|
-
billingAddressRequired: true,
|
|
2510
|
-
billingAddressParameters: {
|
|
2511
|
-
format: 'FULL',
|
|
2512
|
-
phoneNumberRequired: true,
|
|
2513
|
-
},
|
|
2514
|
-
},
|
|
2515
|
-
};
|
|
2516
|
-
}
|
|
2517
|
-
|
|
2518
|
-
/** @returns {google.payments.api.PaymentMethodSpecification[]} */
|
|
2519
|
-
get allowedPaymentMethods() {
|
|
2520
|
-
return [this.cardPaymentMethod];
|
|
2521
|
-
}
|
|
2522
|
-
|
|
2536
|
+
/** @param {Cart} cart */
|
|
2523
2537
|
async createElements(cart) {
|
|
2524
2538
|
const {
|
|
2525
2539
|
elementId = 'googlepay-button',
|
|
2526
2540
|
locale = 'en',
|
|
2541
|
+
require: { phone } = {},
|
|
2527
2542
|
style: { color = 'black', type = 'plain', sizeMode = 'fill' } = {},
|
|
2528
2543
|
} = this.params;
|
|
2529
2544
|
|
|
@@ -2534,10 +2549,35 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2534
2549
|
this.setElementContainer(elementId);
|
|
2535
2550
|
await this.loadScripts(this.scripts);
|
|
2536
2551
|
|
|
2552
|
+
const braintreeClient = await this._createBraintreeClient();
|
|
2553
|
+
|
|
2554
|
+
const googlePayment = await this.braintree.googlePayment.create({
|
|
2555
|
+
client: braintreeClient,
|
|
2556
|
+
googleMerchantId: this.method.merchant_id,
|
|
2557
|
+
googlePayVersion: API_VERSION$1,
|
|
2558
|
+
});
|
|
2559
|
+
|
|
2560
|
+
const paymentDataRequest = googlePayment.createPaymentDataRequest(
|
|
2561
|
+
this._createPaymentRequestData(cart),
|
|
2562
|
+
);
|
|
2563
|
+
|
|
2564
|
+
const cardPaymentMethod = paymentDataRequest.allowedPaymentMethods.find(
|
|
2565
|
+
(method) => method.type === 'CARD',
|
|
2566
|
+
);
|
|
2567
|
+
|
|
2568
|
+
if (cardPaymentMethod !== undefined) {
|
|
2569
|
+
cardPaymentMethod.parameters.billingAddressRequired = true;
|
|
2570
|
+
|
|
2571
|
+
cardPaymentMethod.parameters.billingAddressParameters = {
|
|
2572
|
+
format: 'FULL',
|
|
2573
|
+
phoneNumberRequired: Boolean(phone),
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
|
|
2537
2577
|
const isReadyToPay = await this.googleClient.isReadyToPay({
|
|
2538
2578
|
apiVersion: API_VERSION$1,
|
|
2539
2579
|
apiVersionMinor: API_MINOR_VERSION$1,
|
|
2540
|
-
allowedPaymentMethods:
|
|
2580
|
+
allowedPaymentMethods: paymentDataRequest.allowedPaymentMethods,
|
|
2541
2581
|
existingPaymentMethodRequired: true,
|
|
2542
2582
|
});
|
|
2543
2583
|
|
|
@@ -2547,16 +2587,6 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2547
2587
|
);
|
|
2548
2588
|
}
|
|
2549
2589
|
|
|
2550
|
-
const braintreeClient = await this._createBraintreeClient();
|
|
2551
|
-
const googlePayment = await this.braintree.googlePayment.create({
|
|
2552
|
-
client: braintreeClient,
|
|
2553
|
-
googleMerchantId: this.method.merchant_id,
|
|
2554
|
-
googlePayVersion: API_VERSION$1,
|
|
2555
|
-
});
|
|
2556
|
-
const paymentRequestData = this._createPaymentRequestData(cart);
|
|
2557
|
-
const paymentDataRequest =
|
|
2558
|
-
googlePayment.createPaymentDataRequest(paymentRequestData);
|
|
2559
|
-
|
|
2560
2590
|
this.element = this.googleClient.createButton({
|
|
2561
2591
|
buttonColor: color,
|
|
2562
2592
|
buttonType: type,
|
|
@@ -2583,6 +2613,7 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2583
2613
|
}
|
|
2584
2614
|
}
|
|
2585
2615
|
|
|
2616
|
+
/** @returns {Promise<braintree.Client>} */
|
|
2586
2617
|
async _createBraintreeClient() {
|
|
2587
2618
|
const authorization = await this.authorizeGateway({
|
|
2588
2619
|
gateway: 'braintree',
|
|
@@ -2597,39 +2628,51 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2597
2628
|
});
|
|
2598
2629
|
}
|
|
2599
2630
|
|
|
2600
|
-
/**
|
|
2631
|
+
/**
|
|
2632
|
+
* @param {Cart} cart
|
|
2633
|
+
* @returns {google.payments.api.PaymentDataRequest}
|
|
2634
|
+
*/
|
|
2601
2635
|
_createPaymentRequestData(cart) {
|
|
2602
2636
|
const {
|
|
2603
|
-
settings: { name
|
|
2604
|
-
capture_total,
|
|
2605
|
-
currency,
|
|
2637
|
+
settings: { name },
|
|
2606
2638
|
} = cart;
|
|
2639
|
+
|
|
2607
2640
|
const { require: { email, shipping, phone } = {} } = this.params;
|
|
2608
2641
|
|
|
2642
|
+
/** @type {google.payments.api.CallbackIntent[]} */
|
|
2643
|
+
const callbackIntents = ['OFFER'];
|
|
2644
|
+
|
|
2645
|
+
if (shipping) {
|
|
2646
|
+
callbackIntents.push('SHIPPING_ADDRESS', 'SHIPPING_OPTION');
|
|
2647
|
+
}
|
|
2648
|
+
|
|
2609
2649
|
return {
|
|
2610
2650
|
apiVersion: API_VERSION$1,
|
|
2611
2651
|
apiVersionMinor: API_MINOR_VERSION$1,
|
|
2612
|
-
transactionInfo:
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
allowedPaymentMethods: this.allowedPaymentMethods,
|
|
2652
|
+
transactionInfo: getTransactionInfo.call(this, cart),
|
|
2653
|
+
/**
|
|
2654
|
+
* @see {@link https://developer.paypal.com/braintree/docs/guides/google-pay/client-side/javascript/v3/#requesting-a-payment}
|
|
2655
|
+
*
|
|
2656
|
+
* Braintree automatically populates the `allowedPaymentMethods` property.
|
|
2657
|
+
*/
|
|
2619
2658
|
emailRequired: Boolean(email),
|
|
2620
2659
|
shippingAddressRequired: Boolean(shipping),
|
|
2621
2660
|
shippingAddressParameters: {
|
|
2622
2661
|
phoneNumberRequired: Boolean(phone),
|
|
2623
2662
|
},
|
|
2663
|
+
shippingOptionRequired: Boolean(shipping),
|
|
2664
|
+
shippingOptionParameters: getShippingOptionParameters.call(this, cart),
|
|
2665
|
+
offerInfo: getOfferInfo(cart),
|
|
2624
2666
|
merchantInfo: {
|
|
2625
2667
|
merchantName: name,
|
|
2626
2668
|
merchantId: this.method.merchant_id,
|
|
2627
2669
|
},
|
|
2670
|
+
callbackIntents,
|
|
2628
2671
|
};
|
|
2629
2672
|
}
|
|
2630
2673
|
|
|
2631
2674
|
/**
|
|
2632
|
-
* @param {
|
|
2675
|
+
* @param {braintree.GooglePayment} googlePayment
|
|
2633
2676
|
* @param {google.payments.api.PaymentDataRequest} paymentDataRequest
|
|
2634
2677
|
*/
|
|
2635
2678
|
async _onClick(googlePayment, paymentDataRequest) {
|
|
@@ -2646,34 +2689,59 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2646
2689
|
}
|
|
2647
2690
|
|
|
2648
2691
|
/**
|
|
2649
|
-
* @param {
|
|
2692
|
+
* @param {braintree.GooglePayment} googlePayment
|
|
2650
2693
|
* @param {google.payments.api.PaymentData} paymentData
|
|
2651
2694
|
*/
|
|
2652
2695
|
async _submitPayment(googlePayment, paymentData) {
|
|
2653
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
2654
2696
|
const { nonce } = await googlePayment.parseResponse(paymentData);
|
|
2655
|
-
const { email, shippingAddress, paymentMethodData } =
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
} = paymentMethodData;
|
|
2697
|
+
const { email, shippingAddress, shippingOptionData, paymentMethodData } =
|
|
2698
|
+
paymentData;
|
|
2699
|
+
const { info: { billingAddress } = {} } = paymentMethodData;
|
|
2659
2700
|
|
|
2660
|
-
await this.updateCart({
|
|
2701
|
+
const cart = await this.updateCart({
|
|
2661
2702
|
account: {
|
|
2662
2703
|
email,
|
|
2663
2704
|
},
|
|
2664
2705
|
billing: {
|
|
2665
2706
|
method: 'google',
|
|
2707
|
+
account_card_id: null,
|
|
2708
|
+
card: null,
|
|
2666
2709
|
google: {
|
|
2667
2710
|
nonce,
|
|
2668
2711
|
gateway: 'braintree',
|
|
2669
2712
|
},
|
|
2670
2713
|
...convertToSwellAddress$2(billingAddress),
|
|
2671
2714
|
},
|
|
2672
|
-
...(
|
|
2673
|
-
shipping:
|
|
2715
|
+
...(shippingAddress && {
|
|
2716
|
+
shipping: {
|
|
2717
|
+
...convertToSwellAddress$2(shippingAddress),
|
|
2718
|
+
service: shippingOptionData?.id || undefined,
|
|
2719
|
+
},
|
|
2674
2720
|
}),
|
|
2675
2721
|
});
|
|
2676
2722
|
|
|
2723
|
+
if (cart.subscription_delivery) {
|
|
2724
|
+
try {
|
|
2725
|
+
const card = await cardApi.createToken({
|
|
2726
|
+
gateway: 'braintree',
|
|
2727
|
+
account_id: cart.account_id,
|
|
2728
|
+
nonce,
|
|
2729
|
+
});
|
|
2730
|
+
|
|
2731
|
+
delete card.nonce;
|
|
2732
|
+
|
|
2733
|
+
await this.updateCart({
|
|
2734
|
+
billing: {
|
|
2735
|
+
method: 'card',
|
|
2736
|
+
card,
|
|
2737
|
+
google: null,
|
|
2738
|
+
},
|
|
2739
|
+
});
|
|
2740
|
+
} catch (error) {
|
|
2741
|
+
console.warn('Failed to extract card data from google token', error);
|
|
2742
|
+
}
|
|
2743
|
+
}
|
|
2744
|
+
|
|
2677
2745
|
this.onSuccess();
|
|
2678
2746
|
}
|
|
2679
2747
|
}
|
|
@@ -2703,7 +2771,7 @@ async function onShippingAddressChange(shippingContact) {
|
|
|
2703
2771
|
'Shipping is not available for the provided address.';
|
|
2704
2772
|
|
|
2705
2773
|
return {
|
|
2706
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
2774
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
2707
2775
|
newLineItems: getLineItems(cart),
|
|
2708
2776
|
newShippingMethods: [], // REQUIRED: Must always provide this, even as empty array
|
|
2709
2777
|
errors: [
|
|
@@ -2714,15 +2782,15 @@ async function onShippingAddressChange(shippingContact) {
|
|
|
2714
2782
|
|
|
2715
2783
|
// Success: Return updated totals and shipping methods
|
|
2716
2784
|
return {
|
|
2717
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
2785
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
2718
2786
|
newLineItems: getLineItems(cart),
|
|
2719
|
-
newShippingMethods: getShippingMethods(cart),
|
|
2787
|
+
newShippingMethods: getShippingMethods.call(this, cart),
|
|
2720
2788
|
};
|
|
2721
2789
|
} catch (err) {
|
|
2722
2790
|
const cartData = await this.getCart();
|
|
2723
2791
|
|
|
2724
2792
|
return {
|
|
2725
|
-
newTotal: getTotal(cartData, this.merchantInfo),
|
|
2793
|
+
newTotal: getTotal.call(this, cartData, this.merchantInfo),
|
|
2726
2794
|
newLineItems: getLineItems(cartData),
|
|
2727
2795
|
newShippingMethods: [], // REQUIRED: Must always provide this, even as empty array
|
|
2728
2796
|
errors: [new ApplePayError('unknown', undefined, err.message)],
|
|
@@ -2768,12 +2836,12 @@ async function onShippingMethodChange(shippingMethod) {
|
|
|
2768
2836
|
});
|
|
2769
2837
|
|
|
2770
2838
|
return {
|
|
2771
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
2839
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
2772
2840
|
newLineItems: getLineItems(cart),
|
|
2773
2841
|
};
|
|
2774
2842
|
} catch (err) {
|
|
2775
2843
|
return {
|
|
2776
|
-
newTotal: getTotal(await this.getCart(), this.merchantInfo),
|
|
2844
|
+
newTotal: getTotal.call(this, await this.getCart(), this.merchantInfo),
|
|
2777
2845
|
errors: [new ApplePayError('unknown', undefined, err.message)],
|
|
2778
2846
|
};
|
|
2779
2847
|
}
|
|
@@ -2813,7 +2881,7 @@ async function onCouponCodeUpdated(couponCode) {
|
|
|
2813
2881
|
|
|
2814
2882
|
// Valid coupon applied successfully
|
|
2815
2883
|
return {
|
|
2816
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
2884
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
2817
2885
|
newLineItems: getLineItems(cart),
|
|
2818
2886
|
};
|
|
2819
2887
|
} catch (err) {
|
|
@@ -2821,7 +2889,7 @@ async function onCouponCodeUpdated(couponCode) {
|
|
|
2821
2889
|
const currentCart = await this.getCart();
|
|
2822
2890
|
|
|
2823
2891
|
return {
|
|
2824
|
-
newTotal: getTotal(currentCart, this.merchantInfo),
|
|
2892
|
+
newTotal: getTotal.call(this, currentCart, this.merchantInfo),
|
|
2825
2893
|
newLineItems: getLineItems(currentCart),
|
|
2826
2894
|
errors: [new ApplePayError('couponCodeInvalid', undefined, err.message)],
|
|
2827
2895
|
};
|
|
@@ -2855,15 +2923,17 @@ async function onCouponCodeChanged(session, event) {
|
|
|
2855
2923
|
* This ensures the user sees "pending" until they've selected shipping,
|
|
2856
2924
|
* then sees the final amount once everything is calculated.
|
|
2857
2925
|
*
|
|
2926
|
+
* @this {Payment}
|
|
2858
2927
|
* @param {Cart} cart
|
|
2859
2928
|
* @param {object} [merchantInfo]
|
|
2860
2929
|
* @returns {ApplePayJS.ApplePayLineItem}
|
|
2861
2930
|
*/
|
|
2862
2931
|
function getTotal(cart, merchantInfo) {
|
|
2863
|
-
const {
|
|
2932
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
2933
|
+
const { capture_total, shipping } = cart;
|
|
2864
2934
|
|
|
2865
2935
|
// Use 'final' only after shipping method is selected or not needed, otherwise 'pending'
|
|
2866
|
-
const isFinalPrice = !
|
|
2936
|
+
const isFinalPrice = !shipmentDelivery || shipping?.service;
|
|
2867
2937
|
const type = isFinalPrice ? 'final' : 'pending';
|
|
2868
2938
|
|
|
2869
2939
|
return {
|
|
@@ -2932,16 +3002,19 @@ function getLineItems(cart) {
|
|
|
2932
3002
|
*
|
|
2933
3003
|
* IMPORTANT: Amounts must be formatted as strings with 2 decimals.
|
|
2934
3004
|
*
|
|
3005
|
+
* @this {Payment}
|
|
2935
3006
|
* @param {Cart} cart
|
|
2936
3007
|
* @returns {ApplePayJS.ApplePayShippingMethod[]}
|
|
2937
3008
|
*/
|
|
2938
3009
|
function getShippingMethods(cart) {
|
|
2939
|
-
const {
|
|
3010
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
2940
3011
|
|
|
2941
|
-
if (!
|
|
3012
|
+
if (!shipmentDelivery) {
|
|
2942
3013
|
return [];
|
|
2943
3014
|
}
|
|
2944
3015
|
|
|
3016
|
+
const { shipment_rating } = cart;
|
|
3017
|
+
|
|
2945
3018
|
if (!shipment_rating?.services?.length) {
|
|
2946
3019
|
return [];
|
|
2947
3020
|
}
|
|
@@ -2992,13 +3065,38 @@ function convertToSwellAddress$1(address = {}) {
|
|
|
2992
3065
|
};
|
|
2993
3066
|
}
|
|
2994
3067
|
|
|
2995
|
-
|
|
3068
|
+
/** @param {object} params */
|
|
3069
|
+
function getRequiredContactFields(params) {
|
|
3070
|
+
const { require = {} } = params;
|
|
3071
|
+
/** @type {ApplePayJS.ApplePayContactField[]} */
|
|
3072
|
+
const requiredFields = [];
|
|
3073
|
+
|
|
3074
|
+
if (require.email) {
|
|
3075
|
+
requiredFields.push('email');
|
|
3076
|
+
}
|
|
3077
|
+
|
|
3078
|
+
if (require.name) {
|
|
3079
|
+
requiredFields.push('name');
|
|
3080
|
+
}
|
|
3081
|
+
|
|
3082
|
+
if (require.phone) {
|
|
3083
|
+
requiredFields.push('phone');
|
|
3084
|
+
}
|
|
3085
|
+
|
|
3086
|
+
/** @type {ApplePayJS.ApplePayContactField[]} */
|
|
3087
|
+
const requiredShippingContactFields = require.shipping
|
|
3088
|
+
? [...requiredFields, 'postalAddress']
|
|
3089
|
+
: [];
|
|
3090
|
+
|
|
3091
|
+
/** @type {ApplePayJS.ApplePayContactField[]} */
|
|
3092
|
+
const requiredBillingContactFields = [...requiredFields, 'postalAddress'];
|
|
3093
|
+
|
|
3094
|
+
return { requiredBillingContactFields, requiredShippingContactFields };
|
|
3095
|
+
}
|
|
3096
|
+
|
|
3097
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
2996
3098
|
|
|
2997
|
-
const
|
|
2998
|
-
'supports3DS',
|
|
2999
|
-
'supportsDebit',
|
|
3000
|
-
'supportsCredit',
|
|
3001
|
-
];
|
|
3099
|
+
const VERSION$1 = 14;
|
|
3002
3100
|
|
|
3003
3101
|
class BraintreeApplePayment extends Payment {
|
|
3004
3102
|
constructor(api, options, params, methods) {
|
|
@@ -3030,6 +3128,7 @@ class BraintreeApplePayment extends Payment {
|
|
|
3030
3128
|
return window.ApplePaySession;
|
|
3031
3129
|
}
|
|
3032
3130
|
|
|
3131
|
+
/** @param {Cart} cart */
|
|
3033
3132
|
async createElements(cart) {
|
|
3034
3133
|
const { elementId = 'applepay-button' } = this.params;
|
|
3035
3134
|
|
|
@@ -3043,10 +3142,12 @@ class BraintreeApplePayment extends Payment {
|
|
|
3043
3142
|
}
|
|
3044
3143
|
|
|
3045
3144
|
const braintreeClient = await this._createBraintreeClient();
|
|
3145
|
+
|
|
3046
3146
|
const applePayment = await this.braintree.applePay.create({
|
|
3047
3147
|
client: braintreeClient,
|
|
3048
3148
|
});
|
|
3049
|
-
|
|
3149
|
+
|
|
3150
|
+
const paymentRequest = this._createPaymentRequest(cart, applePayment);
|
|
3050
3151
|
|
|
3051
3152
|
this.element = this._createButton(applePayment, paymentRequest);
|
|
3052
3153
|
}
|
|
@@ -3063,8 +3164,9 @@ class BraintreeApplePayment extends Payment {
|
|
|
3063
3164
|
}
|
|
3064
3165
|
|
|
3065
3166
|
/**
|
|
3066
|
-
* @param {
|
|
3167
|
+
* @param {braintree.ApplePay} applePayment
|
|
3067
3168
|
* @param {ApplePayJS.ApplePayPaymentRequest} paymentRequest
|
|
3169
|
+
* @returns {HTMLDivElement}
|
|
3068
3170
|
*/
|
|
3069
3171
|
_createButton(applePayment, paymentRequest) {
|
|
3070
3172
|
const { style: { type = 'plain', theme = 'black', height = '40px' } = {} } =
|
|
@@ -3085,6 +3187,7 @@ class BraintreeApplePayment extends Payment {
|
|
|
3085
3187
|
return button;
|
|
3086
3188
|
}
|
|
3087
3189
|
|
|
3190
|
+
/** @returns {Promise<braintree.Client>} */
|
|
3088
3191
|
async _createBraintreeClient() {
|
|
3089
3192
|
const authorization = await this.authorizeGateway({
|
|
3090
3193
|
gateway: 'braintree',
|
|
@@ -3099,47 +3202,43 @@ class BraintreeApplePayment extends Payment {
|
|
|
3099
3202
|
});
|
|
3100
3203
|
}
|
|
3101
3204
|
|
|
3102
|
-
/**
|
|
3205
|
+
/**
|
|
3206
|
+
* @param {Cart} cart
|
|
3207
|
+
* @param {braintree.ApplePay} applePayment
|
|
3208
|
+
* @returns {ApplePayJS.ApplePayPaymentRequest}
|
|
3209
|
+
*/
|
|
3103
3210
|
_createPaymentRequest(cart, applePayment) {
|
|
3104
|
-
const { require = {} } = this.params;
|
|
3105
3211
|
const {
|
|
3106
3212
|
settings: { name, country },
|
|
3107
3213
|
capture_total,
|
|
3108
3214
|
currency,
|
|
3109
3215
|
} = cart;
|
|
3110
3216
|
|
|
3111
|
-
const requiredShippingContactFields =
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
if (require.name) {
|
|
3115
|
-
requiredShippingContactFields.push('name');
|
|
3116
|
-
}
|
|
3117
|
-
if (require.email) {
|
|
3118
|
-
requiredShippingContactFields.push('email');
|
|
3119
|
-
}
|
|
3120
|
-
if (require.phone) {
|
|
3121
|
-
requiredShippingContactFields.push('phone');
|
|
3122
|
-
}
|
|
3123
|
-
if (require.shipping) {
|
|
3124
|
-
requiredShippingContactFields.push('postalAddress');
|
|
3125
|
-
}
|
|
3217
|
+
const { requiredBillingContactFields, requiredShippingContactFields } =
|
|
3218
|
+
getRequiredContactFields(this.params);
|
|
3126
3219
|
|
|
3127
3220
|
return applePayment.createPaymentRequest({
|
|
3128
3221
|
total: {
|
|
3129
3222
|
label: name,
|
|
3130
3223
|
type: 'pending',
|
|
3131
|
-
amount: capture_total.
|
|
3224
|
+
amount: (capture_total || 0).toFixed(2),
|
|
3132
3225
|
},
|
|
3133
3226
|
countryCode: country,
|
|
3134
3227
|
currencyCode: currency,
|
|
3135
|
-
|
|
3228
|
+
/**
|
|
3229
|
+
* @see {@link https://developer.paypal.com/braintree/docs/guides/apple-pay/client-side/javascript/v3/#create-anapplepaysession}
|
|
3230
|
+
*
|
|
3231
|
+
* Braintree automatically fills in `supportedNetworks` and `merchantCapabilities`.
|
|
3232
|
+
*/
|
|
3136
3233
|
requiredShippingContactFields,
|
|
3137
3234
|
requiredBillingContactFields,
|
|
3235
|
+
supportsCouponCode: true,
|
|
3236
|
+
lineItems: getLineItems(cart),
|
|
3138
3237
|
});
|
|
3139
3238
|
}
|
|
3140
3239
|
|
|
3141
3240
|
/**
|
|
3142
|
-
* @param {
|
|
3241
|
+
* @param {braintree.ApplePay} applePayment
|
|
3143
3242
|
* @param {ApplePayJS.ApplePayPaymentRequest} paymentRequest
|
|
3144
3243
|
*/
|
|
3145
3244
|
_createPaymentSession(applePayment, paymentRequest) {
|
|
@@ -3160,11 +3259,23 @@ class BraintreeApplePayment extends Payment {
|
|
|
3160
3259
|
}
|
|
3161
3260
|
};
|
|
3162
3261
|
|
|
3262
|
+
session.onshippingcontactselected = onShippingContactSelected.bind(
|
|
3263
|
+
this,
|
|
3264
|
+
session,
|
|
3265
|
+
);
|
|
3266
|
+
|
|
3267
|
+
session.onshippingmethodselected = onShippingMethodSelected.bind(
|
|
3268
|
+
this,
|
|
3269
|
+
session,
|
|
3270
|
+
);
|
|
3271
|
+
|
|
3272
|
+
session.oncouponcodechanged = onCouponCodeChanged.bind(this, session);
|
|
3273
|
+
|
|
3163
3274
|
session.onpaymentauthorized = async (event) => {
|
|
3164
3275
|
const {
|
|
3165
3276
|
payment: { token, shippingContact, billingContact },
|
|
3166
3277
|
} = event;
|
|
3167
|
-
|
|
3278
|
+
|
|
3168
3279
|
const payload = await applePayment
|
|
3169
3280
|
.tokenize({ token })
|
|
3170
3281
|
.catch(this.onError.bind(this));
|
|
@@ -3173,23 +3284,47 @@ class BraintreeApplePayment extends Payment {
|
|
|
3173
3284
|
return session.completePayment(this.ApplePaySession.STATUS_FAILURE);
|
|
3174
3285
|
}
|
|
3175
3286
|
|
|
3176
|
-
await this.updateCart({
|
|
3287
|
+
const cart = await this.updateCart({
|
|
3177
3288
|
account: {
|
|
3178
|
-
email: shippingContact
|
|
3289
|
+
email: shippingContact?.emailAddress || billingContact?.emailAddress,
|
|
3179
3290
|
},
|
|
3180
3291
|
billing: {
|
|
3181
3292
|
method: 'apple',
|
|
3293
|
+
account_card_id: null,
|
|
3294
|
+
card: null,
|
|
3182
3295
|
apple: {
|
|
3183
3296
|
nonce: payload.nonce,
|
|
3184
3297
|
gateway: 'braintree',
|
|
3185
3298
|
},
|
|
3186
3299
|
...convertToSwellAddress$1(billingContact),
|
|
3187
3300
|
},
|
|
3188
|
-
...(
|
|
3301
|
+
...(shippingContact && {
|
|
3189
3302
|
shipping: convertToSwellAddress$1(shippingContact),
|
|
3190
3303
|
}),
|
|
3191
3304
|
});
|
|
3192
3305
|
|
|
3306
|
+
if (cart.subscription_delivery) {
|
|
3307
|
+
try {
|
|
3308
|
+
const card = await cardApi.createToken({
|
|
3309
|
+
gateway: 'braintree',
|
|
3310
|
+
account_id: cart.account_id,
|
|
3311
|
+
nonce: payload.nonce,
|
|
3312
|
+
});
|
|
3313
|
+
|
|
3314
|
+
delete card.nonce;
|
|
3315
|
+
|
|
3316
|
+
await this.updateCart({
|
|
3317
|
+
billing: {
|
|
3318
|
+
method: 'card',
|
|
3319
|
+
card,
|
|
3320
|
+
apple: null,
|
|
3321
|
+
},
|
|
3322
|
+
});
|
|
3323
|
+
} catch (error) {
|
|
3324
|
+
console.warn('Failed to extract card data from apple token', error);
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3193
3328
|
this.onSuccess();
|
|
3194
3329
|
|
|
3195
3330
|
return session.completePayment(this.ApplePaySession.STATUS_SUCCESS);
|
|
@@ -3295,6 +3430,8 @@ class AbstractGooglePayment extends Payment {
|
|
|
3295
3430
|
* @returns {google.payments.api.PaymentMethodSpecification}
|
|
3296
3431
|
*/
|
|
3297
3432
|
_getCardPaymentMethod(submit = false) {
|
|
3433
|
+
const { require: { phone } = {} } = this.params;
|
|
3434
|
+
|
|
3298
3435
|
return {
|
|
3299
3436
|
type: 'CARD',
|
|
3300
3437
|
parameters: {
|
|
@@ -3303,7 +3440,7 @@ class AbstractGooglePayment extends Payment {
|
|
|
3303
3440
|
billingAddressRequired: true,
|
|
3304
3441
|
billingAddressParameters: {
|
|
3305
3442
|
format: 'FULL',
|
|
3306
|
-
phoneNumberRequired:
|
|
3443
|
+
phoneNumberRequired: Boolean(phone),
|
|
3307
3444
|
},
|
|
3308
3445
|
},
|
|
3309
3446
|
...(submit && {
|
|
@@ -3336,29 +3473,30 @@ class AbstractGooglePayment extends Payment {
|
|
|
3336
3473
|
cart.shipment_price = 0;
|
|
3337
3474
|
cart.shipping = {};
|
|
3338
3475
|
|
|
3339
|
-
const { shipment_delivery } = cart;
|
|
3340
3476
|
const { require: { email, shipping, phone } = {} } = this.params;
|
|
3341
3477
|
|
|
3478
|
+
/** @type {google.payments.api.CallbackIntent[]} */
|
|
3479
|
+
const callbackIntents = ['OFFER', 'PAYMENT_AUTHORIZATION'];
|
|
3480
|
+
|
|
3481
|
+
if (shipping) {
|
|
3482
|
+
callbackIntents.push('SHIPPING_ADDRESS', 'SHIPPING_OPTION');
|
|
3483
|
+
}
|
|
3484
|
+
|
|
3342
3485
|
return {
|
|
3343
3486
|
apiVersion: API_VERSION,
|
|
3344
3487
|
apiVersionMinor: API_MINOR_VERSION,
|
|
3345
|
-
transactionInfo: getTransactionInfo(cart),
|
|
3488
|
+
transactionInfo: getTransactionInfo.call(this, cart),
|
|
3346
3489
|
allowedPaymentMethods: this._getAllowedPaymentMethods(true),
|
|
3347
3490
|
emailRequired: Boolean(email),
|
|
3348
3491
|
shippingAddressRequired: Boolean(shipping),
|
|
3349
3492
|
shippingAddressParameters: {
|
|
3350
3493
|
phoneNumberRequired: Boolean(phone),
|
|
3351
3494
|
},
|
|
3352
|
-
shippingOptionRequired: Boolean(
|
|
3495
|
+
shippingOptionRequired: Boolean(shipping),
|
|
3353
3496
|
shippingOptionParameters: getShippingOptionParameters.call(this, cart),
|
|
3354
3497
|
offerInfo: getOfferInfo(cart),
|
|
3355
3498
|
merchantInfo,
|
|
3356
|
-
callbackIntents
|
|
3357
|
-
'OFFER',
|
|
3358
|
-
'SHIPPING_ADDRESS',
|
|
3359
|
-
'SHIPPING_OPTION',
|
|
3360
|
-
'PAYMENT_AUTHORIZATION',
|
|
3361
|
-
],
|
|
3499
|
+
callbackIntents,
|
|
3362
3500
|
};
|
|
3363
3501
|
}
|
|
3364
3502
|
|
|
@@ -3482,6 +3620,22 @@ class AbstractGooglePayment extends Payment {
|
|
|
3482
3620
|
/** @typedef {import('../../../types').Cart} Cart */
|
|
3483
3621
|
|
|
3484
3622
|
class AuthorizeNetGooglePayment extends AbstractGooglePayment {
|
|
3623
|
+
/**
|
|
3624
|
+
* @override
|
|
3625
|
+
* @returns {google.payments.api.CardNetwork[]}
|
|
3626
|
+
*/
|
|
3627
|
+
getAllowedCardNetworks() {
|
|
3628
|
+
return ['AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'];
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
/**
|
|
3632
|
+
* @override
|
|
3633
|
+
* @returns {google.payments.api.CardAuthMethod[]}
|
|
3634
|
+
*/
|
|
3635
|
+
getAllowedCardAuthMethods() {
|
|
3636
|
+
return ['PAN_ONLY', 'CRYPTOGRAM_3DS'];
|
|
3637
|
+
}
|
|
3638
|
+
|
|
3485
3639
|
/**
|
|
3486
3640
|
* @override
|
|
3487
3641
|
* @returns {google.payments.api.PaymentGatewayTokenizationParameters}
|
|
@@ -3499,7 +3653,6 @@ class AuthorizeNetGooglePayment extends AbstractGooglePayment {
|
|
|
3499
3653
|
* @returns {Promise<object>}
|
|
3500
3654
|
*/
|
|
3501
3655
|
async preparePaymentDataForCartUpdate(paymentData) {
|
|
3502
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
3503
3656
|
const { email, shippingAddress, shippingOptionData, paymentMethodData } =
|
|
3504
3657
|
paymentData;
|
|
3505
3658
|
|
|
@@ -3520,7 +3673,7 @@ class AuthorizeNetGooglePayment extends AbstractGooglePayment {
|
|
|
3520
3673
|
},
|
|
3521
3674
|
...convertToSwellAddress$2(billingAddress),
|
|
3522
3675
|
},
|
|
3523
|
-
...(
|
|
3676
|
+
...(shippingAddress && {
|
|
3524
3677
|
shipping: {
|
|
3525
3678
|
...convertToSwellAddress$2(shippingAddress),
|
|
3526
3679
|
service: shippingOptionData?.id || undefined,
|
|
@@ -3587,9 +3740,15 @@ class AbstractApplePayment extends Payment {
|
|
|
3587
3740
|
return window.ApplePaySession;
|
|
3588
3741
|
}
|
|
3589
3742
|
|
|
3590
|
-
/**
|
|
3743
|
+
/**
|
|
3744
|
+
* We should specify the payment methods in the order preferred by the gateway.
|
|
3745
|
+
*
|
|
3746
|
+
* @see {@link https://developer.apple.com/documentation/applepayontheweb/applepaypaymentrequest/supportednetworks}
|
|
3747
|
+
*
|
|
3748
|
+
* @returns {string[]}
|
|
3749
|
+
*/
|
|
3591
3750
|
getSupportedCardNetworks() {
|
|
3592
|
-
return ['
|
|
3751
|
+
return ['visa', 'masterCard', 'amex', 'discover', 'interac', 'jcb'];
|
|
3593
3752
|
}
|
|
3594
3753
|
|
|
3595
3754
|
/** @returns {ApplePayJS.ApplePayMerchantCapability[]} */
|
|
@@ -3600,12 +3759,12 @@ class AbstractApplePayment extends Payment {
|
|
|
3600
3759
|
/**
|
|
3601
3760
|
* Creates the Apple Pay payment request object
|
|
3602
3761
|
*
|
|
3603
|
-
* IMPORTANT: countryCode here is the MERCHANT's country (where your business is located),
|
|
3604
|
-
* NOT the customer's country. Customer country comes from shippingContact.countryCode
|
|
3762
|
+
* IMPORTANT: `countryCode` here is the MERCHANT's country (where your business is located),
|
|
3763
|
+
* NOT the customer's country. Customer country comes from `shippingContact.countryCode`.
|
|
3605
3764
|
*
|
|
3606
|
-
* NOTE: We do NOT pass shippingMethods in the initial request. Shipping methods
|
|
3765
|
+
* NOTE: We do NOT pass `shippingMethods` in the initial request. Shipping methods
|
|
3607
3766
|
* are provided dynamically after the user selects/confirms their address in the
|
|
3608
|
-
* 'shippingcontactselected' event handler.
|
|
3767
|
+
* `'shippingcontactselected'` event handler.
|
|
3609
3768
|
*
|
|
3610
3769
|
* @param {Cart} cart
|
|
3611
3770
|
* @returns {ApplePayJS.ApplePayPaymentRequest}
|
|
@@ -3613,38 +3772,21 @@ class AbstractApplePayment extends Payment {
|
|
|
3613
3772
|
_createPaymentRequest(cart) {
|
|
3614
3773
|
cart = { ...cart };
|
|
3615
3774
|
|
|
3616
|
-
const { require = {} } = this.params;
|
|
3617
3775
|
const {
|
|
3618
3776
|
settings: { country },
|
|
3619
3777
|
currency,
|
|
3620
3778
|
} = cart;
|
|
3621
3779
|
|
|
3622
|
-
const requiredShippingContactFields = [];
|
|
3623
|
-
const requiredBillingContactFields = ['postalAddress'];
|
|
3624
|
-
|
|
3625
|
-
if (require.name) {
|
|
3626
|
-
requiredShippingContactFields.push('name');
|
|
3627
|
-
}
|
|
3628
|
-
|
|
3629
|
-
if (require.email) {
|
|
3630
|
-
requiredShippingContactFields.push('email');
|
|
3631
|
-
}
|
|
3632
|
-
|
|
3633
|
-
if (require.phone) {
|
|
3634
|
-
requiredShippingContactFields.push('phone');
|
|
3635
|
-
}
|
|
3636
|
-
|
|
3637
|
-
if (require.shipping) {
|
|
3638
|
-
requiredShippingContactFields.push('postalAddress');
|
|
3639
|
-
}
|
|
3640
|
-
|
|
3641
3780
|
// When initiating a payment request,
|
|
3642
3781
|
// we should not display the shipping cost, as it will be calculated later.
|
|
3643
3782
|
cart.shipment_price = 0;
|
|
3644
3783
|
cart.shipping = {};
|
|
3645
3784
|
|
|
3785
|
+
const { requiredBillingContactFields, requiredShippingContactFields } =
|
|
3786
|
+
getRequiredContactFields(this.params);
|
|
3787
|
+
|
|
3646
3788
|
return {
|
|
3647
|
-
total: getTotal(cart, this.merchantInfo),
|
|
3789
|
+
total: getTotal.call(this, cart, this.merchantInfo),
|
|
3648
3790
|
countryCode: country, // Merchant's country
|
|
3649
3791
|
currencyCode: currency,
|
|
3650
3792
|
supportedNetworks: this.getSupportedCardNetworks(),
|
|
@@ -3826,6 +3968,22 @@ class AbstractApplePayment extends Payment {
|
|
|
3826
3968
|
}
|
|
3827
3969
|
|
|
3828
3970
|
class AuthorizeNetApplePayment extends AbstractApplePayment {
|
|
3971
|
+
/**
|
|
3972
|
+
* @override
|
|
3973
|
+
* @returns {string[]}
|
|
3974
|
+
*/
|
|
3975
|
+
getSupportedCardNetworks() {
|
|
3976
|
+
return ['visa', 'masterCard', 'amex', 'discover'];
|
|
3977
|
+
}
|
|
3978
|
+
|
|
3979
|
+
/**
|
|
3980
|
+
* @override
|
|
3981
|
+
* @returns {ApplePayJS.ApplePayMerchantCapability[]}
|
|
3982
|
+
*/
|
|
3983
|
+
getMerchantCapabilities() {
|
|
3984
|
+
return ['supports3DS', 'supportsDebit', 'supportsCredit'];
|
|
3985
|
+
}
|
|
3986
|
+
|
|
3829
3987
|
/**
|
|
3830
3988
|
* @override
|
|
3831
3989
|
* @param {ApplePayJS.ApplePayValidateMerchantEvent} event
|
|
@@ -3859,11 +4017,9 @@ class AuthorizeNetApplePayment extends AbstractApplePayment {
|
|
|
3859
4017
|
payment: { token, shippingContact, billingContact },
|
|
3860
4018
|
} = event;
|
|
3861
4019
|
|
|
3862
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
3863
|
-
|
|
3864
4020
|
return {
|
|
3865
4021
|
account: {
|
|
3866
|
-
email: shippingContact
|
|
4022
|
+
email: shippingContact?.emailAddress || billingContact?.emailAddress,
|
|
3867
4023
|
},
|
|
3868
4024
|
billing: {
|
|
3869
4025
|
method: 'apple',
|
|
@@ -3875,7 +4031,7 @@ class AuthorizeNetApplePayment extends AbstractApplePayment {
|
|
|
3875
4031
|
},
|
|
3876
4032
|
...convertToSwellAddress$1(billingContact),
|
|
3877
4033
|
},
|
|
3878
|
-
...(
|
|
4034
|
+
...(shippingContact && {
|
|
3879
4035
|
shipping: convertToSwellAddress$1(shippingContact),
|
|
3880
4036
|
}),
|
|
3881
4037
|
};
|
|
@@ -3995,7 +4151,7 @@ async function getConvesioPaymentSettings(mode, settings, country) {
|
|
|
3995
4151
|
merchantAccount: false,
|
|
3996
4152
|
countryCode: country || 'US',
|
|
3997
4153
|
shopperLocale: 'en-US',
|
|
3998
|
-
// shopperReference: email ? md5(email) : undefined,
|
|
4154
|
+
// shopperReference: email ? md5(email.toLowerCase()) : undefined,
|
|
3999
4155
|
}),
|
|
4000
4156
|
},
|
|
4001
4157
|
).then((res) => res.json());
|
|
@@ -4123,15 +4279,20 @@ class ConvesioCardPayment extends Payment {
|
|
|
4123
4279
|
}
|
|
4124
4280
|
}
|
|
4125
4281
|
|
|
4282
|
+
function getBaseConvesioVaultUrl(mode) {
|
|
4283
|
+
return isLiveMode(mode)
|
|
4284
|
+
? 'https://vault.convesiopay.com'
|
|
4285
|
+
: 'https://qa-vault.convesiopay.com';
|
|
4286
|
+
}
|
|
4287
|
+
|
|
4126
4288
|
function createConvesioCardPaymentToken(settings, data) {
|
|
4127
|
-
const baseUrl =
|
|
4289
|
+
const baseUrl = getBaseConvesioVaultUrl(settings.mode);
|
|
4128
4290
|
|
|
4129
4291
|
return fetch(`${baseUrl}/v1/create-token`, {
|
|
4130
4292
|
method: 'POST',
|
|
4131
4293
|
headers: {
|
|
4132
4294
|
Accept: 'application/json',
|
|
4133
4295
|
'Content-Type': 'application/json',
|
|
4134
|
-
'X-Requested-With': 'convesio-pay-dashboard',
|
|
4135
4296
|
'X-Api-Key': settings.public_key,
|
|
4136
4297
|
},
|
|
4137
4298
|
body: JSON.stringify(data),
|
|
@@ -4246,8 +4407,6 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
|
|
|
4246
4407
|
payment: { token, shippingContact, billingContact },
|
|
4247
4408
|
} = event;
|
|
4248
4409
|
|
|
4249
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
4250
|
-
|
|
4251
4410
|
const payment = await createConvesioApplePaymentToken(
|
|
4252
4411
|
this.method.mode,
|
|
4253
4412
|
this.convesiopay,
|
|
@@ -4269,7 +4428,7 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
|
|
|
4269
4428
|
|
|
4270
4429
|
return {
|
|
4271
4430
|
account: {
|
|
4272
|
-
email: shippingContact
|
|
4431
|
+
email: shippingContact?.emailAddress || billingContact?.emailAddress,
|
|
4273
4432
|
},
|
|
4274
4433
|
billing: {
|
|
4275
4434
|
method: 'apple',
|
|
@@ -4284,7 +4443,7 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
|
|
|
4284
4443
|
},
|
|
4285
4444
|
...convertToSwellAddress$1(billingContact),
|
|
4286
4445
|
},
|
|
4287
|
-
...(
|
|
4446
|
+
...(shippingContact && {
|
|
4288
4447
|
shipping: convertToSwellAddress$1(shippingContact),
|
|
4289
4448
|
}),
|
|
4290
4449
|
};
|
|
@@ -4414,7 +4573,6 @@ class ConvesioPayGooglePayment extends AbstractGooglePayment {
|
|
|
4414
4573
|
* @returns {Promise<object>}
|
|
4415
4574
|
*/
|
|
4416
4575
|
async preparePaymentDataForCartUpdate(paymentData) {
|
|
4417
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
4418
4576
|
const { email, shippingAddress, shippingOptionData, paymentMethodData } =
|
|
4419
4577
|
paymentData;
|
|
4420
4578
|
|
|
@@ -4457,7 +4615,7 @@ class ConvesioPayGooglePayment extends AbstractGooglePayment {
|
|
|
4457
4615
|
},
|
|
4458
4616
|
...convertToSwellAddress$2(billingAddress),
|
|
4459
4617
|
},
|
|
4460
|
-
...(
|
|
4618
|
+
...(shippingAddress && {
|
|
4461
4619
|
shipping: {
|
|
4462
4620
|
...convertToSwellAddress$2(shippingAddress),
|
|
4463
4621
|
service: shippingOptionData?.id || undefined,
|
|
@@ -5353,20 +5511,29 @@ class SezzleDirectPayment extends Payment {
|
|
|
5353
5511
|
settings: { name },
|
|
5354
5512
|
} = cart;
|
|
5355
5513
|
|
|
5356
|
-
const
|
|
5514
|
+
const { require: { shipping } = {} } = this.params;
|
|
5357
5515
|
const cartCurrency = getCartCurrency(cart);
|
|
5358
5516
|
|
|
5359
5517
|
return {
|
|
5360
5518
|
checkout_payload: {
|
|
5361
|
-
express_checkout_type:
|
|
5519
|
+
express_checkout_type: shipping ? 'multi-step' : 'no-shipping',
|
|
5520
|
+
customer: {
|
|
5521
|
+
email: cart.account?.email,
|
|
5522
|
+
first_name: cart.account?.first_name,
|
|
5523
|
+
last_name: cart.account?.last_name,
|
|
5524
|
+
phone: cart.account?.phone,
|
|
5525
|
+
// TODO: recurring payments https://docs.sezzle.com/docs/api/tokenization/intro
|
|
5526
|
+
// tokenize: cart.subscription_delivery,
|
|
5527
|
+
// recurring: cart.subscription_delivery,
|
|
5528
|
+
},
|
|
5362
5529
|
order: {
|
|
5363
5530
|
intent: 'AUTH',
|
|
5364
5531
|
reference_id: cart.checkout_id,
|
|
5365
5532
|
description: `${name} #${cart.number}`,
|
|
5366
|
-
requires_shipping_info:
|
|
5533
|
+
requires_shipping_info: shipping,
|
|
5367
5534
|
items: getItems(cart),
|
|
5368
5535
|
discounts: getDiscounts(cart),
|
|
5369
|
-
tax_amount:
|
|
5536
|
+
tax_amount: shipping
|
|
5370
5537
|
? undefined
|
|
5371
5538
|
: getAmountInCents(cartCurrency, cart.tax_total),
|
|
5372
5539
|
order_amount: getAmountInCents(cartCurrency, cart.capture_total),
|
|
@@ -5626,15 +5793,6 @@ function convertToSwellAddress(address) {
|
|
|
5626
5793
|
};
|
|
5627
5794
|
}
|
|
5628
5795
|
|
|
5629
|
-
/**
|
|
5630
|
-
* @param {string} currency
|
|
5631
|
-
* @param {number} amount
|
|
5632
|
-
* @returns {number}
|
|
5633
|
-
*/
|
|
5634
|
-
function amountInCents(currency, amount) {
|
|
5635
|
-
return Math.round(amount * 100);
|
|
5636
|
-
}
|
|
5637
|
-
|
|
5638
5796
|
class PaymentController {
|
|
5639
5797
|
constructor(api, options) {
|
|
5640
5798
|
this.api = api;
|