@flopay/react 0.5.5 → 0.5.10
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 +91 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +91 -17
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -588,6 +588,39 @@ function resolveTokenizedPaymentMethodId(tokenizedBody) {
|
|
|
588
588
|
return void 0;
|
|
589
589
|
}
|
|
590
590
|
|
|
591
|
+
// src/recent-completion.ts
|
|
592
|
+
var STORAGE_KEY_PREFIX = "flopay_recent_completion_";
|
|
593
|
+
var RECENT_COMPLETION_TTL_MS = 60 * 1e3;
|
|
594
|
+
function markSessionRecentlyCompleted(sessionId) {
|
|
595
|
+
if (!sessionId || typeof window === "undefined") return;
|
|
596
|
+
try {
|
|
597
|
+
const payload = {
|
|
598
|
+
expiresAt: Date.now() + RECENT_COMPLETION_TTL_MS
|
|
599
|
+
};
|
|
600
|
+
window.sessionStorage.setItem(STORAGE_KEY_PREFIX + sessionId, JSON.stringify(payload));
|
|
601
|
+
} catch {
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
function wasSessionRecentlyCompleted(sessionId) {
|
|
605
|
+
if (!sessionId || typeof window === "undefined") return false;
|
|
606
|
+
try {
|
|
607
|
+
const raw = window.sessionStorage.getItem(STORAGE_KEY_PREFIX + sessionId);
|
|
608
|
+
if (!raw) return false;
|
|
609
|
+
const parsed = JSON.parse(raw);
|
|
610
|
+
if (typeof parsed?.expiresAt !== "number") {
|
|
611
|
+
window.sessionStorage.removeItem(STORAGE_KEY_PREFIX + sessionId);
|
|
612
|
+
return false;
|
|
613
|
+
}
|
|
614
|
+
if (parsed.expiresAt <= Date.now()) {
|
|
615
|
+
window.sessionStorage.removeItem(STORAGE_KEY_PREFIX + sessionId);
|
|
616
|
+
return false;
|
|
617
|
+
}
|
|
618
|
+
return true;
|
|
619
|
+
} catch {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
|
|
591
624
|
// src/split-card-form.tsx
|
|
592
625
|
import { FloPayError as FloPayError2 } from "@flopay/shared";
|
|
593
626
|
import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -719,6 +752,17 @@ function PayPalButtonInner({
|
|
|
719
752
|
const redirectStatus = params.get("redirect_status");
|
|
720
753
|
if (!paymentIntentId || !clientSecret) return;
|
|
721
754
|
paypalResumeAttempted.current = true;
|
|
755
|
+
console.info("[FloPay debug] PayPal resume effect firing", {
|
|
756
|
+
paymentIntentId,
|
|
757
|
+
redirectStatus,
|
|
758
|
+
currentSessionId: sessionId,
|
|
759
|
+
url: window.location.href
|
|
760
|
+
});
|
|
761
|
+
const cleanedUrl = new URL(window.location.href);
|
|
762
|
+
cleanedUrl.searchParams.delete("payment_intent");
|
|
763
|
+
cleanedUrl.searchParams.delete("payment_intent_client_secret");
|
|
764
|
+
cleanedUrl.searchParams.delete("redirect_status");
|
|
765
|
+
window.history.replaceState({}, "", cleanedUrl.toString());
|
|
722
766
|
(async () => {
|
|
723
767
|
try {
|
|
724
768
|
setSubmitting(true);
|
|
@@ -741,11 +785,6 @@ function PayPalButtonInner({
|
|
|
741
785
|
threeDSecureActionResultTokenId: paymentIntent.id,
|
|
742
786
|
isPaypal: true
|
|
743
787
|
});
|
|
744
|
-
const url = new URL(window.location.href);
|
|
745
|
-
url.searchParams.delete("payment_intent");
|
|
746
|
-
url.searchParams.delete("payment_intent_client_secret");
|
|
747
|
-
url.searchParams.delete("redirect_status");
|
|
748
|
-
window.history.replaceState({}, "", url.toString());
|
|
749
788
|
} else {
|
|
750
789
|
const message = "PayPal payment was not completed. Please try again.";
|
|
751
790
|
onErrorChange?.(message);
|
|
@@ -773,8 +812,9 @@ function PayPalButtonInner({
|
|
|
773
812
|
accountPatch: beforeClick.accountPatch,
|
|
774
813
|
sessionId: beforeClick.sessionId
|
|
775
814
|
};
|
|
815
|
+
onButtonClick?.("paypal");
|
|
776
816
|
event.resolve();
|
|
777
|
-
}, [isProcessing, runBeforeButtonClick, submitting]);
|
|
817
|
+
}, [isProcessing, onButtonClick, runBeforeButtonClick, submitting]);
|
|
778
818
|
const handlePayPalConfirm = useCallback(async (event) => {
|
|
779
819
|
if (!stripe || !elements) return;
|
|
780
820
|
let prepared = beforeClickRef.current;
|
|
@@ -792,7 +832,6 @@ function PayPalButtonInner({
|
|
|
792
832
|
}
|
|
793
833
|
const effectiveSessionId = prepared?.sessionId ?? sessionId;
|
|
794
834
|
const effectiveEmail = prepared?.accountPatch?.email ?? email;
|
|
795
|
-
onButtonClick?.("paypal");
|
|
796
835
|
try {
|
|
797
836
|
setSubmitting(true);
|
|
798
837
|
onErrorChange?.(null);
|
|
@@ -867,7 +906,7 @@ function PayPalButtonInner({
|
|
|
867
906
|
} finally {
|
|
868
907
|
setSubmitting(false);
|
|
869
908
|
}
|
|
870
|
-
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline,
|
|
909
|
+
}, [stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]);
|
|
871
910
|
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
872
911
|
/* @__PURE__ */ jsx5(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-paypal-placeholder", children: /* @__PURE__ */ jsx5(
|
|
873
912
|
ExpressCheckoutElement,
|
|
@@ -938,7 +977,6 @@ function WalletButtonInner({
|
|
|
938
977
|
const method = walletType === "apple_pay" ? "apple_pay" : "google_pay";
|
|
939
978
|
const effectiveSessionId = prepared?.sessionId ?? sessionId;
|
|
940
979
|
const effectiveEmail = prepared?.accountPatch?.email ?? email;
|
|
941
|
-
onButtonClick?.(walletType === "apple_pay" ? "apple_pay" : "google_pay");
|
|
942
980
|
try {
|
|
943
981
|
setSubmitting(true);
|
|
944
982
|
onErrorChange?.(null);
|
|
@@ -1004,7 +1042,7 @@ function WalletButtonInner({
|
|
|
1004
1042
|
setSubmitting(false);
|
|
1005
1043
|
}
|
|
1006
1044
|
},
|
|
1007
|
-
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline,
|
|
1045
|
+
[stripe, elements, sessionId, email, baseUrl, onTokenizedBody, onErrorChange, onDecline, runBeforeButtonClick]
|
|
1008
1046
|
);
|
|
1009
1047
|
return /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1010
1048
|
/* @__PURE__ */ jsx5(ExpressCheckoutReadySwap, { state: loadState, placeholderTestId: "flopay-wallet-placeholder", children: /* @__PURE__ */ jsx5(
|
|
@@ -1024,6 +1062,7 @@ function WalletButtonInner({
|
|
|
1024
1062
|
accountPatch: beforeClick.accountPatch,
|
|
1025
1063
|
sessionId: beforeClick.sessionId
|
|
1026
1064
|
};
|
|
1065
|
+
onButtonClick?.(lastWalletMethodRef.current);
|
|
1027
1066
|
event.resolve();
|
|
1028
1067
|
},
|
|
1029
1068
|
onConfirm: handleWalletConfirm,
|
|
@@ -1278,6 +1317,11 @@ function SplitCardFormInner({
|
|
|
1278
1317
|
const effectiveAccount = mergeAccountPatch(resolvedAccount, overrides?.accountPatch);
|
|
1279
1318
|
const resolvedCompletionPaymentMethodId = overrides?.completionPaymentMethodId ?? resolveTokenizedPaymentMethodId(tokenizedBody);
|
|
1280
1319
|
const requestTokenizedBody = tokenizedBody.originalPaymentMethodId ? { ...tokenizedBody, originalPaymentMethodId: void 0 } : tokenizedBody;
|
|
1320
|
+
console.info("[FloPay debug] processPaymentInternal -> POST /process", {
|
|
1321
|
+
sessionId: effectiveSessionId,
|
|
1322
|
+
paymentIntentId: tokenizedBody.threeDSecureActionResultTokenId,
|
|
1323
|
+
isPaypal: tokenizedBody.isPaypal
|
|
1324
|
+
});
|
|
1281
1325
|
try {
|
|
1282
1326
|
const response = await fetch(`${baseUrl}/v1/checkouts/sessions/process`, {
|
|
1283
1327
|
method: "POST",
|
|
@@ -1328,6 +1372,7 @@ function SplitCardFormInner({
|
|
|
1328
1372
|
})
|
|
1329
1373
|
});
|
|
1330
1374
|
if (response.ok) {
|
|
1375
|
+
markSessionRecentlyCompleted(effectiveSessionId);
|
|
1331
1376
|
setOverlayStatus("success");
|
|
1332
1377
|
await new Promise((r) => setTimeout(r, PROCESSING_OVERLAY_SUCCESS_DELAY_MS));
|
|
1333
1378
|
onComplete?.({
|
|
@@ -2740,6 +2785,7 @@ async function loadSavedPaymentProviders({
|
|
|
2740
2785
|
import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2741
2786
|
var DEFAULT_BUTTONS_LAYOUT_BUTTON_HEIGHT2 = 44;
|
|
2742
2787
|
var PAYPAL_RESUME_STORAGE_KEY = "flopay_checkout_saved_payment_resume";
|
|
2788
|
+
var sessionInflightMap = /* @__PURE__ */ new Map();
|
|
2743
2789
|
function sleep(ms) {
|
|
2744
2790
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
2745
2791
|
}
|
|
@@ -2981,6 +3027,7 @@ function FloPayCheckout({
|
|
|
2981
3027
|
}
|
|
2982
3028
|
}
|
|
2983
3029
|
}
|
|
3030
|
+
if (activeSessionId2) markSessionRecentlyCompleted(activeSessionId2);
|
|
2984
3031
|
setModeOverlayStatus("success");
|
|
2985
3032
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
2986
3033
|
onCompleteRef.current?.(paymentResult);
|
|
@@ -3077,6 +3124,7 @@ function FloPayCheckout({
|
|
|
3077
3124
|
);
|
|
3078
3125
|
}
|
|
3079
3126
|
const paymentMethodId = typeof paymentIntent.payment_method === "string" ? paymentIntent.payment_method : paymentIntent.payment_method?.id;
|
|
3127
|
+
if (resumeState.sessionId) markSessionRecentlyCompleted(resumeState.sessionId);
|
|
3080
3128
|
setModeOverlayStatus("success");
|
|
3081
3129
|
await sleep(PROCESSING_OVERLAY_SUCCESS_DELAY_MS);
|
|
3082
3130
|
onCompleteRef.current?.({
|
|
@@ -3106,13 +3154,11 @@ function FloPayCheckout({
|
|
|
3106
3154
|
}
|
|
3107
3155
|
})();
|
|
3108
3156
|
}, [emitDecline, locale, normalizeSavedPaymentError, resolvedBillingUrl]);
|
|
3109
|
-
const inflightRef = useRef3(/* @__PURE__ */ new Map());
|
|
3110
3157
|
const initializedHashRef = useRef3(null);
|
|
3111
3158
|
function hashCreateParams(params) {
|
|
3112
3159
|
const key = JSON.stringify({
|
|
3113
3160
|
c: params?.clientId,
|
|
3114
3161
|
a: {
|
|
3115
|
-
u: params?.account?.userId ?? "",
|
|
3116
3162
|
e: params?.account?.email?.trim().toLowerCase() ?? "",
|
|
3117
3163
|
country: params?.account?.country ?? ""
|
|
3118
3164
|
},
|
|
@@ -3151,20 +3197,42 @@ function FloPayCheckout({
|
|
|
3151
3197
|
const api = new PaymentAPI2(resolvedBillingUrl);
|
|
3152
3198
|
let sid = typeof window !== "undefined" ? window.sessionStorage.getItem(cacheKey) : null;
|
|
3153
3199
|
let realResult = null;
|
|
3200
|
+
console.info("[FloPay debug] resolveInlineSession enter", {
|
|
3201
|
+
cacheKey,
|
|
3202
|
+
cachedSid: sid,
|
|
3203
|
+
url: typeof window !== "undefined" ? window.location.href : null
|
|
3204
|
+
});
|
|
3154
3205
|
if (sid) {
|
|
3155
3206
|
try {
|
|
3156
3207
|
realResult = await api.getUnifiedCheckoutSession(sid);
|
|
3157
|
-
|
|
3208
|
+
const status = realResult.data.session?.status;
|
|
3209
|
+
console.info("[FloPay debug] resolveInlineSession cache hit", {
|
|
3210
|
+
cacheKey,
|
|
3211
|
+
sid,
|
|
3212
|
+
status,
|
|
3213
|
+
recentlyCompleted: wasSessionRecentlyCompleted(sid)
|
|
3214
|
+
});
|
|
3215
|
+
if (status === "complete") {
|
|
3216
|
+
if (wasSessionRecentlyCompleted(sid)) {
|
|
3217
|
+
console.info("[FloPay debug] resolveInlineSession reuse-completed", { sid });
|
|
3218
|
+
return { sid, result: realResult };
|
|
3219
|
+
}
|
|
3220
|
+
console.warn("[FloPay debug] resolveInlineSession clearing stale complete cache", { sid });
|
|
3158
3221
|
if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
|
|
3159
3222
|
sid = null;
|
|
3160
3223
|
realResult = null;
|
|
3161
3224
|
}
|
|
3162
|
-
} catch {
|
|
3225
|
+
} catch (err) {
|
|
3226
|
+
console.warn("[FloPay debug] resolveInlineSession getUnifiedCheckoutSession threw", { sid, err });
|
|
3163
3227
|
if (typeof window !== "undefined") window.sessionStorage.removeItem(cacheKey);
|
|
3164
3228
|
sid = null;
|
|
3165
3229
|
}
|
|
3166
3230
|
}
|
|
3167
3231
|
if (!sid) {
|
|
3232
|
+
console.warn("[FloPay debug] resolveInlineSession POSTing /v1/checkouts/sessions", {
|
|
3233
|
+
cacheKey,
|
|
3234
|
+
url: typeof window !== "undefined" ? window.location.href : null
|
|
3235
|
+
});
|
|
3168
3236
|
const paramsWithAnalytics = {
|
|
3169
3237
|
...params,
|
|
3170
3238
|
avsCheck: !!enableAVS,
|
|
@@ -3188,16 +3256,22 @@ function FloPayCheckout({
|
|
|
3188
3256
|
}
|
|
3189
3257
|
const mergedParams = mergeInlineSessionPatch(baseParams, patch);
|
|
3190
3258
|
const cacheKey = hashCreateParams(mergedParams);
|
|
3191
|
-
let promise =
|
|
3259
|
+
let promise = sessionInflightMap.get(cacheKey);
|
|
3260
|
+
const inflightHit = !!promise;
|
|
3192
3261
|
if (!promise) {
|
|
3193
3262
|
promise = resolveInlineSession(mergedParams, cacheKey);
|
|
3194
|
-
|
|
3263
|
+
sessionInflightMap.set(cacheKey, promise);
|
|
3195
3264
|
}
|
|
3265
|
+
console.info("[FloPay debug] bootstrapInlineSession", {
|
|
3266
|
+
cacheKey,
|
|
3267
|
+
inflightHit,
|
|
3268
|
+
url: typeof window !== "undefined" ? window.location.href : null
|
|
3269
|
+
});
|
|
3196
3270
|
let resolved;
|
|
3197
3271
|
try {
|
|
3198
3272
|
resolved = await promise;
|
|
3199
3273
|
} finally {
|
|
3200
|
-
|
|
3274
|
+
sessionInflightMap.delete(cacheKey);
|
|
3201
3275
|
}
|
|
3202
3276
|
initializedHashRef.current = cacheKey;
|
|
3203
3277
|
try {
|