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/swell.cjs CHANGED
@@ -7296,6 +7296,7 @@ async function createPaymentMethod(stripe, cardElement, cart) {
7296
7296
  return error
7297
7297
  ? { error }
7298
7298
  : {
7299
+ gateway: 'stripe',
7299
7300
  token: paymentMethod.id,
7300
7301
  last4: paymentMethod.card.last4,
7301
7302
  exp_month: paymentMethod.card.exp_month,
@@ -7399,13 +7400,13 @@ function getPaymentRequestData(cart, params) {
7399
7400
  tax_included_total,
7400
7401
  settings,
7401
7402
  } = cart;
7402
- const { price: shippingPrice, service_name } = shipping || {};
7403
+ const { price: shippingPrice, service, service_name } = shipping || {};
7403
7404
  const { country, name } = settings || {};
7404
7405
  const { require: { shipping: requireShipping } = {} } = params;
7405
7406
 
7406
7407
  const stripeCurrency = currency.toLowerCase();
7407
7408
  const displayItems = items.map((item) => ({
7408
- label: get(item, 'product.name', 'Unknown product'),
7409
+ label: item.product_name || item.product?.name || 'Unknown product',
7409
7410
  amount: stripeAmountByCurrency(
7410
7411
  currency,
7411
7412
  item.price_total - item.discount_total,
@@ -7427,14 +7428,21 @@ function getPaymentRequestData(cart, params) {
7427
7428
  }
7428
7429
 
7429
7430
  let shippingOptions;
7430
- const services = get(shipment_rating, 'services');
7431
- if (Array.isArray(services) && services.length > 0) {
7431
+ const services = shipment_rating?.services;
7432
+ if (requireShipping && Array.isArray(services) && services.length > 0) {
7432
7433
  shippingOptions = services.map((service) => ({
7433
7434
  id: service.id,
7434
7435
  label: service.name,
7435
7436
  detail: service.description,
7436
7437
  amount: stripeAmountByCurrency(currency, service.price),
7437
7438
  }));
7439
+
7440
+ const index = shippingOptions.findIndex((item) => item.id === service);
7441
+
7442
+ if (index > 0) {
7443
+ // Move selected shipping option to the top
7444
+ shippingOptions.unshift(...shippingOptions.splice(index, 1));
7445
+ }
7438
7446
  }
7439
7447
 
7440
7448
  return {
@@ -7446,7 +7454,7 @@ function getPaymentRequestData(cart, params) {
7446
7454
  pending: true,
7447
7455
  },
7448
7456
  displayItems,
7449
- ...(requireShipping && { shippingOptions }),
7457
+ ...(shippingOptions && { shippingOptions }),
7450
7458
  };
7451
7459
  }
7452
7460
 
@@ -7566,6 +7574,10 @@ class StripeCardPayment extends Payment {
7566
7574
  throw new Error(paymentMethod.error.message);
7567
7575
  }
7568
7576
 
7577
+ if (!isLiveMode(this.method.mode)) {
7578
+ paymentMethod.test = true;
7579
+ }
7580
+
7569
7581
  // should save payment method data when payment amount is not chargeable
7570
7582
  if (!isStripeChargeableAmount(cart.capture_total, cart.currency)) {
7571
7583
  await this.updateCart({
@@ -7990,6 +8002,7 @@ class StripeKlarnaPayment extends Payment {
7990
8002
 
7991
8003
  /** @typedef {import('@stripe/stripe-js').Stripe} Stripe */
7992
8004
  /** @typedef {import('@stripe/stripe-js').PaymentRequestPaymentMethodEvent} PaymentRequestPaymentMethodEvent */
8005
+ /** @typedef {import('../../../types').Cart} Cart */
7993
8006
 
7994
8007
  class StripeGooglePayment extends Payment {
7995
8008
  constructor(api, options, params, methods) {
@@ -8057,6 +8070,7 @@ class StripeGooglePayment extends Payment {
8057
8070
  this.element.mount(`#${this.elementContainer.id}`);
8058
8071
  }
8059
8072
 
8073
+ /** @param {Cart} cart */
8060
8074
  _createPaymentRequest(cart) {
8061
8075
  const { require: { name, email, shipping, phone } = {} } = this.params;
8062
8076
 
@@ -8069,15 +8083,10 @@ class StripeGooglePayment extends Payment {
8069
8083
  ...getPaymentRequestData(cart, this.params),
8070
8084
  });
8071
8085
 
8072
- paymentRequest.on(
8073
- 'shippingaddresschange',
8074
- this._onShippingAddressChange.bind(this),
8075
- );
8076
- paymentRequest.on(
8077
- 'shippingoptionchange',
8078
- this._onShippingOptionChange.bind(this),
8079
- );
8080
- paymentRequest.on('paymentmethod', this._onPaymentMethod.bind(this));
8086
+ paymentRequest
8087
+ .on('shippingaddresschange', this._onShippingAddressChange.bind(this))
8088
+ .on('shippingoptionchange', this._onShippingOptionChange.bind(this))
8089
+ .on('paymentmethod', this._onPaymentMethod.bind(this));
8081
8090
 
8082
8091
  return paymentRequest;
8083
8092
  }
@@ -8085,9 +8094,9 @@ class StripeGooglePayment extends Payment {
8085
8094
  /** @param {import('@stripe/stripe-js').PaymentRequestShippingAddressEvent} event */
8086
8095
  async _onShippingAddressChange(event) {
8087
8096
  const { shippingAddress, updateWith } = event;
8088
- const shipping = this._mapShippingAddress(shippingAddress);
8097
+
8089
8098
  const cart = await this.updateCart({
8090
- shipping: { ...shipping, service: null },
8099
+ shipping: this._mapShippingAddress(shippingAddress),
8091
8100
  shipment_rating: null,
8092
8101
  });
8093
8102
 
@@ -8127,16 +8136,15 @@ class StripeGooglePayment extends Payment {
8127
8136
  shippingOption,
8128
8137
  complete,
8129
8138
  } = event;
8130
- const { require: { shipping: requireShipping } = {} } = this.params;
8131
8139
 
8132
8140
  await this.updateCart({
8133
8141
  account: {
8134
- email: payerEmail,
8142
+ email: payerEmail || billing_details?.email,
8135
8143
  },
8136
- ...(requireShipping && {
8144
+ ...(shippingAddress && {
8137
8145
  shipping: {
8138
8146
  ...this._mapShippingAddress(shippingAddress),
8139
- service: shippingOption.id,
8147
+ service: shippingOption?.id || undefined,
8140
8148
  },
8141
8149
  }),
8142
8150
  billing: {
@@ -8150,9 +8158,9 @@ class StripeGooglePayment extends Payment {
8150
8158
  exp_month: card.exp_month,
8151
8159
  exp_year: card.exp_year,
8152
8160
  last4: card.last4,
8153
- address_check: card.checks.address_line1_check,
8154
- zip_check: card.checks.address_postal_code_check,
8155
- cvc_check: card.checks.cvc_check,
8161
+ address_check: card.checks?.address_line1_check,
8162
+ zip_check: card.checks?.address_postal_code_check,
8163
+ cvc_check: card.checks?.cvc_check,
8156
8164
  },
8157
8165
  },
8158
8166
  });
@@ -8200,8 +8208,8 @@ class StripeGooglePayment extends Payment {
8200
8208
  _mapShippingAddress(address = {}) {
8201
8209
  return {
8202
8210
  name: address.recipient,
8203
- address1: address.addressLine[0],
8204
- address2: address.addressLine[1],
8211
+ address1: address.addressLine?.[0],
8212
+ address2: address.addressLine?.[1],
8205
8213
  city: address.city,
8206
8214
  state: address.region,
8207
8215
  zip: address.postalCode,
@@ -8215,18 +8223,19 @@ class StripeGooglePayment extends Payment {
8215
8223
  return {
8216
8224
  name: address.name,
8217
8225
  phone: address.phone,
8218
- address1: address.address.line1,
8219
- address2: address.address.line2,
8220
- city: address.address.city,
8221
- state: address.address.state,
8222
- zip: address.address.postal_code,
8223
- country: address.address.country,
8226
+ address1: address.address?.line1,
8227
+ address2: address.address?.line2,
8228
+ city: address.address?.city,
8229
+ state: address.address?.state,
8230
+ zip: address.address?.postal_code,
8231
+ country: address.address?.country,
8224
8232
  };
8225
8233
  }
8226
8234
  }
8227
8235
 
8228
8236
  /** @typedef {import('@stripe/stripe-js').Stripe} Stripe */
8229
8237
  /** @typedef {import('@stripe/stripe-js').PaymentRequestPaymentMethodEvent} PaymentRequestPaymentMethodEvent */
8238
+ /** @typedef {import('../../../types').Cart} Cart */
8230
8239
 
8231
8240
  class StripeApplePayment extends Payment {
8232
8241
  constructor(api, options, params, methods) {
@@ -8280,7 +8289,7 @@ class StripeApplePayment extends Payment {
8280
8289
  const paymentRequest = this._createPaymentRequest(cart);
8281
8290
  const canMakePayment = await paymentRequest.canMakePayment();
8282
8291
 
8283
- if (!canMakePayment || !canMakePayment.applePay) {
8292
+ if (!canMakePayment?.applePay) {
8284
8293
  throw new Error(
8285
8294
  'This device is not capable of making Apple Pay payments',
8286
8295
  );
@@ -8317,6 +8326,7 @@ class StripeApplePayment extends Payment {
8317
8326
  }
8318
8327
  }
8319
8328
 
8329
+ /** @param {Cart} cart */
8320
8330
  _createPaymentRequest(cart) {
8321
8331
  const { require: { name, email, shipping, phone } = {} } = this.params;
8322
8332
 
@@ -8329,15 +8339,10 @@ class StripeApplePayment extends Payment {
8329
8339
  ...getPaymentRequestData(cart, this.params),
8330
8340
  });
8331
8341
 
8332
- paymentRequest.on(
8333
- 'shippingaddresschange',
8334
- this._onShippingAddressChange.bind(this),
8335
- );
8336
- paymentRequest.on(
8337
- 'shippingoptionchange',
8338
- this._onShippingOptionChange.bind(this),
8339
- );
8340
- paymentRequest.on('paymentmethod', this._onPaymentMethod.bind(this));
8342
+ paymentRequest
8343
+ .on('shippingaddresschange', this._onShippingAddressChange.bind(this))
8344
+ .on('shippingoptionchange', this._onShippingOptionChange.bind(this))
8345
+ .on('paymentmethod', this._onPaymentMethod.bind(this));
8341
8346
 
8342
8347
  return paymentRequest;
8343
8348
  }
@@ -8345,9 +8350,9 @@ class StripeApplePayment extends Payment {
8345
8350
  /** @param {import('@stripe/stripe-js').PaymentRequestShippingAddressEvent} event */
8346
8351
  async _onShippingAddressChange(event) {
8347
8352
  const { shippingAddress, updateWith } = event;
8348
- const shipping = this._mapShippingAddress(shippingAddress);
8353
+
8349
8354
  const cart = await this.updateCart({
8350
- shipping: { ...shipping, service: null },
8355
+ shipping: this._mapShippingAddress(shippingAddress),
8351
8356
  shipment_rating: null,
8352
8357
  });
8353
8358
 
@@ -8387,16 +8392,15 @@ class StripeApplePayment extends Payment {
8387
8392
  shippingOption,
8388
8393
  complete,
8389
8394
  } = event;
8390
- const { require: { shipping: requireShipping } = {} } = this.params;
8391
8395
 
8392
8396
  await this.updateCart({
8393
8397
  account: {
8394
- email: payerEmail,
8398
+ email: payerEmail || billing_details?.email,
8395
8399
  },
8396
- ...(requireShipping && {
8400
+ ...(shippingAddress && {
8397
8401
  shipping: {
8398
8402
  ...this._mapShippingAddress(shippingAddress),
8399
- service: shippingOption.id,
8403
+ service: shippingOption?.id || undefined,
8400
8404
  },
8401
8405
  }),
8402
8406
  billing: {
@@ -8410,9 +8414,9 @@ class StripeApplePayment extends Payment {
8410
8414
  exp_month: card.exp_month,
8411
8415
  exp_year: card.exp_year,
8412
8416
  last4: card.last4,
8413
- address_check: card.checks.address_line1_check,
8414
- zip_check: card.checks.address_postal_code_check,
8415
- cvc_check: card.checks.cvc_check,
8417
+ address_check: card.checks?.address_line1_check,
8418
+ zip_check: card.checks?.address_postal_code_check,
8419
+ cvc_check: card.checks?.cvc_check,
8416
8420
  },
8417
8421
  },
8418
8422
  });
@@ -8426,8 +8430,8 @@ class StripeApplePayment extends Payment {
8426
8430
  _mapShippingAddress(address = {}) {
8427
8431
  return {
8428
8432
  name: address.recipient,
8429
- address1: address.addressLine[0],
8430
- address2: address.addressLine[1],
8433
+ address1: address.addressLine?.[0],
8434
+ address2: address.addressLine?.[1],
8431
8435
  city: address.city,
8432
8436
  state: address.region,
8433
8437
  zip: address.postalCode,
@@ -8441,12 +8445,12 @@ class StripeApplePayment extends Payment {
8441
8445
  return {
8442
8446
  name: address.name,
8443
8447
  phone: address.phone,
8444
- address1: address.address.line1,
8445
- address2: address.address.line2,
8446
- city: address.address.city,
8447
- state: address.address.state,
8448
- zip: address.address.postal_code,
8449
- country: address.address.country,
8448
+ address1: address.address?.line1,
8449
+ address2: address.address?.line2,
8450
+ city: address.address?.city,
8451
+ state: address.address?.state,
8452
+ zip: address.address?.postal_code,
8453
+ country: address.address?.country,
8450
8454
  };
8451
8455
  }
8452
8456
  }
@@ -8714,6 +8718,44 @@ function getDiscountLabel(discount, cart) {
8714
8718
  return discount.id;
8715
8719
  }
8716
8720
 
8721
+ /** @type {Map<string, number>} */
8722
+ const CURRENCIES_CENTS = new Map();
8723
+
8724
+ /**
8725
+ * @param {string} currency
8726
+ * @returns {number}
8727
+ */
8728
+ function getCurrencyCents(currency) {
8729
+ let cents = CURRENCIES_CENTS.get(currency);
8730
+
8731
+ if (cents !== undefined) {
8732
+ return cents;
8733
+ }
8734
+
8735
+ const formatter = new Intl.NumberFormat('en-US', {
8736
+ style: 'currency',
8737
+ currency,
8738
+ });
8739
+
8740
+ const options = formatter.resolvedOptions();
8741
+ const decimals = options.maximumFractionDigits ?? 2;
8742
+
8743
+ cents = 10 ** decimals;
8744
+
8745
+ CURRENCIES_CENTS.set(currency, cents);
8746
+
8747
+ return cents;
8748
+ }
8749
+
8750
+ /**
8751
+ * @param {string} currency
8752
+ * @param {number} amount
8753
+ * @returns {number}
8754
+ */
8755
+ function amountInCents(currency, amount) {
8756
+ return Math.round(amount * getCurrencyCents(currency));
8757
+ }
8758
+
8717
8759
  /** @typedef {import('./payment').default} Payment */
8718
8760
  /** @typedef {import('../../types').Cart} Cart */
8719
8761
  /** @typedef {import('../../types').Address} Address */
@@ -8801,7 +8843,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
8801
8843
  this,
8802
8844
  cart,
8803
8845
  ),
8804
- newTransactionInfo: getTransactionInfo(cart),
8846
+ newTransactionInfo: getTransactionInfo.call(this, cart),
8805
8847
  };
8806
8848
  }
8807
8849
 
@@ -8814,7 +8856,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
8814
8856
  },
8815
8857
  });
8816
8858
 
8817
- return { newTransactionInfo: getTransactionInfo(cart) };
8859
+ return { newTransactionInfo: getTransactionInfo.call(this, cart) };
8818
8860
  } catch (err) {
8819
8861
  return createError(
8820
8862
  intermediatePaymentData.callbackTrigger,
@@ -8836,7 +8878,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
8836
8878
 
8837
8879
  return {
8838
8880
  newOfferInfo: getOfferInfo(cart),
8839
- newTransactionInfo: getTransactionInfo(cart),
8881
+ newTransactionInfo: getTransactionInfo.call(this, cart),
8840
8882
  };
8841
8883
  } catch (err) {
8842
8884
  return createError(
@@ -8936,12 +8978,13 @@ function getDisplayItems(cart) {
8936
8978
 
8937
8979
  /**
8938
8980
  * Converts cart data to Google Pay transaction information.
8981
+ * @this {Payment}
8939
8982
  * @param {Cart} cart - The current cart data
8940
8983
  * @returns {google.payments.api.TransactionInfo} Transaction info for Google Pay
8941
8984
  */
8942
8985
  function getTransactionInfo(cart) {
8943
- const { settings, capture_total, currency, shipment_delivery, shipping } =
8944
- cart;
8986
+ const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
8987
+ const { settings, capture_total, currency, shipping } = cart;
8945
8988
 
8946
8989
  return {
8947
8990
  countryCode: settings?.country || 'US',
@@ -8949,7 +8992,7 @@ function getTransactionInfo(cart) {
8949
8992
  totalPrice: String(capture_total ?? 0),
8950
8993
  // Set status to FINAL if shipping has been selected, otherwise ESTIMATED
8951
8994
  totalPriceStatus:
8952
- !shipment_delivery || shipping?.service ? 'FINAL' : 'ESTIMATED',
8995
+ !shipmentDelivery || shipping?.service ? 'FINAL' : 'ESTIMATED',
8953
8996
  totalPriceLabel: 'Total',
8954
8997
  displayItems: getDisplayItems(cart),
8955
8998
  };
@@ -8962,12 +9005,14 @@ function getTransactionInfo(cart) {
8962
9005
  * @returns {google.payments.api.ShippingOptionParameters | undefined} Shipping options for Google Pay
8963
9006
  */
8964
9007
  function getShippingOptionParameters(cart) {
8965
- const { shipment_delivery, shipment_rating, shipping } = cart;
9008
+ const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
8966
9009
 
8967
- if (!shipment_delivery) {
9010
+ if (!shipmentDelivery) {
8968
9011
  return undefined;
8969
9012
  }
8970
9013
 
9014
+ const { shipment_rating, shipping } = cart;
9015
+
8971
9016
  if (!shipment_rating?.services?.length) {
8972
9017
  // Return placeholder when no shipping services are available
8973
9018
  return {
@@ -9048,20 +9093,11 @@ function createError(intent, reason, message) {
9048
9093
  };
9049
9094
  }
9050
9095
 
9096
+ /** @typedef {import('../../../types').Cart} Cart */
9097
+
9051
9098
  const API_VERSION$1 = 2;
9052
9099
  const API_MINOR_VERSION$1 = 0;
9053
9100
 
9054
- const ALLOWED_CARD_AUTH_METHODS = ['PAN_ONLY', 'CRYPTOGRAM_3DS'];
9055
-
9056
- const ALLOWED_CARD_NETWORKS = [
9057
- 'AMEX',
9058
- 'DISCOVER',
9059
- 'INTERAC',
9060
- 'JCB',
9061
- 'MASTERCARD',
9062
- 'VISA',
9063
- ];
9064
-
9065
9101
  class BraintreeGooglePayment extends Payment {
9066
9102
  constructor(api, options, params, methods) {
9067
9103
  if (!methods.card) {
@@ -9097,6 +9133,9 @@ class BraintreeGooglePayment extends Payment {
9097
9133
  if (this.google) {
9098
9134
  this.googleClient = new this.google.payments.api.PaymentsClient({
9099
9135
  environment: isLiveMode(this.method.mode) ? 'PRODUCTION' : 'TEST',
9136
+ paymentDataCallbacks: {
9137
+ onPaymentDataChanged: onPaymentDataChanged.bind(this),
9138
+ },
9100
9139
  });
9101
9140
  }
9102
9141
 
@@ -9112,31 +9151,12 @@ class BraintreeGooglePayment extends Payment {
9112
9151
  BraintreeGooglePayment.googleClient = googleClient;
9113
9152
  }
9114
9153
 
9115
- /** @returns {google.payments.api.PaymentMethodSpecification} */
9116
- get cardPaymentMethod() {
9117
- return {
9118
- type: 'CARD',
9119
- parameters: {
9120
- allowedAuthMethods: ALLOWED_CARD_AUTH_METHODS,
9121
- allowedCardNetworks: ALLOWED_CARD_NETWORKS,
9122
- billingAddressRequired: true,
9123
- billingAddressParameters: {
9124
- format: 'FULL',
9125
- phoneNumberRequired: true,
9126
- },
9127
- },
9128
- };
9129
- }
9130
-
9131
- /** @returns {google.payments.api.PaymentMethodSpecification[]} */
9132
- get allowedPaymentMethods() {
9133
- return [this.cardPaymentMethod];
9134
- }
9135
-
9154
+ /** @param {Cart} cart */
9136
9155
  async createElements(cart) {
9137
9156
  const {
9138
9157
  elementId = 'googlepay-button',
9139
9158
  locale = 'en',
9159
+ require: { phone } = {},
9140
9160
  style: { color = 'black', type = 'plain', sizeMode = 'fill' } = {},
9141
9161
  } = this.params;
9142
9162
 
@@ -9147,10 +9167,35 @@ class BraintreeGooglePayment extends Payment {
9147
9167
  this.setElementContainer(elementId);
9148
9168
  await this.loadScripts(this.scripts);
9149
9169
 
9170
+ const braintreeClient = await this._createBraintreeClient();
9171
+
9172
+ const googlePayment = await this.braintree.googlePayment.create({
9173
+ client: braintreeClient,
9174
+ googleMerchantId: this.method.merchant_id,
9175
+ googlePayVersion: API_VERSION$1,
9176
+ });
9177
+
9178
+ const paymentDataRequest = googlePayment.createPaymentDataRequest(
9179
+ this._createPaymentRequestData(cart),
9180
+ );
9181
+
9182
+ const cardPaymentMethod = paymentDataRequest.allowedPaymentMethods.find(
9183
+ (method) => method.type === 'CARD',
9184
+ );
9185
+
9186
+ if (cardPaymentMethod !== undefined) {
9187
+ cardPaymentMethod.parameters.billingAddressRequired = true;
9188
+
9189
+ cardPaymentMethod.parameters.billingAddressParameters = {
9190
+ format: 'FULL',
9191
+ phoneNumberRequired: Boolean(phone),
9192
+ };
9193
+ }
9194
+
9150
9195
  const isReadyToPay = await this.googleClient.isReadyToPay({
9151
9196
  apiVersion: API_VERSION$1,
9152
9197
  apiVersionMinor: API_MINOR_VERSION$1,
9153
- allowedPaymentMethods: this.allowedPaymentMethods,
9198
+ allowedPaymentMethods: paymentDataRequest.allowedPaymentMethods,
9154
9199
  existingPaymentMethodRequired: true,
9155
9200
  });
9156
9201
 
@@ -9160,16 +9205,6 @@ class BraintreeGooglePayment extends Payment {
9160
9205
  );
9161
9206
  }
9162
9207
 
9163
- const braintreeClient = await this._createBraintreeClient();
9164
- const googlePayment = await this.braintree.googlePayment.create({
9165
- client: braintreeClient,
9166
- googleMerchantId: this.method.merchant_id,
9167
- googlePayVersion: API_VERSION$1,
9168
- });
9169
- const paymentRequestData = this._createPaymentRequestData(cart);
9170
- const paymentDataRequest =
9171
- googlePayment.createPaymentDataRequest(paymentRequestData);
9172
-
9173
9208
  this.element = this.googleClient.createButton({
9174
9209
  buttonColor: color,
9175
9210
  buttonType: type,
@@ -9196,6 +9231,7 @@ class BraintreeGooglePayment extends Payment {
9196
9231
  }
9197
9232
  }
9198
9233
 
9234
+ /** @returns {Promise<braintree.Client>} */
9199
9235
  async _createBraintreeClient() {
9200
9236
  const authorization = await this.authorizeGateway({
9201
9237
  gateway: 'braintree',
@@ -9210,39 +9246,51 @@ class BraintreeGooglePayment extends Payment {
9210
9246
  });
9211
9247
  }
9212
9248
 
9213
- /** @returns {google.payments.api.PaymentDataRequest} */
9249
+ /**
9250
+ * @param {Cart} cart
9251
+ * @returns {google.payments.api.PaymentDataRequest}
9252
+ */
9214
9253
  _createPaymentRequestData(cart) {
9215
9254
  const {
9216
- settings: { name, country },
9217
- capture_total,
9218
- currency,
9255
+ settings: { name },
9219
9256
  } = cart;
9257
+
9220
9258
  const { require: { email, shipping, phone } = {} } = this.params;
9221
9259
 
9260
+ /** @type {google.payments.api.CallbackIntent[]} */
9261
+ const callbackIntents = ['OFFER'];
9262
+
9263
+ if (shipping) {
9264
+ callbackIntents.push('SHIPPING_ADDRESS', 'SHIPPING_OPTION');
9265
+ }
9266
+
9222
9267
  return {
9223
9268
  apiVersion: API_VERSION$1,
9224
9269
  apiVersionMinor: API_MINOR_VERSION$1,
9225
- transactionInfo: {
9226
- countryCode: country,
9227
- currencyCode: currency,
9228
- totalPrice: capture_total.toString(),
9229
- totalPriceStatus: 'ESTIMATED',
9230
- },
9231
- allowedPaymentMethods: this.allowedPaymentMethods,
9270
+ transactionInfo: getTransactionInfo.call(this, cart),
9271
+ /**
9272
+ * @see {@link https://developer.paypal.com/braintree/docs/guides/google-pay/client-side/javascript/v3/#requesting-a-payment}
9273
+ *
9274
+ * Braintree automatically populates the `allowedPaymentMethods` property.
9275
+ */
9232
9276
  emailRequired: Boolean(email),
9233
9277
  shippingAddressRequired: Boolean(shipping),
9234
9278
  shippingAddressParameters: {
9235
9279
  phoneNumberRequired: Boolean(phone),
9236
9280
  },
9281
+ shippingOptionRequired: Boolean(shipping),
9282
+ shippingOptionParameters: getShippingOptionParameters.call(this, cart),
9283
+ offerInfo: getOfferInfo(cart),
9237
9284
  merchantInfo: {
9238
9285
  merchantName: name,
9239
9286
  merchantId: this.method.merchant_id,
9240
9287
  },
9288
+ callbackIntents,
9241
9289
  };
9242
9290
  }
9243
9291
 
9244
9292
  /**
9245
- * @param {object} googlePayment
9293
+ * @param {braintree.GooglePayment} googlePayment
9246
9294
  * @param {google.payments.api.PaymentDataRequest} paymentDataRequest
9247
9295
  */
9248
9296
  async _onClick(googlePayment, paymentDataRequest) {
@@ -9259,34 +9307,59 @@ class BraintreeGooglePayment extends Payment {
9259
9307
  }
9260
9308
 
9261
9309
  /**
9262
- * @param {object} googlePayment
9310
+ * @param {braintree.GooglePayment} googlePayment
9263
9311
  * @param {google.payments.api.PaymentData} paymentData
9264
9312
  */
9265
9313
  async _submitPayment(googlePayment, paymentData) {
9266
- const { require: { shipping: requireShipping } = {} } = this.params;
9267
9314
  const { nonce } = await googlePayment.parseResponse(paymentData);
9268
- const { email, shippingAddress, paymentMethodData } = paymentData;
9269
- const {
9270
- info: { billingAddress },
9271
- } = paymentMethodData;
9315
+ const { email, shippingAddress, shippingOptionData, paymentMethodData } =
9316
+ paymentData;
9317
+ const { info: { billingAddress } = {} } = paymentMethodData;
9272
9318
 
9273
- await this.updateCart({
9319
+ const cart = await this.updateCart({
9274
9320
  account: {
9275
9321
  email,
9276
9322
  },
9277
9323
  billing: {
9278
9324
  method: 'google',
9325
+ account_card_id: null,
9326
+ card: null,
9279
9327
  google: {
9280
9328
  nonce,
9281
9329
  gateway: 'braintree',
9282
9330
  },
9283
9331
  ...convertToSwellAddress$2(billingAddress),
9284
9332
  },
9285
- ...(requireShipping && {
9286
- shipping: convertToSwellAddress$2(shippingAddress),
9333
+ ...(shippingAddress && {
9334
+ shipping: {
9335
+ ...convertToSwellAddress$2(shippingAddress),
9336
+ service: shippingOptionData?.id || undefined,
9337
+ },
9287
9338
  }),
9288
9339
  });
9289
9340
 
9341
+ if (cart.subscription_delivery) {
9342
+ try {
9343
+ const card = await cardApi.createToken({
9344
+ gateway: 'braintree',
9345
+ account_id: cart.account_id,
9346
+ nonce,
9347
+ });
9348
+
9349
+ delete card.nonce;
9350
+
9351
+ await this.updateCart({
9352
+ billing: {
9353
+ method: 'card',
9354
+ card,
9355
+ google: null,
9356
+ },
9357
+ });
9358
+ } catch (error) {
9359
+ console.warn('Failed to extract card data from google token', error);
9360
+ }
9361
+ }
9362
+
9290
9363
  this.onSuccess();
9291
9364
  }
9292
9365
  }
@@ -9316,7 +9389,7 @@ async function onShippingAddressChange(shippingContact) {
9316
9389
  'Shipping is not available for the provided address.';
9317
9390
 
9318
9391
  return {
9319
- newTotal: getTotal(cart, this.merchantInfo),
9392
+ newTotal: getTotal.call(this, cart, this.merchantInfo),
9320
9393
  newLineItems: getLineItems(cart),
9321
9394
  newShippingMethods: [], // REQUIRED: Must always provide this, even as empty array
9322
9395
  errors: [
@@ -9327,15 +9400,15 @@ async function onShippingAddressChange(shippingContact) {
9327
9400
 
9328
9401
  // Success: Return updated totals and shipping methods
9329
9402
  return {
9330
- newTotal: getTotal(cart, this.merchantInfo),
9403
+ newTotal: getTotal.call(this, cart, this.merchantInfo),
9331
9404
  newLineItems: getLineItems(cart),
9332
- newShippingMethods: getShippingMethods(cart),
9405
+ newShippingMethods: getShippingMethods.call(this, cart),
9333
9406
  };
9334
9407
  } catch (err) {
9335
9408
  const cartData = await this.getCart();
9336
9409
 
9337
9410
  return {
9338
- newTotal: getTotal(cartData, this.merchantInfo),
9411
+ newTotal: getTotal.call(this, cartData, this.merchantInfo),
9339
9412
  newLineItems: getLineItems(cartData),
9340
9413
  newShippingMethods: [], // REQUIRED: Must always provide this, even as empty array
9341
9414
  errors: [new ApplePayError('unknown', undefined, err.message)],
@@ -9381,12 +9454,12 @@ async function onShippingMethodChange(shippingMethod) {
9381
9454
  });
9382
9455
 
9383
9456
  return {
9384
- newTotal: getTotal(cart, this.merchantInfo),
9457
+ newTotal: getTotal.call(this, cart, this.merchantInfo),
9385
9458
  newLineItems: getLineItems(cart),
9386
9459
  };
9387
9460
  } catch (err) {
9388
9461
  return {
9389
- newTotal: getTotal(await this.getCart(), this.merchantInfo),
9462
+ newTotal: getTotal.call(this, await this.getCart(), this.merchantInfo),
9390
9463
  errors: [new ApplePayError('unknown', undefined, err.message)],
9391
9464
  };
9392
9465
  }
@@ -9426,7 +9499,7 @@ async function onCouponCodeUpdated(couponCode) {
9426
9499
 
9427
9500
  // Valid coupon applied successfully
9428
9501
  return {
9429
- newTotal: getTotal(cart, this.merchantInfo),
9502
+ newTotal: getTotal.call(this, cart, this.merchantInfo),
9430
9503
  newLineItems: getLineItems(cart),
9431
9504
  };
9432
9505
  } catch (err) {
@@ -9434,7 +9507,7 @@ async function onCouponCodeUpdated(couponCode) {
9434
9507
  const currentCart = await this.getCart();
9435
9508
 
9436
9509
  return {
9437
- newTotal: getTotal(currentCart, this.merchantInfo),
9510
+ newTotal: getTotal.call(this, currentCart, this.merchantInfo),
9438
9511
  newLineItems: getLineItems(currentCart),
9439
9512
  errors: [new ApplePayError('couponCodeInvalid', undefined, err.message)],
9440
9513
  };
@@ -9468,15 +9541,17 @@ async function onCouponCodeChanged(session, event) {
9468
9541
  * This ensures the user sees "pending" until they've selected shipping,
9469
9542
  * then sees the final amount once everything is calculated.
9470
9543
  *
9544
+ * @this {Payment}
9471
9545
  * @param {Cart} cart
9472
9546
  * @param {object} [merchantInfo]
9473
9547
  * @returns {ApplePayJS.ApplePayLineItem}
9474
9548
  */
9475
9549
  function getTotal(cart, merchantInfo) {
9476
- const { capture_total, shipment_delivery, shipping } = cart;
9550
+ const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
9551
+ const { capture_total, shipping } = cart;
9477
9552
 
9478
9553
  // Use 'final' only after shipping method is selected or not needed, otherwise 'pending'
9479
- const isFinalPrice = !shipment_delivery || shipping?.service;
9554
+ const isFinalPrice = !shipmentDelivery || shipping?.service;
9480
9555
  const type = isFinalPrice ? 'final' : 'pending';
9481
9556
 
9482
9557
  return {
@@ -9545,16 +9620,19 @@ function getLineItems(cart) {
9545
9620
  *
9546
9621
  * IMPORTANT: Amounts must be formatted as strings with 2 decimals.
9547
9622
  *
9623
+ * @this {Payment}
9548
9624
  * @param {Cart} cart
9549
9625
  * @returns {ApplePayJS.ApplePayShippingMethod[]}
9550
9626
  */
9551
9627
  function getShippingMethods(cart) {
9552
- const { shipment_delivery, shipment_rating } = cart;
9628
+ const { require: { shipping: shipmentDelivery = false } = {} } = this.params;
9553
9629
 
9554
- if (!shipment_delivery) {
9630
+ if (!shipmentDelivery) {
9555
9631
  return [];
9556
9632
  }
9557
9633
 
9634
+ const { shipment_rating } = cart;
9635
+
9558
9636
  if (!shipment_rating?.services?.length) {
9559
9637
  return [];
9560
9638
  }
@@ -9605,13 +9683,38 @@ function convertToSwellAddress$1(address = {}) {
9605
9683
  };
9606
9684
  }
9607
9685
 
9608
- const VERSION$1 = 3;
9686
+ /** @param {object} params */
9687
+ function getRequiredContactFields(params) {
9688
+ const { require = {} } = params;
9689
+ /** @type {ApplePayJS.ApplePayContactField[]} */
9690
+ const requiredFields = [];
9691
+
9692
+ if (require.email) {
9693
+ requiredFields.push('email');
9694
+ }
9695
+
9696
+ if (require.name) {
9697
+ requiredFields.push('name');
9698
+ }
9699
+
9700
+ if (require.phone) {
9701
+ requiredFields.push('phone');
9702
+ }
9703
+
9704
+ /** @type {ApplePayJS.ApplePayContactField[]} */
9705
+ const requiredShippingContactFields = require.shipping
9706
+ ? [...requiredFields, 'postalAddress']
9707
+ : [];
9708
+
9709
+ /** @type {ApplePayJS.ApplePayContactField[]} */
9710
+ const requiredBillingContactFields = [...requiredFields, 'postalAddress'];
9711
+
9712
+ return { requiredBillingContactFields, requiredShippingContactFields };
9713
+ }
9714
+
9715
+ /** @typedef {import('../../../types').Cart} Cart */
9609
9716
 
9610
- const MERCHANT_CAPABILITIES = [
9611
- 'supports3DS',
9612
- 'supportsDebit',
9613
- 'supportsCredit',
9614
- ];
9717
+ const VERSION$1 = 14;
9615
9718
 
9616
9719
  class BraintreeApplePayment extends Payment {
9617
9720
  constructor(api, options, params, methods) {
@@ -9643,6 +9746,7 @@ class BraintreeApplePayment extends Payment {
9643
9746
  return window.ApplePaySession;
9644
9747
  }
9645
9748
 
9749
+ /** @param {Cart} cart */
9646
9750
  async createElements(cart) {
9647
9751
  const { elementId = 'applepay-button' } = this.params;
9648
9752
 
@@ -9656,10 +9760,12 @@ class BraintreeApplePayment extends Payment {
9656
9760
  }
9657
9761
 
9658
9762
  const braintreeClient = await this._createBraintreeClient();
9763
+
9659
9764
  const applePayment = await this.braintree.applePay.create({
9660
9765
  client: braintreeClient,
9661
9766
  });
9662
- const paymentRequest = await this._createPaymentRequest(cart, applePayment);
9767
+
9768
+ const paymentRequest = this._createPaymentRequest(cart, applePayment);
9663
9769
 
9664
9770
  this.element = this._createButton(applePayment, paymentRequest);
9665
9771
  }
@@ -9676,8 +9782,9 @@ class BraintreeApplePayment extends Payment {
9676
9782
  }
9677
9783
 
9678
9784
  /**
9679
- * @param {object} applePayment
9785
+ * @param {braintree.ApplePay} applePayment
9680
9786
  * @param {ApplePayJS.ApplePayPaymentRequest} paymentRequest
9787
+ * @returns {HTMLDivElement}
9681
9788
  */
9682
9789
  _createButton(applePayment, paymentRequest) {
9683
9790
  const { style: { type = 'plain', theme = 'black', height = '40px' } = {} } =
@@ -9698,6 +9805,7 @@ class BraintreeApplePayment extends Payment {
9698
9805
  return button;
9699
9806
  }
9700
9807
 
9808
+ /** @returns {Promise<braintree.Client>} */
9701
9809
  async _createBraintreeClient() {
9702
9810
  const authorization = await this.authorizeGateway({
9703
9811
  gateway: 'braintree',
@@ -9712,47 +9820,43 @@ class BraintreeApplePayment extends Payment {
9712
9820
  });
9713
9821
  }
9714
9822
 
9715
- /** @returns {ApplePayJS.ApplePayPaymentRequest} */
9823
+ /**
9824
+ * @param {Cart} cart
9825
+ * @param {braintree.ApplePay} applePayment
9826
+ * @returns {ApplePayJS.ApplePayPaymentRequest}
9827
+ */
9716
9828
  _createPaymentRequest(cart, applePayment) {
9717
- const { require = {} } = this.params;
9718
9829
  const {
9719
9830
  settings: { name, country },
9720
9831
  capture_total,
9721
9832
  currency,
9722
9833
  } = cart;
9723
9834
 
9724
- const requiredShippingContactFields = [];
9725
- const requiredBillingContactFields = ['postalAddress'];
9726
-
9727
- if (require.name) {
9728
- requiredShippingContactFields.push('name');
9729
- }
9730
- if (require.email) {
9731
- requiredShippingContactFields.push('email');
9732
- }
9733
- if (require.phone) {
9734
- requiredShippingContactFields.push('phone');
9735
- }
9736
- if (require.shipping) {
9737
- requiredShippingContactFields.push('postalAddress');
9738
- }
9835
+ const { requiredBillingContactFields, requiredShippingContactFields } =
9836
+ getRequiredContactFields(this.params);
9739
9837
 
9740
9838
  return applePayment.createPaymentRequest({
9741
9839
  total: {
9742
9840
  label: name,
9743
9841
  type: 'pending',
9744
- amount: capture_total.toString(),
9842
+ amount: (capture_total || 0).toFixed(2),
9745
9843
  },
9746
9844
  countryCode: country,
9747
9845
  currencyCode: currency,
9748
- merchantCapabilities: MERCHANT_CAPABILITIES,
9846
+ /**
9847
+ * @see {@link https://developer.paypal.com/braintree/docs/guides/apple-pay/client-side/javascript/v3/#create-anapplepaysession}
9848
+ *
9849
+ * Braintree automatically fills in `supportedNetworks` and `merchantCapabilities`.
9850
+ */
9749
9851
  requiredShippingContactFields,
9750
9852
  requiredBillingContactFields,
9853
+ supportsCouponCode: true,
9854
+ lineItems: getLineItems(cart),
9751
9855
  });
9752
9856
  }
9753
9857
 
9754
9858
  /**
9755
- * @param {object} applePayment
9859
+ * @param {braintree.ApplePay} applePayment
9756
9860
  * @param {ApplePayJS.ApplePayPaymentRequest} paymentRequest
9757
9861
  */
9758
9862
  _createPaymentSession(applePayment, paymentRequest) {
@@ -9773,11 +9877,23 @@ class BraintreeApplePayment extends Payment {
9773
9877
  }
9774
9878
  };
9775
9879
 
9880
+ session.onshippingcontactselected = onShippingContactSelected.bind(
9881
+ this,
9882
+ session,
9883
+ );
9884
+
9885
+ session.onshippingmethodselected = onShippingMethodSelected.bind(
9886
+ this,
9887
+ session,
9888
+ );
9889
+
9890
+ session.oncouponcodechanged = onCouponCodeChanged.bind(this, session);
9891
+
9776
9892
  session.onpaymentauthorized = async (event) => {
9777
9893
  const {
9778
9894
  payment: { token, shippingContact, billingContact },
9779
9895
  } = event;
9780
- const { require: { shipping: requireShipping } = {} } = this.params;
9896
+
9781
9897
  const payload = await applePayment
9782
9898
  .tokenize({ token })
9783
9899
  .catch(this.onError.bind(this));
@@ -9786,23 +9902,47 @@ class BraintreeApplePayment extends Payment {
9786
9902
  return session.completePayment(this.ApplePaySession.STATUS_FAILURE);
9787
9903
  }
9788
9904
 
9789
- await this.updateCart({
9905
+ const cart = await this.updateCart({
9790
9906
  account: {
9791
- email: shippingContact.emailAddress,
9907
+ email: shippingContact?.emailAddress || billingContact?.emailAddress,
9792
9908
  },
9793
9909
  billing: {
9794
9910
  method: 'apple',
9911
+ account_card_id: null,
9912
+ card: null,
9795
9913
  apple: {
9796
9914
  nonce: payload.nonce,
9797
9915
  gateway: 'braintree',
9798
9916
  },
9799
9917
  ...convertToSwellAddress$1(billingContact),
9800
9918
  },
9801
- ...(requireShipping && {
9919
+ ...(shippingContact && {
9802
9920
  shipping: convertToSwellAddress$1(shippingContact),
9803
9921
  }),
9804
9922
  });
9805
9923
 
9924
+ if (cart.subscription_delivery) {
9925
+ try {
9926
+ const card = await cardApi.createToken({
9927
+ gateway: 'braintree',
9928
+ account_id: cart.account_id,
9929
+ nonce: payload.nonce,
9930
+ });
9931
+
9932
+ delete card.nonce;
9933
+
9934
+ await this.updateCart({
9935
+ billing: {
9936
+ method: 'card',
9937
+ card,
9938
+ apple: null,
9939
+ },
9940
+ });
9941
+ } catch (error) {
9942
+ console.warn('Failed to extract card data from apple token', error);
9943
+ }
9944
+ }
9945
+
9806
9946
  this.onSuccess();
9807
9947
 
9808
9948
  return session.completePayment(this.ApplePaySession.STATUS_SUCCESS);
@@ -9908,6 +10048,8 @@ class AbstractGooglePayment extends Payment {
9908
10048
  * @returns {google.payments.api.PaymentMethodSpecification}
9909
10049
  */
9910
10050
  _getCardPaymentMethod(submit = false) {
10051
+ const { require: { phone } = {} } = this.params;
10052
+
9911
10053
  return {
9912
10054
  type: 'CARD',
9913
10055
  parameters: {
@@ -9916,7 +10058,7 @@ class AbstractGooglePayment extends Payment {
9916
10058
  billingAddressRequired: true,
9917
10059
  billingAddressParameters: {
9918
10060
  format: 'FULL',
9919
- phoneNumberRequired: true,
10061
+ phoneNumberRequired: Boolean(phone),
9920
10062
  },
9921
10063
  },
9922
10064
  ...(submit && {
@@ -9949,29 +10091,30 @@ class AbstractGooglePayment extends Payment {
9949
10091
  cart.shipment_price = 0;
9950
10092
  cart.shipping = {};
9951
10093
 
9952
- const { shipment_delivery } = cart;
9953
10094
  const { require: { email, shipping, phone } = {} } = this.params;
9954
10095
 
10096
+ /** @type {google.payments.api.CallbackIntent[]} */
10097
+ const callbackIntents = ['OFFER', 'PAYMENT_AUTHORIZATION'];
10098
+
10099
+ if (shipping) {
10100
+ callbackIntents.push('SHIPPING_ADDRESS', 'SHIPPING_OPTION');
10101
+ }
10102
+
9955
10103
  return {
9956
10104
  apiVersion: API_VERSION,
9957
10105
  apiVersionMinor: API_MINOR_VERSION,
9958
- transactionInfo: getTransactionInfo(cart),
10106
+ transactionInfo: getTransactionInfo.call(this, cart),
9959
10107
  allowedPaymentMethods: this._getAllowedPaymentMethods(true),
9960
10108
  emailRequired: Boolean(email),
9961
10109
  shippingAddressRequired: Boolean(shipping),
9962
10110
  shippingAddressParameters: {
9963
10111
  phoneNumberRequired: Boolean(phone),
9964
10112
  },
9965
- shippingOptionRequired: Boolean(shipment_delivery),
10113
+ shippingOptionRequired: Boolean(shipping),
9966
10114
  shippingOptionParameters: getShippingOptionParameters.call(this, cart),
9967
10115
  offerInfo: getOfferInfo(cart),
9968
10116
  merchantInfo,
9969
- callbackIntents: [
9970
- 'OFFER',
9971
- 'SHIPPING_ADDRESS',
9972
- 'SHIPPING_OPTION',
9973
- 'PAYMENT_AUTHORIZATION',
9974
- ],
10117
+ callbackIntents,
9975
10118
  };
9976
10119
  }
9977
10120
 
@@ -10095,6 +10238,22 @@ class AbstractGooglePayment extends Payment {
10095
10238
  /** @typedef {import('../../../types').Cart} Cart */
10096
10239
 
10097
10240
  class AuthorizeNetGooglePayment extends AbstractGooglePayment {
10241
+ /**
10242
+ * @override
10243
+ * @returns {google.payments.api.CardNetwork[]}
10244
+ */
10245
+ getAllowedCardNetworks() {
10246
+ return ['AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'];
10247
+ }
10248
+
10249
+ /**
10250
+ * @override
10251
+ * @returns {google.payments.api.CardAuthMethod[]}
10252
+ */
10253
+ getAllowedCardAuthMethods() {
10254
+ return ['PAN_ONLY', 'CRYPTOGRAM_3DS'];
10255
+ }
10256
+
10098
10257
  /**
10099
10258
  * @override
10100
10259
  * @returns {google.payments.api.PaymentGatewayTokenizationParameters}
@@ -10112,7 +10271,6 @@ class AuthorizeNetGooglePayment extends AbstractGooglePayment {
10112
10271
  * @returns {Promise<object>}
10113
10272
  */
10114
10273
  async preparePaymentDataForCartUpdate(paymentData) {
10115
- const { require: { shipping: requireShipping } = {} } = this.params;
10116
10274
  const { email, shippingAddress, shippingOptionData, paymentMethodData } =
10117
10275
  paymentData;
10118
10276
 
@@ -10133,7 +10291,7 @@ class AuthorizeNetGooglePayment extends AbstractGooglePayment {
10133
10291
  },
10134
10292
  ...convertToSwellAddress$2(billingAddress),
10135
10293
  },
10136
- ...(requireShipping && {
10294
+ ...(shippingAddress && {
10137
10295
  shipping: {
10138
10296
  ...convertToSwellAddress$2(shippingAddress),
10139
10297
  service: shippingOptionData?.id || undefined,
@@ -10200,9 +10358,15 @@ class AbstractApplePayment extends Payment {
10200
10358
  return window.ApplePaySession;
10201
10359
  }
10202
10360
 
10203
- /** @returns {string[]} */
10361
+ /**
10362
+ * We should specify the payment methods in the order preferred by the gateway.
10363
+ *
10364
+ * @see {@link https://developer.apple.com/documentation/applepayontheweb/applepaypaymentrequest/supportednetworks}
10365
+ *
10366
+ * @returns {string[]}
10367
+ */
10204
10368
  getSupportedCardNetworks() {
10205
- return ['amex', 'discover', 'interac', 'jcb', 'masterCard', 'visa'];
10369
+ return ['visa', 'masterCard', 'amex', 'discover', 'interac', 'jcb'];
10206
10370
  }
10207
10371
 
10208
10372
  /** @returns {ApplePayJS.ApplePayMerchantCapability[]} */
@@ -10213,12 +10377,12 @@ class AbstractApplePayment extends Payment {
10213
10377
  /**
10214
10378
  * Creates the Apple Pay payment request object
10215
10379
  *
10216
- * IMPORTANT: countryCode here is the MERCHANT's country (where your business is located),
10217
- * NOT the customer's country. Customer country comes from shippingContact.countryCode.
10380
+ * IMPORTANT: `countryCode` here is the MERCHANT's country (where your business is located),
10381
+ * NOT the customer's country. Customer country comes from `shippingContact.countryCode`.
10218
10382
  *
10219
- * NOTE: We do NOT pass shippingMethods in the initial request. Shipping methods
10383
+ * NOTE: We do NOT pass `shippingMethods` in the initial request. Shipping methods
10220
10384
  * are provided dynamically after the user selects/confirms their address in the
10221
- * 'shippingcontactselected' event handler.
10385
+ * `'shippingcontactselected'` event handler.
10222
10386
  *
10223
10387
  * @param {Cart} cart
10224
10388
  * @returns {ApplePayJS.ApplePayPaymentRequest}
@@ -10226,38 +10390,21 @@ class AbstractApplePayment extends Payment {
10226
10390
  _createPaymentRequest(cart) {
10227
10391
  cart = { ...cart };
10228
10392
 
10229
- const { require = {} } = this.params;
10230
10393
  const {
10231
10394
  settings: { country },
10232
10395
  currency,
10233
10396
  } = cart;
10234
10397
 
10235
- const requiredShippingContactFields = [];
10236
- const requiredBillingContactFields = ['postalAddress'];
10237
-
10238
- if (require.name) {
10239
- requiredShippingContactFields.push('name');
10240
- }
10241
-
10242
- if (require.email) {
10243
- requiredShippingContactFields.push('email');
10244
- }
10245
-
10246
- if (require.phone) {
10247
- requiredShippingContactFields.push('phone');
10248
- }
10249
-
10250
- if (require.shipping) {
10251
- requiredShippingContactFields.push('postalAddress');
10252
- }
10253
-
10254
10398
  // When initiating a payment request,
10255
10399
  // we should not display the shipping cost, as it will be calculated later.
10256
10400
  cart.shipment_price = 0;
10257
10401
  cart.shipping = {};
10258
10402
 
10403
+ const { requiredBillingContactFields, requiredShippingContactFields } =
10404
+ getRequiredContactFields(this.params);
10405
+
10259
10406
  return {
10260
- total: getTotal(cart, this.merchantInfo),
10407
+ total: getTotal.call(this, cart, this.merchantInfo),
10261
10408
  countryCode: country, // Merchant's country
10262
10409
  currencyCode: currency,
10263
10410
  supportedNetworks: this.getSupportedCardNetworks(),
@@ -10439,6 +10586,22 @@ class AbstractApplePayment extends Payment {
10439
10586
  }
10440
10587
 
10441
10588
  class AuthorizeNetApplePayment extends AbstractApplePayment {
10589
+ /**
10590
+ * @override
10591
+ * @returns {string[]}
10592
+ */
10593
+ getSupportedCardNetworks() {
10594
+ return ['visa', 'masterCard', 'amex', 'discover'];
10595
+ }
10596
+
10597
+ /**
10598
+ * @override
10599
+ * @returns {ApplePayJS.ApplePayMerchantCapability[]}
10600
+ */
10601
+ getMerchantCapabilities() {
10602
+ return ['supports3DS', 'supportsDebit', 'supportsCredit'];
10603
+ }
10604
+
10442
10605
  /**
10443
10606
  * @override
10444
10607
  * @param {ApplePayJS.ApplePayValidateMerchantEvent} event
@@ -10472,11 +10635,9 @@ class AuthorizeNetApplePayment extends AbstractApplePayment {
10472
10635
  payment: { token, shippingContact, billingContact },
10473
10636
  } = event;
10474
10637
 
10475
- const { require: { shipping: requireShipping } = {} } = this.params;
10476
-
10477
10638
  return {
10478
10639
  account: {
10479
- email: shippingContact.emailAddress,
10640
+ email: shippingContact?.emailAddress || billingContact?.emailAddress,
10480
10641
  },
10481
10642
  billing: {
10482
10643
  method: 'apple',
@@ -10488,7 +10649,7 @@ class AuthorizeNetApplePayment extends AbstractApplePayment {
10488
10649
  },
10489
10650
  ...convertToSwellAddress$1(billingContact),
10490
10651
  },
10491
- ...(requireShipping && {
10652
+ ...(shippingContact && {
10492
10653
  shipping: convertToSwellAddress$1(shippingContact),
10493
10654
  }),
10494
10655
  };
@@ -10501,7 +10662,7 @@ class QuickpayCardPayment extends Payment {
10501
10662
  }
10502
10663
 
10503
10664
  get orderId() {
10504
- return Math.random().toString(36).substr(2, 9);
10665
+ return Math.random().toString(36).slice(2, 11);
10505
10666
  }
10506
10667
 
10507
10668
  async tokenize() {
@@ -10563,6 +10724,12 @@ class QuickpayCardPayment extends Payment {
10563
10724
  throw new Error(card.error.message);
10564
10725
  }
10565
10726
 
10727
+ card.gateway = 'quickpay';
10728
+
10729
+ if (!isLiveMode(this.method.mode)) {
10730
+ card.test = true;
10731
+ }
10732
+
10566
10733
  await this.updateCart({
10567
10734
  billing: {
10568
10735
  method: 'card',
@@ -10602,7 +10769,7 @@ async function getConvesioPaymentSettings(mode, settings, country) {
10602
10769
  merchantAccount: false,
10603
10770
  countryCode: country || 'US',
10604
10771
  shopperLocale: 'en-US',
10605
- // shopperReference: email ? md5(email) : undefined,
10772
+ // shopperReference: email ? md5(email.toLowerCase()) : undefined,
10606
10773
  }),
10607
10774
  },
10608
10775
  ).then((res) => res.json());
@@ -10730,15 +10897,20 @@ class ConvesioCardPayment extends Payment {
10730
10897
  }
10731
10898
  }
10732
10899
 
10900
+ function getBaseConvesioVaultUrl(mode) {
10901
+ return isLiveMode(mode)
10902
+ ? 'https://vault.convesiopay.com'
10903
+ : 'https://qa-vault.convesiopay.com';
10904
+ }
10905
+
10733
10906
  function createConvesioCardPaymentToken(settings, data) {
10734
- const baseUrl = getBaseConvesioApiUrl(settings.mode);
10907
+ const baseUrl = getBaseConvesioVaultUrl(settings.mode);
10735
10908
 
10736
10909
  return fetch(`${baseUrl}/v1/create-token`, {
10737
10910
  method: 'POST',
10738
10911
  headers: {
10739
10912
  Accept: 'application/json',
10740
10913
  'Content-Type': 'application/json',
10741
- 'X-Requested-With': 'convesio-pay-dashboard',
10742
10914
  'X-Api-Key': settings.public_key,
10743
10915
  },
10744
10916
  body: JSON.stringify(data),
@@ -10853,8 +11025,6 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
10853
11025
  payment: { token, shippingContact, billingContact },
10854
11026
  } = event;
10855
11027
 
10856
- const { require: { shipping: requireShipping } = {} } = this.params;
10857
-
10858
11028
  const payment = await createConvesioApplePaymentToken(
10859
11029
  this.method.mode,
10860
11030
  this.convesiopay,
@@ -10876,7 +11046,7 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
10876
11046
 
10877
11047
  return {
10878
11048
  account: {
10879
- email: shippingContact.emailAddress,
11049
+ email: shippingContact?.emailAddress || billingContact?.emailAddress,
10880
11050
  },
10881
11051
  billing: {
10882
11052
  method: 'apple',
@@ -10891,7 +11061,7 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
10891
11061
  },
10892
11062
  ...convertToSwellAddress$1(billingContact),
10893
11063
  },
10894
- ...(requireShipping && {
11064
+ ...(shippingContact && {
10895
11065
  shipping: convertToSwellAddress$1(shippingContact),
10896
11066
  }),
10897
11067
  };
@@ -11021,7 +11191,6 @@ class ConvesioPayGooglePayment extends AbstractGooglePayment {
11021
11191
  * @returns {Promise<object>}
11022
11192
  */
11023
11193
  async preparePaymentDataForCartUpdate(paymentData) {
11024
- const { require: { shipping: requireShipping } = {} } = this.params;
11025
11194
  const { email, shippingAddress, shippingOptionData, paymentMethodData } =
11026
11195
  paymentData;
11027
11196
 
@@ -11064,7 +11233,7 @@ class ConvesioPayGooglePayment extends AbstractGooglePayment {
11064
11233
  },
11065
11234
  ...convertToSwellAddress$2(billingAddress),
11066
11235
  },
11067
- ...(requireShipping && {
11236
+ ...(shippingAddress && {
11068
11237
  shipping: {
11069
11238
  ...convertToSwellAddress$2(shippingAddress),
11070
11239
  service: shippingOptionData?.id || undefined,
@@ -11960,20 +12129,29 @@ class SezzleDirectPayment extends Payment {
11960
12129
  settings: { name },
11961
12130
  } = cart;
11962
12131
 
11963
- const shipmentDelivery = Boolean(cart.shipment_delivery);
12132
+ const { require: { shipping } = {} } = this.params;
11964
12133
  const cartCurrency = getCartCurrency(cart);
11965
12134
 
11966
12135
  return {
11967
12136
  checkout_payload: {
11968
- express_checkout_type: shipmentDelivery ? 'multi-step' : 'no-shipping',
12137
+ express_checkout_type: shipping ? 'multi-step' : 'no-shipping',
12138
+ customer: {
12139
+ email: cart.account?.email,
12140
+ first_name: cart.account?.first_name,
12141
+ last_name: cart.account?.last_name,
12142
+ phone: cart.account?.phone,
12143
+ // TODO: recurring payments https://docs.sezzle.com/docs/api/tokenization/intro
12144
+ // tokenize: cart.subscription_delivery,
12145
+ // recurring: cart.subscription_delivery,
12146
+ },
11969
12147
  order: {
11970
12148
  intent: 'AUTH',
11971
12149
  reference_id: cart.checkout_id,
11972
12150
  description: `${name} #${cart.number}`,
11973
- requires_shipping_info: shipmentDelivery,
12151
+ requires_shipping_info: shipping,
11974
12152
  items: getItems(cart),
11975
12153
  discounts: getDiscounts(cart),
11976
- tax_amount: shipmentDelivery
12154
+ tax_amount: shipping
11977
12155
  ? undefined
11978
12156
  : getAmountInCents(cartCurrency, cart.tax_total),
11979
12157
  order_amount: getAmountInCents(cartCurrency, cart.capture_total),
@@ -12233,15 +12411,6 @@ function convertToSwellAddress(address) {
12233
12411
  };
12234
12412
  }
12235
12413
 
12236
- /**
12237
- * @param {string} currency
12238
- * @param {number} amount
12239
- * @returns {number}
12240
- */
12241
- function amountInCents(currency, amount) {
12242
- return Math.round(amount * 100);
12243
- }
12244
-
12245
12414
  class PaymentController {
12246
12415
  constructor(api, options) {
12247
12416
  this.api = api;
@@ -12944,7 +13113,7 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
12944
13113
  const api = {};
12945
13114
 
12946
13115
  Object.assign(api, {
12947
- version: '5.6.1',
13116
+ version: '5.8.0',
12948
13117
  options,
12949
13118
  request,
12950
13119