@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.cjs CHANGED
@@ -1407,13 +1407,19 @@ function SplitCardFormInner({
1407
1407
  onError?.(submitResult.error);
1408
1408
  return;
1409
1409
  }
1410
- const billingDetails = enableAVS ? {
1411
- name: fullName,
1412
- address: {
1413
- country: selectedCountryRef.current,
1414
- postal_code: zipCodeRef.current
1415
- }
1416
- } : void 0;
1410
+ const billingAddress = {
1411
+ ...(enableAVS ? selectedCountryRef.current : resolvedAccount.country) ? {
1412
+ country: enableAVS ? selectedCountryRef.current : resolvedAccount.country
1413
+ } : {},
1414
+ ...(enableAVS ? zipCodeRef.current.trim() : resolvedAccount.zip) || "" ? {
1415
+ postal_code: enableAVS ? zipCodeRef.current.trim() : resolvedAccount.zip
1416
+ } : {}
1417
+ };
1418
+ const billingDetails = {
1419
+ ...resolvedAccount.email ? { email: resolvedAccount.email } : {},
1420
+ ...fullName.trim() ? { name: fullName.trim() } : {},
1421
+ ...Object.keys(billingAddress).length > 0 ? { address: billingAddress } : {}
1422
+ };
1417
1423
  const pmResult = await flopay.createPaymentMethod(billingDetails);
1418
1424
  if (pmResult.error || !pmResult.paymentMethodId) {
1419
1425
  updateError(pmResult.error?.message ?? "Failed to create payment method.");
@@ -1923,6 +1929,32 @@ function SplitCardFormInner({
1923
1929
  var import_js = require("@flopay/js");
1924
1930
  var import_shared6 = require("@flopay/shared");
1925
1931
  var DEFAULT_SAVED_PAYMENT_DECLINE_METHOD = "card";
1932
+ function getRedirectResultFromCheckoutProcessError(error) {
1933
+ if (!error?.type || !error.threeDSecureToken) {
1934
+ return null;
1935
+ }
1936
+ if (error.type !== "3ds_required" && error.type !== "paypal_redirect_required") {
1937
+ return null;
1938
+ }
1939
+ return {
1940
+ type: error.type,
1941
+ threeDSecureToken: error.threeDSecureToken,
1942
+ paymentMethodId: error.paymentMethodId
1943
+ };
1944
+ }
1945
+ function checkoutProcessErrorToFloPayError(error, fallbackMessage = "Payment failed. Please try again.", options) {
1946
+ const checkoutMethod = options?.checkoutMethod ?? error?.checkoutMethod ?? (error?.type === "paypal_redirect_required" ? "paypal" : "card");
1947
+ return Object.assign(
1948
+ new import_shared6.FloPayError(
1949
+ error?.message ?? fallbackMessage,
1950
+ "api_error",
1951
+ {
1952
+ code: error?.gatewayErrorCode
1953
+ }
1954
+ ),
1955
+ { checkoutMethod }
1956
+ );
1957
+ }
1926
1958
  function resolveSavedPaymentReturnUrl(session) {
1927
1959
  if (typeof window !== "undefined" && window.location.href) {
1928
1960
  return window.location.href;
@@ -2531,19 +2563,45 @@ function FloPayCheckout({
2531
2563
  setModeOverlayStatus("processing");
2532
2564
  const activeSessionId2 = options?.sessionId ?? sess.id;
2533
2565
  try {
2534
- const result = await processSavedPaymentForMode({
2535
- billingApiUrl: resolvedBillingUrl,
2536
- sessionId: activeSessionId2,
2537
- session: sess
2538
- });
2539
- const paymentResult = result.type === "success" ? result.result : await handleSavedPaymentRedirectResult(result, {
2540
- flopay: flopayRef.current,
2541
- paypalFlopay: paypalFlopayRef.current,
2542
- attempt3DS: options?.attempt3DS,
2543
- billingApiUrl: resolvedBillingUrl,
2544
- sessionId: activeSessionId2,
2545
- session: sess
2546
- });
2566
+ const redirectResult = getRedirectResultFromCheckoutProcessError(options?.initialAutoProcessingError);
2567
+ let paymentResult;
2568
+ if (redirectResult) {
2569
+ paymentResult = await handleSavedPaymentRedirectResult(redirectResult, {
2570
+ flopay: flopayRef.current,
2571
+ paypalFlopay: paypalFlopayRef.current,
2572
+ attempt3DS: options?.attempt3DS,
2573
+ billingApiUrl: resolvedBillingUrl,
2574
+ sessionId: activeSessionId2,
2575
+ session: sess
2576
+ });
2577
+ } else if (options?.initialAutoProcessingError) {
2578
+ throw checkoutProcessErrorToFloPayError(
2579
+ options.initialAutoProcessingError,
2580
+ "Automatic payment failed. Please try again.",
2581
+ {
2582
+ checkoutMethod: options.initialAutoProcessingError.checkoutMethod
2583
+ }
2584
+ );
2585
+ } else if (options?.fromCreateSession) {
2586
+ if (options?.fallbackToFull) {
2587
+ setCurrentMode("full");
2588
+ }
2589
+ return false;
2590
+ } else {
2591
+ const result = await processSavedPaymentForMode({
2592
+ billingApiUrl: resolvedBillingUrl,
2593
+ sessionId: activeSessionId2,
2594
+ session: sess
2595
+ });
2596
+ paymentResult = result.type === "success" ? result.result : await handleSavedPaymentRedirectResult(result, {
2597
+ flopay: flopayRef.current,
2598
+ paypalFlopay: paypalFlopayRef.current,
2599
+ attempt3DS: options?.attempt3DS,
2600
+ billingApiUrl: resolvedBillingUrl,
2601
+ sessionId: activeSessionId2,
2602
+ session: sess
2603
+ });
2604
+ }
2547
2605
  setModeOverlayStatus("success");
2548
2606
  await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
2549
2607
  onCompleteRef.current?.(paymentResult);
@@ -2752,6 +2810,9 @@ function FloPayCheckout({
2752
2810
  await runSavedPaymentFlow(resolvedSession, {
2753
2811
  attempt3DS: true,
2754
2812
  fallbackToFull: true,
2813
+ fromCreateSession: true,
2814
+ initialAutoProcessingError: resolved.result.autoProcessingError,
2815
+ autoProcessingAttempted: resolved.result.autoProcessingAttempted,
2755
2816
  sessionId: resolved.sid || resolvedSession.id
2756
2817
  });
2757
2818
  return;
@@ -3572,7 +3633,11 @@ function CheckoutFormInner({
3572
3633
  onError?.(submitResult.error);
3573
3634
  return;
3574
3635
  }
3575
- const pmResult = await flopay.createPaymentMethod();
3636
+ const fullName = `${firstName ?? ""} ${lastName ?? ""}`.trim();
3637
+ const pmResult = await flopay.createPaymentMethod({
3638
+ ...email ? { email } : {},
3639
+ ...fullName ? { name: fullName } : {}
3640
+ });
3576
3641
  if (pmResult.error || !pmResult.paymentMethodId) {
3577
3642
  updateError(pmResult.error?.message ?? "Failed to create payment method.");
3578
3643
  return;
@@ -4075,7 +4140,7 @@ function FloPayAutomaticPaymentButton({
4075
4140
  setOverlayStatus("error");
4076
4141
  await sleep2(PROCESSING_OVERLAY_ERROR_DELAY_MS);
4077
4142
  }, [emitDecline]);
4078
- const processResolvedSession = (0, import_react11.useCallback)(async (apiResult, resolvedSessionId) => {
4143
+ const processResolvedSession = (0, import_react11.useCallback)(async (apiResult, resolvedSessionId, options) => {
4079
4144
  const session = apiResult.data.session ?? null;
4080
4145
  if (!session) {
4081
4146
  throw new import_shared10.FloPayError("No session data returned", "api_error");
@@ -4090,19 +4155,15 @@ function FloPayAutomaticPaymentButton({
4090
4155
  return;
4091
4156
  }
4092
4157
  try {
4093
- const result = await processSavedPaymentForMode({
4094
- billingApiUrl: resolvedBillingUrl,
4095
- sessionId: resolvedSessionId ?? session.id,
4096
- session,
4097
- tokenizedData: automaticPaymentToken
4098
- });
4099
- let paymentResult = result.type === "success" ? result.result : null;
4100
- if (result.type !== "success") {
4158
+ let paymentResult = null;
4159
+ const redirectResult = getRedirectResultFromCheckoutProcessError(apiResult.autoProcessingError);
4160
+ const shouldTreatCreateSessionFlowAsServerAutoAttempt = options?.fromCreateSession && (apiResult.autoProcessingAttempted === true || !!apiResult.autoProcessingError || !!redirectResult);
4161
+ if (redirectResult) {
4101
4162
  const {
4102
4163
  publishableKey,
4103
4164
  paypalPublishableKey
4104
4165
  } = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
4105
- if (result.type === "paypal_redirect_required") {
4166
+ if (redirectResult.type === "paypal_redirect_required") {
4106
4167
  persistPayPalResumeState({
4107
4168
  sessionId: session.id || resolvedSessionId,
4108
4169
  publishableKey,
@@ -4118,7 +4179,7 @@ function FloPayAutomaticPaymentButton({
4118
4179
  billingApiUrl: resolvedBillingUrl,
4119
4180
  locale
4120
4181
  });
4121
- paymentResult = await handleSavedPaymentRedirectResult(result, {
4182
+ paymentResult = await handleSavedPaymentRedirectResult(redirectResult, {
4122
4183
  flopay,
4123
4184
  paypalFlopay,
4124
4185
  attempt3DS: true,
@@ -4126,9 +4187,66 @@ function FloPayAutomaticPaymentButton({
4126
4187
  sessionId: session.id || resolvedSessionId,
4127
4188
  session
4128
4189
  });
4129
- if (result.type === "paypal_redirect_required") {
4190
+ if (redirectResult.type === "paypal_redirect_required") {
4130
4191
  clearPayPalResumeState();
4131
4192
  }
4193
+ } else if (apiResult.autoProcessingError) {
4194
+ throw checkoutProcessErrorToFloPayError(
4195
+ apiResult.autoProcessingError,
4196
+ "Automatic payment failed. Please try again.",
4197
+ {
4198
+ checkoutMethod: apiResult.autoProcessingError.checkoutMethod
4199
+ }
4200
+ );
4201
+ } else if (shouldTreatCreateSessionFlowAsServerAutoAttempt) {
4202
+ throw checkoutProcessErrorToFloPayError(
4203
+ {
4204
+ type: "unknown",
4205
+ message: "Automatic payment failed. Please try again."
4206
+ },
4207
+ "Automatic payment failed. Please try again."
4208
+ );
4209
+ } else {
4210
+ const result = await processSavedPaymentForMode({
4211
+ billingApiUrl: resolvedBillingUrl,
4212
+ sessionId: resolvedSessionId ?? session.id,
4213
+ session,
4214
+ tokenizedData: automaticPaymentToken
4215
+ });
4216
+ paymentResult = result.type === "success" ? result.result : null;
4217
+ if (result.type !== "success") {
4218
+ const {
4219
+ publishableKey,
4220
+ paypalPublishableKey
4221
+ } = resolveSavedPaymentPublishableKeys(apiResult, fallbackPublishableKey);
4222
+ if (result.type === "paypal_redirect_required") {
4223
+ persistPayPalResumeState({
4224
+ sessionId: session.id || resolvedSessionId,
4225
+ publishableKey,
4226
+ paypalPublishableKey
4227
+ });
4228
+ }
4229
+ const {
4230
+ flopay,
4231
+ paypalFlopay
4232
+ } = await loadSavedPaymentProviders({
4233
+ publishableKey,
4234
+ paypalPublishableKey,
4235
+ billingApiUrl: resolvedBillingUrl,
4236
+ locale
4237
+ });
4238
+ paymentResult = await handleSavedPaymentRedirectResult(result, {
4239
+ flopay,
4240
+ paypalFlopay,
4241
+ attempt3DS: true,
4242
+ billingApiUrl: resolvedBillingUrl,
4243
+ sessionId: session.id || resolvedSessionId,
4244
+ session
4245
+ });
4246
+ if (result.type === "paypal_redirect_required") {
4247
+ clearPayPalResumeState();
4248
+ }
4249
+ }
4132
4250
  }
4133
4251
  await showSuccess({
4134
4252
  result: paymentResult ? {
@@ -4145,7 +4263,8 @@ function FloPayAutomaticPaymentButton({
4145
4263
  } catch (err) {
4146
4264
  let floPayErr = normalizeSavedPaymentError(err);
4147
4265
  const fallbackSessionId = session.id || resolvedSessionId;
4148
- if (floPayErr.code === "authentication_required" && fallbackSessionId && automaticPaymentToken?.id && automaticPaymentToken.id.startsWith("pm_")) {
4266
+ const shouldTreatCreateSessionFlowAsServerAutoAttempt = options?.fromCreateSession && apiResult.autoProcessingAttempted === true;
4267
+ if (!shouldTreatCreateSessionFlowAsServerAutoAttempt && floPayErr.code === "authentication_required" && fallbackSessionId && automaticPaymentToken?.id && automaticPaymentToken.id.startsWith("pm_")) {
4149
4268
  try {
4150
4269
  const {
4151
4270
  publishableKey,
@@ -4242,7 +4361,9 @@ function FloPayAutomaticPaymentButton({
4242
4361
  }
4243
4362
  try {
4244
4363
  const result = await api.createAndFetchSession(createSessionDraft);
4245
- await processResolvedSession(result, result.data.session?.id ?? null);
4364
+ await processResolvedSession(result, result.data.session?.id ?? null, {
4365
+ fromCreateSession: true
4366
+ });
4246
4367
  } catch (err) {
4247
4368
  if (err instanceof import_shared10.FloPayError && err.code === "session_auto_completed") {
4248
4369
  await showSuccess({