|
|
/**
|
|
|
* 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<void> {
|
|
|
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<MsCheckoutStatusPayload | null> {
|
|
|
const raw = await withBoundedRedis((redis) => redis.get(key(quoteId)));
|
|
|
if (!raw) return null;
|
|
|
try {
|
|
|
return JSON.parse(raw) as MsCheckoutStatusPayload;
|
|
|
} catch {
|
|
|
return null;
|
|
|
}
|
|
|
}
|