@flopay/react 1.2.6 → 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 +96 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.mjs +99 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -11
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,6 @@ import { FloPay, FloPayElements } from '@flopay/js';
|
|
|
3
3
|
import * as _flopay_shared from '@flopay/shared';
|
|
4
4
|
import { FloPayAppearance, InlineSessionDraft, FloPayError, PaymentResult, DeclineEvent, CheckoutButtonMethod, BeforeButtonClickEvent, InlineSessionPatch, CheckoutMode, CheckoutSession, ElementOptions, ElementChangeEvent, TokenizedBody, AVSFieldConfig, GatewayEnvironment, CheckoutProduct, CheckoutItem, CheckoutSubscription, ThemeId, ButtonsLayoutTheme, ButtonsLayoutStyles } from '@flopay/shared';
|
|
5
5
|
export { BeforeButtonClickEvent, CheckoutButtonMethod, DeclineEvent, InlineSessionDraft, InlineSessionPatch } from '@flopay/shared';
|
|
6
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
6
|
|
|
8
7
|
/** Props for the `FloPayProvider` component. */
|
|
9
8
|
interface FloPayProviderProps {
|
|
@@ -806,6 +805,15 @@ interface FloPayAutomaticPaymentSuccessEvent {
|
|
|
806
805
|
}
|
|
807
806
|
interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {
|
|
808
807
|
sessionId?: string;
|
|
808
|
+
/**
|
|
809
|
+
* Session-bound checkout token for a consumer-supplied {@link sessionId}
|
|
810
|
+
* (the `nonce` returned when that session was created). Post-#640 backends
|
|
811
|
+
* require it as `x-checkout-session-token` to read the session and to
|
|
812
|
+
* `/process` it; without it the existing-session path 401s with
|
|
813
|
+
* "Missing checkout session token.". Ignored on the create-session path,
|
|
814
|
+
* where the SDK mints and threads the nonce itself.
|
|
815
|
+
*/
|
|
816
|
+
nonce?: string;
|
|
809
817
|
createSession?: InlineSessionDraft;
|
|
810
818
|
/**
|
|
811
819
|
* @deprecated Ignored. The backend now picks the customer's most recent
|
|
@@ -858,6 +866,6 @@ interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttribu
|
|
|
858
866
|
onDecline?: (decline: DeclineEvent) => void;
|
|
859
867
|
children?: React.ReactNode;
|
|
860
868
|
}
|
|
861
|
-
declare function FloPayAutomaticPaymentButton({ sessionId, createSession, paymentMethodId: _deprecatedPaymentMethodId, checkoutMethod: _deprecatedCheckoutMethod, clientId, products, items, subscriptions, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata, billingApiUrl, locale, theme, buttonsTheme, buttonsStyles: stylesOverride, onSuccess, onError, onDecline, children, disabled, type, style, ...buttonProps }: FloPayAutomaticPaymentButtonProps):
|
|
869
|
+
declare function FloPayAutomaticPaymentButton({ sessionId, nonce, createSession, paymentMethodId: _deprecatedPaymentMethodId, checkoutMethod: _deprecatedCheckoutMethod, clientId, products, items, subscriptions, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata, billingApiUrl, locale, theme, buttonsTheme, buttonsStyles: stylesOverride, onSuccess, onError, onDecline, children, disabled, type, style, ...buttonProps }: FloPayAutomaticPaymentButtonProps): React.JSX.Element;
|
|
862
870
|
|
|
863
871
|
export { AddressElement, CardCvcElement, CardElement, CardExpiryElement, CardNumberElement, CheckoutForm, type CheckoutFormProps, type CheckoutFormRef, type CheckoutState, DirectPayPalButton, type DirectPayPalButtonProps, type ElementComponentProps, FloPayAutomaticPaymentButton, type FloPayAutomaticPaymentButtonProps, type FloPayAutomaticPaymentSuccessEvent, FloPayCheckout, type FloPayCheckoutProps, FloPayProvider, type FloPayProviderProps, PayPalButton, type PayPalButtonProps, PaymentElement, SplitCardForm, type SplitCardFormProps, type SplitCardFormRef, useCheckout, useElements, useFloPay, usePayPalFloPay };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { FloPay, FloPayElements } from '@flopay/js';
|
|
|
3
3
|
import * as _flopay_shared from '@flopay/shared';
|
|
4
4
|
import { FloPayAppearance, InlineSessionDraft, FloPayError, PaymentResult, DeclineEvent, CheckoutButtonMethod, BeforeButtonClickEvent, InlineSessionPatch, CheckoutMode, CheckoutSession, ElementOptions, ElementChangeEvent, TokenizedBody, AVSFieldConfig, GatewayEnvironment, CheckoutProduct, CheckoutItem, CheckoutSubscription, ThemeId, ButtonsLayoutTheme, ButtonsLayoutStyles } from '@flopay/shared';
|
|
5
5
|
export { BeforeButtonClickEvent, CheckoutButtonMethod, DeclineEvent, InlineSessionDraft, InlineSessionPatch } from '@flopay/shared';
|
|
6
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
7
6
|
|
|
8
7
|
/** Props for the `FloPayProvider` component. */
|
|
9
8
|
interface FloPayProviderProps {
|
|
@@ -806,6 +805,15 @@ interface FloPayAutomaticPaymentSuccessEvent {
|
|
|
806
805
|
}
|
|
807
806
|
interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'children' | 'onError'> {
|
|
808
807
|
sessionId?: string;
|
|
808
|
+
/**
|
|
809
|
+
* Session-bound checkout token for a consumer-supplied {@link sessionId}
|
|
810
|
+
* (the `nonce` returned when that session was created). Post-#640 backends
|
|
811
|
+
* require it as `x-checkout-session-token` to read the session and to
|
|
812
|
+
* `/process` it; without it the existing-session path 401s with
|
|
813
|
+
* "Missing checkout session token.". Ignored on the create-session path,
|
|
814
|
+
* where the SDK mints and threads the nonce itself.
|
|
815
|
+
*/
|
|
816
|
+
nonce?: string;
|
|
809
817
|
createSession?: InlineSessionDraft;
|
|
810
818
|
/**
|
|
811
819
|
* @deprecated Ignored. The backend now picks the customer's most recent
|
|
@@ -858,6 +866,6 @@ interface FloPayAutomaticPaymentButtonProps extends Omit<React.ButtonHTMLAttribu
|
|
|
858
866
|
onDecline?: (decline: DeclineEvent) => void;
|
|
859
867
|
children?: React.ReactNode;
|
|
860
868
|
}
|
|
861
|
-
declare function FloPayAutomaticPaymentButton({ sessionId, createSession, paymentMethodId: _deprecatedPaymentMethodId, checkoutMethod: _deprecatedCheckoutMethod, clientId, products, items, subscriptions, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata, billingApiUrl, locale, theme, buttonsTheme, buttonsStyles: stylesOverride, onSuccess, onError, onDecline, children, disabled, type, style, ...buttonProps }: FloPayAutomaticPaymentButtonProps):
|
|
869
|
+
declare function FloPayAutomaticPaymentButton({ sessionId, nonce, createSession, paymentMethodId: _deprecatedPaymentMethodId, checkoutMethod: _deprecatedCheckoutMethod, clientId, products, items, subscriptions, account, successUrl, cancelUrl, couponCodes, tagsData, utmMetadata, billingApiUrl, locale, theme, buttonsTheme, buttonsStyles: stylesOverride, onSuccess, onError, onDecline, children, disabled, type, style, ...buttonProps }: FloPayAutomaticPaymentButtonProps): React.JSX.Element;
|
|
862
870
|
|
|
863
871
|
export { AddressElement, CardCvcElement, CardElement, CardExpiryElement, CardNumberElement, CheckoutForm, type CheckoutFormProps, type CheckoutFormRef, type CheckoutState, DirectPayPalButton, type DirectPayPalButtonProps, type ElementComponentProps, FloPayAutomaticPaymentButton, type FloPayAutomaticPaymentButtonProps, type FloPayAutomaticPaymentSuccessEvent, FloPayCheckout, type FloPayCheckoutProps, FloPayProvider, type FloPayProviderProps, PayPalButton, type PayPalButtonProps, PaymentElement, SplitCardForm, type SplitCardFormProps, type SplitCardFormRef, useCheckout, useElements, useFloPay, usePayPalFloPay };
|
package/dist/index.mjs
CHANGED
|
@@ -436,7 +436,7 @@ function ProcessingOverlay({
|
|
|
436
436
|
}
|
|
437
437
|
|
|
438
438
|
// src/checkout-utils.ts
|
|
439
|
-
import { FloPayError } from "@flopay/shared";
|
|
439
|
+
import { FloPayError, isSetupIntentClientSecret } from "@flopay/shared";
|
|
440
440
|
function mergeInlineSessionPatches(base, patch) {
|
|
441
441
|
if (!patch) return base;
|
|
442
442
|
if (!base) return patch;
|
|
@@ -605,6 +605,18 @@ function resolvePaymentIntentPaymentMethodId(paymentIntent) {
|
|
|
605
605
|
}
|
|
606
606
|
async function retrievePaymentIntentFromProvider(provider, clientSecret) {
|
|
607
607
|
const retriever = provider;
|
|
608
|
+
if (isSetupIntentClientSecret(clientSecret)) {
|
|
609
|
+
if (!retriever?.retrieveSetupIntent) {
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
const { setupIntent, error: error2 } = await retriever.retrieveSetupIntent(clientSecret);
|
|
613
|
+
if (error2) {
|
|
614
|
+
throw new FloPayError(error2.message ?? "Failed to retrieve setup intent.", "api_error", {
|
|
615
|
+
...error2.code ? { code: error2.code } : {}
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
return setupIntent ?? null;
|
|
619
|
+
}
|
|
608
620
|
if (!retriever?.retrievePaymentIntent) {
|
|
609
621
|
return null;
|
|
610
622
|
}
|
|
@@ -616,6 +628,12 @@ async function retrievePaymentIntentFromProvider(provider, clientSecret) {
|
|
|
616
628
|
}
|
|
617
629
|
return paymentIntent ?? null;
|
|
618
630
|
}
|
|
631
|
+
function resolveWalletElementsMode(amountInMinorUnits) {
|
|
632
|
+
if (typeof amountInMinorUnits !== "number" || !Number.isFinite(amountInMinorUnits) || amountInMinorUnits <= 0) {
|
|
633
|
+
return { mode: "setup" };
|
|
634
|
+
}
|
|
635
|
+
return { mode: "payment", amount: amountInMinorUnits };
|
|
636
|
+
}
|
|
619
637
|
function resolveTokenizedPaymentMethodId(tokenizedBody) {
|
|
620
638
|
const candidates = [
|
|
621
639
|
tokenizedBody?.id,
|
|
@@ -1240,7 +1258,7 @@ ${debugLines.join("\n")}`
|
|
|
1240
1258
|
}
|
|
1241
1259
|
|
|
1242
1260
|
// src/split-card-form.tsx
|
|
1243
|
-
import { FloPayError as FloPayError3, resolveTheme } from "@flopay/shared";
|
|
1261
|
+
import { FloPayError as FloPayError3, isSetupIntentClientSecret as isSetupIntentClientSecret2, resolveTheme } from "@flopay/shared";
|
|
1244
1262
|
import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1245
1263
|
var STRIPE_RESUME_KEY = "flopay_stripe_resume";
|
|
1246
1264
|
var LEGACY_WALLET_RESUME_KEY = "flopay_wallet_resume";
|
|
@@ -1733,10 +1751,7 @@ function WalletButtonInner({
|
|
|
1733
1751
|
const intentJson = await intentResponse.json();
|
|
1734
1752
|
const intentClientSecret = intentJson.data?.id;
|
|
1735
1753
|
if (!intentClientSecret) throw new Error("No client_secret in payment intent response");
|
|
1736
|
-
const { error: confirmError,
|
|
1737
|
-
intentClientSecret,
|
|
1738
|
-
{ payment_method: paymentMethod.id }
|
|
1739
|
-
);
|
|
1754
|
+
const { error: confirmError, intentId } = isSetupIntentClientSecret2(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 }));
|
|
1740
1755
|
if (confirmError) {
|
|
1741
1756
|
const message = confirmError.message ?? "Wallet payment failed.";
|
|
1742
1757
|
onErrorChange?.(message);
|
|
@@ -1748,7 +1763,7 @@ function WalletButtonInner({
|
|
|
1748
1763
|
onTokenizedBody({
|
|
1749
1764
|
id: paymentMethod.id,
|
|
1750
1765
|
type: "card",
|
|
1751
|
-
threeDSecureActionResultTokenId:
|
|
1766
|
+
threeDSecureActionResultTokenId: intentId
|
|
1752
1767
|
}, {
|
|
1753
1768
|
accountPatch: prepared?.accountPatch,
|
|
1754
1769
|
sessionId: effectiveSessionId,
|
|
@@ -2611,14 +2626,17 @@ function SplitCardFormInner({
|
|
|
2611
2626
|
}
|
|
2612
2627
|
};
|
|
2613
2628
|
}, [appearance]);
|
|
2614
|
-
const walletOptions = useMemo3(() =>
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2629
|
+
const walletOptions = useMemo3(() => {
|
|
2630
|
+
const modeOptions = resolveWalletElementsMode(totalAmount);
|
|
2631
|
+
return {
|
|
2632
|
+
...modeOptions,
|
|
2633
|
+
currency: currency.toLowerCase(),
|
|
2634
|
+
paymentMethodCreation: "manual",
|
|
2635
|
+
// captureMethod only applies to payment mode; Stripe rejects it in setup.
|
|
2636
|
+
...modeOptions.mode === "payment" ? { captureMethod: "manual" } : {},
|
|
2637
|
+
...stripeAppearanceProp
|
|
2638
|
+
};
|
|
2639
|
+
}, [totalAmount, currency, stripeAppearanceProp]);
|
|
2622
2640
|
const paypalOptions = useMemo3(() => ({
|
|
2623
2641
|
mode: "payment",
|
|
2624
2642
|
amount: amountInCents,
|
|
@@ -4288,8 +4306,28 @@ function SplitCardFormInner({
|
|
|
4288
4306
|
|
|
4289
4307
|
// src/saved-payment-flow.ts
|
|
4290
4308
|
import { loadFloPay, PaymentAPI as PaymentAPI3 } from "@flopay/js";
|
|
4291
|
-
import { FloPayError as FloPayError4 } from "@flopay/shared";
|
|
4309
|
+
import { FloPayError as FloPayError4, isSetupIntentClientSecret as isSetupIntentClientSecret3 } from "@flopay/shared";
|
|
4292
4310
|
var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
|
|
4311
|
+
async function retrieveResumeIntent(stripe, clientSecret, isSetupIntent) {
|
|
4312
|
+
if (isSetupIntent) {
|
|
4313
|
+
if (typeof stripe.retrieveSetupIntent !== "function") return null;
|
|
4314
|
+
const { setupIntent, error: error2 } = await stripe.retrieveSetupIntent(clientSecret);
|
|
4315
|
+
return { error: error2, intent: setupIntent ?? null };
|
|
4316
|
+
}
|
|
4317
|
+
if (typeof stripe.retrievePaymentIntent !== "function") return null;
|
|
4318
|
+
const { paymentIntent, error } = await stripe.retrievePaymentIntent(clientSecret);
|
|
4319
|
+
return { error, intent: paymentIntent ?? null };
|
|
4320
|
+
}
|
|
4321
|
+
async function confirmResumeIntent(stripe, clientSecret, data, isSetupIntent) {
|
|
4322
|
+
if (isSetupIntent) {
|
|
4323
|
+
if (typeof stripe.confirmCardSetup !== "function") return null;
|
|
4324
|
+
const { setupIntent, error: error2 } = await stripe.confirmCardSetup(clientSecret, data);
|
|
4325
|
+
return { error: error2, intent: setupIntent ?? null };
|
|
4326
|
+
}
|
|
4327
|
+
if (typeof stripe.confirmCardPayment !== "function") return null;
|
|
4328
|
+
const { paymentIntent, error } = await stripe.confirmCardPayment(clientSecret, data);
|
|
4329
|
+
return { error, intent: paymentIntent ?? null };
|
|
4330
|
+
}
|
|
4293
4331
|
function getRedirectResultFromCheckoutProcessError(error) {
|
|
4294
4332
|
if (!error?.type || !error.threeDSecureToken) {
|
|
4295
4333
|
return null;
|
|
@@ -4418,11 +4456,13 @@ async function processSavedPaymentForMode({
|
|
|
4418
4456
|
billingApiUrl,
|
|
4419
4457
|
sessionId,
|
|
4420
4458
|
session,
|
|
4459
|
+
nonce,
|
|
4421
4460
|
tokenizedData,
|
|
4422
4461
|
returnUrl
|
|
4423
4462
|
}) {
|
|
4424
4463
|
const baseUrl = billingApiUrl.replace(/\/+$/, "");
|
|
4425
4464
|
const resolvedSessionId = sessionId ?? session.id;
|
|
4465
|
+
const resolvedNonce = nonce ?? session.clientSecret;
|
|
4426
4466
|
const customerId = session.customer?.id ?? session.accountData?.userId ?? "";
|
|
4427
4467
|
const customerEmail = session.customer?.email ?? session.accountData?.email ?? "";
|
|
4428
4468
|
const firstName = session.customer?.firstName ?? session.accountData?.firstName ?? "";
|
|
@@ -4432,7 +4472,7 @@ async function processSavedPaymentForMode({
|
|
|
4432
4472
|
const api = new PaymentAPI3(baseUrl);
|
|
4433
4473
|
const response = await retryOnceOnFetchFailure(() => api.processPayment(customerId, {
|
|
4434
4474
|
sessionId: resolvedSessionId,
|
|
4435
|
-
nonce:
|
|
4475
|
+
nonce: resolvedNonce,
|
|
4436
4476
|
tokenizedData,
|
|
4437
4477
|
accountData: {
|
|
4438
4478
|
userId: customerId,
|
|
@@ -4475,7 +4515,7 @@ async function processSavedPaymentForMode({
|
|
|
4475
4515
|
const recoveredRedirect = await recover3DSRedirectResult({
|
|
4476
4516
|
billingApiUrl: baseUrl,
|
|
4477
4517
|
sessionId: resolvedSessionId,
|
|
4478
|
-
nonce:
|
|
4518
|
+
nonce: resolvedNonce,
|
|
4479
4519
|
responseJson: json
|
|
4480
4520
|
});
|
|
4481
4521
|
if (recoveredRedirect) {
|
|
@@ -4523,64 +4563,66 @@ async function handleSavedPaymentRedirectResult(redirectResult, {
|
|
|
4523
4563
|
{ checkoutMethod: "card" }
|
|
4524
4564
|
);
|
|
4525
4565
|
}
|
|
4566
|
+
const isSetupIntent = isSetupIntentClientSecret3(redirectResult.threeDSecureToken);
|
|
4526
4567
|
let paymentIntent = null;
|
|
4527
4568
|
let savedPaymentMethodId = redirectResult.paymentMethodId;
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
);
|
|
4532
|
-
if (retrieveError) {
|
|
4569
|
+
const retrieved = await retrieveResumeIntent(stripe, redirectResult.threeDSecureToken, isSetupIntent);
|
|
4570
|
+
if (retrieved) {
|
|
4571
|
+
if (retrieved.error) {
|
|
4533
4572
|
throw Object.assign(
|
|
4534
4573
|
new FloPayError4(
|
|
4535
|
-
|
|
4574
|
+
retrieved.error.message ?? `Failed to retrieve 3DS ${isSetupIntent ? "setup" : "payment"} status.`,
|
|
4536
4575
|
"api_error",
|
|
4537
|
-
{ code:
|
|
4576
|
+
{ code: retrieved.error.code }
|
|
4538
4577
|
),
|
|
4539
4578
|
{ checkoutMethod: "card" }
|
|
4540
4579
|
);
|
|
4541
4580
|
}
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4581
|
+
const existingIntent = retrieved.intent;
|
|
4582
|
+
if (!savedPaymentMethodId && existingIntent?.payment_method) {
|
|
4583
|
+
if (typeof existingIntent.payment_method === "string") {
|
|
4584
|
+
savedPaymentMethodId = existingIntent.payment_method;
|
|
4585
|
+
} else if ("id" in existingIntent.payment_method) {
|
|
4586
|
+
savedPaymentMethodId = existingIntent.payment_method.id ?? void 0;
|
|
4547
4587
|
}
|
|
4548
4588
|
}
|
|
4549
4589
|
}
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4554
|
-
|
|
4555
|
-
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4590
|
+
const confirmed = savedPaymentMethodId ? await confirmResumeIntent(
|
|
4591
|
+
stripe,
|
|
4592
|
+
redirectResult.threeDSecureToken,
|
|
4593
|
+
{
|
|
4594
|
+
payment_method: savedPaymentMethodId,
|
|
4595
|
+
return_url: returnUrl ?? resolveSavedPaymentReturnUrl(session) ?? window.location.href
|
|
4596
|
+
},
|
|
4597
|
+
isSetupIntent
|
|
4598
|
+
) : null;
|
|
4599
|
+
if (confirmed) {
|
|
4600
|
+
if (confirmed.error) {
|
|
4559
4601
|
throw Object.assign(
|
|
4560
4602
|
new FloPayError4(
|
|
4561
|
-
|
|
4603
|
+
confirmed.error.message ?? "3DS authentication failed.",
|
|
4562
4604
|
"api_error",
|
|
4563
|
-
{ code:
|
|
4605
|
+
{ code: confirmed.error.code }
|
|
4564
4606
|
),
|
|
4565
4607
|
{ checkoutMethod: "card" }
|
|
4566
4608
|
);
|
|
4567
4609
|
}
|
|
4568
|
-
paymentIntent =
|
|
4610
|
+
paymentIntent = confirmed.intent;
|
|
4569
4611
|
} else {
|
|
4570
|
-
const
|
|
4612
|
+
const nextAction = await stripe.handleNextAction({
|
|
4571
4613
|
clientSecret: redirectResult.threeDSecureToken
|
|
4572
4614
|
});
|
|
4573
|
-
if (
|
|
4615
|
+
if (nextAction.error) {
|
|
4574
4616
|
throw Object.assign(
|
|
4575
4617
|
new FloPayError4(
|
|
4576
|
-
|
|
4618
|
+
nextAction.error.message ?? "3DS authentication failed.",
|
|
4577
4619
|
"api_error",
|
|
4578
|
-
{ code:
|
|
4620
|
+
{ code: nextAction.error.code }
|
|
4579
4621
|
),
|
|
4580
4622
|
{ checkoutMethod: "card" }
|
|
4581
4623
|
);
|
|
4582
4624
|
}
|
|
4583
|
-
paymentIntent =
|
|
4625
|
+
paymentIntent = (isSetupIntent ? nextAction.setupIntent : nextAction.paymentIntent) ?? null;
|
|
4584
4626
|
}
|
|
4585
4627
|
if (paymentIntent && (paymentIntent.status === "requires_capture" || paymentIntent.status === "succeeded" || paymentIntent.status === "processing")) {
|
|
4586
4628
|
const followUp = await processSavedPaymentForMode({
|
|
@@ -6653,6 +6695,7 @@ function resolveCreateSessionDraft(props) {
|
|
|
6653
6695
|
}
|
|
6654
6696
|
function FloPayAutomaticPaymentButton({
|
|
6655
6697
|
sessionId,
|
|
6698
|
+
nonce,
|
|
6656
6699
|
createSession,
|
|
6657
6700
|
// Deprecated — accepted for back-compat and silently ignored. Backend
|
|
6658
6701
|
// resolves the customer's latest payment method server-side.
|
|
@@ -6784,6 +6827,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6784
6827
|
if (!session) {
|
|
6785
6828
|
throw new FloPayError8("No session data returned", "api_error");
|
|
6786
6829
|
}
|
|
6830
|
+
const effectiveNonce = session.clientSecret || nonce;
|
|
6787
6831
|
if (session.status === "complete") {
|
|
6788
6832
|
await showSuccess({
|
|
6789
6833
|
result: { status: "succeeded" },
|
|
@@ -6839,7 +6883,8 @@ function FloPayAutomaticPaymentButton({
|
|
|
6839
6883
|
const result = await processSavedPaymentForMode({
|
|
6840
6884
|
billingApiUrl: resolvedBillingUrl,
|
|
6841
6885
|
sessionId: resolvedSessionId ?? session.id,
|
|
6842
|
-
session
|
|
6886
|
+
session,
|
|
6887
|
+
nonce: effectiveNonce
|
|
6843
6888
|
});
|
|
6844
6889
|
if (result.type !== "success") {
|
|
6845
6890
|
throw checkoutProcessErrorToFloPayError(
|
|
@@ -6866,11 +6911,13 @@ function FloPayAutomaticPaymentButton({
|
|
|
6866
6911
|
if (shouldShowFallbackCheckout(floPayErr, fallbackSessionId) && fallbackSessionId && isMountedRef.current) {
|
|
6867
6912
|
setFallbackSession({
|
|
6868
6913
|
sessionId: fallbackSessionId,
|
|
6869
|
-
errorMessage: floPayErr.message
|
|
6914
|
+
errorMessage: floPayErr.message,
|
|
6915
|
+
nonce: effectiveNonce || void 0
|
|
6870
6916
|
});
|
|
6871
6917
|
}
|
|
6872
6918
|
}
|
|
6873
6919
|
}, [
|
|
6920
|
+
nonce,
|
|
6874
6921
|
resolvedBillingUrl,
|
|
6875
6922
|
showError,
|
|
6876
6923
|
showSuccess
|
|
@@ -6911,7 +6958,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6911
6958
|
try {
|
|
6912
6959
|
const api = new PaymentAPI7(resolvedBillingUrl);
|
|
6913
6960
|
if (sessionId) {
|
|
6914
|
-
const result = await api.getUnifiedCheckoutSession(sessionId);
|
|
6961
|
+
const result = await api.getUnifiedCheckoutSession(sessionId, nonce);
|
|
6915
6962
|
await processResolvedSession(result, sessionId);
|
|
6916
6963
|
return;
|
|
6917
6964
|
}
|
|
@@ -6950,6 +6997,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
6950
6997
|
createSessionDraft,
|
|
6951
6998
|
disabled,
|
|
6952
6999
|
isProcessing,
|
|
7000
|
+
nonce,
|
|
6953
7001
|
processResolvedSession,
|
|
6954
7002
|
resolvedBillingUrl,
|
|
6955
7003
|
sessionId,
|
|
@@ -7084,6 +7132,7 @@ function FloPayAutomaticPaymentButton({
|
|
|
7084
7132
|
FloPayCheckout,
|
|
7085
7133
|
{
|
|
7086
7134
|
sessionId: fallbackSession.sessionId,
|
|
7135
|
+
nonce: fallbackSession.nonce,
|
|
7087
7136
|
checkoutMode: "full",
|
|
7088
7137
|
billingApiUrl: resolvedBillingUrl,
|
|
7089
7138
|
locale,
|