end of tickets
This commit is contained in:
+100
-40
@@ -30,6 +30,49 @@ const stripePromise = loadStripe(
|
||||
isStripeTesting ? STRIPE_PUBLISHABLE_KEY_TEST : STRIPE_PUBLISHABLE_KEY_LIVE,
|
||||
);
|
||||
|
||||
const isSafariBrowser = () => {
|
||||
if (
|
||||
typeof navigator !== "object" ||
|
||||
typeof navigator.userAgent !== "string"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return (
|
||||
/safari/i.test(navigator.userAgent) &&
|
||||
!/(chrome|crios|android|fxios|edgios|opr|ucbrowser)/i.test(
|
||||
navigator.userAgent,
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const openSafariCheckoutWindow = () => {
|
||||
if (!isWeb || typeof window === "undefined") {
|
||||
return null;
|
||||
}
|
||||
if (!isSafariBrowser()) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
const placeholder = window.open("", "_blank", "noopener,noreferrer");
|
||||
if (!placeholder) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
placeholder.document.write(
|
||||
"<p style='font-family: sans-serif; color: #111; padding: 16px;'>Chargement du paiement Stripe...</p>",
|
||||
);
|
||||
placeholder.document.title = "Stripe Checkout";
|
||||
} catch {
|
||||
// Ignore failures when the window gets reused or is cross-domain.
|
||||
}
|
||||
placeholder.focus?.();
|
||||
return placeholder;
|
||||
} catch (error) {
|
||||
console.warn("[StripeProvider] Safari window pre-open failed", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
export const StripeContext = React.createContext(null);
|
||||
|
||||
export const useStripe = () => {
|
||||
@@ -68,56 +111,70 @@ const StripeProvider = ({ children }) => {
|
||||
setClientSecret(null);
|
||||
}, []);
|
||||
|
||||
const redirectToCheckout = React.useCallback(async (checkoutUrl) => {
|
||||
if (!checkoutUrl) {
|
||||
throw new Error("Session Stripe introuvable.");
|
||||
}
|
||||
const redirectToCheckout = React.useCallback(
|
||||
async (checkoutUrl, { safariWindow } = {}) => {
|
||||
if (!checkoutUrl) {
|
||||
throw new Error("Session Stripe introuvable.");
|
||||
}
|
||||
|
||||
if (isWeb) {
|
||||
if (typeof window !== "undefined") {
|
||||
const openedTab = window.open(
|
||||
checkoutUrl,
|
||||
"_blank",
|
||||
"noopener,noreferrer",
|
||||
);
|
||||
// Fallback to same-tab navigation if the popup is blocked.
|
||||
if (!openedTab) {
|
||||
window.location.assign(checkoutUrl);
|
||||
if (isWeb) {
|
||||
if (safariWindow && !safariWindow.closed) {
|
||||
try {
|
||||
safariWindow.location.replace(checkoutUrl);
|
||||
} catch (navigationError) {
|
||||
safariWindow.location.href = checkoutUrl;
|
||||
}
|
||||
safariWindow.focus?.();
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const openedTab = window.open(
|
||||
checkoutUrl,
|
||||
"_blank",
|
||||
"noopener,noreferrer",
|
||||
);
|
||||
if (openedTab) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
await Linking.openURL(checkoutUrl);
|
||||
return;
|
||||
}
|
||||
throw new Error("Navigation Stripe impossible dans cet environnement.");
|
||||
}
|
||||
|
||||
const isMobileApp =
|
||||
Platform.OS === "ios" || Platform.OS === "android";
|
||||
const isMobileApp =
|
||||
Platform.OS === "ios" || Platform.OS === "android";
|
||||
|
||||
if (isMobileApp) {
|
||||
try {
|
||||
await WebBrowser.openBrowserAsync(checkoutUrl, {
|
||||
enableDefaultShareMenu: false,
|
||||
dismissButtonStyle: "close",
|
||||
presentationStyle:
|
||||
WebBrowser?.WebBrowserPresentationStyle?.PAGE_SHEET,
|
||||
});
|
||||
return;
|
||||
} catch (webBrowserError) {
|
||||
console.warn(
|
||||
"[StripeProvider] WebBrowser checkout fallback",
|
||||
webBrowserError,
|
||||
);
|
||||
if (isMobileApp) {
|
||||
try {
|
||||
await WebBrowser.openBrowserAsync(checkoutUrl, {
|
||||
enableDefaultShareMenu: false,
|
||||
dismissButtonStyle: "close",
|
||||
presentationStyle:
|
||||
WebBrowser?.WebBrowserPresentationStyle?.PAGE_SHEET,
|
||||
});
|
||||
return;
|
||||
} catch (webBrowserError) {
|
||||
console.warn(
|
||||
"[StripeProvider] WebBrowser checkout fallback",
|
||||
webBrowserError,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const canOpen = await Linking.canOpenURL(checkoutUrl);
|
||||
if (!canOpen) {
|
||||
throw new Error("Impossible d'ouvrir l'URL de paiement.");
|
||||
}
|
||||
await Linking.openURL(checkoutUrl);
|
||||
}, []);
|
||||
const canOpen = await Linking.canOpenURL(checkoutUrl);
|
||||
if (!canOpen) {
|
||||
throw new Error("Impossible d'ouvrir l'URL de paiement.");
|
||||
}
|
||||
await Linking.openURL(checkoutUrl);
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const runCheckoutSession = React.useCallback(
|
||||
async ({ callableName, payload, logTag }) => {
|
||||
const safariWindow = openSafariCheckoutWindow();
|
||||
try {
|
||||
const callable = getFunctionsClient(FUNCTIONS_REGION).httpsCallable(
|
||||
callableName,
|
||||
@@ -127,8 +184,11 @@ const StripeProvider = ({ children }) => {
|
||||
if (!checkoutUrl) {
|
||||
throw new Error("Session Stripe introuvable.");
|
||||
}
|
||||
await redirectToCheckout(checkoutUrl);
|
||||
await redirectToCheckout(checkoutUrl, { safariWindow });
|
||||
} catch (error) {
|
||||
if (safariWindow && !safariWindow.closed) {
|
||||
safariWindow.close();
|
||||
}
|
||||
console.error(`[StripeProvider] ${logTag}`, error);
|
||||
throw new Error(
|
||||
error?.message ||
|
||||
|
||||
Reference in New Issue
Block a user