swell-js 5.1.2 → 5.2.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 +559 -92
- package/dist/swell.cjs +560 -93
- package/dist/swell.cjs.map +1 -1
- package/dist/swell.umd.min.js +560 -93
- package/dist/swell.umd.min.js.map +1 -1
- package/package.json +2 -1
- package/types/index.d.ts +14 -12
- package/types/payment/camel.ts +4 -0
- package/types/payment/index.ts +7 -0
- package/types/payment/snake.ts +42 -10
package/dist/payment.mjs
CHANGED
|
@@ -21,6 +21,7 @@ const SCRIPT_HANDLERS = {
|
|
|
21
21
|
'braintree-google-payment': loadBraintreeGoogle,
|
|
22
22
|
'braintree-apple-payment': loadBraintreeApple,
|
|
23
23
|
'amazon-checkout': loadAmazonCheckout,
|
|
24
|
+
'sezzle-sdk': loadSezzleCheckout,
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
const BRAINTREE_VERSION = '3.91.0';
|
|
@@ -188,6 +189,19 @@ async function loadAmazonCheckout() {
|
|
|
188
189
|
}
|
|
189
190
|
}
|
|
190
191
|
|
|
192
|
+
async function loadSezzleCheckout() {
|
|
193
|
+
if (!window.Checkout) {
|
|
194
|
+
await loadScript(
|
|
195
|
+
'sezzle-sdk',
|
|
196
|
+
'https://checkout-sdk.sezzle.com/express_checkout.min.js',
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (!window.Checkout) {
|
|
201
|
+
console.error('Warning: Sezzle Checkout was not loaded');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
191
205
|
async function loadScripts(scripts) {
|
|
192
206
|
if (!scripts) {
|
|
193
207
|
return;
|
|
@@ -441,8 +455,8 @@ class Payment {
|
|
|
441
455
|
/**
|
|
442
456
|
* Calls the onSuccess handler.
|
|
443
457
|
*
|
|
444
|
-
* @param {
|
|
445
|
-
* @returns {
|
|
458
|
+
* @param {unknown} [data]
|
|
459
|
+
* @returns {unknown}
|
|
446
460
|
*/
|
|
447
461
|
onSuccess(data) {
|
|
448
462
|
const successHandler = get(this.params, 'onSuccess');
|
|
@@ -455,7 +469,7 @@ class Payment {
|
|
|
455
469
|
/**
|
|
456
470
|
* Calls the onCancel handler.
|
|
457
471
|
*
|
|
458
|
-
* @returns {
|
|
472
|
+
* @returns {unknown}
|
|
459
473
|
*/
|
|
460
474
|
onCancel() {
|
|
461
475
|
const cancelHandler = get(this.params, 'onCancel');
|
|
@@ -469,7 +483,7 @@ class Payment {
|
|
|
469
483
|
* Calls the onError handler.
|
|
470
484
|
*
|
|
471
485
|
* @param {Error} error
|
|
472
|
-
* @returns {
|
|
486
|
+
* @returns {unknown}
|
|
473
487
|
*/
|
|
474
488
|
onError(error) {
|
|
475
489
|
const errorHandler = get(this.params, 'onError');
|
|
@@ -1983,6 +1997,107 @@ class BraintreePaypalPayment extends Payment {
|
|
|
1983
1997
|
}
|
|
1984
1998
|
}
|
|
1985
1999
|
|
|
2000
|
+
/** @typedef {import('../../types').Cart} Cart */
|
|
2001
|
+
/** @typedef {import('../../types').Discount} Discount */
|
|
2002
|
+
|
|
2003
|
+
function adjustConfig(params) {
|
|
2004
|
+
if (!params.config) {
|
|
2005
|
+
return;
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
if (params.card) {
|
|
2009
|
+
console.warn('Please move the "config" field to the "card.config"');
|
|
2010
|
+
|
|
2011
|
+
params.card.config = params.config;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
if (params.ideal) {
|
|
2015
|
+
console.warn('Please move the "config" field to the "ideal.config"');
|
|
2016
|
+
|
|
2017
|
+
params.ideal.config = params.config;
|
|
2018
|
+
}
|
|
2019
|
+
|
|
2020
|
+
delete params.config;
|
|
2021
|
+
}
|
|
2022
|
+
|
|
2023
|
+
function adjustElementId(methodParams) {
|
|
2024
|
+
if (methodParams.cardNumber) {
|
|
2025
|
+
adjustElementId(methodParams.cardNumber);
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
if (methodParams.cardExpiry) {
|
|
2029
|
+
adjustElementId(methodParams.cardExpiry);
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
if (methodParams.cardCvc) {
|
|
2033
|
+
adjustElementId(methodParams.cardCvc);
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
if (!methodParams.elementId) {
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
if (methodParams.elementId.startsWith('#')) {
|
|
2041
|
+
console.warn(
|
|
2042
|
+
`Please remove the "#" sign from the "${methodParams.elementId}" element ID`,
|
|
2043
|
+
);
|
|
2044
|
+
|
|
2045
|
+
methodParams.elementId = methodParams.elementId.substring(1);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
function adjustParams(_params) {
|
|
2050
|
+
const params = { ..._params };
|
|
2051
|
+
|
|
2052
|
+
adjustConfig(params);
|
|
2053
|
+
|
|
2054
|
+
return params;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
function adjustMethodParams(_methodParams) {
|
|
2058
|
+
const methodParams = { ..._methodParams };
|
|
2059
|
+
|
|
2060
|
+
adjustElementId(methodParams);
|
|
2061
|
+
|
|
2062
|
+
return methodParams;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
/**
|
|
2066
|
+
* @param {Discount} discount
|
|
2067
|
+
* @param {Cart} cart
|
|
2068
|
+
*/
|
|
2069
|
+
function getDiscountLabel(discount, cart) {
|
|
2070
|
+
switch (discount.type) {
|
|
2071
|
+
case 'coupon': {
|
|
2072
|
+
const { coupon } = cart;
|
|
2073
|
+
|
|
2074
|
+
if (coupon?.name) {
|
|
2075
|
+
return coupon.name;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
break;
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
case 'promo': {
|
|
2082
|
+
const { promotions } = cart;
|
|
2083
|
+
|
|
2084
|
+
if (Array.isArray(promotions?.results)) {
|
|
2085
|
+
const promo = promotions.results.find(
|
|
2086
|
+
(promo) => promo.id === discount.source_id,
|
|
2087
|
+
);
|
|
2088
|
+
|
|
2089
|
+
if (promo?.name) {
|
|
2090
|
+
return promo?.name;
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
break;
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
return discount.id;
|
|
2099
|
+
}
|
|
2100
|
+
|
|
1986
2101
|
/** @typedef {import('./payment').default} Payment */
|
|
1987
2102
|
/** @typedef {import('../../types').Cart} Cart */
|
|
1988
2103
|
/** @typedef {import('../../types').Address} Address */
|
|
@@ -2025,7 +2140,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
|
|
|
2025
2140
|
|
|
2026
2141
|
// Update cart with new shipping address and force tax recalculation
|
|
2027
2142
|
let cart = await this.updateCart({
|
|
2028
|
-
shipping: convertToSwellAddress$
|
|
2143
|
+
shipping: convertToSwellAddress$2(
|
|
2029
2144
|
intermediatePaymentData.shippingAddress,
|
|
2030
2145
|
),
|
|
2031
2146
|
});
|
|
@@ -2118,42 +2233,6 @@ async function onPaymentDataChanged(intermediatePaymentData) {
|
|
|
2118
2233
|
return {};
|
|
2119
2234
|
}
|
|
2120
2235
|
|
|
2121
|
-
/**
|
|
2122
|
-
* @param {Discount} discount
|
|
2123
|
-
* @param {Cart} cart
|
|
2124
|
-
*/
|
|
2125
|
-
function getDiscountLabel(discount, cart) {
|
|
2126
|
-
switch (discount.type) {
|
|
2127
|
-
case 'coupon': {
|
|
2128
|
-
const { coupon } = cart;
|
|
2129
|
-
|
|
2130
|
-
if (coupon?.name) {
|
|
2131
|
-
return coupon.name;
|
|
2132
|
-
}
|
|
2133
|
-
|
|
2134
|
-
break;
|
|
2135
|
-
}
|
|
2136
|
-
|
|
2137
|
-
case 'promo': {
|
|
2138
|
-
const { promotions } = cart;
|
|
2139
|
-
|
|
2140
|
-
if (Array.isArray(promotions?.results)) {
|
|
2141
|
-
const promo = promotions.results.find(
|
|
2142
|
-
(promo) => promo.id === discount.source_id,
|
|
2143
|
-
);
|
|
2144
|
-
|
|
2145
|
-
if (promo?.name) {
|
|
2146
|
-
return promo?.name;
|
|
2147
|
-
}
|
|
2148
|
-
}
|
|
2149
|
-
|
|
2150
|
-
break;
|
|
2151
|
-
}
|
|
2152
|
-
}
|
|
2153
|
-
|
|
2154
|
-
return discount.id;
|
|
2155
|
-
}
|
|
2156
|
-
|
|
2157
2236
|
/**
|
|
2158
2237
|
* Converts cart data to Google Pay display items for the payment sheet.
|
|
2159
2238
|
* Only works when payment callbacks are properly configured.
|
|
@@ -2311,7 +2390,7 @@ function getOfferInfo(cart) {
|
|
|
2311
2390
|
* @param {google.payments.api.Address} address
|
|
2312
2391
|
* @returns {Address}
|
|
2313
2392
|
*/
|
|
2314
|
-
function convertToSwellAddress$
|
|
2393
|
+
function convertToSwellAddress$2(address) {
|
|
2315
2394
|
return {
|
|
2316
2395
|
name: address.name,
|
|
2317
2396
|
address1: address.address1,
|
|
@@ -2572,10 +2651,10 @@ class BraintreeGooglePayment extends Payment {
|
|
|
2572
2651
|
nonce,
|
|
2573
2652
|
gateway: 'braintree',
|
|
2574
2653
|
},
|
|
2575
|
-
...convertToSwellAddress$
|
|
2654
|
+
...convertToSwellAddress$2(billingAddress),
|
|
2576
2655
|
},
|
|
2577
2656
|
...(requireShipping && {
|
|
2578
|
-
shipping: convertToSwellAddress$
|
|
2657
|
+
shipping: convertToSwellAddress$2(shippingAddress),
|
|
2579
2658
|
}),
|
|
2580
2659
|
});
|
|
2581
2660
|
|
|
@@ -2612,7 +2691,7 @@ async function onShippingContactSelected(session, event) {
|
|
|
2612
2691
|
// Update cart with Apple Pay shipping address to get shipping options and tax
|
|
2613
2692
|
// This happens immediately when the sheet opens with the default address
|
|
2614
2693
|
const cart = await this.updateCart({
|
|
2615
|
-
shipping: convertToSwellAddress(event.shippingContact),
|
|
2694
|
+
shipping: convertToSwellAddress$1(event.shippingContact),
|
|
2616
2695
|
});
|
|
2617
2696
|
|
|
2618
2697
|
if (!cart.shipment_rating?.services?.length) {
|
|
@@ -2854,7 +2933,7 @@ function getShippingMethods(cart) {
|
|
|
2854
2933
|
* @param {ApplePayJS.ApplePayPaymentContact} [address]
|
|
2855
2934
|
* @returns {Address}
|
|
2856
2935
|
*/
|
|
2857
|
-
function convertToSwellAddress(address = {}) {
|
|
2936
|
+
function convertToSwellAddress$1(address = {}) {
|
|
2858
2937
|
return {
|
|
2859
2938
|
first_name: address.givenName,
|
|
2860
2939
|
last_name: address.familyName,
|
|
@@ -3059,10 +3138,10 @@ class BraintreeApplePayment extends Payment {
|
|
|
3059
3138
|
nonce: payload.nonce,
|
|
3060
3139
|
gateway: 'braintree',
|
|
3061
3140
|
},
|
|
3062
|
-
...convertToSwellAddress(billingContact),
|
|
3141
|
+
...convertToSwellAddress$1(billingContact),
|
|
3063
3142
|
},
|
|
3064
3143
|
...(requireShipping && {
|
|
3065
|
-
shipping: convertToSwellAddress(shippingContact),
|
|
3144
|
+
shipping: convertToSwellAddress$1(shippingContact),
|
|
3066
3145
|
}),
|
|
3067
3146
|
});
|
|
3068
3147
|
|
|
@@ -3240,7 +3319,7 @@ class AuthorizeNetGooglePayment extends Payment {
|
|
|
3240
3319
|
throw new Error('Payment token is missing');
|
|
3241
3320
|
}
|
|
3242
3321
|
|
|
3243
|
-
|
|
3322
|
+
await this.updateCart({
|
|
3244
3323
|
account: {
|
|
3245
3324
|
email,
|
|
3246
3325
|
},
|
|
@@ -3252,14 +3331,14 @@ class AuthorizeNetGooglePayment extends Payment {
|
|
|
3252
3331
|
gateway: 'authorizenet',
|
|
3253
3332
|
token: base64Encode(token),
|
|
3254
3333
|
},
|
|
3255
|
-
...convertToSwellAddress$
|
|
3334
|
+
...convertToSwellAddress$2(billingAddress),
|
|
3256
3335
|
},
|
|
3257
3336
|
...(requireShipping && {
|
|
3258
|
-
shipping: convertToSwellAddress$
|
|
3337
|
+
shipping: convertToSwellAddress$2(shippingAddress),
|
|
3259
3338
|
}),
|
|
3260
3339
|
});
|
|
3261
3340
|
|
|
3262
|
-
this.onSuccess(
|
|
3341
|
+
this.onSuccess();
|
|
3263
3342
|
}
|
|
3264
3343
|
|
|
3265
3344
|
/**
|
|
@@ -3541,7 +3620,7 @@ class AuthorizeNetApplePayment extends Payment {
|
|
|
3541
3620
|
//
|
|
3542
3621
|
// We store the payment token but DO NOT process the order yet.
|
|
3543
3622
|
// The user must manually click "Place Order" to complete the transaction.
|
|
3544
|
-
|
|
3623
|
+
await this.updateCart({
|
|
3545
3624
|
account: {
|
|
3546
3625
|
email: shippingContact.emailAddress,
|
|
3547
3626
|
},
|
|
@@ -3553,10 +3632,10 @@ class AuthorizeNetApplePayment extends Payment {
|
|
|
3553
3632
|
token: base64Encode(JSON.stringify(token.paymentData)),
|
|
3554
3633
|
gateway: 'authorizenet',
|
|
3555
3634
|
},
|
|
3556
|
-
...convertToSwellAddress(billingContact),
|
|
3635
|
+
...convertToSwellAddress$1(billingContact),
|
|
3557
3636
|
},
|
|
3558
3637
|
...(requireShipping && {
|
|
3559
|
-
shipping: convertToSwellAddress(shippingContact),
|
|
3638
|
+
shipping: convertToSwellAddress$1(shippingContact),
|
|
3560
3639
|
}),
|
|
3561
3640
|
});
|
|
3562
3641
|
|
|
@@ -3569,7 +3648,7 @@ class AuthorizeNetApplePayment extends Payment {
|
|
|
3569
3648
|
// Notify that Apple Pay authorization is complete
|
|
3570
3649
|
// The cart now has the payment token and is ready for submission
|
|
3571
3650
|
// NOTE: This does NOT submit the order - user must click "Place Order"
|
|
3572
|
-
this.onSuccess(
|
|
3651
|
+
this.onSuccess();
|
|
3573
3652
|
} catch (err) {
|
|
3574
3653
|
session.completePayment({
|
|
3575
3654
|
status: this.ApplePaySession.STATUS_FAILURE,
|
|
@@ -4395,66 +4474,438 @@ class AmazonDirectPayment extends Payment {
|
|
|
4395
4474
|
}
|
|
4396
4475
|
}
|
|
4397
4476
|
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4477
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
4478
|
+
/** @typedef {import('../../../types').Address} Address */
|
|
4479
|
+
|
|
4480
|
+
/**
|
|
4481
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutPayloadOrderAmount
|
|
4482
|
+
* @prop {number} amount_in_cents
|
|
4483
|
+
* @prop {string} currency
|
|
4484
|
+
*/
|
|
4485
|
+
|
|
4486
|
+
/**
|
|
4487
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutPayloadOrderItem
|
|
4488
|
+
* @prop {string} name
|
|
4489
|
+
* @prop {string} sku
|
|
4490
|
+
* @prop {number} quantity
|
|
4491
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadOrderAmount} price
|
|
4492
|
+
*/
|
|
4493
|
+
|
|
4494
|
+
/**
|
|
4495
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutPayloadOrderDiscount
|
|
4496
|
+
* @prop {string} name
|
|
4497
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadOrderAmount} amount
|
|
4498
|
+
*/
|
|
4499
|
+
|
|
4500
|
+
/**
|
|
4501
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutPayloadOrder
|
|
4502
|
+
* @prop {'AUTH' | 'CAPTURE'} intent
|
|
4503
|
+
* @prop {string} reference_id
|
|
4504
|
+
* @prop {string} description
|
|
4505
|
+
* @prop {boolean} requires_shipping_info
|
|
4506
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadOrderItem[]} items
|
|
4507
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadOrderDiscount[]} discounts
|
|
4508
|
+
* @prop {Record<string, string>} [metadata]
|
|
4509
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadOrderAmount} tax_amount
|
|
4510
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadOrderAmount} order_amount
|
|
4511
|
+
*/
|
|
4512
|
+
|
|
4513
|
+
/**
|
|
4514
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutPayloadData
|
|
4515
|
+
* @prop {'single-step' | 'multi-step' | 'no-shipping'} express_checkout_type
|
|
4516
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadOrder} order
|
|
4517
|
+
*/
|
|
4518
|
+
|
|
4519
|
+
/**
|
|
4520
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutPayload
|
|
4521
|
+
* @prop {SezzleCheckoutSdkCheckoutPayloadData} checkout_payload
|
|
4522
|
+
*/
|
|
4523
|
+
|
|
4524
|
+
/**
|
|
4525
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutUrl
|
|
4526
|
+
* @prop {string} checkout_url
|
|
4527
|
+
*/
|
|
4528
|
+
|
|
4529
|
+
/**
|
|
4530
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutShippingAddress
|
|
4531
|
+
* @prop {string} uuid
|
|
4532
|
+
* @prop {string} name
|
|
4533
|
+
* @prop {string} street
|
|
4534
|
+
* @prop {string} street2
|
|
4535
|
+
* @prop {string} city
|
|
4536
|
+
* @prop {string} state
|
|
4537
|
+
* @prop {string} postal_code
|
|
4538
|
+
* @prop {string} country_code
|
|
4539
|
+
* @prop {string} phone
|
|
4540
|
+
*/
|
|
4541
|
+
|
|
4542
|
+
/**
|
|
4543
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutShippingError
|
|
4544
|
+
* @prop {'merchant_unsupported_shipping_address' | 'merchant_error'} code
|
|
4545
|
+
*/
|
|
4546
|
+
|
|
4547
|
+
/**
|
|
4548
|
+
* @typedef {object} SezzleCheckoutSdkCheckoutShippingResult
|
|
4549
|
+
* @prop {boolean} ok
|
|
4550
|
+
* @prop {SezzleCheckoutSdkCheckoutShippingError} [error]
|
|
4551
|
+
*/
|
|
4552
|
+
|
|
4553
|
+
/**
|
|
4554
|
+
* @typedef {object} SezzleCheckoutSdkInit
|
|
4555
|
+
* @prop {(event: MouseEvent) => void} onClick
|
|
4556
|
+
* @prop {(event: CustomEvent) => void} onComplete
|
|
4557
|
+
* @prop {() => void} onCancel
|
|
4558
|
+
* @prop {() => void} onFailure
|
|
4559
|
+
* @prop {(shippingAddress: SezzleCheckoutSdkCheckoutShippingAddress, orderUuid: string) => Promise<SezzleCheckoutSdkCheckoutShippingResult>} onCalculateAddressRelatedCosts
|
|
4560
|
+
*/
|
|
4561
|
+
|
|
4562
|
+
/**
|
|
4563
|
+
* @typedef {object} SezzleCheckoutSdk
|
|
4564
|
+
* @prop {(containerId: string) => void} renderSezzleButton
|
|
4565
|
+
* @prop {(options: SezzleCheckoutSdkInit) => void} init
|
|
4566
|
+
* @prop {(options: SezzleCheckoutSdkCheckoutPayload | SezzleCheckoutSdkCheckoutUrl) => void} startCheckout
|
|
4567
|
+
*/
|
|
4568
|
+
|
|
4569
|
+
/**
|
|
4570
|
+
* @typedef {object} SezzleCheckoutOptions
|
|
4571
|
+
* @prop {'popup' | 'iframe' | 'redirect'} [mode='popup']
|
|
4572
|
+
* @prop {string} publicKey
|
|
4573
|
+
* @prop {'live' | 'sandbox'} [apiMode='live']
|
|
4574
|
+
* @prop {'v2'} [apiVersion='v2']
|
|
4575
|
+
*/
|
|
4576
|
+
|
|
4577
|
+
/** @typedef {new (options: SezzleCheckoutOptions) => SezzleCheckoutSdk} SezzleCheckout */
|
|
4578
|
+
|
|
4579
|
+
const SEZZLE_BUTTON_ID = 'sezzle-smart-button-container';
|
|
4580
|
+
|
|
4581
|
+
class SezzleDirectPayment extends Payment {
|
|
4582
|
+
constructor(api, options, params, methods) {
|
|
4583
|
+
super(api, options, params, methods.sezzle);
|
|
4584
|
+
|
|
4585
|
+
/** @type {SezzleCheckoutSdkCheckoutPayload | null} */
|
|
4586
|
+
this._paymentRequest = null;
|
|
4401
4587
|
}
|
|
4402
4588
|
|
|
4403
|
-
|
|
4404
|
-
|
|
4589
|
+
get scripts() {
|
|
4590
|
+
return ['sezzle-sdk'];
|
|
4591
|
+
}
|
|
4405
4592
|
|
|
4406
|
-
|
|
4593
|
+
/** @returns {SezzleCheckout} */
|
|
4594
|
+
get SezzleCheckout() {
|
|
4595
|
+
if (!window.Checkout) {
|
|
4596
|
+
throw new LibraryNotLoadedError('Sezzle');
|
|
4597
|
+
}
|
|
4598
|
+
|
|
4599
|
+
return window.Checkout;
|
|
4407
4600
|
}
|
|
4408
4601
|
|
|
4409
|
-
|
|
4410
|
-
|
|
4602
|
+
/** @returns {SezzleCheckoutSdk} */
|
|
4603
|
+
get SezzleSdk() {
|
|
4604
|
+
if (!this._sezzleSdk) {
|
|
4605
|
+
this._sezzleSdk = new this.SezzleCheckout({
|
|
4606
|
+
mode: 'popup',
|
|
4607
|
+
publicKey: this.method.public_key,
|
|
4608
|
+
apiMode: isLiveMode(this.method.mode) ? 'live' : 'sandbox',
|
|
4609
|
+
apiVersion: 'v2',
|
|
4610
|
+
});
|
|
4411
4611
|
|
|
4412
|
-
|
|
4612
|
+
if (!this._sezzleSdk) {
|
|
4613
|
+
throw new LibraryNotLoadedError('Sezzle sdk client');
|
|
4614
|
+
}
|
|
4615
|
+
}
|
|
4616
|
+
|
|
4617
|
+
return this._sezzleSdk;
|
|
4413
4618
|
}
|
|
4414
4619
|
|
|
4415
|
-
|
|
4416
|
-
}
|
|
4620
|
+
/**
|
|
4621
|
+
* @param {Cart} cart
|
|
4622
|
+
* @returns {SezzleCheckoutSdkCheckoutPayload}
|
|
4623
|
+
*/
|
|
4624
|
+
_createPaymentRequest(cart) {
|
|
4625
|
+
const {
|
|
4626
|
+
settings: { name },
|
|
4627
|
+
} = cart;
|
|
4417
4628
|
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4629
|
+
const shipmentDelivery = Boolean(cart.shipment_delivery);
|
|
4630
|
+
const cartCurrency = getCartCurrency(cart);
|
|
4631
|
+
|
|
4632
|
+
return {
|
|
4633
|
+
checkout_payload: {
|
|
4634
|
+
express_checkout_type: shipmentDelivery ? 'multi-step' : 'no-shipping',
|
|
4635
|
+
order: {
|
|
4636
|
+
intent: 'AUTH',
|
|
4637
|
+
reference_id: cart.checkout_id,
|
|
4638
|
+
description: `${name} #${cart.number}`,
|
|
4639
|
+
requires_shipping_info: shipmentDelivery,
|
|
4640
|
+
items: getItems(cart),
|
|
4641
|
+
discounts: getDiscounts(cart),
|
|
4642
|
+
tax_amount: shipmentDelivery
|
|
4643
|
+
? undefined
|
|
4644
|
+
: getAmountInCents(cartCurrency, cart.tax_total),
|
|
4645
|
+
order_amount: getAmountInCents(cartCurrency, cart.capture_total),
|
|
4646
|
+
},
|
|
4647
|
+
},
|
|
4648
|
+
};
|
|
4421
4649
|
}
|
|
4422
4650
|
|
|
4423
|
-
|
|
4424
|
-
|
|
4651
|
+
_createButton() {
|
|
4652
|
+
const { style = {} } = this.params;
|
|
4653
|
+
|
|
4654
|
+
if (!style.templateText) {
|
|
4655
|
+
style.templateText = '%%logo%%';
|
|
4656
|
+
}
|
|
4657
|
+
|
|
4658
|
+
if (!style.borderType) {
|
|
4659
|
+
style.borderType = 'square';
|
|
4660
|
+
}
|
|
4661
|
+
|
|
4662
|
+
if (!style.width) {
|
|
4663
|
+
style.width = '100%';
|
|
4664
|
+
}
|
|
4665
|
+
|
|
4666
|
+
if (!style.height) {
|
|
4667
|
+
style.height = '45px';
|
|
4668
|
+
}
|
|
4669
|
+
|
|
4670
|
+
const button = document.createElement('div');
|
|
4671
|
+
|
|
4672
|
+
for (const attrId of Object.keys(style)) {
|
|
4673
|
+
button.setAttribute(attrId, style[attrId]);
|
|
4674
|
+
}
|
|
4675
|
+
|
|
4676
|
+
button.setAttribute('id', SEZZLE_BUTTON_ID);
|
|
4677
|
+
button.style.textAlign = 'center';
|
|
4678
|
+
|
|
4679
|
+
return button;
|
|
4425
4680
|
}
|
|
4426
4681
|
|
|
4427
|
-
|
|
4428
|
-
|
|
4682
|
+
_initSezzleSdk() {
|
|
4683
|
+
let shippingServices = [];
|
|
4684
|
+
|
|
4685
|
+
this.SezzleSdk.init({
|
|
4686
|
+
onClick: (event) => {
|
|
4687
|
+
event.preventDefault();
|
|
4688
|
+
|
|
4689
|
+
this.SezzleSdk.startCheckout(this._paymentRequest);
|
|
4690
|
+
},
|
|
4691
|
+
onComplete: async (event) => {
|
|
4692
|
+
try {
|
|
4693
|
+
const { order_uuid } = event.data;
|
|
4694
|
+
|
|
4695
|
+
const details = await this.authorizeGateway({
|
|
4696
|
+
gateway: 'sezzle',
|
|
4697
|
+
params: {
|
|
4698
|
+
action: 'details',
|
|
4699
|
+
order_uuid,
|
|
4700
|
+
},
|
|
4701
|
+
});
|
|
4702
|
+
|
|
4703
|
+
let shippingService = null;
|
|
4704
|
+
|
|
4705
|
+
if (details.service_name) {
|
|
4706
|
+
shippingService =
|
|
4707
|
+
shippingServices.find(
|
|
4708
|
+
(service) => service.name === details.service_name,
|
|
4709
|
+
)?.id ?? null;
|
|
4710
|
+
}
|
|
4711
|
+
|
|
4712
|
+
await this.updateCart({
|
|
4713
|
+
account: details.account,
|
|
4714
|
+
shipping: {
|
|
4715
|
+
...details.shipping,
|
|
4716
|
+
service: shippingService,
|
|
4717
|
+
},
|
|
4718
|
+
billing: {
|
|
4719
|
+
method: 'sezzle',
|
|
4720
|
+
account_card_id: null,
|
|
4721
|
+
card: null,
|
|
4722
|
+
sezzle: { order_uuid },
|
|
4723
|
+
...details.billing,
|
|
4724
|
+
},
|
|
4725
|
+
});
|
|
4726
|
+
|
|
4727
|
+
this.onSuccess();
|
|
4728
|
+
} catch (err) {
|
|
4729
|
+
this.onError(err);
|
|
4730
|
+
}
|
|
4731
|
+
},
|
|
4732
|
+
onCancel(_event) {},
|
|
4733
|
+
onFailure: (event) => {
|
|
4734
|
+
this.onError(event.data);
|
|
4735
|
+
},
|
|
4736
|
+
onCalculateAddressRelatedCosts: async (address, orderUuid) => {
|
|
4737
|
+
const cart = await this.updateCart({
|
|
4738
|
+
shipping: convertToSwellAddress(address),
|
|
4739
|
+
});
|
|
4740
|
+
|
|
4741
|
+
if (!cart.shipment_rating?.services?.length) {
|
|
4742
|
+
return {
|
|
4743
|
+
ok: false,
|
|
4744
|
+
error: { code: 'merchant_unsupported_shipping_address' },
|
|
4745
|
+
};
|
|
4746
|
+
}
|
|
4747
|
+
|
|
4748
|
+
shippingServices = cart.shipment_rating.services;
|
|
4749
|
+
|
|
4750
|
+
const result = await this.authorizeGateway({
|
|
4751
|
+
gateway: 'sezzle',
|
|
4752
|
+
params: {
|
|
4753
|
+
action: 'shipping',
|
|
4754
|
+
order_uuid: orderUuid,
|
|
4755
|
+
currency_code: cart.currency,
|
|
4756
|
+
address_uuid: address.uuid,
|
|
4757
|
+
shipping_options: cart.shipment_rating.services.map((service) => ({
|
|
4758
|
+
name: service.name,
|
|
4759
|
+
description: service.description,
|
|
4760
|
+
shipping_amount_in_cents: amountInCents(
|
|
4761
|
+
cart.currency,
|
|
4762
|
+
service.price || 0,
|
|
4763
|
+
),
|
|
4764
|
+
tax_amount_in_cents: amountInCents(
|
|
4765
|
+
cart.currency,
|
|
4766
|
+
cart.tax_total || 0,
|
|
4767
|
+
),
|
|
4768
|
+
final_order_amount_in_cents: amountInCents(
|
|
4769
|
+
cart.currency,
|
|
4770
|
+
(cart.sub_total || 0) +
|
|
4771
|
+
(cart.tax_total || 0) +
|
|
4772
|
+
(service.price || 0),
|
|
4773
|
+
),
|
|
4774
|
+
})),
|
|
4775
|
+
},
|
|
4776
|
+
});
|
|
4777
|
+
|
|
4778
|
+
if (result?.error) {
|
|
4779
|
+
console.error(
|
|
4780
|
+
'[Sezzle] Update checkout by order error:',
|
|
4781
|
+
result.error,
|
|
4782
|
+
);
|
|
4783
|
+
|
|
4784
|
+
return {
|
|
4785
|
+
ok: false,
|
|
4786
|
+
error: { code: 'merchant_error' },
|
|
4787
|
+
};
|
|
4788
|
+
}
|
|
4789
|
+
|
|
4790
|
+
return { ok: true };
|
|
4791
|
+
},
|
|
4792
|
+
});
|
|
4429
4793
|
}
|
|
4430
4794
|
|
|
4431
|
-
|
|
4432
|
-
|
|
4795
|
+
/**
|
|
4796
|
+
* Creates the Sezzle button element
|
|
4797
|
+
*
|
|
4798
|
+
* @param {Cart} cart
|
|
4799
|
+
*/
|
|
4800
|
+
async createElements(cart) {
|
|
4801
|
+
const { elementId = 'sezzle-button' } = this.params;
|
|
4802
|
+
|
|
4803
|
+
this.setElementContainer(elementId);
|
|
4804
|
+
await this.loadScripts(this.scripts);
|
|
4805
|
+
|
|
4806
|
+
this._paymentRequest = this._createPaymentRequest(cart);
|
|
4807
|
+
|
|
4808
|
+
this.element = this._createButton();
|
|
4433
4809
|
}
|
|
4434
4810
|
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4811
|
+
/**
|
|
4812
|
+
* Mounts the Sezzle button to the DOM
|
|
4813
|
+
*/
|
|
4814
|
+
mountElements() {
|
|
4815
|
+
const { classes = {} } = this.params;
|
|
4816
|
+
const container = this.elementContainer;
|
|
4439
4817
|
|
|
4440
|
-
|
|
4818
|
+
container.appendChild(this.element);
|
|
4819
|
+
|
|
4820
|
+
this.SezzleSdk.renderSezzleButton(SEZZLE_BUTTON_ID);
|
|
4821
|
+
|
|
4822
|
+
if (classes.base) {
|
|
4823
|
+
container.classList.add(classes.base);
|
|
4824
|
+
}
|
|
4825
|
+
|
|
4826
|
+
this._initSezzleSdk();
|
|
4441
4827
|
}
|
|
4442
4828
|
}
|
|
4443
4829
|
|
|
4444
|
-
|
|
4445
|
-
|
|
4830
|
+
/**
|
|
4831
|
+
* @param {Cart} cart
|
|
4832
|
+
* @returns {string}
|
|
4833
|
+
*/
|
|
4834
|
+
function getCartCurrency(cart) {
|
|
4835
|
+
const {
|
|
4836
|
+
settings: { currency },
|
|
4837
|
+
} = cart;
|
|
4446
4838
|
|
|
4447
|
-
|
|
4839
|
+
return cart.currency || currency || 'USD';
|
|
4840
|
+
}
|
|
4448
4841
|
|
|
4449
|
-
|
|
4842
|
+
/**
|
|
4843
|
+
* @param {string} currency
|
|
4844
|
+
* @param {number} amount
|
|
4845
|
+
* @returns {SezzleCheckoutSdkCheckoutPayloadOrderAmount}
|
|
4846
|
+
*/
|
|
4847
|
+
function getAmountInCents(currency, amount) {
|
|
4848
|
+
return {
|
|
4849
|
+
amount_in_cents: amountInCents(currency, amount),
|
|
4850
|
+
currency,
|
|
4851
|
+
};
|
|
4450
4852
|
}
|
|
4451
4853
|
|
|
4452
|
-
|
|
4453
|
-
|
|
4854
|
+
/**
|
|
4855
|
+
* @param {Cart} cart
|
|
4856
|
+
* @returns {SezzleCheckoutSdkCheckoutPayloadOrderItem[]}
|
|
4857
|
+
*/
|
|
4858
|
+
function getItems(cart) {
|
|
4859
|
+
const currency = getCartCurrency(cart);
|
|
4860
|
+
|
|
4861
|
+
/** @type {SezzleCheckoutSdkCheckoutPayloadOrderItem[]} */
|
|
4862
|
+
const items = cart.items.map((item, index) => ({
|
|
4863
|
+
name: item.product?.name || `Product ${index + 1}`,
|
|
4864
|
+
sku: item.product?.sku || `Product SKU ${index + 1}`,
|
|
4865
|
+
quantity: item.quantity || 1,
|
|
4866
|
+
price: getAmountInCents(currency, item.price || 0),
|
|
4867
|
+
}));
|
|
4454
4868
|
|
|
4455
|
-
|
|
4869
|
+
return items;
|
|
4870
|
+
}
|
|
4456
4871
|
|
|
4457
|
-
|
|
4872
|
+
/**
|
|
4873
|
+
* @param {Cart} cart
|
|
4874
|
+
* @returns {SezzleCheckoutSdkCheckoutPayloadOrderDiscount[]}
|
|
4875
|
+
*/
|
|
4876
|
+
function getDiscounts(cart) {
|
|
4877
|
+
const currency = getCartCurrency(cart);
|
|
4878
|
+
|
|
4879
|
+
return (cart.discounts || []).map((discount) => ({
|
|
4880
|
+
name: getDiscountLabel(discount, cart),
|
|
4881
|
+
amount: getAmountInCents(currency, discount.amount || 0),
|
|
4882
|
+
}));
|
|
4883
|
+
}
|
|
4884
|
+
|
|
4885
|
+
/**
|
|
4886
|
+
* @param {SezzleCheckoutSdkCheckoutShippingAddress} address
|
|
4887
|
+
* @returns {Address}
|
|
4888
|
+
*/
|
|
4889
|
+
function convertToSwellAddress(address) {
|
|
4890
|
+
return {
|
|
4891
|
+
name: address.name || null,
|
|
4892
|
+
address1: address.street || null,
|
|
4893
|
+
address2: address.street2 || null,
|
|
4894
|
+
city: address.city || null,
|
|
4895
|
+
state: address.state || null,
|
|
4896
|
+
zip: address.postal_code || null,
|
|
4897
|
+
country: address.country_code || null,
|
|
4898
|
+
phone: address.phone || null,
|
|
4899
|
+
};
|
|
4900
|
+
}
|
|
4901
|
+
|
|
4902
|
+
/**
|
|
4903
|
+
* @param {string} currency
|
|
4904
|
+
* @param {number} amount
|
|
4905
|
+
* @returns {number}
|
|
4906
|
+
*/
|
|
4907
|
+
function amountInCents(currency, amount) {
|
|
4908
|
+
return Math.round(amount * 100);
|
|
4458
4909
|
}
|
|
4459
4910
|
|
|
4460
4911
|
class PaymentController {
|
|
@@ -4623,6 +5074,9 @@ class PaymentController {
|
|
|
4623
5074
|
return response;
|
|
4624
5075
|
}
|
|
4625
5076
|
|
|
5077
|
+
/**
|
|
5078
|
+
* @returns {Promise<Payment[]>}
|
|
5079
|
+
*/
|
|
4626
5080
|
async _createPaymentInstances() {
|
|
4627
5081
|
const paymentMethods = await this._getPaymentMethods();
|
|
4628
5082
|
const params = adjustParams(this.params);
|
|
@@ -4668,6 +5122,12 @@ class PaymentController {
|
|
|
4668
5122
|
}, []);
|
|
4669
5123
|
}
|
|
4670
5124
|
|
|
5125
|
+
/**
|
|
5126
|
+
* @param {Payment[]} paymentInstances
|
|
5127
|
+
* @param {string} action
|
|
5128
|
+
* @param {...unknown} args
|
|
5129
|
+
* @returns {Promise<Payment[]>}
|
|
5130
|
+
*/
|
|
4671
5131
|
async _performPaymentAction(paymentInstances, action, ...args) {
|
|
4672
5132
|
const actions = paymentInstances.reduce((acc, instance) => {
|
|
4673
5133
|
const paymentAction = instance[action];
|
|
@@ -4688,9 +5148,7 @@ class PaymentController {
|
|
|
4688
5148
|
await resultPromise;
|
|
4689
5149
|
nextPaymentInstances.push(instance);
|
|
4690
5150
|
} catch (error) {
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
onPaymentError(error);
|
|
5151
|
+
instance.onError(error);
|
|
4694
5152
|
}
|
|
4695
5153
|
}
|
|
4696
5154
|
|
|
@@ -4717,6 +5175,8 @@ class PaymentController {
|
|
|
4717
5175
|
return this._getApplePaymentClass(gateway);
|
|
4718
5176
|
case 'amazon':
|
|
4719
5177
|
return this._getAmazonPaymentClass(gateway);
|
|
5178
|
+
case 'sezzle':
|
|
5179
|
+
return this._getSezzlePaymentClass(gateway);
|
|
4720
5180
|
default:
|
|
4721
5181
|
return null;
|
|
4722
5182
|
}
|
|
@@ -4810,6 +5270,13 @@ class PaymentController {
|
|
|
4810
5270
|
return AmazonDirectPayment;
|
|
4811
5271
|
}
|
|
4812
5272
|
}
|
|
5273
|
+
|
|
5274
|
+
_getSezzlePaymentClass(gateway) {
|
|
5275
|
+
switch (gateway) {
|
|
5276
|
+
default:
|
|
5277
|
+
return SezzleDirectPayment;
|
|
5278
|
+
}
|
|
5279
|
+
}
|
|
4813
5280
|
}
|
|
4814
5281
|
|
|
4815
5282
|
export { PaymentController as default };
|