Files
gitlab-instance-0a899031_salon/app/hooks/useCompleteOrderPolling.ts
2026-03-16 20:08:21 -05:00

65 lines
2.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import { useEffect, useRef } from "react";
import { tryCompleteOrder, applyCompleteSuccess } from "@/app/lib/complete-order";
const DEFAULT_RETRY_DELAYS = [1500, 2500, 3500, 4500, 5500];
export interface UseCompleteOrderPollingOptions {
/** 待完成订单 IDnull 则不轮询 */
orderId: string | null;
/** 成功后的额外回调(用 ref 存储避免 deps 变化) */
onSuccess?: (data: { token: string; record?: { wechatId?: string } }) => void;
/** 重试间隔(毫秒) */
retryDelays?: number[];
}
/** 清除 pending order 的 cookie 和 localStorage */
export function clearPendingOrder(): void {
try {
localStorage.removeItem("join_pay_order");
} catch {
/* ignore */
}
document.cookie = "join_pay_order=; path=/; max-age=0";
}
/** 支付完成后轮询 complete-order成功后同步 session 并清除 pending */
export function useCompleteOrderPolling({
orderId,
onSuccess,
retryDelays = DEFAULT_RETRY_DELAYS,
}: UseCompleteOrderPollingOptions): void {
const onSuccessRef = useRef(onSuccess);
onSuccessRef.current = onSuccess;
useEffect(() => {
if (!orderId || typeof window === "undefined") return;
let cancelled = false;
const run = async () => {
for (let i = 0; i <= retryDelays.length; i++) {
if (cancelled) return;
const result = await tryCompleteOrder(orderId);
if (result.ok) {
if (result.token && result.record) {
applyCompleteSuccess({ token: result.token, record: result.record });
} else if (result.record) {
applyCompleteSuccess({ token: "", record: result.record });
}
clearPendingOrder();
onSuccessRef.current?.({ token: result.token || "", record: result.record });
return;
}
if (i < retryDelays.length && !cancelled) {
await new Promise((r) => setTimeout(r, retryDelays[i]));
}
}
};
void run();
return () => {
cancelled = true;
};
}, [orderId, retryDelays]);
}