swell-js 5.8.1 → 5.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/swell.cjs CHANGED
@@ -6665,13 +6665,18 @@ async function loadStripe() {
6665
6665
 
6666
6666
  async function loadPaypal(params) {
6667
6667
  if (!window.paypal) {
6668
- const { currency, client_id, merchant_id } = params;
6668
+ const { vault, currency, client_id, merchant_id } = params;
6669
+
6669
6670
  const paypalParams = {
6670
6671
  currency,
6671
6672
  'client-id': client_id,
6672
6673
  commit: false,
6673
6674
  };
6674
6675
 
6676
+ if (vault) {
6677
+ paypalParams.vault = vault;
6678
+ }
6679
+
6675
6680
  if (merchant_id) {
6676
6681
  // paypal express and ppcp onboarded
6677
6682
  paypalParams['merchant-id'] = merchant_id;
@@ -8798,7 +8803,7 @@ async function onPaymentDataChanged(intermediatePaymentData) {
8798
8803
 
8799
8804
  // Update cart with new shipping address and force tax recalculation
8800
8805
  let cart = await this.updateCart({
8801
- shipping: convertToSwellAddress$2(
8806
+ shipping: convertToSwellAddress$3(
8802
8807
  intermediatePaymentData.shippingAddress,
8803
8808
  ),
8804
8809
  });
@@ -9064,7 +9069,7 @@ function getOfferInfo(cart) {
9064
9069
  * @param {google.payments.api.Address} address
9065
9070
  * @returns {Address}
9066
9071
  */
9067
- function convertToSwellAddress$2(address) {
9072
+ function convertToSwellAddress$3(address) {
9068
9073
  return {
9069
9074
  name: address.name,
9070
9075
  address1: address.address1,
@@ -9328,11 +9333,11 @@ class BraintreeGooglePayment extends Payment {
9328
9333
  nonce,
9329
9334
  gateway: 'braintree',
9330
9335
  },
9331
- ...convertToSwellAddress$2(billingAddress),
9336
+ ...convertToSwellAddress$3(billingAddress),
9332
9337
  },
9333
9338
  ...(shippingAddress && {
9334
9339
  shipping: {
9335
- ...convertToSwellAddress$2(shippingAddress),
9340
+ ...convertToSwellAddress$3(shippingAddress),
9336
9341
  service: shippingOptionData?.id || undefined,
9337
9342
  },
9338
9343
  }),
@@ -9369,6 +9374,7 @@ class BraintreeGooglePayment extends Payment {
9369
9374
  /** @typedef {import('./payment').default} Payment */
9370
9375
  /** @typedef {import('../../types').Cart} Cart */
9371
9376
  /** @typedef {import('../../types').Address} Address */
9377
+ /** @typedef {import('../../types').CartItemBillingSchedule} CartItemBillingSchedule */
9372
9378
 
9373
9379
  /**
9374
9380
  * @this {Payment}
@@ -9380,7 +9386,7 @@ async function onShippingAddressChange(shippingContact) {
9380
9386
  // Update cart with Apple Pay shipping address to get shipping options and tax
9381
9387
  // This happens immediately when the sheet opens with the default address
9382
9388
  const cart = await this.updateCart({
9383
- shipping: convertToSwellAddress$1(shippingContact),
9389
+ shipping: convertToSwellAddress$2(shippingContact),
9384
9390
  });
9385
9391
 
9386
9392
  if (!cart.shipment_rating?.services?.length) {
@@ -9669,7 +9675,7 @@ function getShippingMethods(cart) {
9669
9675
  * @param {ApplePayJS.ApplePayPaymentContact} [address]
9670
9676
  * @returns {Address}
9671
9677
  */
9672
- function convertToSwellAddress$1(address = {}) {
9678
+ function convertToSwellAddress$2(address = {}) {
9673
9679
  return {
9674
9680
  first_name: address.givenName,
9675
9681
  last_name: address.familyName,
@@ -9712,6 +9718,99 @@ function getRequiredContactFields(params) {
9712
9718
  return { requiredBillingContactFields, requiredShippingContactFields };
9713
9719
  }
9714
9720
 
9721
+ /**
9722
+ * @param {CartItemBillingSchedule} schedule
9723
+ * @returns {{ intervalUnit: ApplePayJS.ApplePayRecurringPaymentDateUnit, intervalCount: number }}
9724
+ */
9725
+ function convertSwellScheduleToAppleRecurringInterval(schedule) {
9726
+ let intervalCount = schedule.interval_count || 1;
9727
+ let intervalUnit = 'day';
9728
+
9729
+ switch (schedule.interval) {
9730
+ case 'daily':
9731
+ intervalUnit = 'day';
9732
+ break;
9733
+
9734
+ case 'weekly':
9735
+ intervalUnit = 'day';
9736
+ intervalCount *= 7;
9737
+ break;
9738
+
9739
+ case 'monthly':
9740
+ intervalUnit = 'month';
9741
+ break;
9742
+
9743
+ case 'yearly':
9744
+ intervalUnit = 'year';
9745
+ break;
9746
+ }
9747
+
9748
+ return { intervalUnit, intervalCount };
9749
+ }
9750
+
9751
+ /**
9752
+ * @param {Cart} cart
9753
+ * @param {string} managementUrl
9754
+ * @returns {ApplePayJS.ApplePayRecurringPaymentRequest | undefined}
9755
+ */
9756
+ function getRecurringPaymentRequest(cart, managementUrl) {
9757
+ if (!cart.subscription_delivery) {
9758
+ return undefined;
9759
+ }
9760
+
9761
+ const item = cart.items.find(
9762
+ (item) =>
9763
+ item.purchase_option?.type === 'subscription' &&
9764
+ item.purchase_option.billing_schedule,
9765
+ );
9766
+
9767
+ if (item === undefined) {
9768
+ return undefined;
9769
+ }
9770
+
9771
+ const { intervalUnit, intervalCount } =
9772
+ convertSwellScheduleToAppleRecurringInterval(
9773
+ item.purchase_option.billing_schedule,
9774
+ );
9775
+
9776
+ /** @type {ApplePayJS.ApplePayRecurringPaymentRequest} */
9777
+ const recurringPaymentRequest = {
9778
+ paymentDescription:
9779
+ item.purchase_option.plan_description ||
9780
+ item.purchase_option.plan_name ||
9781
+ item.product_name ||
9782
+ item.product?.name,
9783
+ regularBilling: {
9784
+ type: 'final',
9785
+ label: item.purchase_option.plan_name || 'Subscription',
9786
+ // Calculate the subscription price manually if a trial period is specified.
9787
+ // However, discounts are not included in the calculation due to the difficulty of taking into account all scenarios.
9788
+ amount: (item.purchase_option.billing_schedule.trial_days
9789
+ ? (item.price || 0) * (item.quantity || 1)
9790
+ : item.price_total
9791
+ ).toFixed(2),
9792
+ paymentTiming: 'recurring',
9793
+ recurringPaymentIntervalUnit: intervalUnit,
9794
+ recurringPaymentIntervalCount: intervalCount,
9795
+ },
9796
+ trialBilling: item.purchase_option.billing_schedule.trial_days
9797
+ ? {
9798
+ type: 'final',
9799
+ label: 'Trial',
9800
+ // When a trial period is set, price_total is 0 (usually)
9801
+ amount: Number(item.price_total || 0).toFixed(2),
9802
+ paymentTiming: 'recurring',
9803
+ recurringPaymentIntervalUnit: 'day',
9804
+ recurringPaymentIntervalCount:
9805
+ item.purchase_option.billing_schedule.trial_days,
9806
+ }
9807
+ : undefined,
9808
+ managementURL: managementUrl,
9809
+ };
9810
+
9811
+ return recurringPaymentRequest;
9812
+ }
9813
+
9715
9814
  /** @typedef {import('../../../types').Cart} Cart */
9716
9815
 
9717
9816
  const VERSION$1 = 14;
@@ -9914,10 +10013,10 @@ class BraintreeApplePayment extends Payment {
9914
10013
  nonce: payload.nonce,
9915
10014
  gateway: 'braintree',
9916
10015
  },
9917
- ...convertToSwellAddress$1(billingContact),
10016
+ ...convertToSwellAddress$2(billingContact),
9918
10017
  },
9919
10018
  ...(shippingContact && {
9920
- shipping: convertToSwellAddress$1(shippingContact),
10019
+ shipping: convertToSwellAddress$2(shippingContact),
9921
10020
  }),
9922
10021
  });
9923
10022
 
@@ -10123,7 +10222,7 @@ class AbstractGooglePayment extends Payment {
10123
10222
  * @returns {Promise<object>}
10124
10223
  */
10125
10224
  // eslint-disable-next-line no-unused-vars
10126
- async preparePaymentDataForCartUpdate(paymentData) {
10225
+ async processPaymentData(paymentData) {
10127
10226
  throw new Error('Implement this!');
10128
10227
  }
10129
10228
 
@@ -10145,9 +10244,7 @@ class AbstractGooglePayment extends Payment {
10145
10244
  throw new Error('Google Pay token is missing');
10146
10245
  }
10147
10246
 
10148
- await this.preparePaymentDataForCartUpdate(paymentData).then((data) =>
10149
- this.updateCart(data),
10150
- );
10247
+ await this.processPaymentData(paymentData);
10151
10248
 
10152
10249
  this.onSuccess();
10153
10250
  }
@@ -10270,7 +10367,7 @@ class AuthorizeNetGooglePayment extends AbstractGooglePayment {
10270
10367
  * @param {google.payments.api.PaymentData} paymentData
10271
10368
  * @returns {Promise<object>}
10272
10369
  */
10273
- async preparePaymentDataForCartUpdate(paymentData) {
10370
+ async processPaymentData(paymentData) {
10274
10371
  const { email, shippingAddress, shippingOptionData, paymentMethodData } =
10275
10372
  paymentData;
10276
10373
 
@@ -10279,7 +10376,7 @@ class AuthorizeNetGooglePayment extends AbstractGooglePayment {
10279
10376
  tokenizationData: { token },
10280
10377
  } = paymentMethodData;
10281
10378
 
10282
- return {
10379
+ await this.updateCart({
10283
10380
  account: { email },
10284
10381
  billing: {
10285
10382
  method: 'google',
@@ -10289,15 +10386,15 @@ class AuthorizeNetGooglePayment extends AbstractGooglePayment {
10289
10386
  gateway: 'authorizenet',
10290
10387
  token: base64Encode(token),
10291
10388
  },
10292
- ...convertToSwellAddress$2(billingAddress),
10389
+ ...convertToSwellAddress$3(billingAddress),
10293
10390
  },
10294
10391
  ...(shippingAddress && {
10295
10392
  shipping: {
10296
- ...convertToSwellAddress$2(shippingAddress),
10393
+ ...convertToSwellAddress$3(shippingAddress),
10297
10394
  service: shippingOptionData?.id || undefined,
10298
10395
  },
10299
10396
  }),
10300
- };
10397
+ });
10301
10398
  }
10302
10399
  }
10303
10400
 
@@ -10412,6 +10509,10 @@ class AbstractApplePayment extends Payment {
10412
10509
  requiredShippingContactFields,
10413
10510
  requiredBillingContactFields,
10414
10511
  supportsCouponCode: true,
10512
+ recurringPaymentRequest: getRecurringPaymentRequest(
10513
+ cart,
10514
+ this.params.managementUrl,
10515
+ ),
10415
10516
  lineItems: getLineItems(cart),
10416
10517
  };
10417
10518
  }
@@ -10434,7 +10535,7 @@ class AbstractApplePayment extends Payment {
10434
10535
  * @returns {Promise<object>}
10435
10536
  */
10436
10537
  // eslint-disable-next-line no-unused-vars
10437
- async preparePaymentDataForCartUpdate(event) {
10538
+ async processPaymentData(event) {
10438
10539
  throw new Error('Implement this!');
10439
10540
  }
10440
10541
 
@@ -10492,9 +10593,7 @@ class AbstractApplePayment extends Payment {
10492
10593
  //
10493
10594
  // We store the payment token but DO NOT process the order yet.
10494
10595
  // The user must manually click "Place Order" to complete the transaction.
10495
- await this.preparePaymentDataForCartUpdate(event).then((data) =>
10496
- this.updateCart(data),
10497
- );
10596
+ await this.processPaymentData(event);
10498
10597
 
10499
10598
  // Complete Apple Pay session successfully
10500
10599
  // This closes the Apple Pay sheet and shows success to the user
@@ -10630,12 +10729,12 @@ class AuthorizeNetApplePayment extends AbstractApplePayment {
10630
10729
  * @param {ApplePayJS.ApplePayPaymentAuthorizedEvent} event
10631
10730
  * @returns {Promise<object>}
10632
10731
  */
10633
- async preparePaymentDataForCartUpdate(event) {
10732
+ async processPaymentData(event) {
10634
10733
  const {
10635
10734
  payment: { token, shippingContact, billingContact },
10636
10735
  } = event;
10637
10736
 
10638
- return {
10737
+ return this.updateCart({
10639
10738
  account: {
10640
10739
  email: shippingContact?.emailAddress || billingContact?.emailAddress,
10641
10740
  },
@@ -10647,12 +10746,12 @@ class AuthorizeNetApplePayment extends AbstractApplePayment {
10647
10746
  gateway: 'authorizenet',
10648
10747
  token: base64Encode(JSON.stringify(token.paymentData)),
10649
10748
  },
10650
- ...convertToSwellAddress$1(billingContact),
10749
+ ...convertToSwellAddress$2(billingContact),
10651
10750
  },
10652
10751
  ...(shippingContact && {
10653
- shipping: convertToSwellAddress$1(shippingContact),
10752
+ shipping: convertToSwellAddress$2(shippingContact),
10654
10753
  }),
10655
- };
10754
+ });
10656
10755
  }
10657
10756
  }
10658
10757
 
@@ -11020,7 +11119,7 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
11020
11119
  * @param {ApplePayJS.ApplePayPaymentAuthorizedEvent} event
11021
11120
  * @returns {Promise<object>}
11022
11121
  */
11023
- async preparePaymentDataForCartUpdate(event) {
11122
+ async processPaymentData(event) {
11024
11123
  const {
11025
11124
  payment: { token, shippingContact, billingContact },
11026
11125
  } = event;
@@ -11044,7 +11143,7 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
11044
11143
  },
11045
11144
  );
11046
11145
 
11047
- return {
11146
+ return this.updateCart({
11048
11147
  account: {
11049
11148
  email: shippingContact?.emailAddress || billingContact?.emailAddress,
11050
11149
  },
@@ -11059,12 +11158,12 @@ class ConvesioPayApplePayment extends AbstractApplePayment {
11059
11158
  convesiopay: {
11060
11159
  return_url: this.params.returnUrl,
11061
11160
  },
11062
- ...convertToSwellAddress$1(billingContact),
11161
+ ...convertToSwellAddress$2(billingContact),
11063
11162
  },
11064
11163
  ...(shippingContact && {
11065
- shipping: convertToSwellAddress$1(shippingContact),
11164
+ shipping: convertToSwellAddress$2(shippingContact),
11066
11165
  }),
11067
- };
11166
+ });
11068
11167
  }
11069
11168
  }
11070
11169
 
@@ -11190,7 +11289,7 @@ class ConvesioPayGooglePayment extends AbstractGooglePayment {
11190
11289
  * @param {google.payments.api.PaymentData} paymentData
11191
11290
  * @returns {Promise<object>}
11192
11291
  */
11193
- async preparePaymentDataForCartUpdate(paymentData) {
11292
+ async processPaymentData(paymentData) {
11194
11293
  const { email, shippingAddress, shippingOptionData, paymentMethodData } =
11195
11294
  paymentData;
11196
11295
 
@@ -11218,7 +11317,7 @@ class ConvesioPayGooglePayment extends AbstractGooglePayment {
11218
11317
  },
11219
11318
  );
11220
11319
 
11221
- return {
11320
+ return this.updateCart({
11222
11321
  account: { email },
11223
11322
  billing: {
11224
11323
  method: 'google',
@@ -11231,15 +11330,15 @@ class ConvesioPayGooglePayment extends AbstractGooglePayment {
11231
11330
  convesiopay: {
11232
11331
  return_url: this.params.returnUrl,
11233
11332
  },
11234
- ...convertToSwellAddress$2(billingAddress),
11333
+ ...convertToSwellAddress$3(billingAddress),
11235
11334
  },
11236
11335
  ...(shippingAddress && {
11237
11336
  shipping: {
11238
- ...convertToSwellAddress$2(shippingAddress),
11337
+ ...convertToSwellAddress$3(shippingAddress),
11239
11338
  service: shippingOptionData?.id || undefined,
11240
11339
  },
11241
11340
  }),
11242
- };
11341
+ });
11243
11342
  }
11244
11343
  }
11245
11344
 
@@ -11442,12 +11541,26 @@ function getKlarnaSessionData(cart) {
11442
11541
  };
11443
11542
  }
11444
11543
 
11544
+ /** @typedef {import('@paypal/paypal-js').PayPalNamespace} PayPal */
11545
+ /** @typedef {import('@paypal/paypal-js').ShippingAddress} ShippingAddress */
11546
+ /** @typedef {import('@paypal/paypal-js').CreateOrderData} CreateOrderData */
11547
+ /** @typedef {import('@paypal/paypal-js').CreateOrderActions} CreateOrderActions */
11548
+ /** @typedef {import('@paypal/paypal-js').OnShippingAddressChangeData} OnShippingAddressChangeData */
11549
+ /** @typedef {import('@paypal/paypal-js').OnShippingAddressChangeActions} OnShippingAddressChangeActions */
11550
+ /** @typedef {import('@paypal/paypal-js').OnShippingOptionsChangeData} OnShippingOptionsChangeData */
11551
+ /** @typedef {import('@paypal/paypal-js').OnShippingOptionsChangeActions} OnShippingOptionsChangeActions */
11552
+ /** @typedef {import('@paypal/paypal-js').OnApproveData} OnApproveData */
11553
+ /** @typedef {import('@paypal/paypal-js').OnApproveActions} OnApproveActions */
11554
+ /** @typedef {import('../../../types').Cart} Cart */
11555
+ /** @typedef {import('../../../types').Address} Address */
11556
+
11445
11557
  class PaypalDirectPayment extends Payment {
11446
11558
  constructor(api, options, params, methods) {
11447
11559
  super(api, options, params, methods.paypal);
11448
11560
  }
11449
11561
 
11450
- get scripts() {
11562
+ /** @param {Cart} cart */
11563
+ getScripts(cart) {
11451
11564
  const { client_id } = this.method;
11452
11565
 
11453
11566
  return [
@@ -11457,11 +11570,13 @@ class PaypalDirectPayment extends Payment {
11457
11570
  client_id,
11458
11571
  merchant_id: this.merchantId,
11459
11572
  cart: ['currency'],
11573
+ vault: cart.subscription_delivery,
11460
11574
  },
11461
11575
  },
11462
11576
  ];
11463
11577
  }
11464
11578
 
11579
+ /** @returns {PayPal} */
11465
11580
  get paypal() {
11466
11581
  if (!window.paypal) {
11467
11582
  throw new LibraryNotLoadedError('PayPal');
@@ -11485,7 +11600,6 @@ class PaypalDirectPayment extends Payment {
11485
11600
  async createElements(cart) {
11486
11601
  const {
11487
11602
  elementId = 'paypal-button',
11488
- locale = 'en_US',
11489
11603
  style: {
11490
11604
  layout = 'horizontal',
11491
11605
  height = 45,
@@ -11494,15 +11608,16 @@ class PaypalDirectPayment extends Payment {
11494
11608
  label = 'paypal',
11495
11609
  tagline = false,
11496
11610
  } = {},
11611
+ require: { shipping: requireShipping = true } = {},
11497
11612
  } = this.params;
11498
11613
 
11499
11614
  this.setElementContainer(elementId);
11500
11615
 
11501
11616
  this._validateCart(cart);
11502
- await this.loadScripts(this.scripts);
11617
+ await this.loadScripts(this.getScripts(cart));
11503
11618
 
11504
- this.element = this.paypal.Buttons({
11505
- locale,
11619
+ /** @type {import('@paypal/paypal-js').PayPalButtonsComponentOptions} */
11620
+ const buttonsOptions = {
11506
11621
  style: {
11507
11622
  layout,
11508
11623
  height,
@@ -11511,11 +11626,27 @@ class PaypalDirectPayment extends Payment {
11511
11626
  label,
11512
11627
  tagline,
11513
11628
  },
11629
+ fundingSource: this.paypal.FUNDING.PAYPAL,
11514
11630
  createOrder: this._onCreateOrder.bind(this, cart),
11515
- onShippingChange: this._onShippingChange.bind(this),
11516
11631
  onApprove: this._onApprove.bind(this),
11517
11632
  onError: this.onError.bind(this),
11518
- });
11633
+ };
11634
+
11635
+ if (requireShipping) {
11636
+ buttonsOptions.onShippingAddressChange =
11637
+ this._onShippingAddressChange.bind(this);
11638
+
11639
+ buttonsOptions.onShippingOptionsChange =
11640
+ this._onShippingOptionsChange.bind(this);
11641
+ }
11642
+
11643
+ const component = this.paypal.Buttons(buttonsOptions);
11644
+
11645
+ if (!component.isEligible()) {
11646
+ throw new Error('PayPal button with provided options is not eligible.');
11647
+ }
11648
+
11649
+ this.element = component;
11519
11650
  }
11520
11651
 
11521
11652
  mountElements() {
@@ -11529,6 +11660,7 @@ class PaypalDirectPayment extends Payment {
11529
11660
  }
11530
11661
  }
11531
11662
 
11663
+ /** @param {Cart} cart */
11532
11664
  _validateCart(cart) {
11533
11665
  const hasSubscriptionProduct = Boolean(cart.subscription_delivery);
11534
11666
 
@@ -11538,27 +11670,35 @@ class PaypalDirectPayment extends Payment {
11538
11670
  );
11539
11671
  }
11540
11672
 
11541
- if (!(cart.capture_total > 0)) {
11673
+ if ((cart.capture_total || 0) <= 0) {
11542
11674
  throw new Error(
11543
11675
  'Invalid PayPal button amount. Value should be greater than zero.',
11544
11676
  );
11545
11677
  }
11546
11678
  }
11547
11679
 
11680
+ /**
11681
+ * @param {Cart} cart
11682
+ * @param {CreateOrderData} _data
11683
+ * @param {CreateOrderActions} _actions
11684
+ * @returns {Promise<string>}
11685
+ */
11548
11686
  async _onCreateOrder(cart, _data, _actions) {
11549
- const { require: { shipping: requireShipping = true } = {} } = this.params;
11687
+ const {
11688
+ locale = 'en-US',
11689
+ require: { shipping: requireShipping = true } = {},
11690
+ } = this.params;
11691
+
11550
11692
  const { capture_total, currency, subscription_delivery } = cart;
11551
11693
  const hasSubscriptionProduct = Boolean(subscription_delivery);
11552
11694
  const merchantId = this.merchantId;
11553
11695
  const returnUrl = this.returnUrl;
11554
- const orderData = {
11555
- application_context: {
11556
- shipping_preference: requireShipping ? 'GET_FROM_FILE' : 'NO_SHIPPING',
11557
- },
11558
- };
11696
+ /** @type {import('@paypal/paypal-js').CreateOrderRequestBody} */
11697
+ const orderData = {};
11698
+ /** @type {import('@paypal/paypal-js').PurchaseUnit} */
11559
11699
  const purchaseUnit = {
11560
11700
  amount: {
11561
- value: Number(capture_total.toFixed(2)),
11701
+ value: Number(capture_total).toFixed(2),
11562
11702
  currency_code: currency,
11563
11703
  },
11564
11704
  };
@@ -11566,29 +11706,44 @@ class PaypalDirectPayment extends Payment {
11566
11706
  if (merchantId) {
11567
11707
  // express checkout and ppcp
11568
11708
  orderData.intent = 'AUTHORIZE';
11709
+
11710
+ orderData.payment_source = {
11711
+ paypal: {
11712
+ experience_context: {
11713
+ locale,
11714
+ shipping_preference: requireShipping
11715
+ ? 'GET_FROM_FILE'
11716
+ : 'NO_SHIPPING',
11717
+ },
11718
+ },
11719
+ };
11720
+
11569
11721
  purchaseUnit.payee = {
11570
11722
  merchant_id: merchantId,
11571
11723
  };
11572
11724
 
11573
11725
  if (hasSubscriptionProduct) {
11574
- orderData.payment_source = {
11575
- paypal: {
11576
- attributes: {
11577
- vault: {
11578
- store_in_vault: 'ON_SUCCESS',
11579
- usage_type: 'MERCHANT',
11580
- },
11581
- },
11582
- experience_context: {
11583
- return_url: `${returnUrl}&redirect_status=succeeded`,
11584
- cancel_url: `${returnUrl}&redirect_status=canceled`,
11585
- },
11726
+ orderData.payment_source.paypal.attributes = {
11727
+ vault: {
11728
+ store_in_vault: 'ON_SUCCESS',
11729
+ usage_type: 'MERCHANT',
11586
11730
  },
11587
11731
  };
11732
+
11733
+ Object.assign(orderData.payment_source.paypal.experience_context, {
11734
+ return_url: `${returnUrl}&redirect_status=succeeded`,
11735
+ cancel_url: `${returnUrl}&redirect_status=canceled`,
11736
+ });
11588
11737
  }
11589
11738
  } else {
11590
11739
  // progressive checkout
11591
11740
  orderData.intent = 'CAPTURE';
11741
+
11742
+ orderData.application_context = {
11743
+ locale,
11744
+ shipping_preference: requireShipping ? 'GET_FROM_FILE' : 'NO_SHIPPING',
11745
+ };
11746
+
11592
11747
  purchaseUnit.payee = {
11593
11748
  email_address: this.method.store_owner_email,
11594
11749
  };
@@ -11604,44 +11759,37 @@ class PaypalDirectPayment extends Payment {
11604
11759
  return order.id;
11605
11760
  }
11606
11761
 
11607
- async _onShippingChange(data, actions) {
11762
+ /**
11763
+ * @param {OnShippingAddressChangeData} data
11764
+ * @param {OnShippingAddressChangeActions} actions
11765
+ */
11766
+ async _onShippingAddressChange(data, actions) {
11608
11767
  try {
11609
- const { orderID, shipping_address, selected_shipping_option } = data;
11610
- const updateData = {
11768
+ const { orderID, shippingAddress } = data;
11769
+
11770
+ const cart = await this.updateCart({
11611
11771
  shipping: {
11612
- state: shipping_address.state,
11613
- city: shipping_address.city,
11614
- zip: shipping_address.postal_code,
11615
- country: shipping_address.country_code,
11772
+ state: shippingAddress.state,
11773
+ city: shippingAddress.city,
11774
+ zip: shippingAddress.postalCode,
11775
+ country: shippingAddress.countryCode,
11616
11776
  },
11617
11777
  shipment_rating: null,
11618
- };
11619
-
11620
- if (selected_shipping_option) {
11621
- updateData.shipping.service = selected_shipping_option.id;
11622
- updateData.$taxes = true;
11623
- }
11778
+ });
11624
11779
 
11625
- const cart = await this.updateCart(updateData);
11626
- const shippingServices = get(cart, 'shipment_rating.services');
11780
+ const shippingServices = cart.shipment_rating?.services;
11627
11781
 
11628
- // can't fulfill shipping to selected address
11782
+ // Can't fulfill shipping to selected address
11629
11783
  if (isEmpty(shippingServices)) {
11630
11784
  return actions.reject();
11631
11785
  }
11632
11786
 
11633
- let selectedShippingService;
11634
-
11635
- if (selected_shipping_option) {
11636
- selectedShippingService = shippingServices.find(
11637
- (shippingService) =>
11638
- shippingService.id === selected_shipping_option.id,
11639
- );
11640
- }
11787
+ let selectedShippingService = cart.shipping?.service;
11641
11788
 
11642
11789
  // need to set first service for cart by default
11643
11790
  if (!selectedShippingService) {
11644
11791
  const [firstShippingService] = shippingServices;
11792
+ selectedShippingService = firstShippingService.id;
11645
11793
 
11646
11794
  await this.updateCart({
11647
11795
  shipping: {
@@ -11658,8 +11806,33 @@ class PaypalDirectPayment extends Payment {
11658
11806
  paypal_order_id: orderID,
11659
11807
  },
11660
11808
  });
11809
+ } catch (error) {
11810
+ this.onError(error);
11811
+
11812
+ return actions.reject();
11813
+ }
11814
+ }
11815
+
11816
+ /**
11817
+ * @param {OnShippingOptionsChangeData} data
11818
+ * @param {OnShippingOptionsChangeActions} actions
11819
+ */
11820
+ async _onShippingOptionsChange(data, actions) {
11821
+ try {
11822
+ const { orderID, selectedShippingOption } = data;
11823
+
11824
+ const cart = await this.updateCart({
11825
+ shipping: { service: selectedShippingOption.id },
11826
+ $taxes: true,
11827
+ });
11661
11828
 
11662
- return orderID;
11829
+ await this.updateIntent({
11830
+ gateway: 'paypal',
11831
+ intent: {
11832
+ cart_id: cart.id,
11833
+ paypal_order_id: orderID,
11834
+ },
11835
+ });
11663
11836
  } catch (error) {
11664
11837
  this.onError(error);
11665
11838
 
@@ -11667,14 +11840,17 @@ class PaypalDirectPayment extends Payment {
11667
11840
  }
11668
11841
  }
11669
11842
 
11843
+ /**
11844
+ * @param {OnApproveData} data
11845
+ * @param {OnApproveActions} actions
11846
+ */
11670
11847
  async _onApprove(data, actions) {
11671
- const { require: { shipping: requireShipping = true } = {} } = this.params;
11672
11848
  const order = await actions.order.get();
11673
11849
  const orderId = order.id;
11674
- const payer = order.payer;
11850
+ const payer = order.payment_source?.paypal || order.payer;
11675
11851
  const billing = payer.address;
11676
- const shipping = get(order, 'purchase_units[0].shipping');
11677
- const name = `${payer.name.given_name} ${payer.name.surname}`;
11852
+ const shipping = order.purchase_units?.[0]?.shipping;
11853
+ const name = `${payer.name?.given_name} ${payer.name?.surname}`;
11678
11854
 
11679
11855
  await this.updateCart({
11680
11856
  account: {
@@ -11686,31 +11862,35 @@ class PaypalDirectPayment extends Payment {
11686
11862
  order_id: orderId,
11687
11863
  },
11688
11864
  name,
11689
- ...this._mapAddress(billing),
11865
+ ...convertToSwellAddress$1(billing),
11690
11866
  },
11691
- ...(requireShipping && {
11867
+ ...(shipping?.address && {
11692
11868
  shipping: {
11693
11869
  first_name: payer.name.given_name,
11694
11870
  last_name: payer.name.surname,
11695
11871
  name: shipping.name.full_name,
11696
- ...this._mapAddress(shipping.address),
11872
+ ...convertToSwellAddress$1(shipping.address),
11697
11873
  },
11698
11874
  }),
11699
11875
  });
11700
11876
 
11701
11877
  this.onSuccess();
11702
11878
  }
11879
+ }
11703
11880
 
11704
- _mapAddress(address) {
11705
- return {
11706
- address1: address.address_line_1,
11707
- address2: address.address_line_2,
11708
- state: address.admin_area_1,
11709
- city: address.admin_area_2,
11710
- zip: address.postal_code,
11711
- country: address.country_code,
11712
- };
11713
- }
11881
+ /**
11882
+ * @param {ShippingAddress} address
11883
+ * @returns {Address}
11884
+ */
11885
+ function convertToSwellAddress$1(address) {
11886
+ return {
11887
+ address1: address.address_line_1,
11888
+ address2: address.address_line_2,
11889
+ state: address.admin_area_1,
11890
+ city: address.admin_area_2,
11891
+ zip: address.postal_code,
11892
+ country: address.country_code,
11893
+ };
11714
11894
  }
11715
11895
 
11716
11896
  class AmazonDirectPayment extends Payment {
@@ -13031,7 +13211,7 @@ function swell(initStore = undefined, initKey, initOptions = {}) {
13031
13211
  const api = {};
13032
13212
 
13033
13213
  Object.assign(api, {
13034
- version: '5.8.1',
13214
+ version: '5.8.2',
13035
13215
  options,
13036
13216
  request,
13037
13217