swell-js 5.6.1 → 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 +409 -240
- package/dist/swell.cjs +410 -241
- package/dist/swell.cjs.map +1 -1
- package/dist/swell.umd.min.js +410 -241
- package/dist/swell.umd.min.js.map +1 -1
- package/package.json +2 -1
package/dist/swell.umd.min.js
CHANGED
|
@@ -12741,6 +12741,7 @@
|
|
|
12741
12741
|
return error
|
|
12742
12742
|
? { error }
|
|
12743
12743
|
: {
|
|
12744
|
+
gateway: 'stripe',
|
|
12744
12745
|
token: paymentMethod.id,
|
|
12745
12746
|
last4: paymentMethod.card.last4,
|
|
12746
12747
|
exp_month: paymentMethod.card.exp_month,
|
|
@@ -12844,13 +12845,13 @@
|
|
|
12844
12845
|
tax_included_total,
|
|
12845
12846
|
settings,
|
|
12846
12847
|
} = cart;
|
|
12847
|
-
const { price: shippingPrice, service_name } = shipping || {};
|
|
12848
|
+
const { price: shippingPrice, service, service_name } = shipping || {};
|
|
12848
12849
|
const { country, name } = settings || {};
|
|
12849
12850
|
const { require: { shipping: requireShipping } = {} } = params;
|
|
12850
12851
|
|
|
12851
12852
|
const stripeCurrency = currency.toLowerCase();
|
|
12852
12853
|
const displayItems = items.map((item) => ({
|
|
12853
|
-
label:
|
|
12854
|
+
label: item.product_name || item.product?.name || 'Unknown product',
|
|
12854
12855
|
amount: stripeAmountByCurrency(
|
|
12855
12856
|
currency,
|
|
12856
12857
|
item.price_total - item.discount_total,
|
|
@@ -12872,14 +12873,21 @@
|
|
|
12872
12873
|
}
|
|
12873
12874
|
|
|
12874
12875
|
let shippingOptions;
|
|
12875
|
-
const services =
|
|
12876
|
-
if (Array.isArray(services) && services.length > 0) {
|
|
12876
|
+
const services = shipment_rating?.services;
|
|
12877
|
+
if (requireShipping && Array.isArray(services) && services.length > 0) {
|
|
12877
12878
|
shippingOptions = services.map((service) => ({
|
|
12878
12879
|
id: service.id,
|
|
12879
12880
|
label: service.name,
|
|
12880
12881
|
detail: service.description,
|
|
12881
12882
|
amount: stripeAmountByCurrency(currency, service.price),
|
|
12882
12883
|
}));
|
|
12884
|
+
|
|
12885
|
+
const index = shippingOptions.findIndex((item) => item.id === service);
|
|
12886
|
+
|
|
12887
|
+
if (index > 0) {
|
|
12888
|
+
// Move selected shipping option to the top
|
|
12889
|
+
shippingOptions.unshift(...shippingOptions.splice(index, 1));
|
|
12890
|
+
}
|
|
12883
12891
|
}
|
|
12884
12892
|
|
|
12885
12893
|
return {
|
|
@@ -12891,7 +12899,7 @@
|
|
|
12891
12899
|
pending: true,
|
|
12892
12900
|
},
|
|
12893
12901
|
displayItems,
|
|
12894
|
-
...(
|
|
12902
|
+
...(shippingOptions && { shippingOptions }),
|
|
12895
12903
|
};
|
|
12896
12904
|
}
|
|
12897
12905
|
|
|
@@ -13011,6 +13019,10 @@
|
|
|
13011
13019
|
throw new Error(paymentMethod.error.message);
|
|
13012
13020
|
}
|
|
13013
13021
|
|
|
13022
|
+
if (!isLiveMode(this.method.mode)) {
|
|
13023
|
+
paymentMethod.test = true;
|
|
13024
|
+
}
|
|
13025
|
+
|
|
13014
13026
|
// should save payment method data when payment amount is not chargeable
|
|
13015
13027
|
if (!isStripeChargeableAmount(cart.capture_total, cart.currency)) {
|
|
13016
13028
|
await this.updateCart({
|
|
@@ -13435,6 +13447,7 @@
|
|
|
13435
13447
|
|
|
13436
13448
|
/** @typedef {import('@stripe/stripe-js').Stripe} Stripe */
|
|
13437
13449
|
/** @typedef {import('@stripe/stripe-js').PaymentRequestPaymentMethodEvent} PaymentRequestPaymentMethodEvent */
|
|
13450
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
13438
13451
|
|
|
13439
13452
|
class StripeGooglePayment extends Payment {
|
|
13440
13453
|
constructor(api, options, params, methods) {
|
|
@@ -13502,6 +13515,7 @@
|
|
|
13502
13515
|
this.element.mount(`#${this.elementContainer.id}`);
|
|
13503
13516
|
}
|
|
13504
13517
|
|
|
13518
|
+
/** @param {Cart} cart */
|
|
13505
13519
|
_createPaymentRequest(cart) {
|
|
13506
13520
|
const { require: { name, email, shipping, phone } = {} } = this.params;
|
|
13507
13521
|
|
|
@@ -13514,15 +13528,10 @@
|
|
|
13514
13528
|
...getPaymentRequestData(cart, this.params),
|
|
13515
13529
|
});
|
|
13516
13530
|
|
|
13517
|
-
paymentRequest
|
|
13518
|
-
'shippingaddresschange',
|
|
13519
|
-
this.
|
|
13520
|
-
|
|
13521
|
-
paymentRequest.on(
|
|
13522
|
-
'shippingoptionchange',
|
|
13523
|
-
this._onShippingOptionChange.bind(this),
|
|
13524
|
-
);
|
|
13525
|
-
paymentRequest.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
13531
|
+
paymentRequest
|
|
13532
|
+
.on('shippingaddresschange', this._onShippingAddressChange.bind(this))
|
|
13533
|
+
.on('shippingoptionchange', this._onShippingOptionChange.bind(this))
|
|
13534
|
+
.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
13526
13535
|
|
|
13527
13536
|
return paymentRequest;
|
|
13528
13537
|
}
|
|
@@ -13530,9 +13539,9 @@
|
|
|
13530
13539
|
/** @param {import('@stripe/stripe-js').PaymentRequestShippingAddressEvent} event */
|
|
13531
13540
|
async _onShippingAddressChange(event) {
|
|
13532
13541
|
const { shippingAddress, updateWith } = event;
|
|
13533
|
-
|
|
13542
|
+
|
|
13534
13543
|
const cart = await this.updateCart({
|
|
13535
|
-
shipping:
|
|
13544
|
+
shipping: this._mapShippingAddress(shippingAddress),
|
|
13536
13545
|
shipment_rating: null,
|
|
13537
13546
|
});
|
|
13538
13547
|
|
|
@@ -13572,16 +13581,15 @@
|
|
|
13572
13581
|
shippingOption,
|
|
13573
13582
|
complete,
|
|
13574
13583
|
} = event;
|
|
13575
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
13576
13584
|
|
|
13577
13585
|
await this.updateCart({
|
|
13578
13586
|
account: {
|
|
13579
|
-
email: payerEmail,
|
|
13587
|
+
email: payerEmail || billing_details?.email,
|
|
13580
13588
|
},
|
|
13581
|
-
...(
|
|
13589
|
+
...(shippingAddress && {
|
|
13582
13590
|
shipping: {
|
|
13583
13591
|
...this._mapShippingAddress(shippingAddress),
|
|
13584
|
-
service: shippingOption
|
|
13592
|
+
service: shippingOption?.id || undefined,
|
|
13585
13593
|
},
|
|
13586
13594
|
}),
|
|
13587
13595
|
billing: {
|
|
@@ -13595,9 +13603,9 @@
|
|
|
13595
13603
|
exp_month: card.exp_month,
|
|
13596
13604
|
exp_year: card.exp_year,
|
|
13597
13605
|
last4: card.last4,
|
|
13598
|
-
address_check: card.checks
|
|
13599
|
-
zip_check: card.checks
|
|
13600
|
-
cvc_check: card.checks
|
|
13606
|
+
address_check: card.checks?.address_line1_check,
|
|
13607
|
+
zip_check: card.checks?.address_postal_code_check,
|
|
13608
|
+
cvc_check: card.checks?.cvc_check,
|
|
13601
13609
|
},
|
|
13602
13610
|
},
|
|
13603
13611
|
});
|
|
@@ -13645,8 +13653,8 @@
|
|
|
13645
13653
|
_mapShippingAddress(address = {}) {
|
|
13646
13654
|
return {
|
|
13647
13655
|
name: address.recipient,
|
|
13648
|
-
address1: address.addressLine[0],
|
|
13649
|
-
address2: address.addressLine[1],
|
|
13656
|
+
address1: address.addressLine?.[0],
|
|
13657
|
+
address2: address.addressLine?.[1],
|
|
13650
13658
|
city: address.city,
|
|
13651
13659
|
state: address.region,
|
|
13652
13660
|
zip: address.postalCode,
|
|
@@ -13660,18 +13668,19 @@
|
|
|
13660
13668
|
return {
|
|
13661
13669
|
name: address.name,
|
|
13662
13670
|
phone: address.phone,
|
|
13663
|
-
address1: address.address
|
|
13664
|
-
address2: address.address
|
|
13665
|
-
city: address.address
|
|
13666
|
-
state: address.address
|
|
13667
|
-
zip: address.address
|
|
13668
|
-
country: address.address
|
|
13671
|
+
address1: address.address?.line1,
|
|
13672
|
+
address2: address.address?.line2,
|
|
13673
|
+
city: address.address?.city,
|
|
13674
|
+
state: address.address?.state,
|
|
13675
|
+
zip: address.address?.postal_code,
|
|
13676
|
+
country: address.address?.country,
|
|
13669
13677
|
};
|
|
13670
13678
|
}
|
|
13671
13679
|
}
|
|
13672
13680
|
|
|
13673
13681
|
/** @typedef {import('@stripe/stripe-js').Stripe} Stripe */
|
|
13674
13682
|
/** @typedef {import('@stripe/stripe-js').PaymentRequestPaymentMethodEvent} PaymentRequestPaymentMethodEvent */
|
|
13683
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
13675
13684
|
|
|
13676
13685
|
class StripeApplePayment extends Payment {
|
|
13677
13686
|
constructor(api, options, params, methods) {
|
|
@@ -13725,7 +13734,7 @@
|
|
|
13725
13734
|
const paymentRequest = this._createPaymentRequest(cart);
|
|
13726
13735
|
const canMakePayment = await paymentRequest.canMakePayment();
|
|
13727
13736
|
|
|
13728
|
-
if (!canMakePayment
|
|
13737
|
+
if (!canMakePayment?.applePay) {
|
|
13729
13738
|
throw new Error(
|
|
13730
13739
|
'This device is not capable of making Apple Pay payments',
|
|
13731
13740
|
);
|
|
@@ -13762,6 +13771,7 @@
|
|
|
13762
13771
|
}
|
|
13763
13772
|
}
|
|
13764
13773
|
|
|
13774
|
+
/** @param {Cart} cart */
|
|
13765
13775
|
_createPaymentRequest(cart) {
|
|
13766
13776
|
const { require: { name, email, shipping, phone } = {} } = this.params;
|
|
13767
13777
|
|
|
@@ -13774,15 +13784,10 @@
|
|
|
13774
13784
|
...getPaymentRequestData(cart, this.params),
|
|
13775
13785
|
});
|
|
13776
13786
|
|
|
13777
|
-
paymentRequest
|
|
13778
|
-
'shippingaddresschange',
|
|
13779
|
-
this.
|
|
13780
|
-
|
|
13781
|
-
paymentRequest.on(
|
|
13782
|
-
'shippingoptionchange',
|
|
13783
|
-
this._onShippingOptionChange.bind(this),
|
|
13784
|
-
);
|
|
13785
|
-
paymentRequest.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
13787
|
+
paymentRequest
|
|
13788
|
+
.on('shippingaddresschange', this._onShippingAddressChange.bind(this))
|
|
13789
|
+
.on('shippingoptionchange', this._onShippingOptionChange.bind(this))
|
|
13790
|
+
.on('paymentmethod', this._onPaymentMethod.bind(this));
|
|
13786
13791
|
|
|
13787
13792
|
return paymentRequest;
|
|
13788
13793
|
}
|
|
@@ -13790,9 +13795,9 @@
|
|
|
13790
13795
|
/** @param {import('@stripe/stripe-js').PaymentRequestShippingAddressEvent} event */
|
|
13791
13796
|
async _onShippingAddressChange(event) {
|
|
13792
13797
|
const { shippingAddress, updateWith } = event;
|
|
13793
|
-
|
|
13798
|
+
|
|
13794
13799
|
const cart = await this.updateCart({
|
|
13795
|
-
shipping:
|
|
13800
|
+
shipping: this._mapShippingAddress(shippingAddress),
|
|
13796
13801
|
shipment_rating: null,
|
|
13797
13802
|
});
|
|
13798
13803
|
|
|
@@ -13832,16 +13837,15 @@
|
|
|
13832
13837
|
shippingOption,
|
|
13833
13838
|
complete,
|
|
13834
13839
|
} = event;
|
|
13835
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
13836
13840
|
|
|
13837
13841
|
await this.updateCart({
|
|
13838
13842
|
account: {
|
|
13839
|
-
email: payerEmail,
|
|
13843
|
+
email: payerEmail || billing_details?.email,
|
|
13840
13844
|
},
|
|
13841
|
-
...(
|
|
13845
|
+
...(shippingAddress && {
|
|
13842
13846
|
shipping: {
|
|
13843
13847
|
...this._mapShippingAddress(shippingAddress),
|
|
13844
|
-
service: shippingOption
|
|
13848
|
+
service: shippingOption?.id || undefined,
|
|
13845
13849
|
},
|
|
13846
13850
|
}),
|
|
13847
13851
|
billing: {
|
|
@@ -13855,9 +13859,9 @@
|
|
|
13855
13859
|
exp_month: card.exp_month,
|
|
13856
13860
|
exp_year: card.exp_year,
|
|
13857
13861
|
last4: card.last4,
|
|
13858
|
-
address_check: card.checks
|
|
13859
|
-
zip_check: card.checks
|
|
13860
|
-
cvc_check: card.checks
|
|
13862
|
+
address_check: card.checks?.address_line1_check,
|
|
13863
|
+
zip_check: card.checks?.address_postal_code_check,
|
|
13864
|
+
cvc_check: card.checks?.cvc_check,
|
|
13861
13865
|
},
|
|
13862
13866
|
},
|
|
13863
13867
|
});
|
|
@@ -13871,8 +13875,8 @@
|
|
|
13871
13875
|
_mapShippingAddress(address = {}) {
|
|
13872
13876
|
return {
|
|
13873
13877
|
name: address.recipient,
|
|
13874
|
-
address1: address.addressLine[0],
|
|
13875
|
-
address2: address.addressLine[1],
|
|
13878
|
+
address1: address.addressLine?.[0],
|
|
13879
|
+
address2: address.addressLine?.[1],
|
|
13876
13880
|
city: address.city,
|
|
13877
13881
|
state: address.region,
|
|
13878
13882
|
zip: address.postalCode,
|
|
@@ -13886,12 +13890,12 @@
|
|
|
13886
13890
|
return {
|
|
13887
13891
|
name: address.name,
|
|
13888
13892
|
phone: address.phone,
|
|
13889
|
-
address1: address.address
|
|
13890
|
-
address2: address.address
|
|
13891
|
-
city: address.address
|
|
13892
|
-
state: address.address
|
|
13893
|
-
zip: address.address
|
|
13894
|
-
country: address.address
|
|
13893
|
+
address1: address.address?.line1,
|
|
13894
|
+
address2: address.address?.line2,
|
|
13895
|
+
city: address.address?.city,
|
|
13896
|
+
state: address.address?.state,
|
|
13897
|
+
zip: address.address?.postal_code,
|
|
13898
|
+
country: address.address?.country,
|
|
13895
13899
|
};
|
|
13896
13900
|
}
|
|
13897
13901
|
}
|
|
@@ -14159,6 +14163,44 @@
|
|
|
14159
14163
|
return discount.id;
|
|
14160
14164
|
}
|
|
14161
14165
|
|
|
14166
|
+
/** @type {Map<string, number>} */
|
|
14167
|
+
const CURRENCIES_CENTS = new Map();
|
|
14168
|
+
|
|
14169
|
+
/**
|
|
14170
|
+
* @param {string} currency
|
|
14171
|
+
* @returns {number}
|
|
14172
|
+
*/
|
|
14173
|
+
function getCurrencyCents(currency) {
|
|
14174
|
+
let cents = CURRENCIES_CENTS.get(currency);
|
|
14175
|
+
|
|
14176
|
+
if (cents !== undefined) {
|
|
14177
|
+
return cents;
|
|
14178
|
+
}
|
|
14179
|
+
|
|
14180
|
+
const formatter = new Intl.NumberFormat('en-US', {
|
|
14181
|
+
style: 'currency',
|
|
14182
|
+
currency,
|
|
14183
|
+
});
|
|
14184
|
+
|
|
14185
|
+
const options = formatter.resolvedOptions();
|
|
14186
|
+
const decimals = options.maximumFractionDigits ?? 2;
|
|
14187
|
+
|
|
14188
|
+
cents = 10 ** decimals;
|
|
14189
|
+
|
|
14190
|
+
CURRENCIES_CENTS.set(currency, cents);
|
|
14191
|
+
|
|
14192
|
+
return cents;
|
|
14193
|
+
}
|
|
14194
|
+
|
|
14195
|
+
/**
|
|
14196
|
+
* @param {string} currency
|
|
14197
|
+
* @param {number} amount
|
|
14198
|
+
* @returns {number}
|
|
14199
|
+
*/
|
|
14200
|
+
function amountInCents(currency, amount) {
|
|
14201
|
+
return Math.round(amount * getCurrencyCents(currency));
|
|
14202
|
+
}
|
|
14203
|
+
|
|
14162
14204
|
/** @typedef {import('./payment').default} Payment */
|
|
14163
14205
|
/** @typedef {import('../../types').Cart} Cart */
|
|
14164
14206
|
/** @typedef {import('../../types').Address} Address */
|
|
@@ -14246,7 +14288,7 @@
|
|
|
14246
14288
|
this,
|
|
14247
14289
|
cart,
|
|
14248
14290
|
),
|
|
14249
|
-
newTransactionInfo: getTransactionInfo(cart),
|
|
14291
|
+
newTransactionInfo: getTransactionInfo.call(this, cart),
|
|
14250
14292
|
};
|
|
14251
14293
|
}
|
|
14252
14294
|
|
|
@@ -14259,7 +14301,7 @@
|
|
|
14259
14301
|
},
|
|
14260
14302
|
});
|
|
14261
14303
|
|
|
14262
|
-
return { newTransactionInfo: getTransactionInfo(cart) };
|
|
14304
|
+
return { newTransactionInfo: getTransactionInfo.call(this, cart) };
|
|
14263
14305
|
} catch (err) {
|
|
14264
14306
|
return createError(
|
|
14265
14307
|
intermediatePaymentData.callbackTrigger,
|
|
@@ -14281,7 +14323,7 @@
|
|
|
14281
14323
|
|
|
14282
14324
|
return {
|
|
14283
14325
|
newOfferInfo: getOfferInfo(cart),
|
|
14284
|
-
newTransactionInfo: getTransactionInfo(cart),
|
|
14326
|
+
newTransactionInfo: getTransactionInfo.call(this, cart),
|
|
14285
14327
|
};
|
|
14286
14328
|
} catch (err) {
|
|
14287
14329
|
return createError(
|
|
@@ -14381,12 +14423,13 @@
|
|
|
14381
14423
|
|
|
14382
14424
|
/**
|
|
14383
14425
|
* Converts cart data to Google Pay transaction information.
|
|
14426
|
+
* @this {Payment}
|
|
14384
14427
|
* @param {Cart} cart - The current cart data
|
|
14385
14428
|
* @returns {google.payments.api.TransactionInfo} Transaction info for Google Pay
|
|
14386
14429
|
*/
|
|
14387
14430
|
function getTransactionInfo(cart) {
|
|
14388
|
-
const {
|
|
14389
|
-
|
|
14431
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
14432
|
+
const { settings, capture_total, currency, shipping } = cart;
|
|
14390
14433
|
|
|
14391
14434
|
return {
|
|
14392
14435
|
countryCode: settings?.country || 'US',
|
|
@@ -14394,7 +14437,7 @@
|
|
|
14394
14437
|
totalPrice: String(capture_total ?? 0),
|
|
14395
14438
|
// Set status to FINAL if shipping has been selected, otherwise ESTIMATED
|
|
14396
14439
|
totalPriceStatus:
|
|
14397
|
-
!
|
|
14440
|
+
!shipmentDelivery || shipping?.service ? 'FINAL' : 'ESTIMATED',
|
|
14398
14441
|
totalPriceLabel: 'Total',
|
|
14399
14442
|
displayItems: getDisplayItems(cart),
|
|
14400
14443
|
};
|
|
@@ -14407,12 +14450,14 @@
|
|
|
14407
14450
|
* @returns {google.payments.api.ShippingOptionParameters | undefined} Shipping options for Google Pay
|
|
14408
14451
|
*/
|
|
14409
14452
|
function getShippingOptionParameters(cart) {
|
|
14410
|
-
const {
|
|
14453
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
14411
14454
|
|
|
14412
|
-
if (!
|
|
14455
|
+
if (!shipmentDelivery) {
|
|
14413
14456
|
return undefined;
|
|
14414
14457
|
}
|
|
14415
14458
|
|
|
14459
|
+
const { shipment_rating, shipping } = cart;
|
|
14460
|
+
|
|
14416
14461
|
if (!shipment_rating?.services?.length) {
|
|
14417
14462
|
// Return placeholder when no shipping services are available
|
|
14418
14463
|
return {
|
|
@@ -14493,20 +14538,11 @@
|
|
|
14493
14538
|
};
|
|
14494
14539
|
}
|
|
14495
14540
|
|
|
14541
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
14542
|
+
|
|
14496
14543
|
const API_VERSION$1 = 2;
|
|
14497
14544
|
const API_MINOR_VERSION$1 = 0;
|
|
14498
14545
|
|
|
14499
|
-
const ALLOWED_CARD_AUTH_METHODS = ['PAN_ONLY', 'CRYPTOGRAM_3DS'];
|
|
14500
|
-
|
|
14501
|
-
const ALLOWED_CARD_NETWORKS = [
|
|
14502
|
-
'AMEX',
|
|
14503
|
-
'DISCOVER',
|
|
14504
|
-
'INTERAC',
|
|
14505
|
-
'JCB',
|
|
14506
|
-
'MASTERCARD',
|
|
14507
|
-
'VISA',
|
|
14508
|
-
];
|
|
14509
|
-
|
|
14510
14546
|
class BraintreeGooglePayment extends Payment {
|
|
14511
14547
|
constructor(api, options, params, methods) {
|
|
14512
14548
|
if (!methods.card) {
|
|
@@ -14542,6 +14578,9 @@
|
|
|
14542
14578
|
if (this.google) {
|
|
14543
14579
|
this.googleClient = new this.google.payments.api.PaymentsClient({
|
|
14544
14580
|
environment: isLiveMode(this.method.mode) ? 'PRODUCTION' : 'TEST',
|
|
14581
|
+
paymentDataCallbacks: {
|
|
14582
|
+
onPaymentDataChanged: onPaymentDataChanged.bind(this),
|
|
14583
|
+
},
|
|
14545
14584
|
});
|
|
14546
14585
|
}
|
|
14547
14586
|
|
|
@@ -14557,31 +14596,12 @@
|
|
|
14557
14596
|
BraintreeGooglePayment.googleClient = googleClient;
|
|
14558
14597
|
}
|
|
14559
14598
|
|
|
14560
|
-
/** @
|
|
14561
|
-
get cardPaymentMethod() {
|
|
14562
|
-
return {
|
|
14563
|
-
type: 'CARD',
|
|
14564
|
-
parameters: {
|
|
14565
|
-
allowedAuthMethods: ALLOWED_CARD_AUTH_METHODS,
|
|
14566
|
-
allowedCardNetworks: ALLOWED_CARD_NETWORKS,
|
|
14567
|
-
billingAddressRequired: true,
|
|
14568
|
-
billingAddressParameters: {
|
|
14569
|
-
format: 'FULL',
|
|
14570
|
-
phoneNumberRequired: true,
|
|
14571
|
-
},
|
|
14572
|
-
},
|
|
14573
|
-
};
|
|
14574
|
-
}
|
|
14575
|
-
|
|
14576
|
-
/** @returns {google.payments.api.PaymentMethodSpecification[]} */
|
|
14577
|
-
get allowedPaymentMethods() {
|
|
14578
|
-
return [this.cardPaymentMethod];
|
|
14579
|
-
}
|
|
14580
|
-
|
|
14599
|
+
/** @param {Cart} cart */
|
|
14581
14600
|
async createElements(cart) {
|
|
14582
14601
|
const {
|
|
14583
14602
|
elementId = 'googlepay-button',
|
|
14584
14603
|
locale = 'en',
|
|
14604
|
+
require: { phone } = {},
|
|
14585
14605
|
style: { color = 'black', type = 'plain', sizeMode = 'fill' } = {},
|
|
14586
14606
|
} = this.params;
|
|
14587
14607
|
|
|
@@ -14592,10 +14612,35 @@
|
|
|
14592
14612
|
this.setElementContainer(elementId);
|
|
14593
14613
|
await this.loadScripts(this.scripts);
|
|
14594
14614
|
|
|
14615
|
+
const braintreeClient = await this._createBraintreeClient();
|
|
14616
|
+
|
|
14617
|
+
const googlePayment = await this.braintree.googlePayment.create({
|
|
14618
|
+
client: braintreeClient,
|
|
14619
|
+
googleMerchantId: this.method.merchant_id,
|
|
14620
|
+
googlePayVersion: API_VERSION$1,
|
|
14621
|
+
});
|
|
14622
|
+
|
|
14623
|
+
const paymentDataRequest = googlePayment.createPaymentDataRequest(
|
|
14624
|
+
this._createPaymentRequestData(cart),
|
|
14625
|
+
);
|
|
14626
|
+
|
|
14627
|
+
const cardPaymentMethod = paymentDataRequest.allowedPaymentMethods.find(
|
|
14628
|
+
(method) => method.type === 'CARD',
|
|
14629
|
+
);
|
|
14630
|
+
|
|
14631
|
+
if (cardPaymentMethod !== undefined) {
|
|
14632
|
+
cardPaymentMethod.parameters.billingAddressRequired = true;
|
|
14633
|
+
|
|
14634
|
+
cardPaymentMethod.parameters.billingAddressParameters = {
|
|
14635
|
+
format: 'FULL',
|
|
14636
|
+
phoneNumberRequired: Boolean(phone),
|
|
14637
|
+
};
|
|
14638
|
+
}
|
|
14639
|
+
|
|
14595
14640
|
const isReadyToPay = await this.googleClient.isReadyToPay({
|
|
14596
14641
|
apiVersion: API_VERSION$1,
|
|
14597
14642
|
apiVersionMinor: API_MINOR_VERSION$1,
|
|
14598
|
-
allowedPaymentMethods:
|
|
14643
|
+
allowedPaymentMethods: paymentDataRequest.allowedPaymentMethods,
|
|
14599
14644
|
existingPaymentMethodRequired: true,
|
|
14600
14645
|
});
|
|
14601
14646
|
|
|
@@ -14605,16 +14650,6 @@
|
|
|
14605
14650
|
);
|
|
14606
14651
|
}
|
|
14607
14652
|
|
|
14608
|
-
const braintreeClient = await this._createBraintreeClient();
|
|
14609
|
-
const googlePayment = await this.braintree.googlePayment.create({
|
|
14610
|
-
client: braintreeClient,
|
|
14611
|
-
googleMerchantId: this.method.merchant_id,
|
|
14612
|
-
googlePayVersion: API_VERSION$1,
|
|
14613
|
-
});
|
|
14614
|
-
const paymentRequestData = this._createPaymentRequestData(cart);
|
|
14615
|
-
const paymentDataRequest =
|
|
14616
|
-
googlePayment.createPaymentDataRequest(paymentRequestData);
|
|
14617
|
-
|
|
14618
14653
|
this.element = this.googleClient.createButton({
|
|
14619
14654
|
buttonColor: color,
|
|
14620
14655
|
buttonType: type,
|
|
@@ -14641,6 +14676,7 @@
|
|
|
14641
14676
|
}
|
|
14642
14677
|
}
|
|
14643
14678
|
|
|
14679
|
+
/** @returns {Promise<braintree.Client>} */
|
|
14644
14680
|
async _createBraintreeClient() {
|
|
14645
14681
|
const authorization = await this.authorizeGateway({
|
|
14646
14682
|
gateway: 'braintree',
|
|
@@ -14655,39 +14691,51 @@
|
|
|
14655
14691
|
});
|
|
14656
14692
|
}
|
|
14657
14693
|
|
|
14658
|
-
/**
|
|
14694
|
+
/**
|
|
14695
|
+
* @param {Cart} cart
|
|
14696
|
+
* @returns {google.payments.api.PaymentDataRequest}
|
|
14697
|
+
*/
|
|
14659
14698
|
_createPaymentRequestData(cart) {
|
|
14660
14699
|
const {
|
|
14661
|
-
settings: { name
|
|
14662
|
-
capture_total,
|
|
14663
|
-
currency,
|
|
14700
|
+
settings: { name },
|
|
14664
14701
|
} = cart;
|
|
14702
|
+
|
|
14665
14703
|
const { require: { email, shipping, phone } = {} } = this.params;
|
|
14666
14704
|
|
|
14705
|
+
/** @type {google.payments.api.CallbackIntent[]} */
|
|
14706
|
+
const callbackIntents = ['OFFER'];
|
|
14707
|
+
|
|
14708
|
+
if (shipping) {
|
|
14709
|
+
callbackIntents.push('SHIPPING_ADDRESS', 'SHIPPING_OPTION');
|
|
14710
|
+
}
|
|
14711
|
+
|
|
14667
14712
|
return {
|
|
14668
14713
|
apiVersion: API_VERSION$1,
|
|
14669
14714
|
apiVersionMinor: API_MINOR_VERSION$1,
|
|
14670
|
-
transactionInfo:
|
|
14671
|
-
|
|
14672
|
-
|
|
14673
|
-
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
allowedPaymentMethods: this.allowedPaymentMethods,
|
|
14715
|
+
transactionInfo: getTransactionInfo.call(this, cart),
|
|
14716
|
+
/**
|
|
14717
|
+
* @see {@link https://developer.paypal.com/braintree/docs/guides/google-pay/client-side/javascript/v3/#requesting-a-payment}
|
|
14718
|
+
*
|
|
14719
|
+
* Braintree automatically populates the `allowedPaymentMethods` property.
|
|
14720
|
+
*/
|
|
14677
14721
|
emailRequired: Boolean(email),
|
|
14678
14722
|
shippingAddressRequired: Boolean(shipping),
|
|
14679
14723
|
shippingAddressParameters: {
|
|
14680
14724
|
phoneNumberRequired: Boolean(phone),
|
|
14681
14725
|
},
|
|
14726
|
+
shippingOptionRequired: Boolean(shipping),
|
|
14727
|
+
shippingOptionParameters: getShippingOptionParameters.call(this, cart),
|
|
14728
|
+
offerInfo: getOfferInfo(cart),
|
|
14682
14729
|
merchantInfo: {
|
|
14683
14730
|
merchantName: name,
|
|
14684
14731
|
merchantId: this.method.merchant_id,
|
|
14685
14732
|
},
|
|
14733
|
+
callbackIntents,
|
|
14686
14734
|
};
|
|
14687
14735
|
}
|
|
14688
14736
|
|
|
14689
14737
|
/**
|
|
14690
|
-
* @param {
|
|
14738
|
+
* @param {braintree.GooglePayment} googlePayment
|
|
14691
14739
|
* @param {google.payments.api.PaymentDataRequest} paymentDataRequest
|
|
14692
14740
|
*/
|
|
14693
14741
|
async _onClick(googlePayment, paymentDataRequest) {
|
|
@@ -14704,34 +14752,59 @@
|
|
|
14704
14752
|
}
|
|
14705
14753
|
|
|
14706
14754
|
/**
|
|
14707
|
-
* @param {
|
|
14755
|
+
* @param {braintree.GooglePayment} googlePayment
|
|
14708
14756
|
* @param {google.payments.api.PaymentData} paymentData
|
|
14709
14757
|
*/
|
|
14710
14758
|
async _submitPayment(googlePayment, paymentData) {
|
|
14711
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
14712
14759
|
const { nonce } = await googlePayment.parseResponse(paymentData);
|
|
14713
|
-
const { email, shippingAddress, paymentMethodData } =
|
|
14714
|
-
|
|
14715
|
-
|
|
14716
|
-
} = paymentMethodData;
|
|
14760
|
+
const { email, shippingAddress, shippingOptionData, paymentMethodData } =
|
|
14761
|
+
paymentData;
|
|
14762
|
+
const { info: { billingAddress } = {} } = paymentMethodData;
|
|
14717
14763
|
|
|
14718
|
-
await this.updateCart({
|
|
14764
|
+
const cart = await this.updateCart({
|
|
14719
14765
|
account: {
|
|
14720
14766
|
email,
|
|
14721
14767
|
},
|
|
14722
14768
|
billing: {
|
|
14723
14769
|
method: 'google',
|
|
14770
|
+
account_card_id: null,
|
|
14771
|
+
card: null,
|
|
14724
14772
|
google: {
|
|
14725
14773
|
nonce,
|
|
14726
14774
|
gateway: 'braintree',
|
|
14727
14775
|
},
|
|
14728
14776
|
...convertToSwellAddress$2(billingAddress),
|
|
14729
14777
|
},
|
|
14730
|
-
...(
|
|
14731
|
-
shipping:
|
|
14778
|
+
...(shippingAddress && {
|
|
14779
|
+
shipping: {
|
|
14780
|
+
...convertToSwellAddress$2(shippingAddress),
|
|
14781
|
+
service: shippingOptionData?.id || undefined,
|
|
14782
|
+
},
|
|
14732
14783
|
}),
|
|
14733
14784
|
});
|
|
14734
14785
|
|
|
14786
|
+
if (cart.subscription_delivery) {
|
|
14787
|
+
try {
|
|
14788
|
+
const card = await cardApi.createToken({
|
|
14789
|
+
gateway: 'braintree',
|
|
14790
|
+
account_id: cart.account_id,
|
|
14791
|
+
nonce,
|
|
14792
|
+
});
|
|
14793
|
+
|
|
14794
|
+
delete card.nonce;
|
|
14795
|
+
|
|
14796
|
+
await this.updateCart({
|
|
14797
|
+
billing: {
|
|
14798
|
+
method: 'card',
|
|
14799
|
+
card,
|
|
14800
|
+
google: null,
|
|
14801
|
+
},
|
|
14802
|
+
});
|
|
14803
|
+
} catch (error) {
|
|
14804
|
+
console.warn('Failed to extract card data from google token', error);
|
|
14805
|
+
}
|
|
14806
|
+
}
|
|
14807
|
+
|
|
14735
14808
|
this.onSuccess();
|
|
14736
14809
|
}
|
|
14737
14810
|
}
|
|
@@ -14761,7 +14834,7 @@
|
|
|
14761
14834
|
'Shipping is not available for the provided address.';
|
|
14762
14835
|
|
|
14763
14836
|
return {
|
|
14764
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
14837
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
14765
14838
|
newLineItems: getLineItems(cart),
|
|
14766
14839
|
newShippingMethods: [], // REQUIRED: Must always provide this, even as empty array
|
|
14767
14840
|
errors: [
|
|
@@ -14772,15 +14845,15 @@
|
|
|
14772
14845
|
|
|
14773
14846
|
// Success: Return updated totals and shipping methods
|
|
14774
14847
|
return {
|
|
14775
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
14848
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
14776
14849
|
newLineItems: getLineItems(cart),
|
|
14777
|
-
newShippingMethods: getShippingMethods(cart),
|
|
14850
|
+
newShippingMethods: getShippingMethods.call(this, cart),
|
|
14778
14851
|
};
|
|
14779
14852
|
} catch (err) {
|
|
14780
14853
|
const cartData = await this.getCart();
|
|
14781
14854
|
|
|
14782
14855
|
return {
|
|
14783
|
-
newTotal: getTotal(cartData, this.merchantInfo),
|
|
14856
|
+
newTotal: getTotal.call(this, cartData, this.merchantInfo),
|
|
14784
14857
|
newLineItems: getLineItems(cartData),
|
|
14785
14858
|
newShippingMethods: [], // REQUIRED: Must always provide this, even as empty array
|
|
14786
14859
|
errors: [new ApplePayError('unknown', undefined, err.message)],
|
|
@@ -14826,12 +14899,12 @@
|
|
|
14826
14899
|
});
|
|
14827
14900
|
|
|
14828
14901
|
return {
|
|
14829
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
14902
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
14830
14903
|
newLineItems: getLineItems(cart),
|
|
14831
14904
|
};
|
|
14832
14905
|
} catch (err) {
|
|
14833
14906
|
return {
|
|
14834
|
-
newTotal: getTotal(await this.getCart(), this.merchantInfo),
|
|
14907
|
+
newTotal: getTotal.call(this, await this.getCart(), this.merchantInfo),
|
|
14835
14908
|
errors: [new ApplePayError('unknown', undefined, err.message)],
|
|
14836
14909
|
};
|
|
14837
14910
|
}
|
|
@@ -14871,7 +14944,7 @@
|
|
|
14871
14944
|
|
|
14872
14945
|
// Valid coupon applied successfully
|
|
14873
14946
|
return {
|
|
14874
|
-
newTotal: getTotal(cart, this.merchantInfo),
|
|
14947
|
+
newTotal: getTotal.call(this, cart, this.merchantInfo),
|
|
14875
14948
|
newLineItems: getLineItems(cart),
|
|
14876
14949
|
};
|
|
14877
14950
|
} catch (err) {
|
|
@@ -14879,7 +14952,7 @@
|
|
|
14879
14952
|
const currentCart = await this.getCart();
|
|
14880
14953
|
|
|
14881
14954
|
return {
|
|
14882
|
-
newTotal: getTotal(currentCart, this.merchantInfo),
|
|
14955
|
+
newTotal: getTotal.call(this, currentCart, this.merchantInfo),
|
|
14883
14956
|
newLineItems: getLineItems(currentCart),
|
|
14884
14957
|
errors: [new ApplePayError('couponCodeInvalid', undefined, err.message)],
|
|
14885
14958
|
};
|
|
@@ -14913,15 +14986,17 @@
|
|
|
14913
14986
|
* This ensures the user sees "pending" until they've selected shipping,
|
|
14914
14987
|
* then sees the final amount once everything is calculated.
|
|
14915
14988
|
*
|
|
14989
|
+
* @this {Payment}
|
|
14916
14990
|
* @param {Cart} cart
|
|
14917
14991
|
* @param {object} [merchantInfo]
|
|
14918
14992
|
* @returns {ApplePayJS.ApplePayLineItem}
|
|
14919
14993
|
*/
|
|
14920
14994
|
function getTotal(cart, merchantInfo) {
|
|
14921
|
-
const {
|
|
14995
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
14996
|
+
const { capture_total, shipping } = cart;
|
|
14922
14997
|
|
|
14923
14998
|
// Use 'final' only after shipping method is selected or not needed, otherwise 'pending'
|
|
14924
|
-
const isFinalPrice = !
|
|
14999
|
+
const isFinalPrice = !shipmentDelivery || shipping?.service;
|
|
14925
15000
|
const type = isFinalPrice ? 'final' : 'pending';
|
|
14926
15001
|
|
|
14927
15002
|
return {
|
|
@@ -14990,16 +15065,19 @@
|
|
|
14990
15065
|
*
|
|
14991
15066
|
* IMPORTANT: Amounts must be formatted as strings with 2 decimals.
|
|
14992
15067
|
*
|
|
15068
|
+
* @this {Payment}
|
|
14993
15069
|
* @param {Cart} cart
|
|
14994
15070
|
* @returns {ApplePayJS.ApplePayShippingMethod[]}
|
|
14995
15071
|
*/
|
|
14996
15072
|
function getShippingMethods(cart) {
|
|
14997
|
-
const {
|
|
15073
|
+
const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
|
|
14998
15074
|
|
|
14999
|
-
if (!
|
|
15075
|
+
if (!shipmentDelivery) {
|
|
15000
15076
|
return [];
|
|
15001
15077
|
}
|
|
15002
15078
|
|
|
15079
|
+
const { shipment_rating } = cart;
|
|
15080
|
+
|
|
15003
15081
|
if (!shipment_rating?.services?.length) {
|
|
15004
15082
|
return [];
|
|
15005
15083
|
}
|
|
@@ -15050,13 +15128,38 @@
|
|
|
15050
15128
|
};
|
|
15051
15129
|
}
|
|
15052
15130
|
|
|
15053
|
-
|
|
15131
|
+
/** @param {object} params */
|
|
15132
|
+
function getRequiredContactFields(params) {
|
|
15133
|
+
const { require = {} } = params;
|
|
15134
|
+
/** @type {ApplePayJS.ApplePayContactField[]} */
|
|
15135
|
+
const requiredFields = [];
|
|
15136
|
+
|
|
15137
|
+
if (require.email) {
|
|
15138
|
+
requiredFields.push('email');
|
|
15139
|
+
}
|
|
15140
|
+
|
|
15141
|
+
if (require.name) {
|
|
15142
|
+
requiredFields.push('name');
|
|
15143
|
+
}
|
|
15144
|
+
|
|
15145
|
+
if (require.phone) {
|
|
15146
|
+
requiredFields.push('phone');
|
|
15147
|
+
}
|
|
15148
|
+
|
|
15149
|
+
/** @type {ApplePayJS.ApplePayContactField[]} */
|
|
15150
|
+
const requiredShippingContactFields = require.shipping
|
|
15151
|
+
? [...requiredFields, 'postalAddress']
|
|
15152
|
+
: [];
|
|
15153
|
+
|
|
15154
|
+
/** @type {ApplePayJS.ApplePayContactField[]} */
|
|
15155
|
+
const requiredBillingContactFields = [...requiredFields, 'postalAddress'];
|
|
15156
|
+
|
|
15157
|
+
return { requiredBillingContactFields, requiredShippingContactFields };
|
|
15158
|
+
}
|
|
15159
|
+
|
|
15160
|
+
/** @typedef {import('../../../types').Cart} Cart */
|
|
15054
15161
|
|
|
15055
|
-
const
|
|
15056
|
-
'supports3DS',
|
|
15057
|
-
'supportsDebit',
|
|
15058
|
-
'supportsCredit',
|
|
15059
|
-
];
|
|
15162
|
+
const VERSION$1 = 14;
|
|
15060
15163
|
|
|
15061
15164
|
class BraintreeApplePayment extends Payment {
|
|
15062
15165
|
constructor(api, options, params, methods) {
|
|
@@ -15088,6 +15191,7 @@
|
|
|
15088
15191
|
return window.ApplePaySession;
|
|
15089
15192
|
}
|
|
15090
15193
|
|
|
15194
|
+
/** @param {Cart} cart */
|
|
15091
15195
|
async createElements(cart) {
|
|
15092
15196
|
const { elementId = 'applepay-button' } = this.params;
|
|
15093
15197
|
|
|
@@ -15101,10 +15205,12 @@
|
|
|
15101
15205
|
}
|
|
15102
15206
|
|
|
15103
15207
|
const braintreeClient = await this._createBraintreeClient();
|
|
15208
|
+
|
|
15104
15209
|
const applePayment = await this.braintree.applePay.create({
|
|
15105
15210
|
client: braintreeClient,
|
|
15106
15211
|
});
|
|
15107
|
-
|
|
15212
|
+
|
|
15213
|
+
const paymentRequest = this._createPaymentRequest(cart, applePayment);
|
|
15108
15214
|
|
|
15109
15215
|
this.element = this._createButton(applePayment, paymentRequest);
|
|
15110
15216
|
}
|
|
@@ -15121,8 +15227,9 @@
|
|
|
15121
15227
|
}
|
|
15122
15228
|
|
|
15123
15229
|
/**
|
|
15124
|
-
* @param {
|
|
15230
|
+
* @param {braintree.ApplePay} applePayment
|
|
15125
15231
|
* @param {ApplePayJS.ApplePayPaymentRequest} paymentRequest
|
|
15232
|
+
* @returns {HTMLDivElement}
|
|
15126
15233
|
*/
|
|
15127
15234
|
_createButton(applePayment, paymentRequest) {
|
|
15128
15235
|
const { style: { type = 'plain', theme = 'black', height = '40px' } = {} } =
|
|
@@ -15143,6 +15250,7 @@
|
|
|
15143
15250
|
return button;
|
|
15144
15251
|
}
|
|
15145
15252
|
|
|
15253
|
+
/** @returns {Promise<braintree.Client>} */
|
|
15146
15254
|
async _createBraintreeClient() {
|
|
15147
15255
|
const authorization = await this.authorizeGateway({
|
|
15148
15256
|
gateway: 'braintree',
|
|
@@ -15157,47 +15265,43 @@
|
|
|
15157
15265
|
});
|
|
15158
15266
|
}
|
|
15159
15267
|
|
|
15160
|
-
/**
|
|
15268
|
+
/**
|
|
15269
|
+
* @param {Cart} cart
|
|
15270
|
+
* @param {braintree.ApplePay} applePayment
|
|
15271
|
+
* @returns {ApplePayJS.ApplePayPaymentRequest}
|
|
15272
|
+
*/
|
|
15161
15273
|
_createPaymentRequest(cart, applePayment) {
|
|
15162
|
-
const { require = {} } = this.params;
|
|
15163
15274
|
const {
|
|
15164
15275
|
settings: { name, country },
|
|
15165
15276
|
capture_total,
|
|
15166
15277
|
currency,
|
|
15167
15278
|
} = cart;
|
|
15168
15279
|
|
|
15169
|
-
const requiredShippingContactFields =
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
if (require.name) {
|
|
15173
|
-
requiredShippingContactFields.push('name');
|
|
15174
|
-
}
|
|
15175
|
-
if (require.email) {
|
|
15176
|
-
requiredShippingContactFields.push('email');
|
|
15177
|
-
}
|
|
15178
|
-
if (require.phone) {
|
|
15179
|
-
requiredShippingContactFields.push('phone');
|
|
15180
|
-
}
|
|
15181
|
-
if (require.shipping) {
|
|
15182
|
-
requiredShippingContactFields.push('postalAddress');
|
|
15183
|
-
}
|
|
15280
|
+
const { requiredBillingContactFields, requiredShippingContactFields } =
|
|
15281
|
+
getRequiredContactFields(this.params);
|
|
15184
15282
|
|
|
15185
15283
|
return applePayment.createPaymentRequest({
|
|
15186
15284
|
total: {
|
|
15187
15285
|
label: name,
|
|
15188
15286
|
type: 'pending',
|
|
15189
|
-
amount: capture_total.
|
|
15287
|
+
amount: (capture_total || 0).toFixed(2),
|
|
15190
15288
|
},
|
|
15191
15289
|
countryCode: country,
|
|
15192
15290
|
currencyCode: currency,
|
|
15193
|
-
|
|
15291
|
+
/**
|
|
15292
|
+
* @see {@link https://developer.paypal.com/braintree/docs/guides/apple-pay/client-side/javascript/v3/#create-anapplepaysession}
|
|
15293
|
+
*
|
|
15294
|
+
* Braintree automatically fills in `supportedNetworks` and `merchantCapabilities`.
|
|
15295
|
+
*/
|
|
15194
15296
|
requiredShippingContactFields,
|
|
15195
15297
|
requiredBillingContactFields,
|
|
15298
|
+
supportsCouponCode: true,
|
|
15299
|
+
lineItems: getLineItems(cart),
|
|
15196
15300
|
});
|
|
15197
15301
|
}
|
|
15198
15302
|
|
|
15199
15303
|
/**
|
|
15200
|
-
* @param {
|
|
15304
|
+
* @param {braintree.ApplePay} applePayment
|
|
15201
15305
|
* @param {ApplePayJS.ApplePayPaymentRequest} paymentRequest
|
|
15202
15306
|
*/
|
|
15203
15307
|
_createPaymentSession(applePayment, paymentRequest) {
|
|
@@ -15218,11 +15322,23 @@
|
|
|
15218
15322
|
}
|
|
15219
15323
|
};
|
|
15220
15324
|
|
|
15325
|
+
session.onshippingcontactselected = onShippingContactSelected.bind(
|
|
15326
|
+
this,
|
|
15327
|
+
session,
|
|
15328
|
+
);
|
|
15329
|
+
|
|
15330
|
+
session.onshippingmethodselected = onShippingMethodSelected.bind(
|
|
15331
|
+
this,
|
|
15332
|
+
session,
|
|
15333
|
+
);
|
|
15334
|
+
|
|
15335
|
+
session.oncouponcodechanged = onCouponCodeChanged.bind(this, session);
|
|
15336
|
+
|
|
15221
15337
|
session.onpaymentauthorized = async (event) => {
|
|
15222
15338
|
const {
|
|
15223
15339
|
payment: { token, shippingContact, billingContact },
|
|
15224
15340
|
} = event;
|
|
15225
|
-
|
|
15341
|
+
|
|
15226
15342
|
const payload = await applePayment
|
|
15227
15343
|
.tokenize({ token })
|
|
15228
15344
|
.catch(this.onError.bind(this));
|
|
@@ -15231,23 +15347,47 @@
|
|
|
15231
15347
|
return session.completePayment(this.ApplePaySession.STATUS_FAILURE);
|
|
15232
15348
|
}
|
|
15233
15349
|
|
|
15234
|
-
await this.updateCart({
|
|
15350
|
+
const cart = await this.updateCart({
|
|
15235
15351
|
account: {
|
|
15236
|
-
email: shippingContact
|
|
15352
|
+
email: shippingContact?.emailAddress || billingContact?.emailAddress,
|
|
15237
15353
|
},
|
|
15238
15354
|
billing: {
|
|
15239
15355
|
method: 'apple',
|
|
15356
|
+
account_card_id: null,
|
|
15357
|
+
card: null,
|
|
15240
15358
|
apple: {
|
|
15241
15359
|
nonce: payload.nonce,
|
|
15242
15360
|
gateway: 'braintree',
|
|
15243
15361
|
},
|
|
15244
15362
|
...convertToSwellAddress$1(billingContact),
|
|
15245
15363
|
},
|
|
15246
|
-
...(
|
|
15364
|
+
...(shippingContact && {
|
|
15247
15365
|
shipping: convertToSwellAddress$1(shippingContact),
|
|
15248
15366
|
}),
|
|
15249
15367
|
});
|
|
15250
15368
|
|
|
15369
|
+
if (cart.subscription_delivery) {
|
|
15370
|
+
try {
|
|
15371
|
+
const card = await cardApi.createToken({
|
|
15372
|
+
gateway: 'braintree',
|
|
15373
|
+
account_id: cart.account_id,
|
|
15374
|
+
nonce: payload.nonce,
|
|
15375
|
+
});
|
|
15376
|
+
|
|
15377
|
+
delete card.nonce;
|
|
15378
|
+
|
|
15379
|
+
await this.updateCart({
|
|
15380
|
+
billing: {
|
|
15381
|
+
method: 'card',
|
|
15382
|
+
card,
|
|
15383
|
+
apple: null,
|
|
15384
|
+
},
|
|
15385
|
+
});
|
|
15386
|
+
} catch (error) {
|
|
15387
|
+
console.warn('Failed to extract card data from apple token', error);
|
|
15388
|
+
}
|
|
15389
|
+
}
|
|
15390
|
+
|
|
15251
15391
|
this.onSuccess();
|
|
15252
15392
|
|
|
15253
15393
|
return session.completePayment(this.ApplePaySession.STATUS_SUCCESS);
|
|
@@ -15353,6 +15493,8 @@
|
|
|
15353
15493
|
* @returns {google.payments.api.PaymentMethodSpecification}
|
|
15354
15494
|
*/
|
|
15355
15495
|
_getCardPaymentMethod(submit = false) {
|
|
15496
|
+
const { require: { phone } = {} } = this.params;
|
|
15497
|
+
|
|
15356
15498
|
return {
|
|
15357
15499
|
type: 'CARD',
|
|
15358
15500
|
parameters: {
|
|
@@ -15361,7 +15503,7 @@
|
|
|
15361
15503
|
billingAddressRequired: true,
|
|
15362
15504
|
billingAddressParameters: {
|
|
15363
15505
|
format: 'FULL',
|
|
15364
|
-
phoneNumberRequired:
|
|
15506
|
+
phoneNumberRequired: Boolean(phone),
|
|
15365
15507
|
},
|
|
15366
15508
|
},
|
|
15367
15509
|
...(submit && {
|
|
@@ -15394,29 +15536,30 @@
|
|
|
15394
15536
|
cart.shipment_price = 0;
|
|
15395
15537
|
cart.shipping = {};
|
|
15396
15538
|
|
|
15397
|
-
const { shipment_delivery } = cart;
|
|
15398
15539
|
const { require: { email, shipping, phone } = {} } = this.params;
|
|
15399
15540
|
|
|
15541
|
+
/** @type {google.payments.api.CallbackIntent[]} */
|
|
15542
|
+
const callbackIntents = ['OFFER', 'PAYMENT_AUTHORIZATION'];
|
|
15543
|
+
|
|
15544
|
+
if (shipping) {
|
|
15545
|
+
callbackIntents.push('SHIPPING_ADDRESS', 'SHIPPING_OPTION');
|
|
15546
|
+
}
|
|
15547
|
+
|
|
15400
15548
|
return {
|
|
15401
15549
|
apiVersion: API_VERSION,
|
|
15402
15550
|
apiVersionMinor: API_MINOR_VERSION,
|
|
15403
|
-
transactionInfo: getTransactionInfo(cart),
|
|
15551
|
+
transactionInfo: getTransactionInfo.call(this, cart),
|
|
15404
15552
|
allowedPaymentMethods: this._getAllowedPaymentMethods(true),
|
|
15405
15553
|
emailRequired: Boolean(email),
|
|
15406
15554
|
shippingAddressRequired: Boolean(shipping),
|
|
15407
15555
|
shippingAddressParameters: {
|
|
15408
15556
|
phoneNumberRequired: Boolean(phone),
|
|
15409
15557
|
},
|
|
15410
|
-
shippingOptionRequired: Boolean(
|
|
15558
|
+
shippingOptionRequired: Boolean(shipping),
|
|
15411
15559
|
shippingOptionParameters: getShippingOptionParameters.call(this, cart),
|
|
15412
15560
|
offerInfo: getOfferInfo(cart),
|
|
15413
15561
|
merchantInfo,
|
|
15414
|
-
callbackIntents
|
|
15415
|
-
'OFFER',
|
|
15416
|
-
'SHIPPING_ADDRESS',
|
|
15417
|
-
'SHIPPING_OPTION',
|
|
15418
|
-
'PAYMENT_AUTHORIZATION',
|
|
15419
|
-
],
|
|
15562
|
+
callbackIntents,
|
|
15420
15563
|
};
|
|
15421
15564
|
}
|
|
15422
15565
|
|
|
@@ -15540,6 +15683,22 @@
|
|
|
15540
15683
|
/** @typedef {import('../../../types').Cart} Cart */
|
|
15541
15684
|
|
|
15542
15685
|
class AuthorizeNetGooglePayment extends AbstractGooglePayment {
|
|
15686
|
+
/**
|
|
15687
|
+
* @override
|
|
15688
|
+
* @returns {google.payments.api.CardNetwork[]}
|
|
15689
|
+
*/
|
|
15690
|
+
getAllowedCardNetworks() {
|
|
15691
|
+
return ['AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'];
|
|
15692
|
+
}
|
|
15693
|
+
|
|
15694
|
+
/**
|
|
15695
|
+
* @override
|
|
15696
|
+
* @returns {google.payments.api.CardAuthMethod[]}
|
|
15697
|
+
*/
|
|
15698
|
+
getAllowedCardAuthMethods() {
|
|
15699
|
+
return ['PAN_ONLY', 'CRYPTOGRAM_3DS'];
|
|
15700
|
+
}
|
|
15701
|
+
|
|
15543
15702
|
/**
|
|
15544
15703
|
* @override
|
|
15545
15704
|
* @returns {google.payments.api.PaymentGatewayTokenizationParameters}
|
|
@@ -15557,7 +15716,6 @@
|
|
|
15557
15716
|
* @returns {Promise<object>}
|
|
15558
15717
|
*/
|
|
15559
15718
|
async preparePaymentDataForCartUpdate(paymentData) {
|
|
15560
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
15561
15719
|
const { email, shippingAddress, shippingOptionData, paymentMethodData } =
|
|
15562
15720
|
paymentData;
|
|
15563
15721
|
|
|
@@ -15578,7 +15736,7 @@
|
|
|
15578
15736
|
},
|
|
15579
15737
|
...convertToSwellAddress$2(billingAddress),
|
|
15580
15738
|
},
|
|
15581
|
-
...(
|
|
15739
|
+
...(shippingAddress && {
|
|
15582
15740
|
shipping: {
|
|
15583
15741
|
...convertToSwellAddress$2(shippingAddress),
|
|
15584
15742
|
service: shippingOptionData?.id || undefined,
|
|
@@ -15645,9 +15803,15 @@
|
|
|
15645
15803
|
return window.ApplePaySession;
|
|
15646
15804
|
}
|
|
15647
15805
|
|
|
15648
|
-
/**
|
|
15806
|
+
/**
|
|
15807
|
+
* We should specify the payment methods in the order preferred by the gateway.
|
|
15808
|
+
*
|
|
15809
|
+
* @see {@link https://developer.apple.com/documentation/applepayontheweb/applepaypaymentrequest/supportednetworks}
|
|
15810
|
+
*
|
|
15811
|
+
* @returns {string[]}
|
|
15812
|
+
*/
|
|
15649
15813
|
getSupportedCardNetworks() {
|
|
15650
|
-
return ['
|
|
15814
|
+
return ['visa', 'masterCard', 'amex', 'discover', 'interac', 'jcb'];
|
|
15651
15815
|
}
|
|
15652
15816
|
|
|
15653
15817
|
/** @returns {ApplePayJS.ApplePayMerchantCapability[]} */
|
|
@@ -15658,12 +15822,12 @@
|
|
|
15658
15822
|
/**
|
|
15659
15823
|
* Creates the Apple Pay payment request object
|
|
15660
15824
|
*
|
|
15661
|
-
* IMPORTANT: countryCode here is the MERCHANT's country (where your business is located),
|
|
15662
|
-
* NOT the customer's country. Customer country comes from shippingContact.countryCode
|
|
15825
|
+
* IMPORTANT: `countryCode` here is the MERCHANT's country (where your business is located),
|
|
15826
|
+
* NOT the customer's country. Customer country comes from `shippingContact.countryCode`.
|
|
15663
15827
|
*
|
|
15664
|
-
* NOTE: We do NOT pass shippingMethods in the initial request. Shipping methods
|
|
15828
|
+
* NOTE: We do NOT pass `shippingMethods` in the initial request. Shipping methods
|
|
15665
15829
|
* are provided dynamically after the user selects/confirms their address in the
|
|
15666
|
-
* 'shippingcontactselected' event handler.
|
|
15830
|
+
* `'shippingcontactselected'` event handler.
|
|
15667
15831
|
*
|
|
15668
15832
|
* @param {Cart} cart
|
|
15669
15833
|
* @returns {ApplePayJS.ApplePayPaymentRequest}
|
|
@@ -15671,38 +15835,21 @@
|
|
|
15671
15835
|
_createPaymentRequest(cart) {
|
|
15672
15836
|
cart = { ...cart };
|
|
15673
15837
|
|
|
15674
|
-
const { require = {} } = this.params;
|
|
15675
15838
|
const {
|
|
15676
15839
|
settings: { country },
|
|
15677
15840
|
currency,
|
|
15678
15841
|
} = cart;
|
|
15679
15842
|
|
|
15680
|
-
const requiredShippingContactFields = [];
|
|
15681
|
-
const requiredBillingContactFields = ['postalAddress'];
|
|
15682
|
-
|
|
15683
|
-
if (require.name) {
|
|
15684
|
-
requiredShippingContactFields.push('name');
|
|
15685
|
-
}
|
|
15686
|
-
|
|
15687
|
-
if (require.email) {
|
|
15688
|
-
requiredShippingContactFields.push('email');
|
|
15689
|
-
}
|
|
15690
|
-
|
|
15691
|
-
if (require.phone) {
|
|
15692
|
-
requiredShippingContactFields.push('phone');
|
|
15693
|
-
}
|
|
15694
|
-
|
|
15695
|
-
if (require.shipping) {
|
|
15696
|
-
requiredShippingContactFields.push('postalAddress');
|
|
15697
|
-
}
|
|
15698
|
-
|
|
15699
15843
|
// When initiating a payment request,
|
|
15700
15844
|
// we should not display the shipping cost, as it will be calculated later.
|
|
15701
15845
|
cart.shipment_price = 0;
|
|
15702
15846
|
cart.shipping = {};
|
|
15703
15847
|
|
|
15848
|
+
const { requiredBillingContactFields, requiredShippingContactFields } =
|
|
15849
|
+
getRequiredContactFields(this.params);
|
|
15850
|
+
|
|
15704
15851
|
return {
|
|
15705
|
-
total: getTotal(cart, this.merchantInfo),
|
|
15852
|
+
total: getTotal.call(this, cart, this.merchantInfo),
|
|
15706
15853
|
countryCode: country, // Merchant's country
|
|
15707
15854
|
currencyCode: currency,
|
|
15708
15855
|
supportedNetworks: this.getSupportedCardNetworks(),
|
|
@@ -15884,6 +16031,22 @@
|
|
|
15884
16031
|
}
|
|
15885
16032
|
|
|
15886
16033
|
class AuthorizeNetApplePayment extends AbstractApplePayment {
|
|
16034
|
+
/**
|
|
16035
|
+
* @override
|
|
16036
|
+
* @returns {string[]}
|
|
16037
|
+
*/
|
|
16038
|
+
getSupportedCardNetworks() {
|
|
16039
|
+
return ['visa', 'masterCard', 'amex', 'discover'];
|
|
16040
|
+
}
|
|
16041
|
+
|
|
16042
|
+
/**
|
|
16043
|
+
* @override
|
|
16044
|
+
* @returns {ApplePayJS.ApplePayMerchantCapability[]}
|
|
16045
|
+
*/
|
|
16046
|
+
getMerchantCapabilities() {
|
|
16047
|
+
return ['supports3DS', 'supportsDebit', 'supportsCredit'];
|
|
16048
|
+
}
|
|
16049
|
+
|
|
15887
16050
|
/**
|
|
15888
16051
|
* @override
|
|
15889
16052
|
* @param {ApplePayJS.ApplePayValidateMerchantEvent} event
|
|
@@ -15917,11 +16080,9 @@
|
|
|
15917
16080
|
payment: { token, shippingContact, billingContact },
|
|
15918
16081
|
} = event;
|
|
15919
16082
|
|
|
15920
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
15921
|
-
|
|
15922
16083
|
return {
|
|
15923
16084
|
account: {
|
|
15924
|
-
email: shippingContact
|
|
16085
|
+
email: shippingContact?.emailAddress || billingContact?.emailAddress,
|
|
15925
16086
|
},
|
|
15926
16087
|
billing: {
|
|
15927
16088
|
method: 'apple',
|
|
@@ -15933,7 +16094,7 @@
|
|
|
15933
16094
|
},
|
|
15934
16095
|
...convertToSwellAddress$1(billingContact),
|
|
15935
16096
|
},
|
|
15936
|
-
...(
|
|
16097
|
+
...(shippingContact && {
|
|
15937
16098
|
shipping: convertToSwellAddress$1(shippingContact),
|
|
15938
16099
|
}),
|
|
15939
16100
|
};
|
|
@@ -15946,7 +16107,7 @@
|
|
|
15946
16107
|
}
|
|
15947
16108
|
|
|
15948
16109
|
get orderId() {
|
|
15949
|
-
return Math.random().toString(36).
|
|
16110
|
+
return Math.random().toString(36).slice(2, 11);
|
|
15950
16111
|
}
|
|
15951
16112
|
|
|
15952
16113
|
async tokenize() {
|
|
@@ -16008,6 +16169,12 @@
|
|
|
16008
16169
|
throw new Error(card.error.message);
|
|
16009
16170
|
}
|
|
16010
16171
|
|
|
16172
|
+
card.gateway = 'quickpay';
|
|
16173
|
+
|
|
16174
|
+
if (!isLiveMode(this.method.mode)) {
|
|
16175
|
+
card.test = true;
|
|
16176
|
+
}
|
|
16177
|
+
|
|
16011
16178
|
await this.updateCart({
|
|
16012
16179
|
billing: {
|
|
16013
16180
|
method: 'card',
|
|
@@ -16047,7 +16214,7 @@
|
|
|
16047
16214
|
merchantAccount: false,
|
|
16048
16215
|
countryCode: country || 'US',
|
|
16049
16216
|
shopperLocale: 'en-US',
|
|
16050
|
-
// shopperReference: email ? md5(email) : undefined,
|
|
16217
|
+
// shopperReference: email ? md5(email.toLowerCase()) : undefined,
|
|
16051
16218
|
}),
|
|
16052
16219
|
},
|
|
16053
16220
|
).then((res) => res.json());
|
|
@@ -16175,15 +16342,20 @@
|
|
|
16175
16342
|
}
|
|
16176
16343
|
}
|
|
16177
16344
|
|
|
16345
|
+
function getBaseConvesioVaultUrl(mode) {
|
|
16346
|
+
return isLiveMode(mode)
|
|
16347
|
+
? 'https://vault.convesiopay.com'
|
|
16348
|
+
: 'https://qa-vault.convesiopay.com';
|
|
16349
|
+
}
|
|
16350
|
+
|
|
16178
16351
|
function createConvesioCardPaymentToken(settings, data) {
|
|
16179
|
-
const baseUrl =
|
|
16352
|
+
const baseUrl = getBaseConvesioVaultUrl(settings.mode);
|
|
16180
16353
|
|
|
16181
16354
|
return fetch(`${baseUrl}/v1/create-token`, {
|
|
16182
16355
|
method: 'POST',
|
|
16183
16356
|
headers: {
|
|
16184
16357
|
Accept: 'application/json',
|
|
16185
16358
|
'Content-Type': 'application/json',
|
|
16186
|
-
'X-Requested-With': 'convesio-pay-dashboard',
|
|
16187
16359
|
'X-Api-Key': settings.public_key,
|
|
16188
16360
|
},
|
|
16189
16361
|
body: JSON.stringify(data),
|
|
@@ -16298,8 +16470,6 @@
|
|
|
16298
16470
|
payment: { token, shippingContact, billingContact },
|
|
16299
16471
|
} = event;
|
|
16300
16472
|
|
|
16301
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
16302
|
-
|
|
16303
16473
|
const payment = await createConvesioApplePaymentToken(
|
|
16304
16474
|
this.method.mode,
|
|
16305
16475
|
this.convesiopay,
|
|
@@ -16321,7 +16491,7 @@
|
|
|
16321
16491
|
|
|
16322
16492
|
return {
|
|
16323
16493
|
account: {
|
|
16324
|
-
email: shippingContact
|
|
16494
|
+
email: shippingContact?.emailAddress || billingContact?.emailAddress,
|
|
16325
16495
|
},
|
|
16326
16496
|
billing: {
|
|
16327
16497
|
method: 'apple',
|
|
@@ -16336,7 +16506,7 @@
|
|
|
16336
16506
|
},
|
|
16337
16507
|
...convertToSwellAddress$1(billingContact),
|
|
16338
16508
|
},
|
|
16339
|
-
...(
|
|
16509
|
+
...(shippingContact && {
|
|
16340
16510
|
shipping: convertToSwellAddress$1(shippingContact),
|
|
16341
16511
|
}),
|
|
16342
16512
|
};
|
|
@@ -16466,7 +16636,6 @@
|
|
|
16466
16636
|
* @returns {Promise<object>}
|
|
16467
16637
|
*/
|
|
16468
16638
|
async preparePaymentDataForCartUpdate(paymentData) {
|
|
16469
|
-
const { require: { shipping: requireShipping } = {} } = this.params;
|
|
16470
16639
|
const { email, shippingAddress, shippingOptionData, paymentMethodData } =
|
|
16471
16640
|
paymentData;
|
|
16472
16641
|
|
|
@@ -16509,7 +16678,7 @@
|
|
|
16509
16678
|
},
|
|
16510
16679
|
...convertToSwellAddress$2(billingAddress),
|
|
16511
16680
|
},
|
|
16512
|
-
...(
|
|
16681
|
+
...(shippingAddress && {
|
|
16513
16682
|
shipping: {
|
|
16514
16683
|
...convertToSwellAddress$2(shippingAddress),
|
|
16515
16684
|
service: shippingOptionData?.id || undefined,
|
|
@@ -17405,20 +17574,29 @@
|
|
|
17405
17574
|
settings: { name },
|
|
17406
17575
|
} = cart;
|
|
17407
17576
|
|
|
17408
|
-
const
|
|
17577
|
+
const { require: { shipping } = {} } = this.params;
|
|
17409
17578
|
const cartCurrency = getCartCurrency(cart);
|
|
17410
17579
|
|
|
17411
17580
|
return {
|
|
17412
17581
|
checkout_payload: {
|
|
17413
|
-
express_checkout_type:
|
|
17582
|
+
express_checkout_type: shipping ? 'multi-step' : 'no-shipping',
|
|
17583
|
+
customer: {
|
|
17584
|
+
email: cart.account?.email,
|
|
17585
|
+
first_name: cart.account?.first_name,
|
|
17586
|
+
last_name: cart.account?.last_name,
|
|
17587
|
+
phone: cart.account?.phone,
|
|
17588
|
+
// TODO: recurring payments https://docs.sezzle.com/docs/api/tokenization/intro
|
|
17589
|
+
// tokenize: cart.subscription_delivery,
|
|
17590
|
+
// recurring: cart.subscription_delivery,
|
|
17591
|
+
},
|
|
17414
17592
|
order: {
|
|
17415
17593
|
intent: 'AUTH',
|
|
17416
17594
|
reference_id: cart.checkout_id,
|
|
17417
17595
|
description: `${name} #${cart.number}`,
|
|
17418
|
-
requires_shipping_info:
|
|
17596
|
+
requires_shipping_info: shipping,
|
|
17419
17597
|
items: getItems(cart),
|
|
17420
17598
|
discounts: getDiscounts(cart),
|
|
17421
|
-
tax_amount:
|
|
17599
|
+
tax_amount: shipping
|
|
17422
17600
|
? undefined
|
|
17423
17601
|
: getAmountInCents(cartCurrency, cart.tax_total),
|
|
17424
17602
|
order_amount: getAmountInCents(cartCurrency, cart.capture_total),
|
|
@@ -17678,15 +17856,6 @@
|
|
|
17678
17856
|
};
|
|
17679
17857
|
}
|
|
17680
17858
|
|
|
17681
|
-
/**
|
|
17682
|
-
* @param {string} currency
|
|
17683
|
-
* @param {number} amount
|
|
17684
|
-
* @returns {number}
|
|
17685
|
-
*/
|
|
17686
|
-
function amountInCents(currency, amount) {
|
|
17687
|
-
return Math.round(amount * 100);
|
|
17688
|
-
}
|
|
17689
|
-
|
|
17690
17859
|
class PaymentController {
|
|
17691
17860
|
constructor(api, options) {
|
|
17692
17861
|
this.api = api;
|
|
@@ -18389,7 +18558,7 @@
|
|
|
18389
18558
|
const api = {};
|
|
18390
18559
|
|
|
18391
18560
|
Object.assign(api, {
|
|
18392
|
-
version: '5.
|
|
18561
|
+
version: '5.8.0',
|
|
18393
18562
|
options,
|
|
18394
18563
|
request,
|
|
18395
18564
|
|