/** * MotherShip fill-only 结账进度(Redis) */ import { withBoundedRedis } from "@/lib/redis"; export type MsCheckoutStatusPayload = { quote_id: string; status: "processing" | "done" | "failed"; stage?: string | null; selected_carrier?: string | null; selected_total?: number | null; coverage?: "basic" | "freight_protect" | null; cargo_value_usd?: number | null; message?: string | null; /** 仅服务端日志/诊断,不对前端暴露 */ screenshot_path?: string | null; updated_at_ms: number; }; /** GET 报价附加字段:脱敏 */ export type MsCheckoutPublic = { status: "processing" | "done" | "failed"; stage?: string | null; selected_carrier?: string | null; selected_total?: number | null; coverage?: "basic" | "freight_protect" | null; cargo_value_usd?: number | null; message?: string | null; }; const PREFIX = "ms_checkout:"; const TTL_SEC = 30 * 60; const SAFE_DONE_MSG = "已在官网填齐详情(未支付)"; const SAFE_FAIL_MSG = "官网同步失败,请稍后重试"; const SAFE_PROCESSING_MSG = "正在官网选择承运商与保障并填齐详情…"; function key(quoteId: string): string { return `${PREFIX}${quoteId}`; } export function toMsCheckoutPublic( payload: MsCheckoutStatusPayload, ): MsCheckoutPublic { let message = payload.message ?? null; if (payload.status === "failed") { message = SAFE_FAIL_MSG; } else if (payload.status === "done") { message = SAFE_DONE_MSG; } else if (payload.status === "processing") { message = SAFE_PROCESSING_MSG; } return { status: payload.status, stage: payload.stage ?? null, selected_carrier: payload.selected_carrier ?? null, selected_total: payload.selected_total ?? null, coverage: payload.coverage ?? null, cargo_value_usd: payload.cargo_value_usd ?? null, message, }; } export async function saveMsCheckoutStatus( payload: MsCheckoutStatusPayload, ): Promise { const ok = await withBoundedRedis((redis) => redis.setex(key(payload.quote_id), TTL_SEC, JSON.stringify(payload)), ); if (ok === null) { console.warn("[ms-checkout] save skipped: Redis 不可达"); } } export async function readMsCheckoutStatus( quoteId: string, ): Promise { const raw = await withBoundedRedis((redis) => redis.get(key(quoteId))); if (!raw) return null; try { return JSON.parse(raw) as MsCheckoutStatusPayload; } catch { return null; } }