@flopay/react 1.2.7 → 1.2.8

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/index.cjs CHANGED
@@ -633,6 +633,18 @@ function resolvePaymentIntentPaymentMethodId(paymentIntent) {
633
633
  }
634
634
  async function retrievePaymentIntentFromProvider(provider, clientSecret) {
635
635
  const retriever = provider;
636
+ if ((0, import_shared3.isSetupIntentClientSecret)(clientSecret)) {
637
+ if (!retriever?.retrieveSetupIntent) {
638
+ return null;
639
+ }
640
+ const { setupIntent, error: error2 } = await retriever.retrieveSetupIntent(clientSecret);
641
+ if (error2) {
642
+ throw new import_shared3.FloPayError(error2.message ?? "Failed to retrieve setup intent.", "api_error", {
643
+ ...error2.code ? { code: error2.code } : {}
644
+ });
645
+ }
646
+ return setupIntent ?? null;
647
+ }
636
648
  if (!retriever?.retrievePaymentIntent) {
637
649
  return null;
638
650
  }
@@ -644,6 +656,12 @@ async function retrievePaymentIntentFromProvider(provider, clientSecret) {
644
656
  }
645
657
  return paymentIntent ?? null;
646
658
  }
659
+ function resolveWalletElementsMode(amountInMinorUnits) {
660
+ if (typeof amountInMinorUnits !== "number" || !Number.isFinite(amountInMinorUnits) || amountInMinorUnits <= 0) {
661
+ return { mode: "setup" };
662
+ }
663
+ return { mode: "payment", amount: amountInMinorUnits };
664
+ }
647
665
  function resolveTokenizedPaymentMethodId(tokenizedBody) {
648
666
  const candidates = [
649
667
  tokenizedBody?.id,
@@ -1761,10 +1779,7 @@ function WalletButtonInner({
1761
1779
  const intentJson = await intentResponse.json();
1762
1780
  const intentClientSecret = intentJson.data?.id;
1763
1781
  if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
1764
- const { error: confirmError, paymentIntent } = await stripe.confirmCardPayment(
1765
- intentClientSecret,
1766
- { payment_method: paymentMethod.id }
1767
- );
1782
+ const { error: confirmError, intentId } = (0, import_shared6.isSetupIntentClientSecret)(intentClientSecret) ? await stripe.confirmCardSetup(intentClientSecret, { payment_method: paymentMethod.id }).then((r) => ({ error: r.error, intentId: r.setupIntent?.id })) : await stripe.confirmCardPayment(intentClientSecret, { payment_method: paymentMethod.id }).then((r) => ({ error: r.error, intentId: r.paymentIntent?.id }));
1768
1783
  if (confirmError) {
1769
1784
  const message = confirmError.message ?? "Wallet payment failed.";
1770
1785
  onErrorChange?.(message);
@@ -1776,7 +1791,7 @@ function WalletButtonInner({
1776
1791
  onTokenizedBody({
1777
1792
  id: paymentMethod.id,
1778
1793
  type: "card",
1779
- threeDSecureActionResultTokenId: paymentIntent?.id
1794
+ threeDSecureActionResultTokenId: intentId
1780
1795
  }, {
1781
1796
  accountPatch: prepared?.accountPatch,
1782
1797
  sessionId: effectiveSessionId,
@@ -2639,14 +2654,17 @@ function SplitCardFormInner({
2639
2654
  }
2640
2655
  };
2641
2656
  }, [appearance]);
2642
- const walletOptions = (0, import_react8.useMemo)(() => ({
2643
- mode: "payment",
2644
- amount: amountInCents,
2645
- currency: currency.toLowerCase(),
2646
- paymentMethodCreation: "manual",
2647
- captureMethod: "manual",
2648
- ...stripeAppearanceProp
2649
- }), [amountInCents, currency, stripeAppearanceProp]);
2657
+ const walletOptions = (0, import_react8.useMemo)(() => {
2658
+ const modeOptions = resolveWalletElementsMode(totalAmount);
2659
+ return {
2660
+ ...modeOptions,
2661
+ currency: currency.toLowerCase(),
2662
+ paymentMethodCreation: "manual",
2663
+ // captureMethod only applies to payment mode; Stripe rejects it in setup.
2664
+ ...modeOptions.mode === "payment" ? { captureMethod: "manual" } : {},
2665
+ ...stripeAppearanceProp
2666
+ };
2667
+ }, [totalAmount, currency, stripeAppearanceProp]);
2650
2668
  const paypalOptions = (0, import_react8.useMemo)(() => ({
2651
2669
  mode: "payment",
2652
2670
  amount: amountInCents,
@@ -4318,6 +4336,26 @@ function SplitCardFormInner({
4318
4336
  var import_js3 = require("@flopay/js");
4319
4337
  var import_shared7 = require("@flopay/shared");
4320
4338
  var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
4339
+ async function retrieveResumeIntent(stripe, clientSecret, isSetupIntent) {
4340
+ if (isSetupIntent) {
4341
+ if (typeof stripe.retrieveSetupIntent !== "function") return null;
4342
+ const { setupIntent, error: error2 } = await stripe.retrieveSetupIntent(clientSecret);
4343
+ return { error: error2, intent: setupIntent ?? null };
4344
+ }
4345
+ if (typeof stripe.retrievePaymentIntent !== "function") return null;
4346
+ const { paymentIntent, error } = await stripe.retrievePaymentIntent(clientSecret);
4347
+ return { error, intent: paymentIntent ?? null };
4348
+ }
4349
+ async function confirmResumeIntent(stripe, clientSecret, data, isSetupIntent) {
4350
+ if (isSetupIntent) {
4351
+ if (typeof stripe.confirmCardSetup !== "function") return null;
4352
+ const { setupIntent, error: error2 } = await stripe.confirmCardSetup(clientSecret, data);
4353
+ return { error: error2, intent: setupIntent ?? null };
4354
+ }
4355
+ if (typeof stripe.confirmCardPayment !== "function") return null;
4356
+ const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, data);
4357
+ return { error, intent: paymentIntent ?? null };
4358
+ }
4321
4359
  function getRedirectResultFromCheckoutProcessError(error) {
4322
4360
  if (!error?.type || !error.threeDSecureToken) {
4323
4361
  return null;
@@ -4553,64 +4591,66 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
4553
4591
  { checkoutMethod: "card" }
4554
4592
  );
4555
4593
  }
4594
+ const isSetupIntent = (0, import_shared7.isSetupIntentClientSecret)(redirectResult.threeDSecureToken);
4556
4595
  let paymentIntent = null;
4557
4596
  let savedPaymentMethodId = redirectResult.paymentMethodId;
4558
- if (typeof stripe.retrievePaymentIntent === "function") {
4559
- const { paymentIntent: existingPaymentIntent, error: retrieveError } = await stripe.retrievePaymentIntent(
4560
- redirectResult.threeDSecureToken
4561
- );
4562
- if (retrieveError) {
4597
+ const retrieved = await retrieveResumeIntent(stripe, redirectResult.threeDSecureToken, isSetupIntent);
4598
+ if (retrieved) {
4599
+ if (retrieved.error) {
4563
4600
  throw Object.assign(
4564
4601
  new import_shared7.FloPayError(
4565
- retrieveError.message ?? "Failed to retrieve 3DS payment status.",
4602
+ retrieved.error.message ?? `Failed to retrieve 3DS ${isSetupIntent ? "setup" : "payment"} status.`,
4566
4603
  "api_error",
4567
- { code: retrieveError.code }
4604
+ { code: retrieved.error.code }
4568
4605
  ),
4569
4606
  { checkoutMethod: "card" }
4570
4607
  );
4571
4608
  }
4572
- if (!savedPaymentMethodId && existingPaymentIntent?.payment_method) {
4573
- if (typeof existingPaymentIntent.payment_method === "string") {
4574
- savedPaymentMethodId = existingPaymentIntent.payment_method;
4575
- } else if ("id" in existingPaymentIntent.payment_method) {
4576
- savedPaymentMethodId = existingPaymentIntent.payment_method.id;
4609
+ const existingIntent = retrieved.intent;
4610
+ if (!savedPaymentMethodId && existingIntent?.payment_method) {
4611
+ if (typeof existingIntent.payment_method === "string") {
4612
+ savedPaymentMethodId = existingIntent.payment_method;
4613
+ } else if ("id" in existingIntent.payment_method) {
4614
+ savedPaymentMethodId = existingIntent.payment_method.id ?? void 0;
4577
4615
  }
4578
4616
  }
4579
4617
  }
4580
- if (savedPaymentMethodId && typeof stripe.confirmCardPayment === "function") {
4581
- const { error: confirmError, paymentIntent: confirmedPaymentIntent } = await stripe.confirmCardPayment(
4582
- redirectResult.threeDSecureToken,
4583
- {
4584
- payment_method: savedPaymentMethodId,
4585
- return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
4586
- }
4587
- );
4588
- if (confirmError) {
4618
+ const confirmed = savedPaymentMethodId ? await confirmResumeIntent(
4619
+ stripe,
4620
+ redirectResult.threeDSecureToken,
4621
+ {
4622
+ payment_method: savedPaymentMethodId,
4623
+ return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
4624
+ },
4625
+ isSetupIntent
4626
+ ) : null;
4627
+ if (confirmed) {
4628
+ if (confirmed.error) {
4589
4629
  throw Object.assign(
4590
4630
  new import_shared7.FloPayError(
4591
- confirmError.message ?? "3DS authentication failed.",
4631
+ confirmed.error.message ?? "3DS authentication failed.",
4592
4632
  "api_error",
4593
- { code: confirmError.code }
4633
+ { code: confirmed.error.code }
4594
4634
  ),
4595
4635
  { checkoutMethod: "card" }
4596
4636
  );
4597
4637
  }
4598
- paymentIntent = confirmedPaymentIntent ?? null;
4638
+ paymentIntent = confirmed.intent;
4599
4639
  } else {
4600
- const { error: nextActionError, paymentIntent: nextActionPaymentIntent } = await stripe.handleNextAction({
4640
+ const nextAction = await stripe.handleNextAction({
4601
4641
  clientSecret: redirectResult.threeDSecureToken
4602
4642
  });
4603
- if (nextActionError) {
4643
+ if (nextAction.error) {
4604
4644
  throw Object.assign(
4605
4645
  new import_shared7.FloPayError(
4606
- nextActionError.message ?? "3DS authentication failed.",
4646
+ nextAction.error.message ?? "3DS authentication failed.",
4607
4647
  "api_error",
4608
- { code: nextActionError.code }
4648
+ { code: nextAction.error.code }
4609
4649
  ),
4610
4650
  { checkoutMethod: "card" }
4611
4651
  );
4612
4652
  }
4613
- paymentIntent = nextActionPaymentIntent ?? null;
4653
+ paymentIntent = (isSetupIntent ? nextAction.setupIntent : nextAction.paymentIntent) ?? null;
4614
4654
  }
4615
4655
  if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded" || paymentIntent.status === "processing")) {
4616
4656
  const followUp = await processSavedPaymentForMode({