's'
This commit is contained in:
64
app/hooks/useCompleteOrderPolling.ts
Normal file
64
app/hooks/useCompleteOrderPolling.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
"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]);
|
||||
}
|
||||
Reference in New Issue
Block a user