65 lines
2.0 KiB
TypeScript
65 lines
2.0 KiB
TypeScript
"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 {
|
||
/** 待完成订单 ID,null 则不轮询 */
|
||
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]);
|
||
}
|