@flopay/react 0.4.5 → 0.4.7

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.mjs CHANGED
@@ -1361,13 +1361,19 @@ function SplitCardFormInner({
1361
1361
  onError?.(submitResult.error);
1362
1362
  return;
1363
1363
  }
1364
- const billingDetails = enableAVS ? {
1365
- name: fullName,
1366
- address: {
1367
- country: selectedCountryRef.current,
1368
- postal_code: zipCodeRef.current
1369
- }
1370
- } : void 0;
1364
+ const billingAddress = {
1365
+ ...(enableAVS ? selectedCountryRef.current : resolvedAccount.country) ? {
1366
+ country: enableAVS ? selectedCountryRef.current : resolvedAccount.country
1367
+ } : {},
1368
+ ...(enableAVS ? zipCodeRef.current.trim() : resolvedAccount.zip) || "" ? {
1369
+ postal_code: enableAVS ? zipCodeRef.current.trim() : resolvedAccount.zip
1370
+ } : {}
1371
+ };
1372
+ const billingDetails = {
1373
+ ...resolvedAccount.email ? { email: resolvedAccount.email } : {},
1374
+ ...fullName.trim() ? { name: fullName.trim() } : {},
1375
+ ...Object.keys(billingAddress).length > 0 ? { address: billingAddress } : {}
1376
+ };
1371
1377
  const pmResult = await flopay.createPaymentMethod(billingDetails);
1372
1378
  if (pmResult.error || !pmResult.paymentMethodId) {
1373
1379
  updateError(pmResult.error?.message ?? "Failed to create payment method.");
@@ -1877,6 +1883,32 @@ function SplitCardFormInner({
1877
1883
  import { loadFloPay, PaymentAPI } from "@flopay/js";
1878
1884
  import { FloPayError as FloPayError3 } from "@flopay/shared";
1879
1885
  var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
1886
+ function getRedirectResultFromCheckoutProcessError(error) {
1887
+ if (!error?.type || !error.threeDSecureToken) {
1888
+ return null;
1889
+ }
1890
+ if (error.type !== "3ds_required" && error.type !== "paypal_redirect_required") {
1891
+ return null;
1892
+ }
1893
+ return {
1894
+ type: error.type,
1895
+ threeDSecureToken: error.threeDSecureToken,
1896
+ paymentMethodId: error.paymentMethodId
1897
+ };
1898
+ }
1899
+ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
1900
+ const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
1901
+ return Object.assign(
1902
+ new FloPayError3(
1903
+ error?.message ?? fallbackMessage,
1904
+ "api_error",
1905
+ {
1906
+ code: error?.gatewayErrorCode
1907
+ }
1908
+ ),
1909
+ { checkoutMethod }
1910
+ );
1911
+ }
1880
1912
  function resolveSavedPaymentReturnUrl(session) {
1881
1913
  if (typeof window !== "undefined" && window.location.href) {
1882
1914
  return window.location.href;
@@ -2485,19 +2517,45 @@ function FloPayCheckout({
2485
2517
  setModeOverlayStatus("processing");
2486
2518
  const activeSessionId2 = options?.sessionId ?? sess.id;
2487
2519
  try {
2488
- const result = await processSavedPaymentForMode({
2489
- billingApiUrl: resolvedBillingUrl,
2490
- sessionId: activeSessionId2,
2491
- session: sess
2492
- });
2493
- const paymentResult = result.type === "success" ? result.result : await handleSavedPaymentRedirectResult(result, {
2494
- flopay: flopayRef.current,
2495
- paypalFlopay: paypalFlopayRef.current,
2496
- attempt3DS: options?.attempt3DS,
2497
- billingApiUrl: resolvedBillingUrl,
2498
- sessionId: activeSessionId2,
2499
- session: sess
2500
- });
2520
+ const redirectResult = getRedirectResultFromCheckoutProcessError(options?.initialAutoProcessingError);
2521
+ let paymentResult;
2522
+ if (redirectResult) {
2523
+ paymentResult = await handleSavedPaymentRedirectResult(redirectResult, {
2524
+ flopay: flopayRef.current,
2525
+ paypalFlopay: paypalFlopayRef.current,
2526
+ attempt3DS: options?.attempt3DS,
2527
+ billingApiUrl: resolvedBillingUrl,
2528
+ sessionId: activeSessionId2,
2529
+ session: sess
2530
+ });
2531
+ } else if (options?.initialAutoProcessingError) {
2532
+ throw checkoutProcessErrorToFloPayError(
2533
+ options.initialAutoProcessingError,
2534
+ "Automatic payment failed. Please try again.",
2535
+ {
2536
+ checkoutMethod: options.initialAutoProcessingError.checkoutMethod
2537
+ }
2538
+ );
2539
+ } else if (options?.fromCreateSession) {
2540
+ if (options?.fallbackToFull) {
2541
+ setCurrentMode("full");
2542
+ }
2543
+ return false;
2544
+ } else {
2545
+ const result = await processSavedPaymentForMode({
2546
+ billingApiUrl: resolvedBillingUrl,
2547
+ sessionId: activeSessionId2,
2548
+ session: sess
2549
+ });
2550
+ paymentResult = result.type === "success" ? result.result : await handleSavedPaymentRedirectResult(result, {
2551
+ flopay: flopayRef.current,
2552
+ paypalFlopay: paypalFlopayRef.current,
2553
+ attempt3DS: options?.attempt3DS,
2554
+ billingApiUrl: resolvedBillingUrl,
2555
+ sessionId: activeSessionId2,
2556
+ session: sess
2557
+ });
2558
+ }
2501
2559
  setModeOverlayStatus("success");
2502
2560
  await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
2503
2561
  onCompleteRef.current?.(paymentResult);
@@ -2706,6 +2764,9 @@ function FloPayCheckout({
2706
2764
  await runSavedPaymentFlow(resolvedSession, {
2707
2765
  attempt3DS: true,
2708
2766
  fallbackToFull: true,
2767
+ fromCreateSession: true,
2768
+ initialAutoProcessingError: resolved.result.autoProcessingError,
2769
+ autoProcessingAttempted: resolved.result.autoProcessingAttempted,
2709
2770
  sessionId: resolved.sid || resolvedSession.id
2710
2771
  });
2711
2772
  return;
@@ -3526,7 +3587,11 @@ function CheckoutFormInner({
3526
3587
  onError?.(submitResult.error);
3527
3588
  return;
3528
3589
  }
3529
- const pmResult = await flopay.createPaymentMethod();
3590
+ const fullName = `${firstName ?? ""} ${lastName ?? ""}`.trim();
3591
+ const pmResult = await flopay.createPaymentMethod({
3592
+ ...email ? { email } : {},
3593
+ ...fullName ? { name: fullName } : {}
3594
+ });
3530
3595
  if (pmResult.error || !pmResult.paymentMethodId) {
3531
3596
  updateError(pmResult.error?.message ?? "Failed to create payment method.");
3532
3597
  return;
@@ -4029,7 +4094,7 @@ function FloPayAutomaticPaymentButton({
4029
4094
  setOverlayStatus("error");
4030
4095
  await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
4031
4096
  }, [emitDecline]);
4032
- const processResolvedSession = useCallback5(async (apiResult, resolvedSessionId) => {
4097
+ const processResolvedSession = useCallback5(async (apiResult, resolvedSessionId, options) => {
4033
4098
  const session = apiResult.data.session ?? null;
4034
4099
  if (!session) {
4035
4100
  throw new FloPayError7("No session data returned", "api_error");
@@ -4044,19 +4109,15 @@ function FloPayAutomaticPaymentButton({
4044
4109
  return;
4045
4110
  }
4046
4111
  try {
4047
- const result = await processSavedPaymentForMode({
4048
- billingApiUrl: resolvedBillingUrl,
4049
- sessionId: resolvedSessionId ?? session.id,
4050
- session,
4051
- tokenizedData: automaticPaymentToken
4052
- });
4053
- let paymentResult = result.type === "success" ? result.result : null;
4054
- if (result.type !== "success") {
4112
+ let paymentResult = null;
4113
+ const redirectResult = getRedirectResultFromCheckoutProcessError(apiResult.autoProcessingError);
4114
+ const shouldTreatCreateSessionFlowAsServerAutoAttempt = options?.fromCreateSession && (apiResult.autoProcessingAttempted === true || !!apiResult.autoProcessingError || !!redirectResult);
4115
+ if (redirectResult) {
4055
4116
  const {
4056
4117
  publishableKey,
4057
4118
  paypalPublishableKey
4058
4119
  } = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
4059
- if (result.type === "paypal_redirect_required") {
4120
+ if (redirectResult.type === "paypal_redirect_required") {
4060
4121
  persistPayPalResumeState({
4061
4122
  sessionId: session.id || resolvedSessionId,
4062
4123
  publishableKey,
@@ -4072,7 +4133,7 @@ function FloPayAutomaticPaymentButton({
4072
4133
  billingApiUrl: resolvedBillingUrl,
4073
4134
  locale
4074
4135
  });
4075
- paymentResult = await handleSavedPaymentRedirectResult(result, {
4136
+ paymentResult = await handleSavedPaymentRedirectResult(redirectResult, {
4076
4137
  flopay,
4077
4138
  paypalFlopay,
4078
4139
  attempt3DS: true,
@@ -4080,9 +4141,66 @@ function FloPayAutomaticPaymentButton({
4080
4141
  sessionId: session.id || resolvedSessionId,
4081
4142
  session
4082
4143
  });
4083
- if (result.type === "paypal_redirect_required") {
4144
+ if (redirectResult.type === "paypal_redirect_required") {
4084
4145
  clearPayPalResumeState();
4085
4146
  }
4147
+ } else if (apiResult.autoProcessingError) {
4148
+ throw checkoutProcessErrorToFloPayError(
4149
+ apiResult.autoProcessingError,
4150
+ "Automatic payment failed. Please try again.",
4151
+ {
4152
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
4153
+ }
4154
+ );
4155
+ } else if (shouldTreatCreateSessionFlowAsServerAutoAttempt) {
4156
+ throw checkoutProcessErrorToFloPayError(
4157
+ {
4158
+ type: "unknown",
4159
+ message: "Automatic payment failed. Please try again."
4160
+ },
4161
+ "Automatic payment failed. Please try again."
4162
+ );
4163
+ } else {
4164
+ const result = await processSavedPaymentForMode({
4165
+ billingApiUrl: resolvedBillingUrl,
4166
+ sessionId: resolvedSessionId ?? session.id,
4167
+ session,
4168
+ tokenizedData: automaticPaymentToken
4169
+ });
4170
+ paymentResult = result.type === "success" ? result.result : null;
4171
+ if (result.type !== "success") {
4172
+ const {
4173
+ publishableKey,
4174
+ paypalPublishableKey
4175
+ } = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
4176
+ if (result.type === "paypal_redirect_required") {
4177
+ persistPayPalResumeState({
4178
+ sessionId: session.id || resolvedSessionId,
4179
+ publishableKey,
4180
+ paypalPublishableKey
4181
+ });
4182
+ }
4183
+ const {
4184
+ flopay,
4185
+ paypalFlopay
4186
+ } = await loadSavedPaymentProviders({
4187
+ publishableKey,
4188
+ paypalPublishableKey,
4189
+ billingApiUrl: resolvedBillingUrl,
4190
+ locale
4191
+ });
4192
+ paymentResult = await handleSavedPaymentRedirectResult(result, {
4193
+ flopay,
4194
+ paypalFlopay,
4195
+ attempt3DS: true,
4196
+ billingApiUrl: resolvedBillingUrl,
4197
+ sessionId: session.id || resolvedSessionId,
4198
+ session
4199
+ });
4200
+ if (result.type === "paypal_redirect_required") {
4201
+ clearPayPalResumeState();
4202
+ }
4203
+ }
4086
4204
  }
4087
4205
  await showSuccess({
4088
4206
  result: paymentResult ? {
@@ -4099,7 +4217,8 @@ function FloPayAutomaticPaymentButton({
4099
4217
  } catch (err) {
4100
4218
  let floPayErr = normalizeSavedPaymentError(err);
4101
4219
  const fallbackSessionId = session.id || resolvedSessionId;
4102
- if (floPayErr.code === "authentication_required" && fallbackSessionId && automaticPaymentToken?.id && automaticPaymentToken.id.startsWith("pm_")) {
4220
+ const shouldTreatCreateSessionFlowAsServerAutoAttempt = options?.fromCreateSession && apiResult.autoProcessingAttempted === true;
4221
+ if (!shouldTreatCreateSessionFlowAsServerAutoAttempt && floPayErr.code === "authentication_required" && fallbackSessionId && automaticPaymentToken?.id && automaticPaymentToken.id.startsWith("pm_")) {
4103
4222
  try {
4104
4223
  const {
4105
4224
  publishableKey,
@@ -4196,7 +4315,9 @@ function FloPayAutomaticPaymentButton({
4196
4315
  }
4197
4316
  try {
4198
4317
  const result = await api.createAndFetchSession(createSessionDraft);
4199
- await processResolvedSession(result, result.data.session?.id ?? null);
4318
+ await processResolvedSession(result, result.data.session?.id ?? null, {
4319
+ fromCreateSession: true
4320
+ });
4200
4321
  } catch (err) {
4201
4322
  if (err instanceof FloPayError7 && err.code === "session_auto_completed") {
4202
4323
  await showSuccess({